16 LED Christmas Tree With Shift Registers And Motion Detection

I’m lucky that Christmas has such a wide array of acceptable aesthetics. There are two things in life that I can cut out with a jigsaw and the ol’ lady still dig it and I haven’t found the second. The first is the Christmas tree.

The wife has a birthday in November, which means I get an excuse to partake in a deadline-based, obligatory project. Deadlines are hyper important for any project as they prevent self-defeating logic that results in projects that never finished. The obligatory part means I’m a scumbag if I don’t finish it. This trait allows me to work on the project when I should probably be working on Calc3 integrals.

With every project I try to do something new. In this case, I wanted to learn shift registers. I used two 74HC50N shift register in DIP package form. The Arduino code makes the shift register thing a breeze, but I don’t love their examples. The examples remind me of the way text books teach for some reason.

Here’s the gist on shift registers.

digitalWrite(latchPin, 0); // Puts the shift register into "read mode" to acquire the new value you are cramming in.
shiftOut(dataPin, clockPin,MSBFIRST, x); // does the damage. x is the integer which will ulltimately be converted to binary in this case. 255 is 1111111 in binary and would turn 8 LEDs on.
digitalWrite(latchPin, 1); // Turn off "read mode".

That’s about it.

If you want to blink all LED’s, you could turn them all off by setting x = 0 and looping through the same code above with a delay(1000) after each one.

In my case, I had 2 shift registers. The only thing different was I had 2 shiftOut statements like this:
digitalWrite(latchPin, 0);
shiftOut(dataPin, clockPin,MSBFIRST, x);
shiftOut(dataPin, clockPin,MSBFIRST, x);
digitalWrite(latchPin, 1);

Put Arduino To Sleep

I’m using unethical Ebay Arduino Mini Pro clones that I paid $1.80 for. (Sue me! You won’t get anything. I’m in school.) I always forget whether I have the 3.3V or 5V version. I have no idea how to tell the difference. Maybe I should do my homework before writing this. I gouged out the on LED with a soldering iron to prevent it using the few mA it likes to devour. For this one I didn’t go too bonkers with power reduction. I just wanted the Arduino to go to sleep, wake up when it detected RISING from the PIR motion detector pin, run through the blinking sequence for 20 second or so (I can’t remember what value I through in there) and then go back to sleep when the sequence was over.

Too Bright LEDs

I believe I tossed in 330 ohm, current-limiting resistors for the LEDs. In my dungeon/lab, this looked about right. When viewed directly on axis, this was painful to look at on the Christmas tree. So, I toyed around with a function that blinked the LEDs off and on. I can’t say if this was a good way to achieve the goal, but I turned on the lights, delay(1) and then turned them off for delay(5). This knocked down the pain factor when looking at the Christmas tree head on. I’ve got a feeling this isn’t right, but my power supply tells me I’m barely pulling any current – about 10mA. I probably did something wrong there, too. I don’t trust that number. Oh well, I’m using a big ass 18650 battery and it only needs to last for a month. We’ll be alright.

Arduino Code


#include "LowPower.h"

volatile boolean motionState = 0;
//Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 11;  //flipped
////Pin connected to DS of 74HC595
int dataPin = 12;  // flipped
long lasttime = 0;
int i = 0;
void setup()
{
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode (13, OUTPUT);
  attachInterrupt(0, thing, RISING);
  Serial.begin(9600);
 
}


void loop ()
{
  attachInterrupt(0, thing, RISING);
  LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); 
  detachInterrupt(0); 
  motionDetected2(0);  // The value passed to this function resets i to zero.
}


void thing()
{
motionState = 1;
}
void motionDetected2(int i){

// LOOP THROUGH 20 RANDOMLY GENERATED NUMBERS
// EACH NUMBER GETS brantotime MILLISECONDS.
  while ( i < 20){
      int thingtime = 1;
      int brandotime = 1000;
      int dimness = 10000;  
      int x = random(1,256);    
      lasttime = millis();
  
      // BLINK CURRENT VALUE OF x FOR brandotime MS.  THIS IS TO REDUCE BRIGHTNESS
      while (millis() - lasttime < brandotime) {
        digitalWrite(latchPin, 0);
        shiftOut(dataPin, clockPin,MSBFIRST, x); 
        shiftOut(dataPin, clockPin,MSBFIRST, x); 
        digitalWrite(latchPin, 1);
        delay(thingtime);
        
        digitalWrite(latchPin, 0);
        shiftOut(dataPin, clockPin,MSBFIRST, 0); 
        shiftOut(dataPin, clockPin,MSBFIRST, 0); 
        digitalWrite(latchPin, 1);
        delay(thingtime * 5);   
      }
      
      digitalWrite(latchPin, 0);
      shiftOut(dataPin, clockPin,MSBFIRST, 0); 
      shiftOut(dataPin, clockPin,MSBFIRST, 0); 
      digitalWrite(latchPin, 1);
      delay(1);
      i++;
  }  
  
  
}

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.