I am writing an I2C library for a sensor. The sensor requires the data to be read out in 4 blocks and then processed every 100ms.
I need a non blocking implementation so i’m planning to call an update function that checks whether a block is complete (by reading a register on the sensor) and then either returns if not, starts the next block if the previous one has finished or processes the data if all 4 blocks have been read out.
What would be the best way to call my update function? software timer, hardware timer, thread or another method?
@joe4465, so if I understand correctly, you want to request 4 blocks in a row (total of 108ms) then processed for less than 3ms (for total of 111ms or 9Hz) and the cycle starts over. To do this, you could use a 1ms software timer with a finite state machine in it to trigger at the different 27ms intervals to acquire the data as long as the acquire takes less than 1ms (time between timer callbacks). The final state would be processing which needs to either take less than 1ms OR you set a flag for loop() to process the data though timing might be off. You could double-buffer the acquired data so the timer fills one buffer, set a flag and lets loop() do the processing while the timer switches to the second buffer and so on. Using the double buffer approach gives loop() 108ms to process a buffer of data.
Yeah I would have to double buffer as it takes around 60ms to process the data.
I guess I’m just not sure what kind of timer to use as it needs to:
Trigger fairly accurately - within 1ms is probably OK
Allow me to read and write registers over I2C within the callback
Be resistant to double triggering, i.e. 1ms timer triggers and then triggers again whilst I’m in the original callback
Should I be asking the sensor for its state every 1ms knowing that I will get 26 replies back before the block is ready or will this sap resources? Alternatively I could ask every 3ms and expect 8 replies back before the block is ready, or every 10ms but this would mean I would waste 3ms where the block is ready but I have not requested the data.
I am at a loss of what to try next - maybe the SparkIntervalTimer but I think it will be the same.
I can’t really call the update function using millis() from my main loop as the code needed to process the full set of blocks takes around 60ms to finish and is blocking.
_updateTimer = new Timer(1000, (void(*)())&HTPA32x32::update);
This isn’t going to work as you expect, unless you make the HTPA32x32::update method static. As it is, the real signature of that function is
void HTPA32x32__update(HTPA32x32* const _this);
But you’re casting it to function that takes no arguments, so the this pointer will be random, rather than a pointer to the object instance.
I will add support for class function callbacks in the 0.4.9 release next week. In the meantime, you can subclass Timer to include a pointer to your HTPA32x32 instance: