Friday, October 18, 2013

Dimmable LED Street Lights

What's a city play mat without street lights? These model train set street lights I purchased from eBay arrived and I incorporated them into the previous "Potentiometer Controlled LEDs" circuit.
One complicating factor is that these LEDs operate on 12 Volts. Technically, it's the LED together with the attached 400 Ω resistor that requires 12V. Each LED also draws about 20mA of current, and a simple calculation using Ohm's Law (Voltage = Current x Resistance) yields the result that the resistor consumes about 8V leaving 4V for the actual LED itself. So if I had a 4V power source then I could cut off the resistor completely and power just the LED by itself, but since I already have a 12V power source ready I decided to just stick to "stock." Also, I plan to string together 10 of these street lights together, which would draw far more current than the max 40mA that each digital output pin on the Arduino is capable of. So an external power supply would be necessary anyway.

Transistors

However, the inclusion of an external power supply requires using a transistor in order to interface with an Arduino. This adafruit tutorial gives a great basic lesson on transistors. Essentially, the transistor acts as an electronic switch that allows a small current flow from the digital output of the Arduino to "switch on" a much larger flow of electricity (provided by the external power supply) through the circuit loop that the LEDs are connected to.
By Simon Monk, from http://learn.adafruit.com/assets/2348


Here is the complete circuit showing how the PN2222 transistor and the potentiometer are connected to control the LEDs, powered by the external 12 Volt power supply:
The Arduino sketch is the same as the earlier "Potentiometer Controlled LEDs," with analog input A1 reading the potentiometer and then translating that input to a PWM signal through digital pin 3.

Below are a couple pictures of the messy, but working prototype for this circuit.

Debugging

It actually took quite some time to get this circuit to finally work, and again a multimeter was invaluable in the debugging process. First, the multimeter helped me determine that my power supply (which was a 12 Volt "wall wart" that had the adapter end cut off, leaving separate + and - wires) went against convention and had the striped wire as negative, opposite to what I had determined with a quick Google search. But the LEDs still wouldn't light, so using the multimeter I was able to determine that proper signals were coming out from the Arduino.

The LEDs also lit up when I connected the power supply to them directly. I then remembered that I needed to have the all the components tied to a common ground, and one extra jumper from the GND pin of the Arduino to the breadboard pins that the negative wire of the power supply was connected to completed the circuit and the lights were able to be dimmed and controlled by the potentiometer.

Next step, actually mounting these lights to the play mat and wiring it up more neatly!

Additional References:

bildr >> High-Power Control: Arduino + TIP120 transistor

Thursday, October 3, 2013

Potentiometer Controlled LEDs

Another part of my Interactive Town Play Mat project is a series of "street lights" along a few of the streets. I originally thought about using a light sensor that would automatically turn on the streets lights when the ambient light level grew dim (like a night light), but I decided to scrap this idea after several prototypes. The main problem was that the light sensor that came with the Lilypad ProtoSnap is very fidgety, in that the reading from the sensor fluctuates even at a constant ambient light level. If I set a certain light reading level (say, <50) as the trigger for when the LEDs would turn on, when the ambient light dropped near that level, the light sensor would continually flip above and below that threshold, causing the lights to flicker on and off. The sensor works fine for gross changes in light (like when the sensor is covered) but I could not figure out a way to effectively apply it with gradually dimming ambient light.

So instead I decided to incorporate a manual "dimmer" control to control the lights. This is accomplished through the use of a potentiometer.

The circuit is represented by the diagram below, made using the open-source software from Fritzing.org.


A brief video of how it works:


The full sketch is included at the bottom of this post for reference. The neat new function was using map(potReading, 0, 1024, 0, 255) to convert the analog readings from the potentiometer (ranging from 0-1024) to the output range for the digital pins (ranging from 0-255).

