A popular LED project is the “Larson Scanner.” This scanner emulates the effect seen on KIT from Knight Rider and the Cylons in Battlestar Galactica. The code is usually written using “delay()” which means you can’t combine it with anything else. The following code could be put into a function, called periodically and allow your code to scan while doing other things.
One thing to note, a proper Larson Scanner has some persistence to the next and previous LEDs, this code does not. Maybe that would be a good exercise for the reader?
Inspired from this Arduino Forum post.
The Code
// Simple macros to remember which direction to shift LEDs #define UP true #define DOWN false // Will be used to track how long since last event "fired" unsigned long previousMillis=0; // Delay to determine when we see the next LED unsigned long interval = 250; // Array with Arduino pins containing LEDs in sequence byte LEDpins[] = { 2,3,4,5,6,7}; // Variable to track which LED to turn on, start at 000001 int LEDstate=0x01; // State variable to know which direction to shift boolean direction=UP; void setup() { // Optional: Push Button to turn on all LEDs (to test) pinMode(12, INPUT_PULLUP); // Set Pins with LEDs to OUTPUT for (int x=0; x < 6; x++) pinMode(LEDpins[x], OUTPUT); } void loop() { // Set the pins of each LED during each iteration // You'll only see something change when "LEDpins" gets updated for (int x=0; x < 6; x++) digitalWrite(LEDpins[x], bitRead(LEDstate,x)); // Test Funciton to turn on all LEDs with pushbutton if (digitalRead(12) == LOW) turnOnAll(); // Get current time and determine how long since last check unsigned long currentMillis = millis(); if ((unsigned long)(currentMillis - previousMillis) >= interval) { // We've waited "interval" amount of time, so let's do some stuff! // "Reset" our clock previousMillis = currentMillis; if (direction==UP) { // Use "<<" to "bit-shift" everything to the left once LEDstate = LEDstate << 1; // 0x20 is the "last" LED, another shift makes the value 0x40 if (LEDstate == 0x40) { // turn on the one before "0x20" and reverse direction LEDstate = 0x10; direction = DOWN; } } else { // use ">>" to "bit-shift" all bits in LEDstate once to the right LEDstate = LEDstate >> 1; // This means we ran out of bits! if (LEDstate == 0x00) { // set one ahead so no extra delay LEDstate = 0x02; direction = UP; } } } } void turnOnAll() { // Simple code to turn on all LEDs, this "blocks" // so when code returns, the same LED in LEDstate will be "saved" while (digitalRead(12)==LOW) { for (int x=0; x< 6; x++) digitalWrite(LEDpins[x], HIGH); } }
Notes
A couple of notes in this code.
Defines
The defines give us which direction the counter is running. I used the arbitrary names “UP” and “DOWN”, but could have used “LEFT” and “RIGHT.”
Array of Pins
To simplify addressing which pins are connected to LEDs (and in which order) an array is created with the order which the LEDs are connected. If this is the only thing you’re doing in your project, you’ll probably have the pins in order like the example. Using the array lets you use whatever pins are available.
LEDstate and Shifting
The “magic” in this code is the shifting done with LEDstate. The HEX value 0x01 is the initial state. With each iteration, the variable is shifted once to the left or right. So this means it’ll be:
0000 0001 0000 0010 0000 0100 0000 1000 0001 0000 0010 0000 0001 0000 0000 1000 0000 0010 0000 0001
When the sequence goes one bit too far, the sequence resets with one bit “seeded.”
turnAllOn
To test to make sure the LEDs are connected correctly, I included a function to turn on all the LEDs.
How can I do this with 8 or 10 led’s I cant get it to work.
Thanks Ed
In all of the for() loops, you would need to change the references from 6 to the number of LEDs you have. Then you would need to match the value in line 52 to be the binary or hex for the number of LEDs + 1. (8 = 0x100 or 10 = 0x400, I think).
Thank You very much, For 8 led’s 0x100 worked when I also changed line 54 to 0x40 it was skipping led’s 7 and 6 on the way back with line 54 at 0x10. I’m going to try 10 led’s now.
Awesome! Glad to hear you got it work. Send some pictures if you get 10 going.
10 led’s are going good Had to make line 54 0x100 Don’t know how to send pics on here
There is a typo in your sample code.
in the if (direction == UP) branch, you have a <<1 for LEDstate
But you also have <>1 here otherwise the state never decreases.
Regards
Jean-Luc
Code has been corrected
how i can make this work with neopixel
my code down here is perfect result i want but i need replace delay() by millis()
any clue ?