Data Capture with Recorders
Goals
- I want to implement something that behaves like the MotionScope but is something that I can automate. (Sadly, MotionScope is very onerous to automate.)
- I do not want to interfere with other threads/code that uses their own recorders.
- I want to minimize synchronization time between my app, the host and the firmware. (Some API calls do some internal locking/waiting, and that is what I want to minimize.)
Performance
The topic and API doc about recorders are useful, but don’t directly answer all my questions, particularly about performance.
Algorithm
This algorithm seems like it might be what I want.
- The count of recorders is set elsewhere (earlier), but reserves enough for this facility.
- Configure a subset of recorders (say 0 & 1) that this facility owns. For
recorder_number
in (0,1):
0.RecorderStop(recorder_number)
1.RecorderCircularBufferSet(recorder_number, false)
// don’t overwrite data
2.RecorderPeriodSet(recorder_number, 1)
// max resolution
3.RecorderDataCountSet(recorder_number, <sufficiently_high_number_ASTERISK>)
4. For each item/address to be tracked in this recorder,data_index
:RecorderDataAddressSet(recorder_number, data_index, <host_address>)
- Start capturing data (some time later), For
recorder_number
in (0,1):
1.RecorderStart(recorder_number)
- Periodically gather the data. For
recorder_number
in (0,1):
1.record_count = RecorderRecordDataRetrieveBulk(recorder_number, <sufficiently_high_number_ASTERISK>)
2. For each item/address to be tracked in this recorder,data_index
:- For each record,
record_index
in (0,record_count-1):value = RecorderRecordDataValueGet(recorder_number,data_index,record_index)
- Do something with the value.
- For each record,
- Stop capturing data (some time later), For
recorder_number
in (0,1):
1.RecorderStop(recorder_number)
sufficiently_high_number_ASTERISK
This should probably be larger than frequency with which I intend to gather the data. How high? If I want 1-sample resolution, and I intend to gather the data every ms, should I just choose some number that’s (probably) large enough that the Windows thread scheduler can meet most of the time?
Because I already have an interrupt handler (running in a different thread) for the MotionController*
object, if I wanted to have event-driven behavior, I’d have to add a scheme for the interrupt-wait thread to notify the thread handling these recorders. This could introduce delays that I don’t want, particularly when the recorder data will be coming in at a regular rate. I can’t have multiple threads waiting for (different) interrupts on the same object, right?
Questions
- Does this algorithm minimize sync/locking time/requests?
- Does
RecorderRecordDataRetrieveBulk(...)
move a bunch of data out of the (small) firmware (?) containers and into theMotionCotroller
object, so that retrieving it viaRecorderRecordDataValueGet(...)
avoids synchronization? - The recorder.cs sample does something queer: it sets the data count to 2 and the sample rate to 1, then waits 250 milliseconds before retrieving the data. That would result in getting two records from 249 ms ago (ancient, in terms of run time), right?
- What’s the total amount of data that a recorder can handle?
RecorderRecordMaxCountGet() * data_item_count
? Does the max count ever change?