Thursday, December 4, 2014

Stair or Path Way Lights

Intro:

Did you ever wish you had light that comes on as you walk up the stairs? With small kids running up and down stairs in the dark can be dangerous. I created lights that will come on as you go up or down the stairs. It use PIR sensors to see you. So lets see what you will need.
This is not a tutorial in how Arduino works or electronics. You must know at least how Arduino works to do this project. Most code is from Arduino IDE examples. I just put it all together to make it work.

Buy list:

  1. 1 x Arduino Uno
  2. 2 x DSN-FIR800 PIR sensors or compatible ones
  3. 14 x WS2801 30mm LEDS 
  4. 1 x 12 Volt 2 Amp Switch Mode power supply
  5. 6 x 22k Ohm Resistors
  6. 1 x 15k Ohm Pot
  7. Dip 5 Switch or Dip 2 & 3 Switch

Arduino Uno:



The Arduino Uno comes with 15 digital pins and 6 analog pins. The analog pins will be used as digital pin 15, 16, 17, 18 and 19. Analog A0 will stay as it is but its digital pin is 14.

 DSN-FIR800 PIR:


This PIR sensor comes with 3 pins. 2 Setting pots for Time(Tx) on and Sensitivity(Sx). The signal out can be changed to LOW but we need it HIGH so we leave it as is. First sensor pin 2 will be connected to Arduino pin 5 and the other sensor pin 2 to the Aruino pin 3. PIR pin 1 goes to 5 volt on Arduino and Ground to Ground on Arduino.
  • Pin 1 is 5 Volt
  • Pin 2 is Signal out is HIGH 
  • Pin 3 is Ground

WS2801 30mm LEDS:



This is where the magic starts. This LED's have 3 RGB LED's inside. They are fitted with a WS2801 chip that control the color and address which one should be on. There are 4 wires Connected to them.
  1. First wire is 12 volt only!
  2. Then the clock wire that goes to Arduino Pin12.
  3. Then the data wire that goes to Arduino Pin13.
  4. Then Ground. Important Ground must be connected to Arduino Ground also.
  5. Very important! Look at the arrow on the LED to see direction of the DATA flow. 

Fritzing:

Fritzing is a circuit building program that helps a lot with explaining and layout of components.
This image is to show you where to put the LED wire and the 2 PIR sensor wires.


All resistors are 22k ohm resistors. They are use to pull the Arduino INPUT pins HIGH. So when you press or select the buttons they will pull Arduino pins LOW. The code will do the rest.
  • D2 is a push button to change to next demo.
  • A1 will switch on Demo mode.
  • A2 is to set the speed of the next lights to turn on.
  • A3 to set Blue value.
  • A4 to set Green value.
  • A5 to set Red value.
The pot is connected between 5 Volt and Ground. the wiper goes to pin A0 on Arduino.


MY CODE: 

#include "WS2801.h"  //for use with WS2801 Chip
#include "SPI.h"
#include <EEPROM.h>  //to write and read from EEPROM

