Motion-activated lighting with Arduino

Creating an infrared "tripwire" allows for very focused motion-detected LED lighting

arduino,physical computing

3/17/2015

I built a pair of very unsafe stairs to my loft, and after falling off them one morning and nearly destroying my laptop in the process, I decided to make some motion triggered lights for the stairs. While contemplating giving the stairs an effect like Michael Jackson's Billie Jean Video, my end goal was to have them be subtle and simple and all the wiring to be hidden, so as not to get the whole thing vetoed.

THE MATERIALS:

I found these LED strips at adafruit. They're way overblown for my needs (60 LEDs per meter, waterproof) and thus they're not cheap - I needed 3M so that put me at $60, which is way more than you'd pay for something similar on the market, but it was an opportunity to learn, plus I could fine tune it to my own specs, so I went ahead with it.

To activate them, I got a couple pairs of IR breakbeam sensors. These act as a trip wire - when the path between the emitter and the receiver is blocked, it registers a high or low state to the arduino, which can be used to activate the LED strip. I wanted to avoid accidental activation of the sensors, so I stayed away from a motion / proximity sensor, but in retrospect, I'm not sure they were the right thing. For one, the range is really small (10cm), so I couldn't put them as far apart as I would've liked. I'm sure there's something with a better range out there (garage door sensors, but smaller and cheaper?), but I didn't find it. Plus, the wiring for the breakbeams at the top of the stairs seemed excessive - 3 meters of wiring for each of the sensors' leads - power, ground, and a read pin on the receiver.

I might later pursue something like a force sensitive resistor or even a sound-triggered sensor. Or maybe setting a super short throw on a motion sensor. If you happen to read this and have any recommendations, please let me know!

The power the LED strips require scared me - I knew I'd be dealing with wall power and not a little 5V supply or battery pack and my familiarity with power / resistance is pretty rudimentary at the moment. I knew enough to know I'd need to get one of these and run the voltage through a transistor. What I didn't know was how to balance the power the arduino / sensors need with the power the led strip needs. I ended up smoking out a breakbeam emitter in the process and having to order another.

Then one of the cheery staff at Adafruit pointed out something that probably is obvious to most people - you can use the power pin of the arduino to supply voltage to your sensors, and the Vin pin to power the led strip. The voltage goes first to the LED strip through a regulator, and whatever is not used is passed to the arduino. Once I had that set up, everything was good to go.

I fooled around with a couple different methods of triggering. First I had it set up so stepping through the first breakbeam would trigger the lights on, and stepping through the next would turn them off. But it seemed a little buggy (probably just needed to be debounced), and didn't account for things like 2 people being on the stairs at the same time, or crossing a sensor and then going back the way you'd come. In the end I figured it was best to put them on a timer. 10 seconds was just about perfect. I made sure that the LED strip went to a PWM pin so I could fade up and fade down.

If I work on this further, I may look into whether the single color strips are individually addressable. Still kinda wanna get my Michael Jackson on...

CODE:


int ledPin = 6;

int sensorPin = 3;
int sensorState = 0, lastState=0;

int sensorPin2 = 9;
int sensorState2 = 0, lastState2 = 0;

boolean tripBottom = false;
boolean tripTop = false;
boolean activateLights = false;

int curFade = 0; //brightness of lights
int fadeSpeed = 5;


void setup() {
  pinMode(sensorPin, INPUT);
  pinMode(sensorPin2, INPUT);
  digitalWrite(sensorPin, HIGH);
  digitalWrite(sensorPin2, HIGH);

  pinMode(ledPin, OUTPUT);

  Serial.begin(9600);
}

// the loop function runs over and over again forever
void loop() {

  sensorState = digitalRead(sensorPin);
  sensorState2 = digitalRead(sensorPin2);


  if (lastState && !sensorState && !tripTop){ //we are entering the bottom of the stairs, turn lights on
   tripBottom = true;
   activateLights = true;
   Serial.println("enter bottom");
  }

  if (lastState2 && !sensorState2 && !tripBottom){ //we are entering the top of the stairs, turn lights on
   tripTop = true;
   activateLights = true;
   Serial.println("enter top");
  }


  if (lastState && !sensorState && tripTop){ //exiting the bottom of the stairs, turn the lights off
    activateLights = false;
    tripTop = false;
    tripBottom = false;
    Serial.println("exit bottom");
  }

  if (lastState && !sensorState2 && tripBottom){ //exiting the top of the stairs, turn the lights off
    activateLights = false;
    tripTop = false;
    tripBottom = false;
    Serial.println("exit top");
  }




  if (activateLights) {
    //digitalWrite(ledPin, HIGH);
    //delay(2000);

    if (curFade < 255){
      analogWrite(ledPin, curFade);
      delay(30);
      curFade+=fadeSpeed;
    } else {
      curFade = 255;
      delay(2000);
    }

  } else {
    if (curFade > 0){
      analogWrite(ledPin, curFade);
      delay(30);
      curFade-=fadeSpeed;
    } else {
      curFade = 0;
      digitalWrite(ledPin, LOW);
      delay(2000);
    }


  }

  lastState = sensorState;
  lastState2 = sensorState;



}