Arduino Microcontrollers

Language
English
Simpson College
Computer Science

Chapter 4: Light Strip Tube Lamp

This Arduino-based project uses a digital addressable RGB LED strip from Adafruit. The strip is three meters long and contains 160 RGB LEDs. Power is provided from a 5 volt 10 amp switching power supply, similar to what would power a notebook computer. (Don't use 6 volts or more!)

The strip has been wrapped in a spiral around a six-foot section of PVC pipe. Every seventh LED is lined up vertically. The pipe has a 6" plywood base and top. Four pieces of electrical conduit provide supports. Around that is wrapped some translucent paper.

Simpson students may program the lamp by following these steps:

  1. You can download a zip file of the Arduino development environment along with supporting libraries here.
  2. Right click and expand those files.
  3. Find the file arduino-1.6.0\drivers\dpinst-amd64.exe and use it to install the drivers needed. You only need to do this once on the computer.
  4. After the drivers are installed, run arduino-1.6.0\arduino.exe to bring up the Arduino development environment.
  5. Download the light_strip_tube.zip project as a starting point.
  6. Right click and expand the files.
  7. Using the Arduino software, open the LightStripTubeDisplay.ino files.
  8. Plug in the USB cable on the light strip tube to your notebook and follow the “Getting Started” guide.

If the Arduino stops working correctly, please notify Professor Craven so he can fix it. Also, if you come up with a good light display, e-mail Professor Craven, and he'll post it here.

4.1 Code

This file sets up the light strip, and then will start a loop. It will randomly choose one of the functions to call. Each function has a different light display. It is a simple task to add more functions and light displays.

#include "LPD8806.h"
#include "SPI.h"

// Number of RGB LEDs in strand:
int nLEDs = 160;

// Chose 2 pins for output; can be any valid output pins:
int dataPin  = 2;
int clockPin = 3;
int pinState = HIGH;

int curSpot = 0;

// First parameter is the number of LEDs in the strand.  The LED strips
// are 32 LEDs per meter but you can extend or cut the strip.  Next two
// parameters are SPI data and clock pins:
LPD8806 strip = LPD8806(nLEDs, dataPin, clockPin);

// This function is run once.
void setup() {
  // Start up the LED strip
  strip.begin();
}

// This function gets called over and over again.
void loop() {

  // If you are trying out your own function, then put the function
  // call below, and remove the rest of the code before the
  // curly brace.
  //simple_pong();
  
  // Create a random number
  int d = random(10);
  
  // Depending on the random number, run that animation.
  if( d == 0 )
    simple_1();  
  else if( d == 1 )
    simple_2();  
  else if( d == 2 )
    simple_up();  
  else if( d == 3 )
    simple_pong();  
  else if( d == 4 )
    rainbowChase();
  else if( d == 5 )
    rainbow();
  else if( d == 6 )
    engine();
  else if( d == 7 )
    fire();
  else if( d == 8 )
    fireflies();
  else if( d == 9 )
    sparks();
  else if( d == 10 )
    rain();
    
}


This file simply lights one LED up after another, starting at LED 0 and going up to LED 159.

void simple_1() {
  
  // Current LED we want to light up
  int curSpot = 0;
  
  // Boolean that we should set to true when the animation is done
  boolean done = false;
  
  // Repeat for each fram of the animation
  while (!done) {
    
    // Start by turning all pixels off.
    // Basically, clear the screen.
    for(int i=0; i<strip.numPixels(); i++) 
      strip.setPixelColor(i, 0);
  
    // Turn on the pixel at curSpot
    strip.setPixelColor(curSpot, strip.Color(127,127,127)); // Set new pixel 'on'
  
    // Show all the LEDs. "Flip" the screen.
    strip.show();
  
    // Move to the next LED.  
    curSpot += 1;
    
    // Wait 50ms
    delay(50);

    // If we reached the top of the 160 LEDs, then we are done.
    if (curSpot > nLEDs)
      done = true;

  }
}

This is similar to the prior example, but we light up three LEDs, and different levels of brightness.

void simple_2() {
  
  // Current LED we want to light up
  int curSpot = 0;
  
  // Boolean that we should set to true when the animation is done
  boolean done = false;
  
  // Repeat for each fram of the animation
  while (!done) {
    
    // Start by turning all pixels off.
    // Basically, clear the screen.
    for(int i=0; i<strip.numPixels(); i++) 
      strip.setPixelColor(i, 0);
  
    // This turns on three pixels. The first dimly,
    // The next more brightly, the third as bright
    // as possible. This gives it a bit of a 'tail.'
    strip.setPixelColor(curSpot, strip.Color(30, 30, 30));
    strip.setPixelColor(curSpot+1, strip.Color(45, 45, 45));
    strip.setPixelColor(curSpot+2, strip.Color(127,127,127));
  
    // Show all the LEDs. "Flip" the screen.
    strip.show();
  
    // Move to the next LED.  
    curSpot += 1;
    
    // Wait a few ms
    delay(30);

    // If we reached the top of the 160 LEDs, then we are done.
    if (curSpot > nLEDs)
      done = true;

  }
}

This example lights up multiple LEDs but with different colors.

void rainbowChase() {
  int curSpot = 0;
  boolean done = false;

  while (!done) {

    // Start by turning all pixels off:
    for(int i=0; i<strip.numPixels(); i++) 
      strip.setPixelColor(i, 0);
  
    // Create a rainbow starting at curSpot
    strip.setPixelColor(curSpot, strip.Color(20,0,0)); // Set new pixel 'on'
    strip.setPixelColor(curSpot + 1, strip.Color(127,0,0)); // Set new pixel 'on'
    strip.setPixelColor(curSpot + 2, strip.Color(0,127,0)); // Set new pixel 'on'
    strip.setPixelColor(curSpot + 3, strip.Color(0,0,127)); // Set new pixel 'on'
    strip.setPixelColor(curSpot + 4, strip.Color(60,0,127)); // Set new pixel 'on'
    strip.setPixelColor(curSpot + 5, strip.Color(15,0,40)); // Set new pixel 'on'
  
    // 'Flip' and show the new LED states
    strip.show();
  
    // Move up
    curSpot += 1;

    // If we are at the end, then stop.
    if (curSpot > nLEDs)
      done = true;

    // Wait...
    delay(100);
  }
}

Instead of going up one pixel at a time, this goes up seven. Since it takes seven pixels to go around the pole, it allows makes the light go 'up' rather than spiral around.

void simple_up() {
  
  // This example uses the fact that the LEDs are in a spiral
  // and that it takes 7 LEDs to loop around the pole.
  
  // Select one of the first 7 LEDs to start with
  int curSpot = random(7);
  
  // Boolean that we should set to true when the animation is done
  boolean done = false;
  
  // Repeat for each fram of the animation
  while (!done) {
    
    // Start by turning all pixels off.
    // Basically, clear the screen.
    for(int i=0; i<strip.numPixels(); i++) 
      strip.setPixelColor(i, 0);

    strip.setPixelColor(curSpot, strip.Color(127, 0, 127));
  
    // Show all the LEDs. "Flip" the screen.
    strip.show();
  
    // Move to the next LED straight up. (which is 7 LEDs up.)
    curSpot += 7;
    
    // Wait a few ms
    delay(30);

    // If we reached the top of the 160 LEDs, then we are done.
    if (curSpot > nLEDs)
      done = true;

  }
}

Now, rather than go up, we store the direction of the light in a variable and multiply by -1 when we hit the end.

void simple_pong() {
  
  // This example uses the fact that the LEDs are in a spiral
  // and that it takes 7 LEDs to loop around the pole.
  
  // Select one of the first 7 LEDs to start with
  int curSpot = random(7);
  
  // Set the direction the 'ball' is moving. To start with, it moves
  // down the chain 7 LEDs at a time. 
  int pixel_direction = 7;
  
  // Boolean that we should set to true when the animation is done
  boolean done = false;
 
  // Keep a count
  int count = 0;
  
  // Repeat for each fram of the animation
  while (!done) {
    
    // Start by turning all pixels off.
    // Basically, clear the screen.
    for(int i=0; i<strip.numPixels(); i++) 
      strip.setPixelColor(i, 0);

    strip.setPixelColor(curSpot, strip.Color(127, 127, 0));
  
    // Show all the LEDs. "Flip" the screen.
    strip.show();
  
    // Move to the next LED straight up. (which is 7 LEDs up or down)
    curSpot += pixel_direction;
    
    // Wait a few ms
    delay(20);

    // See if we hit the edge
    if (curSpot > nLEDs || curSpot < 0) {
      // Reverse the direction by multiplying by -1
      pixel_direction *= -1;
      
      // Randomly move it left/right one pixel
      curSpot += random(3)-1;
    }
      
    // If we have changed the LED so many times, quit.
    count += 1;
    if (count > 200)
      done = true;

  }
}

This example simulates rain. It uses a list (array) to hold up to 20 different rain drops and their position.

void rain() {
  
  int count = 20;
  int pos[count];
  
  // Set all the rain drop locations to -1. We use this
  // to signify that 'drop' hasn't started yet.
  for (int i = 0; i < count; i++) {
    pos[i] = -1;
  }
  
  boolean done = false;
  int counter = 0;

  while (!done) {

    // Start by turning all pixels off:
    for (int i = 0; i < strip.numPixels(); i++) 
      strip.setPixelColor(i, 0);  

    // Go through each rain drop
    for (int i = 0; i < count; i++) {

      // If the drop isn't -1, then it is active
      if( pos[i] >= 0 ) {

        // Show the active drop
        strip.setPixelColor(pos[i], strip.Color(0,0,127));

        // Move the drop down
        pos[i] -= 7;
   
        // If the drop has hit the bottom, set it to be inactive 
        if (pos[i] < 0)
          pos[i] = -1;    
      }
      
      // Randomly set any inactive drop to be active
      if ( pos[i] == -1 && random(40) == 0 && counter < 380 ) {
        pos[i] = 159 - random(7);
      }
    }

    // 'Flip'
    strip.show(); 

    // Wait
    delay(25);

    // Count the number of 'frames' and quit after so long
    counter += 1;
    if (counter > 400) {
      done = true;
    }
  }    
}

void rainbow() {
  // Start by turning all pixels off:
  for(int i=0; i<strip.numPixels(); i++) 
    strip.setPixelColor(i, 0);

  for(int i=0; i<strip.numPixels(); i+=7) 
    strip.setPixelColor(i, strip.Color(127,0,0));

  for(int i=1; i<strip.numPixels(); i+=7) 
    strip.setPixelColor(i, strip.Color(127,127,0));

  for(int i=2; i<strip.numPixels(); i+=7) 
    strip.setPixelColor(i, strip.Color(0,0,127));

  for(int i=3; i<strip.numPixels(); i+=7) 
    strip.setPixelColor(i, strip.Color(50,0,127));

  for(int i=4; i<strip.numPixels(); i+=7) 
    strip.setPixelColor(i, strip.Color(127,127,127));
    
  for(int i=5; i<strip.numPixels(); i+=7) 
    strip.setPixelColor(i, strip.Color(0,127,127));

  for(int i=6; i<strip.numPixels(); i+=7) 
    strip.setPixelColor(i, strip.Color(0,127,2));

  strip.show();              // Refresh LED states

  curSpot++;
  if (curSpot > nLEDs)
    curSpot = 0;

  delay(3000);
}


void fire() {
  int states[160];
  for( int i=0; i < 160; i++ )
    states[i]=0;
    
  boolean done=false;
  int topend=17;
  
  int counter=0;
  while(!done) {
    
    for( int i=0; i < 160; i++ ) {
      int change = random(topend)-5;
      states[i] += change;
    }
 
     for( int i=7; i < 160; i++ ) {
      if (states[i] >states[i-7])
        states[i] = states[i-7];
    }
    for( int i=1; i < 160; i++ ) {
      if( states[i] - states[i-1] > 20 )
        states[i] = states[i-1] - 20;
    /*
      if( states[i] - states[i-1] < 10 )
        states[i] = states[i-1] + 10;
   */
    }
    for( int i=1; i < 160; i++ ) {
      if( states[i] < 0 )
        states[i] = 0;
      if( states[i] > 120 )
        states[i]=120;
    }
    for( int i=0; i < 160; i++ ) {
      if( states[i] <= 40 )
        strip.setPixelColor(i, strip.Color(states[i],0,0));
      else if ( states[i] <= 80 )
        strip.setPixelColor(i, strip.Color(40,states[i]-40,0));
      else
        strip.setPixelColor(i, strip.Color(0,0,states[i]-80));
    }
    strip.show();

    delay(50);
    counter++;
    if( counter > 200 )
      topend=10;
    if( counter > 400 )
      done=true;
  }
}

void fireflies() {
  const int fireflycount = 3;
  int flyPos[fireflycount];
  
  for( int i = 0; i < fireflycount; i++) {
    flyPos[i] = random(160);
  }
  
  boolean done = false;
  int counter = 0;

  while (!done) {

    // Start by turning all pixels off:
    for(int i=0; i<strip.numPixels(); i++) 
      strip.setPixelColor(i, 0);  

    for( int i=0; i < fireflycount; i++) {
      strip.setPixelColor(flyPos[i], strip.Color(127, 127, 127));  
      
      if( random(4) == 0 ) {

        // Randomly choose a direction
        int d = random(7) + 1;

        // Up
        if( (d == 1 || d == 2 || d == 3) && flyPos[i] < (160 - 7) )
          flyPos[i] += 7;

        // Down
        if( (d == 7 || d == 6 || d == 5) && flyPos[i] >= 7 )
          flyPos[i] -= 7;

        // Over
        if( (d == 3 || d == 4 || d == 5) && flyPos[i] < 159 )
          flyPos[i] += 1;

        // The other over
        if( (d == 1 || d == 8 || d == 7) && flyPos[i] > 0 )
          flyPos[i] -= 1;
      }
      
    }
    strip.show(); 
    delay(250);

    counter++;
    if( counter > 40 )
      done = true;
  }    
}

void sparks() {
  const int count = 4;
  int pos[count];
  
  for( int i=0; i < count; i++) {
    pos[i]=-1;
  }
  
  boolean done=false;
  int counter = 0;
  while(!done) {
    // Start by turning all pixels off:
    for(int i=0; i<strip.numPixels(); i++) 
      strip.setPixelColor(i, 0);  

    for( int i=0; i < count; i++) {
      if( pos[i] >= 0 ) {
        strip.setPixelColor(pos[i], strip.Color(127,127,0));  
        pos[i] += 7;
        
        if( random(4) == 0 ) {
          int d = random(7)+1;
          // Up
          if( (d == 1 || d == 2 || d == 3) && pos[i] < (160-7) )
            pos[i] += 7;
          if( (d == 7 || d == 6 || d == 5) && pos[i] >=7 )
            pos[i] -= 7;
          if( (d == 3 || d == 4 || d == 5) && pos[i] < 159 )
            pos[i] += 1;
          if( (d == 1 || d == 8 || d == 7) && pos[i] > 0 )
            pos[i] -= 1;
        }    
        if( pos[i] > 159 )
          pos[i]=-1;    
      }
      
      
      if ( pos[i] == -1 && random(40) == 0 ) {
        pos[i] = random(7);
      }

      
    }
    strip.show(); 
    delay(25);
    counter++;
    if( counter > 400 )
      done=true;
  }    
}