I am currently working on a little code which needs to react fast. Here is what I am trying to accomplish:
Using a sine wave phase detector I am detecting every zero crossing and feeding that pulse into the Arduino.
Using an ISR the Arduino detects this zero crossing pulse using RISING. Once one pulse has been detected AND I have pressed a button, I need there to be a delay of 0 - 10ms before switching on an output.
If I don't use an ISR and set a delay of up to 10ms inside the loop, it won't really be 10ms and it will be some other delay, nothing consistent. (I checked with an oscilloscope).
Only when using an ISR and using delayMicrosenconds() inside the ISR I can delay the output consistently for up to 10 ms everytime.
Now I have read that doing this is wrong...Even though it works perfectly. Which better way could I use?
Thanks!
EDIT: While 100% accuracy may not be possible, it needs to be as precise as possible. More important is the repeatability. Using my method I could reproduce the outcome everytime with an accuracy in the nano seconds range.
1 Answer 1
It's quite simple: You don't.
Instead you use your initial ISR to configure and enable one of the ATMega's Timer peripherals. Set that to the length of your required delay - then the ISR exists.
When the chosen time has passed the timer interrupt triggers, and you use that interrupt to turn on your output.
-
I have tried this. How would I enable for example Timer1 inside my initial ISR? TIMER1_OVF_vect and TIMER1_COMPB_VECT did not give me the expected results. When switching my output inside these routines, there was no delay.Bavilo– Bavilo03/04/2018 18:04:38Commented Mar 4, 2018 at 18:04
-
Using the TimerOne library is easiest.Majenko– Majenko03/04/2018 18:05:20Commented Mar 4, 2018 at 18:05
-
But would it be ok to completly configure the Timer1 inside the ISR? Setting prescaler, compare match register, etc?Bavilo– Bavilo03/04/2018 18:24:35Commented Mar 4, 2018 at 18:24
-
1Sure. Or do the config elsewhere and just turn it on in the ISR. Whatever makes more sense for your program.Majenko– Majenko03/04/2018 18:25:26Commented Mar 4, 2018 at 18:25
-
You could configure the timer to make it trigger only once, using the technique used here: wp.josh.com/2015/03/12/avr-timer-based-one-shot-explained . (Though this might be overkill in this case. )Gerben– Gerben03/05/2018 09:05:41Commented Mar 5, 2018 at 9:05
millis()
andmicros()
) getting off, and if you don't use libraries that rely on interrupts, then your method should be OK.