// BE SURE TO CHECK YOUR PIXELS TO SEE WHICH WIRES TO USE!
uint8_t dataPin  = 13;
uint8_t clockPin = 12;
// Connect the ground wire Pixels to Arduino ground
// Set the first variable to the NUMBER of pixels. 5 = 5 pixels in a row
WS2801 strip = WS2801(15, dataPin, clockPin);
// EEPROM addresses to save to
const int addr = 0;  
const int addrR = 1;
const int addrG = 2;
const int addrB = 3;
const int addrSpeed = 4;
// Where we going to store to byte
byte value;  
// Temp holds your color value
int color;
// Motion sensor inputs
const int bottomPIR = 3;
const int topPIR = 5;
// Analog pin used as digital pins 14 to 19
const int redSwitch = 15; //Red Switch
const int greenSwitch = 16; //Green Switch
const int blueSwitch = 17; //Blue Switch
const int speedSwitch = 18; //Speed switch
const int demoSwitch = 19; //Demo Switch
// Which demo to run :) EEPROM save this value
unsigned int switchSelect;  
// The time lights stays on before all goes dark
unsigned int lighton = 5000;
// Time lights comes on one by one
unsigned int lightspeed = 100; 
// LED Colors
unsigned int RGB1 = 90;
unsigned int RGB2 = 125;
unsigned int RGB3 = 125;
//************************************************************
void setup() {
  Serial.begin(19200);
  while (!Serial) {
    delay(10);
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  pinMode(topPIR, INPUT);
  pinMode(bottomPIR, INPUT);
  
  pinMode(redSwitch, INPUT);
  pinMode(greenSwitch, INPUT);
  pinMode(blueSwitch, INPUT);
  pinMode(speedSwitch, INPUT);
  pinMode(demoSwitch, INPUT);
  
  delay(400);//Wait for serial LCD to start up
  Serial.print("Reading EEPROM   ");
  Serial.print('\n');
  delay(300);

  strip.begin();// Start WS2801
  strip.show();// Start al off
  // Read addresses in the EEPROM then save it
  value = EEPROM.read(addr); 
  switchSelect = int(value);
  RGB1 = EEPROM.read(addrR);
  RGB2 = EEPROM.read(addrG);
  RGB3 = EEPROM.read(addrB);
  // Read this addresses in the EEPROM then save it
  //Miltiply by 10 to allow more time for lights
  lightspeed = EEPROM.read(addrSpeed);  
  lightspeed =  lightspeed * 10;
  // Set interrupt button. Help select the demo
  attachInterrupt(0, debounceInterrupt, HIGH); 
  Serial.print("Starting....      ");
  Serial.print('\n');
  delay(1000);
}
//************************************************************
// We use long variables because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long lastDebounceTime = 0;// Last time the output pin was pressed
long debounceDelay = 350;// Time to wait before button will be active
boolean change = true;// Needed to save to EEPROM
void debounceInterrupt() {
  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:
    switchSelect++;
    lastDebounceTime = millis();
    change = true;
  }
}
//************************************************************
int Direction = 0;// What direction we moving
void loop() {
  //***  Settings  ***
  if (!digitalRead(redSwitch)) {//A1 to A5 used as digital pins for switches to set values
    while (!digitalRead(redSwitch)) {// Stay active till value is set
      change = true;//Update the colors
      pickColor();// Function to select a color
      Serial.print("Red: ");// Show me the color value on LCD
      Serial.print(color);
      Serial.print("        ");
      Serial.print('\n');
      WipeDown(Color(color, RGB2, RGB3), 1);// Show me the color
    }
    EEPROM.write(addrR, color);// Save value to EEPRM
  }  else if (!digitalRead(greenSwitch)) {
    while (!digitalRead(greenSwitch)) {
      change = true;
      pickColor();
      Serial.print("Green: ");
      Serial.print(color);
      Serial.print("      ");
      Serial.print('\n');
      WipeDown(Color(RGB1, color, RGB3), 1);
    }
    EEPROM.write(addrG, color);
  }  else if (!digitalRead(blueSwitch)) {
    while (!digitalRead(blueSwitch)) {
      change = true;
      pickColor();
      Serial.print("Blue: ");
      Serial.print(color);
      Serial.print("       ");
      Serial.print('\n');
      WipeDown(Color(RGB1, RGB2, color), 1);
    }
    EEPROM.write(addrB, color);
  }  else if (!digitalRead(speedSwitch)) {
    // You can only save to EEPROM 100 000 times. Save it this way
    change = true;// When you done picking speed save to EEPROM
    while (!digitalRead(speedSwitch)) {
      double T;// Needed to test only
      lightspeed = analogRead(A0);// Read analog pin
      lightspeed = map(lightspeed, 0, 1023, 0, 255);// Map it to workable value
      // DONT use Constrains it comes with errors
      if (lightspeed > 255) {// Constrains it between 0 and 255
        lightspeed = 255;
      }  else if (lightspeed <= 1) {
        lightspeed = 0;
      }
      T =  lightspeed * 10;// Convert to usable value
      Serial.print("Speed: ");
      Serial.print(T);
      Serial.print("      ");
      Serial.print('\n');   
      for (int i = strip.numPixels() ; i >= 0; i--) {
        strip.setPixelColor(i, Color(175, 70, 0));
      }
      strip.show();
      delay(T);
      AllOff();
      delay(T);
    }
    EEPROM.write(addrSpeed, lightspeed);// Save to EEPROM
  }
  if (change) {// IF true 
    change = false;// Set False
    EEPROM.write(addr, switchSelect);// Save to EEPROM
    value = EEPROM.read(addr); 
    switchSelect = int(value);
    RGB1 = EEPROM.read(addrR);
    RGB2 = EEPROM.read(addrG);
    RGB3 = EEPROM.read(addrB);
  }
    //if DEMO is selected run it
  if (digitalRead(demoSwitch)) {//NO DEMO
    //check if PIR detect motion
    if (digitalRead(topPIR) == HIGH) {
        Serial.println("PIR 1 Active     ");
        Serial.println('\n');
        WipeUp(Color(RGB1, RGB2, RGB3), lightspeed);// Lights on
        if (Direction == 0) Direction = 1;// To switch off in same direction
      }
    else if (digitalRead(bottomPIR) == HIGH) {
        Serial.println("PIR 2 Active      ");
        Serial.println('\n');
        WipeDown(Color(RGB1, RGB2, RGB3), lightspeed);
        if (Direction == 0) Direction = 2;
      }
    else {
      if (Direction == 1) {//switch lights off
        delay(lighton);
        WipeUp(Color(0, 0, 0), lightspeed);
      }
      if (Direction == 2) {
        delay(lighton);
        WipeDown(Color(0, 0, 0), lightspeed);
      }
      Direction = 0;//Reset it else it will on switch on again
    }
  }
  else if (!digitalRead(demoSwitch)) {
    demo();  // Call DEMO
  }
}
//************************************************************
// When function is called. it will display the lights
//Add funtions so its not needed to repeat this calls over and over
//it save time
void WipeUp(uint32_t c, double wait) {
  for (int i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();// Activate Lights
    delay(wait);//Waiting time that is saved in EEPROM
  }
}
//************************************************************
void WipeDown(uint32_t c, double wait) {
  for (int i = strip.numPixels() ; i >= 0; i--) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}
