Hey everyone, a friend and I are designing an LED hula hoop that will contain a range of patterns. We want to add a button that allows incrementing through the patterns. The only issue is that upon button click, we want the current pattern (function) to immediately stop and jump to the next pattern. My first idea on this was to attach an external interrupt command to the button that overrides the current pattern and reads through code that increments the button. Since delay() and millis() timing does not work in external interrupts, this caused debounce issues which I cannot get rid of. If anyone could give some guidance I would greatly appreciate it. Maybe there is a way to make external interrupts work without debounce, or there is a better code altogether to accomplish this?
An update on this, I have external interrupts in place that immediately increment the button click, but you have to wait for the current pattern to stop running before the pattern switches. Is there any way to stop the current pattern immediately? It’s part of its own function, not part of the void loop().
When you catch a button push via interrupts or however you decide, set a global variable called “gMustExit” (or something like that) to 1 (true).
Then, inside your animation function, put a line like this:
if( gMustExit == 1) { gMustExit = 0; return; }
Put copies of that line wherever needed in your animation to make sure that it checks often enough.
The real world may be more complicated than this; you may have to do other ‘cleanup’ before you exit, etc, but this is the main idea: inside your animation, periodically check to see if you should exit, and if so, do!
The better long term approach is to turn each animation into a function that gets called repeatedly, and does just one frame of animation each time – sort of like Arduino’s loop() itself.
Eg:
void anim1() {
// draw one frame of animation 1
}
void anim2() {
// draw one frame of animation 2
}
void anim3() {
// draw one frame of animation 3
}
Then in your main loop() function, do something like this:
int whichAnim;
void loop() {
// check buttons.
…
// choose which anim should run.
…
// now draw one frame of the right animation:
if( whichAnim == 1) anim1();
if( whichAnim == 2) anim2();
if( whichAnim == 3) anim3();
// send to LEDs
FastLED.show();
// delay if needed
…
}
Some of the animation functions will take more thought to write this way, but this is sort of the more advanced/fancy way to do things if you can easily. If it’s too much of a pain this time, there’s nothing wrong with the previous approach: just check for a “should I exit now?” variable to be set and if so, return immediately from your animation function.
the latter approach is the one I end up using the vast majority of the time. It’s a little harder the first time around, but is way more flexible. the key is to use a static variable in your animation functions and keep all of the increment code inside of that instead of putting that part of the logic in your “loop”.
Thanks for the info guys. We are setting it up so that eventually people will be able to design and add their own patterns to the hoop. In those cases implementing check points will be a little difficult, but it sounds like we will have to work around that. Maybe include instructions for people who want to manually add checkpoints.
I’ve built a controller box for my 119 pixel hoop.
It contains a 5V 3A Power Supply, an Arduino Nano, a Piezo beeper, a toggle switch, a rotary ecoder and 3 Potentiometers.
Software is Teldredges Demo code with some stuff added.
The Beeper just does a birth cry on boot-up.
The rotary encoder selects which animation to play.
The toggle switch is to stop/run the animation.
Potentiometers control delay (speed), step and hue for most demo animations where applicable(I may add a 4th for brightness later).
I’ve added a mode where they control R, G, B intensties so I can adjust colour.
I would like to add a 2 digit display for the active mode, maybe a small LCD.
USB/serial controls still work but I run the hoop without a computer when I am not hacking it.
The rotary encoder generates interrupts on digi-pins 2 and 3
(code from http://playground.arduino.cc/Main/RotaryEncoders)
Interrupt routines count a variable up/down and call the change_mode function with the variable value at the end of the interrupt routine.
Interrupts are cool because they are outside the loop and only occupy the processor when the encoder is moved.
My code is working but bloody ugly. I’ll post it if I manage to tidy it up.
That’s cool, yeah interruptors are very handy but were a pain to mess with starting out. I’m using 5 external interruptors to control a 5 way switch. Since delay() will not work, I am using delayMicroseconds() to prevent debounce. I added some lines of code like what Mark was talking about so it checks for button changes frequently. Only problem is it switches patterns at the button click, but momentarily returns to the previous pattern to finish it out. I know I have to clear it but don’t know how.