5 Colored buttons from Chance Game

Dancing Buttons

If you saw the video of the Chance game running you undoubtedly noticed the five big buttons that sat in front of the screen. You might have even noticed that there were a number of different patterns that played. This post explores how that was done.

Why, when the Chance game only needs one button, did I use five? Two reasons:

  1. It’s very difficult to make linear patterns with only a single button
  2. Look how cool they are! How could I choose just one and put the others aside?

I initially wanted to use something very similar to the “Easy” button from the Staples commercials.

Staples Easy Button

Easy Button from Staples

As I perused Amazon.com – which actually has a surprising amount of electronics to choose from, plus, 2-day shipping for many things – I found these beauties!   Just what I wanted and with five of them, I thought I could make them dance.

Of course, I would have to do some work to do this, but how hard could it be? Since I was using the Raspberry Pi anyway, my initial thought was to just have the RPi do it. However, I wasn’t sure how to add in their essentially independent operation to the python script flow. I knew it could be done, but it would have been significant work and learning for me, and I didn’t have the time. So I turned to Arduino this time.

Arduino is much, much less powerful than Raspberry Pi, but it is every bit as focused on DIY and the hacker community. There are a number of Genuino and Arduino (as well as other unofficial boards) out there based on a number of different microcontrollers, from 8-bit to 32-bit ARM Cortex-M0. I have just started to play with Arduino boards (there are some really fun kits out there for cheap) so I decided to use my Mega 2560 as the brains for the button.

Genuino Mega2560

Image from Amazon.uk

By the way, there is a fascinating history behind the Genuino and Arduino companies and rivalry. If you get curious, just search for “Arduino vs Genuino”.   Also, I use the term “Arduino” to refer to any board that is supported by the Arduino compiler (under Tools/Boards).

Hardware:

There was a little work to be done on the hardware side of things. Each button had 4 terminals, two for the switch (normally open) and two for the LEDs. The switches were dead simple to wire up. Since my Python script is set up to read a single GPIO, I just wired the buttons in parallel so any button press triggered a video to play.

 

RPi Switch Schematic

The Switch Wiring

That would actually be good enough for the game; blinking lights were a bonus. I could also have just wired all the LEDs in parallel and driven them with a constant 12V source, leaving them on all the time. But where is the stress in doing that? Time to add another undertaking to my already overwhelming list of tasks! As a fallback I knew I could just keep them always illuminated – but I really wanted dancing lights.

The LEDs in the buttons are run from 12V and the Arduino’s pins are only 5V tolerant. Plus, they are limited to 20mA. So I needed to add a transistor to safely drive the LED. The LEDs in the buttons actually have a current limiting resistor built into them so you can directly attach 12V to them and they won’t turn into smoke. This is great, since I can now run the transistor in saturation (like a switch, not a dimmer) and that current limiting resistor will limit the current to what the LEDs can handle.

2N2222 are your basic, cheap NPN transistor, and I have a bunch just strewn about the place, so they were an easy choice. Generally 2N2222 transistors are assumed to have a gain of about 100. The gain is the ratio of the collector current (the load current) to the base current (the signal current). So if I have the Arduino drive with 1mA, I would get about 100mA through the LEDs, which is plenty. The current limiting resistor in the button will hold the current to well below that 100mA. So I can just drive the transistor as hard as I want and everything will be fine. But let’s double the base current to be sure!

Calculations for the proper resistor for the base are simple. I will skip the theory, but if you are curious, Google “NPN transistor biasing” and there will be plenty of write-ups to choose from. To determine the correct value of the base resistor for my setup, the formula to get 2mA base current is:

R = (5V – 0.7V)/2mA = 2150 ohms

So I used a 2Kohm resistor, which will be close enough. That left me with the extremely simple circuit shown below.

Drive Schematic for LEDs

LED Drive Circuit

For the 12V supply, I just used an old wall wart from some retired electronics I had in my electronics pile. It was rated for 2A, so PLENTY of power. A quick breadboard set up to make sure everything worked as expected and it was time to get out the soldering iron. My soldering isn’t pretty, but I went for compactness here. I was able to get all 5 of those drives circuits into an area less than 1 square inch! Little victories.

Drive Circuit Close-Up

The Tiny LED Driver Board