//************************************************************
void AllOff() {
  for (int i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, 0);
  }
  strip.show();
}
//************************************************************
//***** DEMO MODES *****
// Ths is just repeat of top functions. its needed for demo mode only
void demo() {
  //  Serial.println("DEMO IS RUNNING....");
  int PicR = random(255);
  int PicG = random(255);
  int PicB = random(255);
  switch (switchSelect) {
    case 1:
      Serial.print("Demo 1 Running    ");
      Serial.println('\n');
      WipeDown(Color(color, RGB2, RGB3), lightspeed);
      delay(lightspeed);
      AllOff();
      delay(lightspeed);
      break;
    case 2:
      Serial.print("Demo 2 Running    ");
      Serial.println('\n');
      strip.setPixelColor(random(strip.numPixels()), Color(random(255), random(255), random(255)));
      strip.show();
      delay(300);
      break;
    case 3:
      Serial.print("Demo 3 Running    ");
      Serial.println('\n');
      int i, j;
      for (j = 0; j < 256; j++) {   // 3 cycles of all 256 colors in the wheel
        for (i = 0; i < strip.numPixels(); i++) {
          strip.setPixelColor(i, Wheel( (i + j) % 255));
          strip.show();
        }
        // write all the pixels out
        delay(30);
      }
      break;
    case 4:
      Serial.print("Demo 4 Running    ");
      Serial.println('\n');
      strip.setPixelColor(random(strip.numPixels()), Color(random(255), random(255), random(255)));
      strip.show();
      delay(150);
      AllOff();
      delay(80);
      break;
    case 5:
      Serial.print("Demo 5 Running    ");
      Serial.println('\n');
      for (i = 0; i < strip.numPixels(); i++) {
        strip.setPixelColor(i, Color(random(255), random(255), random(255)));
        strip.show();
        delay(150);
      }
      AllOff();
      delay(150);
      break;
    case 6:
      Serial.print("Demo 6 Running    ");
      Serial.println('\n');    
      for (int i = strip.numPixels() ; i >= 0; i--) {
        strip.setPixelColor(i, Color(random(255), random(255), random(255)));
        strip.show();
        delay(100);
      }

      delay(500);
      break;
    case 7:
      Serial.print("Demo 7 Running    ");
      Serial.println('\n');
      for (int i = 0 ; i < strip.numPixels(); i++) {
        strip.setPixelColor(i, Color(PicR, PicG, PicB));
        strip.show();
        delay(180);
      }
      break;
    case 8:
      Serial.print("Demo 8 Running    ");
      Serial.println('\n');
      for (int i = strip.numPixels() ; i >= 0; i--) {
        strip.setPixelColor(i, Color(PicR, 0, PicB));
      }
      strip.show();
      delay(100);
      AllOff();
      delay(50);
      break;
      
    default:
      Serial.print("NOTHING SELECTED ");
      Serial.println('\n');
      AllOff();
      while(!change){
        if (analogRead(A5) > 100){change = 1;}
        delay(10); }        
      break;
  }
  if (switchSelect > 8) switchSelect = 0;//End of demo - start over
}
//************************************************************
//*****  Needed Functions  *****
// Create a 24 bit color value from R,G,B
uint32_t Color(byte r, byte g, byte b)
{
  uint32_t c;
  c = r;
  c <<= 8;
  c |= g;
  c <<= 8;
  c |= b;
  return c;
}

void pickColor() {
  color = analogRead(A0);//Read analog pin
  color = map(color, 0, 1023, 0, 255);//map it
  if (color > 255) {// Constrains it between 0 and 255
    color = 255;
  }
  else if (color <= 1) {
    color = 0;
  }
}
//************************************************************
//Input a value 0 to 255 to get a color value.
//The colours are a transition r - g -b - back to r
uint32_t Wheel(byte WheelPos)
{
  if (WheelPos < 85) {
    return Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if (WheelPos < 170) {
    WheelPos -= 85;
    return Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
    WheelPos -= 170;
    return Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}

No comments:

Post a Comment