Making the Lights Dance

My previous post, Making the Little Lights Twinkle, covered my coding of the NodeJS server that could take simply relay numbers and command (on|off) and put them to use. Now that I have a server/service up and running, it was time for me to be able to control the lights. I removed my Orchestra of Lights and put my new Raspberry Pi hardware device in its place. The only downside is that my setup has 8 outlets and the Orchestra of Lights only had 6. As I built out some of my light sequences, I noticed there’s a delay due to relays 7 and 8 being triggered but nothing being connected to them. Maybe that’s something I can do for next year. I’ll plan for 8 lighting areas instead of just 6.

In addition to needing to be able to plan for two more strands of lights, I still hadn’t figured out my audio configuration yet. I’ve only had the time to focus on the lights themselves. For the time being, I’ve got a weatherproof bluetooth speaker outside that I sync my iPad to for music. I just tell my iPad to loop through a playlist that my wonderful wife has put together. Thank you deer!

The Initial Script

While I still struggled to find some time to continue to research making the lights dance to music, I figured it was a really good idea to get something up and running. I thought randomness was key. I wanted it to be random because I was sick of the Orchestra of lights running through the same/similar light pattern over and over and over and over…..and over. With that, I built the initial script control my lights:

#!/bin/bash

COMMANDS=("off" "on")
i=0

trap exitout SIGINT

exitout() {
  echo "We Are Done Here!"
  exit
}

while :
do
  CMD=$(( ${RANDOM} % 2 ))
  RELAY=$(( ${RANDOM} % 8 + 1 ))
  curl 127.0.0.1:8080/light/$RELAY/${COMMANDS[$CMD]}
  echo $RELAY ${COMMANDS[$CMD]}
  sleep 0.2
done

Obviously, this is a really quick hack of a script but it works. It’s also obvious that it is a simple shell script. I created the array “COMMANDS” with two elements “off” and “on”. I ended up not using “i” but oh well it’s still here. I have the script setup to exit “cleanly” by calling exitout whenever someone presses CTRL+C on the keyboard. You need this because as you can tell the script is created with a while loop that never exits.

Let’s talk about what is going on inside that while loop. With each iteration, I’m setting CMD to a random number modulo 2 which gives us either 0 or 1. I’m also setting RELAY to a random number modulo 8 which gives us something 0 – 7 on each iteration. You’ll notice I add +1 so that I actually make RELAY be 1 – 8. Next, I run a curl command with my relay number and the element 0 or 1 aka off on from the COMMANDS array. From there, I just echo out what I sent to the server and then sleep for 0.2 seconds. This loop runs forever until something crashes or the user does CTRL+C.

Oh My Goodness This is Ok

The above simple script did the trick. This made my lights randomly turn on and off. I was quite happy with the results we got with this. I had light strands turning on and off. Sometimes, the lights were doing something that appeared like it was in tune with the music. There was one little flaw in this. The flaw was that because it was random, you could have the same relay being given the same command or the randomness would focus on a single light strand turning on and off.

Ultimately, my major concern was that we had too many lights out at the same time. So, this was a really good initial step and worked well for my immediate wants and needs. I wanted more. I got bored with random and put a little time into something a little more.

Building the More Interesting Client

Ok like I said before, I was getting bored with the original client script. I wanted to be able to do just a little bit more. I built a script that does a few sequences as you can see below.

#!/bin/bash

COMMANDS=("blinkUp" "blinkDown" "danceUp" "danceDown" "blinkAll" "crazyRun")
i=0

trap exitout SIGINT

exitout() {
  echo "We Are Done Here!"
  exit
}

allLights() {
  a=1
  while [ $a -le 8 ]
  do
    curl 127.0.0.1:8080/light/$a/$1
    echo ""
    a=$(( a + 1 ))
  done 
}

blinkUp() {
  echo "Blinking Up"
  allLights on
  a=1
  while [ $a -le 8 ]
  do
    curl 127.0.0.1:8080/lights/$a/off
    echo ""
    sleep 0.5
    curl 127.0.0.1:8080/lights/$a/on
    echo ""
    sleep 1
    a=$(( a + 1 ))
  done
}

blinkDown() {
  echo "Blinking Down"
  allLights on
  a=8
  while [ $a -ge 1 ]
  do
    curl 127.0.0.1:8080/lights/$a/off
    echo ""
    sleep 0.5
    curl 127.0.0.1:8080/lights/$a/on
    echo ""
    sleep 1
    a=$(( a - 1 ))
  done
}

danceUp() {
  echo "Dancing Up"
  allLights off
  a=1
  while [ $a -le 8 ]
  do
    curl 127.0.0.1:8080/lights/$a/on
    echo ""
    sleep 0.5
    curl 127.0.0.1:8080/lights/$a/off
    echo ""
    a=$(( a + 1 ))
  done
}

danceDown() {
  echo "Dancing Down"
  allLights off
  a=8
  while [ $a -ge 1 ]
  do
    curl 127.0.0.1:8080/lights/$a/on
    echo ""
    sleep 0.5
    curl 127.0.0.1:8080/lights/$a/off
    echo ""
    a=$(( a - 1 ))
  done
}

blinkAll() {
  echo "Blinking All"
  allLights on
  allLights off
  allLights on
  allLights off
  allLights on
  allLights off
}

crazyRun() {
  echo "Doing Crazy Shit"
  danceUp
  danceDown
  allLights off
  sleep 0.5
  allLights on
  sleep 0.5
  danceDown
  danceUp
  blinkAll
  danceUp
  danceDown
  danceUp
  danceDown
}

while :
do
  CMD=$(( ${RANDOM} % 6 ))
  ${COMMANDS[$CMD]}
  sleep 0.2
done

I’ve added a bunch of different functions to this new script:

allLights This function takes an argument of “on” or “off”. When called, it will either turn on or off all of the lights by issuing curl commands for all relays and either on or off.
blinkUp This function starts by turning on all of the lights and then every 0.5 seconds it turns off and then on a light staying at 1 and continuing through 8.
blinkDown This function is similar to blinkUp but it just works backwards from 8 through 1.
danceUp This function starts by turning all of the lights off and then works its way up from 1 through to 8. It works up by turning each light on and then off.
danceDown This function is similar to danceUp but it just works backwards starting at 8 and continuing through to 1.
blinkAll This function just flashes all of the lights on and off.
crazyRun This function just takes each of the above options and runs them all as a sequence that I’ve picked out.

Finally, the while statement in this script is now being used to randomly select one of the predefined sequences. So now I’ve got something a little more sophisticated to run my light show. I still want to up the game on this to sequence on its own to music and add more lights. Here’s an example below.

This got us through this Christmas season so more upgrades for next year and I can’t wait!