So I thought this would be a very straightforward circuit and sketch to create. The two tutorials I reference at the end of this post helped me understand how to read a potentiometer using an Arduino, and then how to output the signal to a string of LEDs. However, when I applied power to the circuit the first time, no LEDs turned on. I had set up the serial monitor to indicate both the potentiometer reading as well as the brightness level being sent to the LED, but turning on the serial monitor indicated readings of zero across the board.

Some debugging and browsing Arduino reference sites revealed that I had declared the potPin variable incorrectly. One of the tutorials I referenced used "const byte" to declare the variable for the analog pin that was reading the potentiometer, but apparently this would not work for the Uno because it used "A1" for the analog pin rather than just "1". Or something. Anyway, all I know is that when I switched to "const int" to declare that variable it worked, and I started getting readings through the serial monitor.

Unfortunately, the serial monitor output seemed to lag considerably behind what the potentiometer was set to, as in I could turn the pot full on but the serial monitor would still display a low value for several more seconds. I figured out that this was due to a bug in Codebender, and when I used the Arduino IDE the serial monitor kept in sync perfectly.

And while the serial monitor was showing the right values, for some reason the LEDs were still not lighting. It took me awhile to figure out that I had forgotten to turn on the little on/off slider switch that I had added to the circuit. DUH! This just goes to show that so many little things can cause a circuit to fail, and it's part of the challenge of electronics to follow the trail and try to find and fix every single little thing.

References:

http://www.arduino.cc/en/Tutorial/Potentiometer
http://www.electroschematics.com/9009/led-brightness-fan-speed-arduino/

The Sketch:

/*
 Potentiometer Controlled Street Lights
 Sketch that adjusts the brightness of a string of LED lights
 based on analog readings of a potentiometer

 Created 9/30/13
 By Ken Yeh

*/

/*  Pin Definitions  */
const int potPin = A1;  // Potentiometer connected to analog input A1
const int ledPin = 3;     // LED connected to PWM pin 6
int potReading;   // Variable to hold the reading from the potentiometer
int ledBrightness;  // Variable that holds the LED brightness level

void setup()
{
 pinMode(ledPin, OUTPUT);
 pinMode(potPin, INPUT);
 Serial.begin(9600);
}

void loop()
{
 potReading = analogRead(potPin); // Read value from potentiometer
 ledBrightness = map(potReading, 0, 1024, 0, 255); // Converts analog reading from pot to 8-bit value  
 analogWrite(ledPin, ledBrightness); // Output at this level for the LED
 Serial.print("Potentiometer=");
 Serial.print(potReading);
 Serial.print("   LED Level=");
 Serial.println(ledBrightness); 
}

Tuesday, October 1, 2013

Traffic Signal Prototype

After achieving success with getting the RGB NeoPixels to work, I quickly put together a sketch to control a traffic signal for a four-way intersection.

This is what it looks like while running:

A few things that I learned while putting this together.

1. NeoPixels are awesome!

My original intent in using NeoPixels rather than separate Red, Yellow, and Green LEDs or even "normal" RGB LEDs was to reduce the wiring needed, and the NeoPixels have certainly lived up to my intent. Using ordinary LEDs, each pair of like colored LEDs would have required a separate Arduino pin and a separate circuit leading from the power supply to the LED. This would have meant 6 separate sets of wires leading to the traffic signal, with additional wiring between the LEDs. Using ordinary RGB LEDs would have still required two separate pins and circuits, but with the NeoPixels I can independently control all four signal lights with just one pin and circuit.

The full sketch is included at the bottom of this post for reference, but the code for controlling each NeoPixel is as simple as:
 strip.setPixelColor(0, red);
 strip.setPixelColor(1, green);
 strip.show();
 delay(timeGreen);
The strip.setPixelColor function sets the color of the first pixel (0) red and the second pixel (1) green, and then the strip.show function actually makes the strip light up. So even though the NeoPixels are all wired together in one strip, you can still address each LED on an individual basis.

2. External libraries can be useful

