3

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.

  • how critical is those 10 ms really? – ratchet freak Mar 4 '18 at 12:25
  • 1
    If your program has nothing else to do during these 10 ms, and if you don't care about the Arduino timekeeping (millis() and micros()) getting off, and if you don't use libraries that rely on interrupts, then your method should be OK. – Edgar Bonet Mar 4 '18 at 12:26
  • Those 10ms need to be 100% exact. I need to switch on an output which drives a TRIAC. The TRIAC will then turn on an electronic ballast at exactly the desired sine phase. I.e. if I delay for 5ms, the TRIAC will switch on AC at exactly 90° – Bavilo Mar 4 '18 at 12:28
  • 2
    “100% exact” is not achievable in the real world. Not with an Arduino nor with the most precise equipment available on earth. – Edgar Bonet Mar 4 '18 at 12:31
  • 2
    The question of @ratchetfreak is very relevant because single cycle accuracy, while achievable, will require somewhat complex low-level programming. If you can live with a few 10 µs of jitter, then the problem is much easier. Please, edit your question to provide a reasonable answer to that question. – Edgar Bonet Mar 4 '18 at 12:37
4

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 Mar 4 '18 at 18:04
  • Using the TimerOne library is easiest. – Majenko Mar 4 '18 at 18:05
  • But would it be ok to completly configure the Timer1 inside the ISR? Setting prescaler, compare match register, etc? – Bavilo Mar 4 '18 at 18:24
  • 1
    Sure. Or do the config elsewhere and just turn it on in the ISR. Whatever makes more sense for your program. – Majenko Mar 4 '18 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 Mar 5 '18 at 9:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.