winIDEA SDK
data_recorder_with_live_plot.py
1# This script is licensed under BSD License, see file LICENSE.txt.
2#
3# (c) TASKING Germany GmbH, 2023
4
5"""
6This script opens a window with chart and reads and draws values of target
7variable given in command line in real-time for 5 seconds. Since
8data acquisition is used, sampling times can be around 1ms (target dependent).
9
10This script requires 'matplotlib', 'numpy', and 'scipy' to be
11installed. They are available at:
12 http://matplotlib.sourceforge.net/
13 http://www.scipy.org/Download
14"""
15
16import matplotlib
17matplotlib.use('TkAgg')
18
19import sys
20import pylab as p
21import time
22import pylab
23import numpy
24import matplotlib.animation as animation
25
26import isystem.connect as ic
27
28
29winidea_id = ''
30
31
32def printHelp():
33 print('Usage:')
34 print(' dataRecorderWithLivePlot.py <recordingTime> <viewTime> <miny> <maxy> <varName> <samplingTime>')
35 print(' recordingTime - how long to record data in seconds')
36 print(' viewTime - time interval shown on X axis in seconds')
37 print(' minY - lower limit on Y axis')
38 print(' maxY - upper limit on Y axis')
39 print(' varName - name of the variable to record')
40 print(' samplingTime - sampling time. It is rounded to the nearest ')
41 print(' lower available number (1s, 100 ms,')
42 print(' 10 ms, 1 ms). If specified as 0, the lowest available ')
43 print(' sampling time is used.')
44 print('Example:')
45 print(' dataRecorderWithLivePlot.py 10 3 -300 20000 main_loop_counter 0.1 g_baseStruct.i_base 0')
46
47
48def parseCmdLine():
49
50 if len(sys.argv) < 7:
51 printHelp()
52 print()
53 raise Exception('Not enough command line parameters!')
54
55 samplingInfo = []
56
57 recordingTime = float(sys.argv[1])
58 viewTime = float(sys.argv[2])
59 minY = float(sys.argv[3])
60 maxY = float(sys.argv[4])
61
62 # create (varName, samplingTime) pairs from params in command line
63 for idx in range(5, len(sys.argv), 2):
64 samplingInfo.append([sys.argv[idx], float(sys.argv[idx + 1])])
65
66 return [recordingTime, viewTime, minY, maxY], samplingInfo
67
68
69def initTarget():
70 cmgr = ic.ConnectionMgr()
71 cmgr.connect(ic.CConnectionConfig().instanceId(winidea_id))
72
73 debugCtrl = ic.CDebugFacade(cmgr)
74 print('Downloading ... ', end=' ')
75 debugCtrl.download()
76 print('finished!')
77 debugCtrl.runUntilFunction('main')
78 debugCtrl.waitUntilStopped()
79 debugCtrl.run()
80
81 return cmgr, debugCtrl
82
83
84def realTimeToDAQTimeFlags(samplTime):
85 """
86 Converts the given sampling time in seconds to EDAQSamplingFlags.
87 """
88 if samplTime < 0.001:
89 return ic.CDAQController.daqSampleMax
90 elif samplTime < 0.01:
91 return ic.CDAQController.daqSample1ms
92 elif samplTime < 0.1:
93 return ic.CDAQController.daqSample10ms
94 elif samplTime < 1:
95 return ic.CDAQController.daqSample100ms
96 else:
97 return ic.CDAQController.daqSample1s
98
99
100def initDAQ(cmgr, samplingInfo):
101 daqCtrl = ic.CDAQController(cmgr)
102
103 # check if DAQ system is available
104 daqInfo = daqCtrl.info()
105 if daqInfo.getMaxItems() == 0:
106 raise Exception("Data Acquisition (DAQ) system is not available.")
107
108 print('MaxItems = ', daqInfo.getMaxItems())
109
110 daqVariables = ic.DAQConfigVector()
111 for varSamplData in samplingInfo:
112 varName = varSamplData[0]
113 if varSamplData[1] == 0:
114 daqVariables.append(ic.CDAQConfigItem(varName))
115 else:
116 samplTime = realTimeToDAQTimeFlags(varSamplData[1])
117 daqVariables.append(ic.CDAQConfigItem(varName, samplTime))
118
119 # note the time of the DAQ system
120 daqTimeStart = daqCtrl.status().getTime()
121
122 daqCtrl.configure(daqVariables)
123
124 # enable DAQ on the entire SoC
125 daqCtrl.enableGlobal(True)
126
127 return [daqCtrl, daqTimeStart]
128
129
130def readValuesFromTarget():
131 timeStamps = pylab.array([])
132 values = []
133 daqStatus = daqCtrl.status()
134 # if any sample is available, display the status and print the samples
135 if daqStatus.getNumSamplesAvailable() > 0:
136 if daqStatus.getOverflow():
137 print('SAMPLING OVERFLOW!')
138
139 # read available samples into daqSamples
140 daqSamples = ic.DAQSampleVector()
141 daqCtrl.read(daqSamples)
142
143 for daqSample in daqSamples:
144 timeStamps = pylab.append(timeStamps, (daqSample.getTime() - daqTimeStart) / 1e6)
145 values.append(daqCtrl.getDataValue(daqSample).getLong())
146
147 return timeStamps, values
148
149
150def animate(i):
151 global timeOffset, xData, yData, endTime, line
152
153 timeStamps, values = readValuesFromTarget()
154
155 if time.time() < endTime and values:
156
157 print(values, i)
158
159 toff = timeStamps[-1] - viewTime
160 if toff > 0:
161 timeStamps -= toff
162 xData -= toff - timeOffset
163 timeOffset = toff
164
165 xData = pylab.append(xData, timeStamps)
166 yData = pylab.append(yData, values)
167
168 xData = xData[xData > 0]
169 yData = yData[-len(xData):]
170
171 line.set_xdata(xData)
172 line.set_ydata(yData)
173
174 return line,
175
176
177#Init only required for blitting to give a clean slate.
178def init():
179 global xData, yData
180
181 line.set_xdata(xData)
182 line.set_ydata(yData)
183 return line,
184
185
186def main():
187 global daqCtrl, yData, xData, line, daqTimeStart, endTime, viewTime, timeOffset
188
189 plotParams, samplingInfo = parseCmdLine()
190 cmgr, debugCtrl = initTarget()
191 daqCtrl, daqTimeStart = initDAQ(cmgr, samplingInfo)
192 xData = pylab.array([])
193 yData = pylab.array([])
194 timeOffset = 0
195
196 fig = pylab.figure()
197 ax = fig.add_subplot(111)
198 line, = ax.plot([0], [0])
199
200 # define ranges on X and Y axis
201 recordingTime, viewTime, minY, maxY = plotParams
202 pylab.axis([0, viewTime, minY, maxY])
203
204 startTime = time.time()
205 endTime = startTime + recordingTime
206
207 ani = animation.FuncAnimation(fig, animate, numpy.arange(0, 10), init_func=init,
208 interval=25, blit=True)
209
210 pylab.show()
211
212
213if __name__ == '__main__':
214 main()