Of course, there's a lot more to make these NeoPixels work than just the code in my sketch. These strip functions are actually calling very complex code that is contained in an external library, which was called by the initial line:
#include <Adafruit_NeoPixel.h>
The Adafruit_NeoPixel library contains the code that does the "heavy-lifting" that tells the Arduino what to do to get the pixel strand to work. The great thing about these external libraries is that you don't need to know any of the details about how these functions work, you just need to know the proper syntax to call up these functions, including the variables to be passed to get the results that you want. This also simplifies your own sketch, as you do not need to include the actual lines of code that define these functions; they are contained in the external library.

3. Define a value once, easily tweak many times later

In this sketch, there are several values that appear multiple times in the code, such as the RGB values for the different colors and the time periods for how long each color is on. While the program would work just fine if the actual values are typed in for each occasion that it is needed, if later tweaks are required (and they inevitably are) it becomes quite a chore to manually change those values to new ones, especially if there are many repetitions. A very effective technique is to declare variables in your sketch to hold these values, and then call these variables rather than the actual values themselves in the rest of your sketch. This way, if you need to tweak the values later, you just need to change the variable value once.

For example, in my traffic signal sketch, I declare these variables:
// Define the color codes by name to make it easier to call later on
uint32_t red = strip.Color(255, 0, 0);
uint32_t green = strip.Color(0, 255, 0);
uint32_t yellow = strip.Color(255, 100, 0);

// Define time intervals to make it easier to tweak later
timeGreen = 5000; // time interval that light stays green
timeYellow = 2000; // time interval that light stays yellow
timeRed = 1000;  // time interval that light stays red before other signal turns green
The first three variables define the RGB codes for red, green, and yellow, while the other three define the time intervals for how long the various colors stay on. I had to tweak the RGB values for yellow multiple times to get the right shade, and it was significantly easier to just change the value in one location in my sketch rather than each time yellow was called. It was also easier to just call "red" rather than write out stripe.Color(255, 0, 0) each time I needed the NeoPixel to be red. If I want to change the time that the traffic signal stays green, I can just change the value of timeGreen once and it would apply throughout without having to manually change the delay value at each location.

Judicious use of variables can greatly speed up the fine-tuning of a project.

Full Sketch:

#include <Adafruit_NeoPixel.h>

#define PIN 6

// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(4, PIN, NEO_RGB + NEO_KHZ800);

// Define the color codes by name to make it easier to call later on
uint32_t red = strip.Color(255, 0, 0);
uint32_t green = strip.Color(0, 255, 0);
uint32_t yellow = strip.Color(255, 100, 0);

// Define time intervals to make it easier to tweak later
timeGreen = 5000; // time interval that light stays green
timeYellow = 2000; // time interval that light stays yellow
timeRed = 1000;  // time interval that light stays red before other signal turns green

void setup()
{
 strip.begin();
 strip.show();  // Initialize all pixels to 'off'
}

void loop()
{
 //Traffic Light, Phase 1
 strip.setPixelColor(0, red);
 strip.setPixelColor(2, red);
 strip.setPixelColor(1, green);
 strip.setPixelColor(3, green);
 strip.show();
 delay(timeGreen);

 //Traffic Light, Phase 2 - Green lights turn to yellow, then red
 strip.setPixelColor(1, yellow);
 strip.setPixelColor(3, yellow);
 strip.show();
 delay(timeYellow);
 strip.setPixelColor(1, red);
 strip.setPixelColor(3, red);
 strip.show();
 delay(timeRed);

 //Traffic Light, Phase 3 - Red lights turn Green
 strip.setPixelColor(0, green);
 strip.setPixelColor(2, green);
 strip.show();
 delay(timeGreen);

 //Traffic Light, Phase 4 - Green lights turn to yellow, then red
 strip.setPixelColor(0, yellow);
 strip.setPixelColor(2, yellow);
 strip.show();
 delay(timeYellow);
 strip.setPixelColor(0, red);
 strip.setPixelColor(2, red);
 strip.show();
 delay(timeRed);
}