winIDEA SDK
Loading...
Searching...
No Matches
daq_recorder.py
1# This script is licensed under BSD License, see file LICENSE.txt, or search for `License` in the SDK online help.
2#
3# (c) TASKING Germany GmbH, 2023
4#
5#
6# This script simply connects to a most recently used instance of winIDEA
7# and starts recording data using the fast data acquisition (DAQ) controller.
8# In order to do this the application must be running on the target, otherwise
9# no data will be received.
10#
11# Specify variable names and their acquisition times in command line.
12
13
14import sys
15import time
16import isystem.connect as ic
17
18
19winidea_id = ''
20
21
22def printHelp():
23 print("Usage: daqRecorder.py [--verbose] <var1 samplingRate1> <var2 samplingRate2> ... <varN samplingRateN>")
24 print()
25 print(" Max number of DAQ items (N) is displayed before the start of the DAQ acquisition process.")
26 print()
27 print(" --verbose: also prints details regarding the DAQ acquisition process.")
28 print()
29 print(" If 'samplingRateInSeconds' == 0, the smallest possible sampling")
30 print(" time is used. Supported values: 0.001, 0.01, 0.1, 1 second.")
31 print()
32 print(" To read data from digital and analog channels use name")
33 print(" DigitalIn.DIN# and AnalogIn.AIN# where # is the desired channel number.")
34 print()
35 print(" To read from a desired (32bit only) memory location use 0x#")
36 print(" where # is the desired memory address.")
37 print()
38 print("Example: daqRecorder.py main_loop_counter 0.1 g_int 0.001")
39 print(" records main_loop_counter each 100 ms, and g_int with 1 ms period.")
40
41
42def initTarget(cmgr):
43 """
44 This function initializes the target. Customize it according to
45 your needs.
46 """
47
48 debugCtrl = ic.CDebugFacade(cmgr)
49 debugCtrl.download()
50 debugCtrl.runUntilFunction('main')
51 debugCtrl.waitUntilStopped()
52
53 return debugCtrl
54
55
56def realTimeToDAQTimeFlags(samplTime):
57 """
58 Converts the given sampling time in seconds to EDAQSamplingFlags.
59 """
60 if samplTime < 0.001:
61 return ic.CDAQController.daqSampleMax
62 elif samplTime < 0.01:
63 return ic.CDAQController.daqSample1ms
64 elif samplTime < 0.1:
65 return ic.CDAQController.daqSample10ms
66 elif samplTime < 1:
67 return ic.CDAQController.daqSample100ms
68 else:
69 return ic.CDAQController.daqSample1s
70
71# Supports:
72# DIN
73# DIN0
74# DIN27
75# DIN13457
76def getDinSignalMask(varName):
77 prefix = 'DigitalIn.DIN'
78
79 # No suffix
80 if not varName.startswith(prefix):
81 return 0, 0
82
83 indices = varName[len(prefix):].strip()
84
85 # just DIN
86 if len(indices) == 0:
87 return 8, 0xff
88
89 mask = 0
90 bitCount = 0
91
92 # DIN346
93 try:
94 for c in indices:
95 num = int(c)
96
97 if (num >= 0 and num < 8):
98 bit = (1 << num)
99
100 if mask & bit == 0:
101 mask |= bit
102 bitCount += 1
103 else:
104 sys.exit(-1)
105 finally:
106 return bitCount, mask
107
108
109def recordVariables(cmgr,
110 debugCtrl,
111 variables,
112 isVerboseLogging):
113 """
114 Parameters:
115
116 debugCtrl - iSYSTEM's debugCtrl controller, which provides access to target
117
118 variables - array of two element arrays, where the first element contains
119 variable name and the second element contains sampling interval,
120 for example: [['main_loop_counter', 0.1], ['g_char', 0]].
121 Sampling interval set to 0 means the smallest interval possible.
122
123 isVerboseLogging - prints details regarding daq acquisition process.
124
125 Returns:
126 List of rows, where each row is a list containing time stamp and recorded
127 values in the same order as variable names were specified. Example for
128 two samples of three variables:
129 [[0, 23, 45, 4.35],
130 [0.1, 24, -525, 1.78]
131 ]
132
133 """
134
135 daqCtrl = ic.CDAQController(cmgr)
136 # check if DAQ system is available
137 daqInfo = daqCtrl.info()
138 if daqInfo.getMaxItems() == 0:
139 raise Exception("Data Acquisition (DAQ) system is not available.")
140
141 print('System properties:')
142 print(' MaxItems = ', daqInfo.getMaxItems())
143 print(' MaxItemSize = ', daqInfo.getMaxItemSize())
144 print()
145
146 print('Configuration:')
147 for varSamplData in variables:
148 varName = varSamplData[0]
149 samplingTime = varSamplData[1]
150 print(" - '%s': %f"%(varName, samplingTime))
151 print()
152
153 daqVariables = ic.DAQConfigVector()
154 for varSamplData in variables:
155 varName = varSamplData[0]
156 samplTime = realTimeToDAQTimeFlags(varSamplData[1])
157
158 # Direct memory address reading
159 if varName.startswith('0x'): # Sample: 0x20001000,2 for a 16bit integer @ address 20001000
160 bySize = 4 # Default size of variables is 32bit.
161 bitNumIdx = varName.index(',')
162 if bitNumIdx > 0:
163 bySizeStr = varName[bitNumIdx+1:]
164 bySize = int(bySizeStr) // 8
165 varName = varName[:bitNumIdx]
166 print(" Size in bytes: %d"%(bySize))
167
168 addr = varName[2:]
169 memAddr = int(addr, 16)
170 print(" addr: 0x%x"%(memAddr))
171
172 daqVariables.append(ic.CDAQConfigItem(bySize, 0, memAddr, samplTime))
173
174 # Reading a regular variable
175 else:
176 daqVariables.append(ic.CDAQConfigItem(varName, samplTime))
177
178 daqCtrl.configure(daqVariables)
179
180 # note the time of the DAQ system
181 daqTimeStart = daqCtrl.status().getTime()
182
183 # enable DAQ on the entire SoC
184 daqCtrl.enableGlobal(True)
185
186 numVars = len(variables)
187 varNames = []
188
189 longestVarName = 0
190 for varData in variables:
191 varName = varData[0]
192 varNames.append(varName)
193 nameLen = len(varName)
194 if nameLen > longestVarName:
195 longestVarName = nameLen
196
197 startTime = time.time()
198 RECORDING_TIME_S = 5 # seconds
199 RECORDING_END_TIME = startTime + RECORDING_TIME_S
200
201 while time.time() < RECORDING_END_TIME:
202 daqStatus = daqCtrl.status()
203 # if any sample is available, display the status and print the samples
204 if daqStatus.getNumSamplesAvailable() > 0:
205 if isVerboseLogging:
206 print(f"available no. of samples: {daqStatus.getNumSamplesAvailable()}")
207 if daqStatus.getOverflow():
208 print('SAMPLING OVERFLOW!')
209
210 # read available samples into daqSamples
211 daqSamples = ic.DAQSampleVector()
212
213 if isVerboseLogging:
214 t0 = time.time()
215 daqCtrl.read(daqSamples)
216 if isVerboseLogging:
217 t1 = time.time()
218
219 if isVerboseLogging:
220 print()
221 print("Sample acquisition duration: %fms"%((t1-t0)*1000))
222 print("Sample count: %d"%(len(daqSamples)))
223
224 # print 'Number of samples = ', daqSamples.size()
225 for daqSample in daqSamples:
226
227 varName = varNames[daqSample.getIndex()]
228
229 sampleTimeMs = (daqSample.getTime() - daqTimeStart) / 1000
230 columnIndex = daqSample.getIndex()+1
231
232 var = daqCtrl.getDataValue(daqSample)
233
234 if var.isTypeUnsigned() or var.isTypeSigned ():
235 value = var.getLong()
236 elif var.isTypeFloat():
237 value = var.getDouble()
238 elif var.isTypeAddress():
239 value = var.getAddress().m_aAddress
240 elif var.isTypeCompound():
241 value = 'Struct'
242
243 print(f"{varName:>12} @ {sampleTimeMs:9.3f} ms: {value}")
244
245 # exit the loop if 'q' was pressed
246
247 daqCtrl.enableGlobal(False)
248
249def main():
250
251 if len(sys.argv) < 2 or '--help' in sys.argv:
252 printHelp()
253 return
254
255 samplingInfo = []
256 varNames = []
257 isVerboseLogging = False
258
259 if '--verbose' in sys.argv:
260 isVerboseLogging = True
261 sys.argv.remove('--verbose')
262
263 # create (varName, samplingTime) pairs from params in command line
264 # Example input parameters:
265 # a_my_signal 0.01 a_my_int 0 a_my_char 1 DigitalIn.DIN0 0.1 AnalogIn.AIN1 0.1 DigitalIn.DIN125
266 # For digital mask testing:
267 # DigitalIn.DIN 1 DigitalIn.DIN2 1 DigitalIn.DIN123 1 DigitalIn.DIN765 1 DigitalIn.DIN23456 1
268 for idx in range(1, len(sys.argv), 2):
269 varName = sys.argv[idx]
270 varNames.append(varName)
271 samplingInfo.append([varName, float(sys.argv[idx + 1])])
272
273 cmgr = ic.ConnectionMgr()
274 cmgr.initLogger('daq', 'daqExample.log', ic.CLogger.PYTHON)
275 cmgr.connect(ic.CConnectionConfig().instanceId(winidea_id))
276 print()
277 if not cmgr.isAttached():
278 print("The connection to winIDEA has not been established - exiting script.")
279 sys.exit(-1)
280 else:
281 print("Established connection to winIDEA.")
282 print()
283 debugCtrl = initTarget(cmgr)
284
285 debugCtrl.run() # run target so that variable is changing
286
287 # Here you can modify recording time and file name.
288 recordVariables(cmgr, debugCtrl, samplingInfo, isVerboseLogging)
289
290
291if __name__ == '__main__':
292 main()