Nothing is more rewarding than getting a new strip of NeoPixels from Adafruit, plugging them in, running the example strand test sketch and seeing those puppies light up and animate. At some point, after the NeoPixel library has been mastered and the examples been tweaked and modified, there will come a time when you might want to create a responsive application using them. One where you can continually poll for input to affect the output – like proximity, a button press, maybe something more complex. It won’t take long for you to realize, this won’t be possible if you are using the delay function – the one liberally used by the example NeoPixel sketches.
The delay function, when used, actually pauses the program for the period of time designated – it will stop everything except for interrupts.That means nothing happens, as the program is effectively suspended. Initially, no big deal right? But if you are trying to do two things – like animating a NeoPixel strand and want to capture a button press to start and stop it, using delay can throw a wrench into your best laid plans.
So how do you avoid using delay? There are a few libraries you can use that use a few different techniques. For myself, I dropped using delay with the NeoPixel animations by using a method that involved using the millis() function in Arduino. It is important to note that the millis() function will reset itself to zero after around 50 days. With the millis() function, we can get the number milliseconds since the start of the program. Now, if we store the last or previous time in the loop which runs very fast and then subtract it from the current time, we have a sense of how much time has elapsed. If the time elapsed is greater than or equal to the threshold or delay time we set, we know we can go ahead and do what we need to do.
In the case of NeoPixels, I had to do a few things to recreate some of the animations in the example sketches. The color wipe function, which iterates through the pixels in the strand, changes the color of each pixel one after another with a delay between each one. To do this without using delay, I would need to call the same function from the loop repeatedly for each pixel.If the proper “delay” time had elapsed, the current pixel color would be set,and the current pixel index incremented. This would require me to store the current pixel index I was to set and increment that value each time that function would run. If the number of pixels in the strand was the same as the current pixel index, I would know that animation was complete. Here is a very basic example – of course you could completely reorganize it if that’s your style and put the logic in a different place:
Now, this is just the start of getting rid of the delay, something I needed to do so that I could handle input – in my case, I would be monitoring the Twitter Streaming API for particular events such as favoriting of my tweets or unfollows, and I would want to notify my SparkCore so that it could run different animations with the NeoPixels to visualize those events.