2022-05-10 11:59 AM
I have a hardware timer using its updateEvent interrupt to increment a ms_passed variable every 1 ms. I have a freeRTOS task reading ms_passed ( via TaskNotification ) in a while(1) loop to toggle a pin at a given time interval/tempo based on a variable BPM ( beats per minute ).
I would like to be able to divide 4 'clocks' in software based on the ms_passed ticks. I have implemented a rough solution based on a similar way of setting baud rates registers, ( integer and remainder registers ) and use no floating points, but I still get drift. If I run toggle 2 leds, they are in sync initially but end up out of sync with drift introduced after several minutes.
Does anyone know of an example i can look at in case this has already been done or have suggestions on the best approach?
Thanks!
2022-05-10 02:23 PM
Well NCO/DDS methods use an ADDER, basically you add a value to a 32-bit "phase accumulator" register, and the high order bit(s) can reflect the on/off state, or phase angle into a SINE ROM. Usually done in HW, usually clocked at high rates.
If it is walking off, you might need to add/subtract 1 from the value you're adding in. Generally pretty good at doing fractional rates that simple integer divider/counter methods fail at spectacularly.
Where are the TWO LEDs connected?
2022-05-10 02:32 PM
Whaty you are trying to do is in conflict with RTOS philosophy. That's what timing system was designed for. Use osDelayUntil() or RTOS timers.
2022-05-10 03:10 PM
Good info. for me to research, thanks. I'm currently using a DISCO F407 dev board and I'm just toggling LEDs when I trigger 2 of my clock divisions. ( GPIOD, GPIO_PIN_14 and GPIOD, GPIO_PIN_15 ) I plan replacing my LED toggles with a trigger to a hardware timer to generate a one-time-pulse. ( I have that part working well )
For my test, I set BPM to 65 and divide 2 clocks to run them both side-by-side to detect drift. One clock is divided by /1 and the second is divided /2 with the idea of seeing one LED toggle at half of the other's rate. This is where I'm seeing the drift after a few minutes.
2022-05-10 03:12 PM
Thanks for pointing this out, I will revisit using freeRTOS software timers, which is where I started. I thought they may not be accurate enough ( 1ms resolution ) but did not know about compensating for drift at the time.
2022-05-11 07:48 AM
I noticed a native freeRTOS vTaskDelayUntil() function. Should I use it instead of osDelayUntil()?
2022-05-11 10:10 AM
It's roughly the same. I would recommend to stick to one RTOS interface; I believe CMSIS-RTOS2 is the way to go. Generally CMSIS osXxx calls are easier to use and more immune to simple mistakes than native FreeRTOS calls.