Arduino Microcontrollers

Language
English
Follow on
Twitter

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. Download the Arduino Development software from here. Versions exist for Windows, Mac, and Linux-based computers.
  2. Download the light_strip_tube.zip project as a starting point.
  3. 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"

// Simple test for 160 (5 meters) of LPD8806-based RGB LED strip

/*****************************************************************************/

// 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);

// You can optionally use hardware SPI for faster writes, just leave out
// the data and clock pin parameters.  But this does limit use to very
// specific pins on the Arduino.  For "classic" Arduinos (Uno, Duemilanove,
// etc.), data = pin 11, clock = pin 13.  For Arduino Mega, data = pin 51,
// clock = pin 52.  For 32u4 Breakout Board+ and Teensy, data = pin B2,
// clock = pin B1.  For Leonardo, this can ONLY be done on the ICSP pins.
//LPD8806 strip = LPD8806(nLEDs);

void setup() {
  // Start up the LED strip
  strip.begin();

  // Update the strip, to start they are all 'off'
  strip.show();
}

void loop() {
  int d = random(7);
  if( d == 0 )
    rainbowChase();
  if( d == 1 )
    rainbow();
  if( d == 2 )
    engine();
  if( d == 3 )
    fire();
  if( d == 4 )
    fireflies();
  if( d == 5 )
    sparks();
  if( d == 6 )
    rain();
}


void rain() {
  // Create an array of 20 raindrops
  const int count = 20;
  int pos[count];
  
  // Set each rain drop at the starting gate.
  // Signify by a position of -1
  for( int i=0; i < count; i++) {
    pos[i]=-1;
  }
  
  // Main loop. Keep looping until we've done
  // enough "frames."
  boolean done=false;
  int counter = 0;
  while(!done) {
  
    // Start by turning all LEDs off:
    for(int i=0; i<strip.numPixels(); i++) 
      strip.setPixelColor(i, 0);  

    // Loop for each rain drop
    for( int i=0; i < count; i++) {
      // If the drop is out of the starting gate,
      // turn on the LED for it.
      if( pos[i] >= 0 ) {
        strip.setPixelColor(pos[i], strip.Color(0,0,127));  
        
        // Move the drop down one row
        pos[i] -= 7;
   
        // If we've fallen off the strip, but us back at the starting gate.
        if( pos[i] < 0 )
          pos[i]=-1;    
      }
      
      // If this drop is at the starting gate, randomly
      // see if we should start it falling.
      if ( pos[i] == -1 && random(40) == 0 && counter < 380 ) {
        // Pick one of the 6 starting spots to begin falling
        pos[i] = 159-random(6);
      }

      
    }
    strip.show(); 
    delay(25);
    counter++;
    
    // See if we should stop.
    if( counter > 400 )
      done=true;
  }    
}

void rainbowChase() {
  // Current spot along the strip to start the rainbow
  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);
  
    // Temp holding spot for where we start the rainbox
    int spot=curSpot;
    
    // Start setting LEDs and moving "up" the strip
    strip.setPixelColor(spot++, strip.Color(20,0,0)); // Set new pixel 'on'
    strip.setPixelColor(spot++, strip.Color(127,0,0)); // Set new pixel 'on'
    strip.setPixelColor(spot++, strip.Color(0,127,0)); // Set new pixel 'on'
    strip.setPixelColor(spot++, strip.Color(0,0,127)); // Set new pixel 'on'
    strip.setPixelColor(spot++, strip.Color(60,0,127)); // Set new pixel 'on'
    strip.setPixelColor(spot++, strip.Color(15,0,40)); // Set new pixel 'on'
    
    strip.show();              // Refresh LED states
  
    curSpot++;
    if (curSpot > nLEDs)
      done=true;
    delay(100);
  }
}

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;
    }
    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 ) {
        int d = random(7)+1;
        // Up
        if( (d == 1 || d == 2 || d == 3) && flyPos[i] < (160-7) )
          flyPos[i] += 7;
        if( (d == 7 || d == 6 || d == 5) && flyPos[i] >=7 )
          flyPos[i] -= 7;
        if( (d == 3 || d == 4 || d == 5) && flyPos[i] < 159 )
          flyPos[i] += 1;
        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)); 

        // Move up one row        
        pos[i] += 7;
        
        // Randomly flip the spark in a direction
        if( random(4) == 0 ) {
          int d = random(7)+1;
          // Up
          if( (d == 1 || d == 2 || d == 3) && pos[i] < (160-7) )
            pos[i] += 7;
          // Down
          if( (d == 7 || d == 6 || d == 5) && pos[i] >=7 )
            pos[i] -= 7;
          // Left
          if( (d == 3 || d == 4 || d == 5) && pos[i] < 159 )
            pos[i] += 1;
          // Right
          if( (d == 1 || d == 8 || d == 7) && pos[i] > 0 )
            pos[i] -= 1;
        }
        // End of the strip, go back to start
        if( pos[i] > 159 )
          pos[i]=-1;    
      }
      
      // Possibly start one of the sparks
      if ( pos[i] == -1 && random(40) == 0 ) {
        pos[i] = random(7);
      }

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