Hi, i am coding a program that will tell the time between two can messages
so i am coding a sending program so every 10ms he send me a message
The problem is that when i check the time between two IT i don't have 10ms, so i use micros() to check the time passed
if i don't put anything in the IT fonction i have 10ms but if i put the send i have ~8ms that should be longer in time !
To run something every n ms approximately (assuming nothing comes to kills the millis() timer) the typical approach is to use a construct as such
const uint32_t period = 10ul;
uint32_t chrono;
void setup()
{
chrono = millis();
}
void loop()
{
if (millis() - chrono > period) {
// it's time to do something, of course it should not be longer than period
// ...
chrono += period;
}
// you can do other stuff here
}
for example if you were to time how long it takes to Serial.print() something, you'd be surprised that in most cases the function returns almost immediately...that's because the data is put in a buffer and interrupts are used to send it out whilst your code continues to do other stuff.
There is probably a function to check if a transmit has completed. that's what you should monitor for execution.
Hey thanks for answering
my problem is not the time that CanSendMsg takes , it was an old test.
The thing is that is want msg to be sent every 10ms but the loop will do other things, as LCD print or so
and IT are more precise than that loop exemple, i think they are ?
So why does my IT is less precise when i put that function in it?
I'm unsure why you would see 8ms, but I'm unsure either I would trust your code timing.
Timer1 will run a function each time the timer period finishes. The function is run as an interrupt, so special care is needed to share any variables between the interrupt function and your main program (as you did using volatile) as well as other functions such as Serial.print or SPI or your CAN stuff can create challenges leading to weird behaviors.
For example the print you do in the time() function won't execute until after you exit the ISR, or could be blocking if you overflow the 64 bit buffer...
The micros (On 16 MHz Arduino board) function has a resolution of four microseconds, so you should be on the safe side there.
The question is more what are you timing? Given you are within an ISR, whatever depends on interrupt (like sending your CAN message possibly) won't start happening until you exit the time() function.
100Hz (10ms) is possibly still a manageable pace and I would suggest you first drop the TimerOne approach and give a try to what I described in #3.
Of course it means the loop() should cycle in less than 10ms. LCDs are known to be slow and anything that uses interrupts will come into competition with your 100Hz requirement.
--> You need to time everything else to see if that can work
If you record the difference in a volatile variable you can see this in loop().
But you are probably confusing yourself, timers work reliably, micros() works reliably, its 99.99% certain
its not a bug in the system, but in how you are using it.
AnotherBeginner:
Well i think you didn't understand my problem sorry i think i'm not very confortable with it
I want to test if micros() is very precise to time lenght between message so i made an IT every 10ms and i check with micros to see if i get 10000
So when there's nothing in my IT function it's fine i get everytime 10000
BUT
when i put the sendCanmsg function it starts to move a lot for 10000 to 8999 -> 9500
So that make me think that micros is not trustable but i need to be at 1ms error maximum to time can msg how can i do that?
I think I understand but you don't get what I'm saying. let me try again
micros() is relatively precise, not at the low end - ie it's less precise to measure a few microsecond (given the 4µs resolution it will tell you 4, 8, 12, 16 etc not 3µs or 7µs) than longer delays. Micros is managed through timer0 and the resolution is 4µs because of a prescaler of 64. Timers depends on the system clock of your Arduino, which by itself is also not purely 16MHz, but again for a relatively short duration and limited precision you can ignore drifts and imprecisions.
So here your are not talking about timing just a few µs and you theoretically would be fine. But you want to measure something with a tool that is sensitive to ISR conflicts.
micros() always reads the hardware timer 0 and as we said this is constantly being updated by the hardware every 4µs. Timer 0 is a 8 bit timer, so after 256 clock ticks , Timer 0 overflows and there is an interrupt which updates counts .
However if you spend too long in ISRs then you might miss the overflow update and precision will drop.
--> I'm unsure of what the CAN library stuff do but depending on what is being sent etc, it might affect time spent in ISR and thus miss some timer 0 cycles that would add up... just a guess...