Unlike the switches, LEDs are polarized, meaning that the positive voltage must be connected to the correct pin (anode). Since the buttons’ terminals weren’t labeled, I had no way to know which was which. Since I was dealing with such low voltages and currents, I just randomly connected the leads up and then reversed the leads on the buttons that didn’t light up. Not very scientific, but simple and safe enough this time.

That’s all the hardware work. I used spade connectors so I could easily take this apart, which came in handy when I brought it in to work for our Halloween event. The wires to the base resistors are pre-terminated with pins to easily connect to the Arduino headers.

Entire Button System

The Hardware

OK, time to head on to the software.

Dance, Pardner!

For simplicity, I just chose one of the built-in Arduino examples, renamed it and started hacking at the code. As a matter of fact, as I am looking at the code for this post, I realize how much “trash” I left lying around the code. So I cleaned up the version I uploaded to Github.

Like last week, I will walk through the code section by section, but it’s actually simpler than the RPi code. That’s largely due to the Arduino not only having a complete BSP, but also having a huge ecosystem surrounding it. Actually, “ecosystem” barely covers it. The community has created many complementary add-ons (shields) that include the firmware and usually lots of example software. It’s so completely developed that you generally only need to modify one file for an entire program. And you can usually find an example that will get you well along your way.

Such was the case with my button routine. I used one of the built-in examples, called “Fading”. Literally 3 clicks to get started:

  • Click #1 opened the Arduino app
  • Click #2 on “File”  and navigate through “Examples” and “03. Analog” and
  • Click #3 on “Fading”

Now to start in on the code.

Configuration:

int Blue = 12;   // LED connected to digital pin 8
int Green = 11;   // LED connected to digital pin 10
int Yellow = 10;   // LED connected to digital pin 9
int White = 8;   // LED connected to digital pin 11
int Red = 9;   // LED connected to digital pin 12

long RandNum;

void setup() {
randomSeed(analogRead(0));
}

The first five lines simply assign easy to remember names to the different color buttons. The numbers are the pin numbers on the Arduino board.

I need a random number for one of routines, so I initialize a variable called “RandNum” to hold this. Although, I think I could remove it here since I only use the random number within local functions.

Very similar to the Python script, I invoked a random seed, however this time randomness was important to me, so I read the analog voltage on Pin0 and use that as the seed. It’s a standard way to get a good seed, assuming you have an analog pin and we have plenty.

OK, the set up is done. Seriously. We can now go make lights blink – woohoo!

Main Loop:

void loop() {
BlinkRandom(20);
BlinkAround(4);
BlinkUpDown(4);
BlinkRandom(20);
FancyRampUpDown();
BlinkRandom(20);
BlinkSeq(5);
BlinkSeqRev(5);
BlinkRandom(20);
RampUpDown();
}

For Arduino, the loop that executes the code is called “Loop”, similar to “Main” in C. This is called and is run indefinitely.   So here are all routines that I call – they just run through and then loop around again.

OK, that’s it – we’re done! Quick and painless, right?

Just kidding, we’re not quite done, but the main program actually is complete. Below it are all those subroutines (I think in Arduino-speak they’re actually called “Functions”).

First, let’s look at “Blink” since so much else is based on it. I don’t directly call this in the Loop function, but I call it in many of the other functions that I call. It’s the building block for the rest.

void Blink(int pin){
     analogWrite(pin, 100);
   // wait for 200 milliseconds
   delay(200);
   analogWrite(pin, 0);
   // wait for 200 milliseconds
   delay(200);
}

You can see that I only pass it one argument, the pin number that I want it to blink and I call this “pin”. But remember, I have set up human-friendly names like “Green”, so I can just call it with that, instead of having to remember that the green LED is on pin 11.

AnalogWrite is the Arduino command to send a PWM (Pulse Width Modulated) signal to the pin. A PWM signal is essentially a dimmed signal. It’s more complex, but for Arduino sending a PWM signal of value 0 is off and 255 would be completely on. Any value in between is just that percentage of on. I initially have it turn the pin on with a PWM value of 100 (about 40% of full brightness).

I then wait 200mS, which is 1/5 of a second.

I then do the same thing but with a signal to turn the LED completely off, and wait 200mS again. Then I exit the function.

It might seem odd to wait 200mS at the end since I am just exiting the function, but without that delay, it would immediately start doing the next thing I have programmed. I want to be certain that the off time is noticed and in this case is the same as the time it is on. Note that it’s very simple to adjust it so that the time on would be long and the time off would be short (or vice versa) – just change the values in the two “delay(200)” calls.

