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