DeanIsMe / SevSeg

Seven segment display controller library for Arduino
MIT License
326 stars 130 forks source link

Issue with delay() #23

Open SlevenCalevra opened 7 years ago

SlevenCalevra commented 7 years ago

Hi, is there no way to use this correctly when you have delays in your program???

DeanIsMe commented 7 years ago

It would be possible to run the update function on an interrupt rather than through the loop() function. I have not included this in the library because the timers available to set up interrupts are different on each micro-controller, so it gets complicated fairly quickly when considering all possible devices.

You could set up a timer-driven interrupt that repeatedly runs refreshDislay() in the background. If you do this, make sure to configure the library to NOT use delays.

MehdiGol commented 3 years ago

@DeanIsMe Could you please elaborate a bit on this? Maybe an example?

DeanIsMe commented 3 years ago

You need to set up a regular timed interrupt, running @ at least 500Hz (every 2 ms or less). Here's an Instructable for the arduino Uno: https://www.instructables.com/Arduino-Timer-Interrupts/ Call refreshDisplayinside ISR(TIMER0_COMPA_vect){}. Don't call refreshDisplay from anywhere else. Make sure to configure the SevSeg library to NOT use delays (updateWithDelaysIn=0). Doing this properly would require making several library variables volatile, but I think that it will work fine without library modifications.

mbratch commented 3 years ago

@MehdiGol @SlevenCalevra something to try... you can use a PWM output as a nearly 500Hz clock (one of the PWMs is 490Hz by default on some Arduinos, and others get you close or better, I think). Plug a 1k resistor from the PWM output to a digital input and setup the digital input to interrupt on the rising edge. Create a function that calls the refreshDisplay() method and in your setup() use that new function as the interrupt handler. Turn on the PWM output to a value that's about 50% of maximum, which would give you a 50% duty cycle on the output (duty cycle doesn't matter too much as long as you trigger on the rising edge). I've used this technique successfully for other recurring tasks.

machmar commented 1 year ago

@mbratch not to be offensive or anything but that's a really roundabout way of doing this. I'd sudgest looking into timer interrupts or other kinds of internal interrupts. In short however, basically you can use one of the timers that create the WM signal to instead of (or while) generating PWM issue an internal interrupt which forces the processor to jump into some other part of code and execute it (like refreshing the display).

mbratch commented 1 year ago

@machmar meh, no offense taken. That was 2 years ago. A fun little idea I had on my breadboard when I first got my Arduino before I determined how to tap into the timer interrupts. A little round-about but it was very easy to do. I certainly wasn't touting it as the best approach (I had prefaced my suggestion as "something you can try...")