That’s the basis for all the functions I call, except for RampUpDown() and FancyRampUpDown(). Those two routines are really similar to the Blink function, except multiple LEDs are turned on at the same time. Blink() only blinks one LED at a time. Let’s explore BlinkSeq() and then BlinkRandom(). The other functions will be obvious after that.

BlinkSeq()

void BlinkSeq(int Blinks){
for (int i = 0; i <= Blinks; i++){
   Blink(White);
}

for (int i = 0; i <= Blinks; i++){
   Blink(Red);
}

for (int i = 0; i <= Blinks; i++){
   Blink(Yellow);
}

for (int i = 0; i <= Blinks; i++){
 Blink(Green);
}

for (int i = 0; i <= Blinks; i++){
   Blink(Blue);
}    

}

From the first line, we can see that I will be passing in integer and calling it “Blinks” – this is the number of time that I want the LEDs to blink.

Then I just set up a simple FOR loop to call the function Blink() the number of times that I configured the variable “Blinks” to. I do this for each LED in sequence starting with the White LED and finishing up with the Blue LED. This is the same order the buttons are arranged, so they blink in a line.

In the Loop function, I call BlinkSeq(5) –the result is that I get 5 blinks of the white LED, then 5 blinks of the Red LED, 5 blinks of the Yellow LED, 5 of the Green and then 5 of the Blue LED. That’s the entire function. Having made Blink() a separate function made this code very simple to implement – and quite readable.

BlinkSeqRev is the same exact function with the LEDs in the opposite direction, starting with the Blue.  Copy & paste, change 5 words and I have a new function!

BlinkRandom()

void BlinkRandom(int Rounds){
long RandNumber;
for (int i = 0; i <= Rounds; i++){
   RandNumber = random(8,13);
   Blink(RandNumber);
}
}

As you probably guessed, this blinks a random LED. When I call it, I pass it an integer that I call “Rounds”. This is how many times a random LED will blink. I could have easily set it up to blink a random LED multiple times (or even a random number of times), but I chose to blink each LED just once – unless it is randomly chosen next time through.

I instantiated a variable called RandNumber which will be the LED to be blinked. Arduino expects that variable to be a long.

Then I have a simple FOR loop which is executed the number of times I passed into the integer “Rounds”.

The function “random” chooses a random number between the first value (8) and the last value minus 1 (13-1) and assigns it to RandNumber. This is the Pin to blink, and is used in the next line.

Once again, we turn to my Blink() function – and simply send it the pin to blink. Even though we send it a long, the Blink() function recasts it as an integer. Afterall, there is no pin 9.62874304342 to be driven!

After Blink() is done, we return to our FOR loop and complete the number of iterations I asked for and exit.

I could go through all the routines, but that would be tedious, well MORE tedious. 🙂  The logic is so simple to understand that there’s no value in doing that. That simplicity also means that creating your own unique functions is a snap. Once I had Blink() working (which was very simple) it took practically no time to create the other functions that I call. And then just like the screensaver video I created, it was simply a matter of copying & pasting the calls into Loop() over and over, and mixing up the order and the number of blinks that occurred.

Just like the RapsberryPi portion of this prop, the time I spent on the code was about an hour. That was starting out knowing essentially nothing about Arduino too. Again, it is the ecosystem that is built around these hacker platforms that make creating your own custom project possible in these incredibly short amounts of time. The hardware portion of this was not much more than an hour, and that was only due to soldering up the drive circuits. If I had just breadboarded the circuits, it would have been closer to 30 minutes.

This entire project, including the housing I put it in was 4-5 hours in total. That does exclude Robyt’s time for creating the videos though. While this was a really simple project, it is unique and is fully customized and customizable. It plays videos smoothly and has less than $100 of hardware (excluding the monitor) – and most of that was stuff I had anyway.

I can’t help but to think back to my youth when Dragon’s Lair ate my quarters like a trick-or-treater eats a fun-sized Snickers. And thanks to the hacker communities for Raspberry Pi and Arduino, I was able to make my own “Dragon’s Lair” in 4 hours with stuff I had lying around. Imagine what other wonderful things can be built to take advantage of all the awesomely scary video content out there! If you end up building your own video prop, please let us know – we’d love to hear what you guys are making!

 

Leave a Reply