Introduction
Howdy Again Everyone!
So today I sat down and slapped together what I am referring to as a "volume board." Really, there is no sound involved with this project yet, so it's not much of a volume board. However, what the project does do is display a very simple digital output based on an analog input signal, or, an electrical "volume." Hence the name.
I put together this project because I needed some practice in dealing with analog signals as inputs to my microcontrollers. Hence, I did some browsing on LadyAda.net and Sheepdog Guides and found this and this tutorial respectively. Both of these guides discuss safe ways of hooking LEDs up to Arduino's 5V power output pin. They also touch on the Analog input pins. The Sheepdog tutorial gave me the idea to use a potentiometer to control an analog signal to my Arduino board in order to light up certain LEDs. Thus, I mostly ripped off that design and modified it for my own purposes. Since my primary goal was to learn about Arduino analog signals, I did not feel it necessary to design an entire concept by myself. So, without further ado, I'll explain a bit more about what I did and how I did it.
So today I sat down and slapped together what I am referring to as a "volume board." Really, there is no sound involved with this project yet, so it's not much of a volume board. However, what the project does do is display a very simple digital output based on an analog input signal, or, an electrical "volume." Hence the name.
I put together this project because I needed some practice in dealing with analog signals as inputs to my microcontrollers. Hence, I did some browsing on LadyAda.net and Sheepdog Guides and found this and this tutorial respectively. Both of these guides discuss safe ways of hooking LEDs up to Arduino's 5V power output pin. They also touch on the Analog input pins. The Sheepdog tutorial gave me the idea to use a potentiometer to control an analog signal to my Arduino board in order to light up certain LEDs. Thus, I mostly ripped off that design and modified it for my own purposes. Since my primary goal was to learn about Arduino analog signals, I did not feel it necessary to design an entire concept by myself. So, without further ado, I'll explain a bit more about what I did and how I did it.
Setting up my LEDs
Figure 1: Notice that 1 leg of the resistor and
the positive lead of the LED are on alternate
rows. This connects the components
without shorting themselves along the row.
the positive lead of the LED are on alternate
rows. This connects the components
without shorting themselves along the row.
The primary design and purpose of my volume board is to light up a sequence of ten LEDs based on the magnitude of input to the Arduino analog input pin. My first step in setting this up, therefore, was to hook up ten LEDs in an appropriate manner. Basically, I decided to hook up all ten LEDs in a line down one side of my breadboard. I connected a 1,000 ohm (or 1k ohm) resistor to each LED positive leg. This set up is reflected in Figure 1. You can see that the first leg of each resistor sits in its own row on the breadboard. The second leg shares a row with the positive LED lead (that's usually the longer lead). The negative lead of each LED is then connected to one of the rails on the breadboard. I jumped this rail to the GND pin of the Arduino board so that all of the LEDs were hooked into the same ground path. The resistor leg that was plugged into its own row would eventually be hooked to the 5V output pin of the Arduino board to test it. Notice how this configuration allows an organized staggering of the rows for each component: 1 resistor leg, 1 resistor leg + 1 LED leg, 1 resistor leg, 1 resistor leg + 1 LED leg, etc.
Figure 2: Ten LEDs all lined up and ready to light.
Once I had all ten LEDs lined up in the manner described above (depicted in Figure 2), I was ready to begin testing each LED. Remember that lesson I learned about testing circuits early on in my Symet project? Well this is where that lesson kicked in. I took a hot lead from the 5V output pin on the Arduino board and plugged it into each row that had only 1 resistor leg stuck in it. This established a circuit between the 5 V pin and the GND path that went through the resistor and LED. It is important to keep the resistor in sequence with the LED because the LED could burn out if hooked up backwards. The 1k resistor helps dissipate some of the energy in the circuit and prevents this from happening, even if the LED is hooked up backwards.
I should note that I activated the Arduino board with a simple 9V battery hooked to the Vin and GND pins of the Arduino board. With this configuration, each LED should have lit as I touched the 5V lead to each LED's respective resistor. This process is depicted below in Video 1.
Video 1: Here I am testing each LED for my analog input board. Essentially, I need
to make sure that each LED is hooked up in the right direction. Thus, I am using
the 5V pin on the Arduino board to test each separately.
to make sure that each LED is hooked up in the right direction. Thus, I am using
the 5V pin on the Arduino board to test each separately.
Configuring the Potentiometer
Figure 3: The middle pin of the potentiometer,
or wiper, is actually the bottom row in this picture.
The first terminal is the top row and the second,
or ground, terminal connects to the second row
from the top.
or wiper, is actually the bottom row in this picture.
The first terminal is the top row and the second,
or ground, terminal connects to the second row
from the top.
This board will eventually be used to test and analyze an array of analog sensors that I will utilize for my robot Ardie. Currently, the only sensor I have is a passive infrared (PIR) sensor. This is a simple digital motion sensor that sends a '1' when it detects a change in the blackbody radiation of the surrounding environment. Since it is a digital sensor (sending a 1 or 0) it is not particularly useful for configuring an analog test bed. As such, I snagged a 5,000 ohm (5k) potentiometer to use for this test instead.
A potentiometer is really just a variable resistor. It has three legs. The first two (usually the ends) are just like the terminals of a typical resistor. The third leg, known as the wiper (usually the middle pin) acts as a variable resistor. A potentiometer, therefore, can act as a simple volume knob. By attaching a lead to the wiper pin, one can record a variable voltage between the ground and the wiper. This voltage variance can be used as a fake analog sensor since most analog sensors do something very similar. Based on a particular input (sound, mechanical stress, heat, whatever) they output a variable voltage between 0 volts and some maximum (often 5 volts).
To use the potentiometer, therefore, all I had to do was connect the 5V output lead from the Arduino board to 1 terminal and connect the second terminal to the GND pin on the Arduino board. I could then connect the middle pin (wiper) to the analog input of the Arduino board and simulate an analog input sensor (like a simple microphone). This whole setup is depicted in Figure 3. Please note, however, that the pin configuration on my potentiometer was a bit weird. As such, the top breadboard row in the picture is the hot lead (5V), the second breadboard row is the ground lead (GND), and the third breadboard row (from the top) is the wiper lead (analog input pin 0).
A potentiometer is really just a variable resistor. It has three legs. The first two (usually the ends) are just like the terminals of a typical resistor. The third leg, known as the wiper (usually the middle pin) acts as a variable resistor. A potentiometer, therefore, can act as a simple volume knob. By attaching a lead to the wiper pin, one can record a variable voltage between the ground and the wiper. This voltage variance can be used as a fake analog sensor since most analog sensors do something very similar. Based on a particular input (sound, mechanical stress, heat, whatever) they output a variable voltage between 0 volts and some maximum (often 5 volts).
To use the potentiometer, therefore, all I had to do was connect the 5V output lead from the Arduino board to 1 terminal and connect the second terminal to the GND pin on the Arduino board. I could then connect the middle pin (wiper) to the analog input of the Arduino board and simulate an analog input sensor (like a simple microphone). This whole setup is depicted in Figure 3. Please note, however, that the pin configuration on my potentiometer was a bit weird. As such, the top breadboard row in the picture is the hot lead (5V), the second breadboard row is the ground lead (GND), and the third breadboard row (from the top) is the wiper lead (analog input pin 0).
Setting Up the Arduino
With the "analog sensor" (potentiometer) connected to the breadboard, the next step in setting up the board was simply connecting everything to the Arduino board.I've gone over the basic configuration already, but for completeness I will list every pin utilized on the Arduino board below. Please note, I am not going to configure a circuit diagram for this particular project as I consider that to be overkill. If you are trying to emulate this, and really need a diagram, please contact me. I will put something together if you ask really nicely. Otherwise, the Arduino pin assignments are listed below:
The source code for the volume controller is listed below. It breaks down into some very basic parts and is commented so that you can get a feel for what each line does. As such, I just want to point out some of the basic parts of the code here. Please e-mail me if you have any specific questions, as this is not meant to be an Arduino language tutorial. For that, I recommend checking out the Sheepdog guides and LadyAda tutorials linked to in the introduction of this blog.
The first thing I do is assign names to all of my pins. Notice that the pins are called out simply as integers (0, 1, 2, etc.) and that they only gain meaning as they are used in context later in the code. In the next section, I assign all of the LED pins as OUTPUT pins (this is the context I was talking about). This tells the Arduino board that it will be sending a 5V signal to digital pins 0 - 9 (my LEDs) when commanded to do so.
Next, I set up the primary loop. This loop will repeat over and over again, processing each contained command sequentially until I disconnect power from the circuit. Notice that a few of the commands are prepended by //. These lines are known as comments and they show where I was manipulating things directly for testing purposes. Since they are commented out, they will not be processed by the Arduino controller.
The first two active lines within the loop, therefore, prime the circuit. The first line reads the analog input (analogRead command) from pin 0 (AnalogInPin). Notice that this same effect could be achieved by saying analogRead(0). The only reason we name the AnalogInPin is so that we humans can understand what is happening when we read the code. This command assigns the read analog input value (which varies between 0 and 1023, based on the input voltage coming from the potentiometer) and assigns the integer value to the variable AnalogIn. Note that all of these variables and pin names were declared at the beginning of the sketch. This is necessary based on the structure of the Arduino language.
After reading the analog input, the board will process a series of commands based on the setLEDs subroutine which I define later. The second active line within the primary loop feeds ten inputs, all zeros, to this custom routine. Essentially, I am telling the Arduino board to turn off every LED pin until further notice.
That further notice comes in the form of a series of 11 if statements. These if statements tell the Arduino chip to do something only if the portion contained within the parentheses is true. Thus, the first one says to send an input set of (0,0,0,0,0,0,0,0,0,1) to the setLEDs routine if and only if the AnalogIn value is greater than 0. In other words, only turn the first LED on if some voltage is detected on the incoming line. The next 10 statements then turn on one more LED for each interval of 102. This interval was chosen because 1024 divided by 10 is approximately 102 (technically it's 102.4, so I rounded down and the top pin has a bit of a larger buffer on it).
So now all we have to do is tell the Arduino chip what the setLEDs routine does. Well that's the last chunk of code shown in the source code. Notice that it expects ten bytes as inputs (bL0 through bL9). Bytes are simple variables that can be 1 or 0. By using bytes, rather than integers, I save myself a lot of memory footprint in the compiled sketch. Each bL# byte is mapped to an LED pin in the succeeding logic. I expand the if statement to become an if-else statement which says, :"if whatever is in the parentheses is true, do X, otherwise do Y." In the case of this routine, I tell the Arduino to write a LOW voltage (off setting) to each LED pin if the respective bit is 0, otherwise (if the bit is 1) write a HIGH voltage to the pin (turn the LED on).
By writing the code in such a boiler plate manner (1 if and 1 if-else statement per LED) I create a directly controlled mapping between each LED and the analog input signal. I could, instead, process the signal through algebra (divide by ten and do some other stuff), map the resulting value to a binary 10 bit, byte value, and simply activate the setLEDs routine once using that byte value. This might be something I set up in the future, but for now, the code I posted below works beautifully as demonstrated in Video 2.
- Vin: Connects to the positive (+) terminal of the 9V battery
- 5V: Connects to the primary lead of the potentiometer (top row in Figure 3)
- Analog In 0: Connects to the wiper lead of the potentiometer (bottom row in Figure 3)
- Digital Pin 0: Connects to the first LED (green) in the sequence, bL0 in source code
- Digital Pin 1: Connects to the next LED (green) in the sequence, bL1 in source code
- Digital Pin 2: Connects to the next LED (green) in the sequence, bL2 in source code
- Digital Pin 3: Connects to the next LED (green) in the sequence, bL3 in source code
- Digital Pin 4: Connects to the next LED (yellow) in the sequence, bL4 in source code
- Digital Pin 5: Connects to the next LED (yellow) in the sequence, bL5 in source code
- Digital Pin 6: Connects to the next LED (yellow) in the sequence, bL6 in source code
- Digital Pin 7: Connects to the next LED (yellow) in the sequence, bL7 in source code
- Digital Pin 8: Connects to the next LED (red) in the sequence, bL8 in source code
- Digital Pin 9: Connects to the last LED (red) in the sequence, bL9 in source code
- GND Pin: Connects to one rail on the breadboard, to which the negative leads of all LEDs, plus the third pin of the potentiometer (second row in Figure 3) are all connected. Also connects to the negative (-) lead on the 9V battery.
The source code for the volume controller is listed below. It breaks down into some very basic parts and is commented so that you can get a feel for what each line does. As such, I just want to point out some of the basic parts of the code here. Please e-mail me if you have any specific questions, as this is not meant to be an Arduino language tutorial. For that, I recommend checking out the Sheepdog guides and LadyAda tutorials linked to in the introduction of this blog.
The first thing I do is assign names to all of my pins. Notice that the pins are called out simply as integers (0, 1, 2, etc.) and that they only gain meaning as they are used in context later in the code. In the next section, I assign all of the LED pins as OUTPUT pins (this is the context I was talking about). This tells the Arduino board that it will be sending a 5V signal to digital pins 0 - 9 (my LEDs) when commanded to do so.
Next, I set up the primary loop. This loop will repeat over and over again, processing each contained command sequentially until I disconnect power from the circuit. Notice that a few of the commands are prepended by //. These lines are known as comments and they show where I was manipulating things directly for testing purposes. Since they are commented out, they will not be processed by the Arduino controller.
The first two active lines within the loop, therefore, prime the circuit. The first line reads the analog input (analogRead command) from pin 0 (AnalogInPin). Notice that this same effect could be achieved by saying analogRead(0). The only reason we name the AnalogInPin is so that we humans can understand what is happening when we read the code. This command assigns the read analog input value (which varies between 0 and 1023, based on the input voltage coming from the potentiometer) and assigns the integer value to the variable AnalogIn. Note that all of these variables and pin names were declared at the beginning of the sketch. This is necessary based on the structure of the Arduino language.
After reading the analog input, the board will process a series of commands based on the setLEDs subroutine which I define later. The second active line within the primary loop feeds ten inputs, all zeros, to this custom routine. Essentially, I am telling the Arduino board to turn off every LED pin until further notice.
That further notice comes in the form of a series of 11 if statements. These if statements tell the Arduino chip to do something only if the portion contained within the parentheses is true. Thus, the first one says to send an input set of (0,0,0,0,0,0,0,0,0,1) to the setLEDs routine if and only if the AnalogIn value is greater than 0. In other words, only turn the first LED on if some voltage is detected on the incoming line. The next 10 statements then turn on one more LED for each interval of 102. This interval was chosen because 1024 divided by 10 is approximately 102 (technically it's 102.4, so I rounded down and the top pin has a bit of a larger buffer on it).
So now all we have to do is tell the Arduino chip what the setLEDs routine does. Well that's the last chunk of code shown in the source code. Notice that it expects ten bytes as inputs (bL0 through bL9). Bytes are simple variables that can be 1 or 0. By using bytes, rather than integers, I save myself a lot of memory footprint in the compiled sketch. Each bL# byte is mapped to an LED pin in the succeeding logic. I expand the if statement to become an if-else statement which says, :"if whatever is in the parentheses is true, do X, otherwise do Y." In the case of this routine, I tell the Arduino to write a LOW voltage (off setting) to each LED pin if the respective bit is 0, otherwise (if the bit is 1) write a HIGH voltage to the pin (turn the LED on).
By writing the code in such a boiler plate manner (1 if and 1 if-else statement per LED) I create a directly controlled mapping between each LED and the analog input signal. I could, instead, process the signal through algebra (divide by ten and do some other stuff), map the resulting value to a binary 10 bit, byte value, and simply activate the setLEDs routine once using that byte value. This might be something I set up in the future, but for now, the code I posted below works beautifully as demonstrated in Video 2.
Video 2: The final build of my volume board turned out quite nicely. As you can see,
I can vary the potentiometer signal to vary the number of LEDs lit.
I can vary the potentiometer signal to vary the number of LEDs lit.
Lessons Learned
Well, this entire project was primarily meant to be an exercise regarding the Arduino analog capabilities. In that mission it was a success. I learned a lot about the analog language of the Arduino chip as well as some of the nuances of dealing with potentiometers. It really helps if a manufacturer labels the pins on their potentiometer. If they don't, prepare to swap leads until you get the right configuration.
Aside from simply learning the Arduino analog language. I also learned that I can't trust Radio Shack brand items to follow any kind of standard. It turns out that my breadboard (which I bought from them awhile ago) actually has four separate sets of rails on it. The two sets on the right and left hand sides of the board are each split along the middle of the board horizontally. This was the source of much annoyance for me until I figure out to jump one set to the next. I think I'll add those jumpers permanently to the board.
Besides that, this project was all sorts of fun and it was simple too. (and I think only $10 for all the supplies excluding the Arduino chip and breadboard ). For anyone looking to learn a bit about analog reading, I suggest configuring something similar yourself.
So until next time, good hacking, and have fun building.
Best of Luck,
Brady C. Jackson
Aside from simply learning the Arduino analog language. I also learned that I can't trust Radio Shack brand items to follow any kind of standard. It turns out that my breadboard (which I bought from them awhile ago) actually has four separate sets of rails on it. The two sets on the right and left hand sides of the board are each split along the middle of the board horizontally. This was the source of much annoyance for me until I figure out to jump one set to the next. I think I'll add those jumpers permanently to the board.
Besides that, this project was all sorts of fun and it was simple too. (and I think only $10 for all the supplies excluding the Arduino chip and breadboard ). For anyone looking to learn a bit about analog reading, I suggest configuring something similar yourself.
So until next time, good hacking, and have fun building.
Best of Luck,
Brady C. Jackson
Arduino Source Code
/* Volume_Board_v1.0.pde
Author: Brady C. Jackson
Date: 09/25/2010
Thanks to: http://sheepdogguides.com/arduino/FA1adc.htm
http://www.ladyada.net/learn/arduino/lesson3.html
Description: This sketch will be used to read the analog voltage
input from a 5k potentiometer and convert the signal into digital
commands to pins 0 - 9 which are connected to LEDs. The sketch
will, therefore, control a visual volume board.
*/
int AnalogIn=0; // Prime Analog Input reading
const byte AnalogInPin=0; // Name Analog Input Pin 0
const byte LED0=0; // LED for least significant bit connected here
const byte LED1=1; // LED bit 1
const byte LED2=2; // LED bit 2
const byte LED3=3; // LED bit 3
const byte LED4=4; // LED bit 4
const byte LED5=5; // LED bit 5
const byte LED6=6; // LED bit 6
const byte LED7=7; // LED bit 7
const byte LED8=8; // LED bit 8
const byte LED9=9; // LED for most significant bit connected here
void setup() // Enable all LED pins for OUTPUT mode
{
pinMode(LED0,OUTPUT);
pinMode(LED1,OUTPUT);
pinMode(LED2,OUTPUT);
pinMode(LED3,OUTPUT);
pinMode(LED4,OUTPUT);
pinMode(LED5,OUTPUT);
pinMode(LED6,OUTPUT);
pinMode(LED7,OUTPUT);
pinMode(LED8,OUTPUT);
pinMode(LED9,OUTPUT);
}
void loop()
{
AnalogIn=analogRead(AnalogInPin);
//AnalogIn=450;
setLEDs(0,0,0,0,0,0,0,0,0,0);
// Set up volume mapping such that a new LED gets turned on for
//every 102 units increased
if (AnalogIn>0 ) setLEDs(0,0,0,0,0,0,0,0,0,1);
if (AnalogIn>102) setLEDs(0,0,0,0,0,0,0,0,1,1);
if (AnalogIn>204) setLEDs(0,0,0,0,0,0,0,1,1,1);
if (AnalogIn>306) setLEDs(0,0,0,0,0,0,1,1,1,1);
if (AnalogIn>408) setLEDs(0,0,0,0,0,1,1,1,1,1);
if (AnalogIn>510) setLEDs(0,0,0,0,1,1,1,1,1,1);
if (AnalogIn>612) setLEDs(0,0,0,1,1,1,1,1,1,1);
if (AnalogIn>714) setLEDs(0,0,0,1,1,1,1,1,1,1);
if (AnalogIn>816) setLEDs(0,0,1,1,1,1,1,1,1,1);
if (AnalogIn>918) setLEDs(0,1,1,1,1,1,1,1,1,1);
if (AnalogIn==1023) setLEDs(1,1,1,1,1,1,1,1,1,1);
// delay(100); // To slow down how rapidly readings are taken.
}
/* Use single routine, setLEDs, to enable and disable all digital
output pins based on 10 bit input
Set up LED outputs such that a 0 in the given bit slot will
result in an off LED, but any other reading (1) will turn
the mapped LED on
*/void setLEDs(byte bL9, byte bL8, byte bL7, byte bL6, byte bL5,
byte bL4, byte bL3, byte bL2, byte bL1, byte bL0)
{
if (bL0==0) digitalWrite(LED0,LOW);
else digitalWrite(LED0,HIGH);
if (bL1==0) digitalWrite(LED1,LOW);
else digitalWrite(LED1,HIGH);
if (bL2==0) digitalWrite(LED2,LOW);
else digitalWrite(LED2,HIGH);
if (bL3==0) digitalWrite(LED3,LOW);
else digitalWrite(LED3,HIGH);
if (bL4==0) digitalWrite(LED4,LOW);
else digitalWrite(LED4,HIGH);
if (bL5==0) digitalWrite(LED5,LOW);
else digitalWrite(LED5,HIGH);
if (bL6==0) digitalWrite(LED6,LOW);
else digitalWrite(LED6,HIGH);
if (bL7==0) digitalWrite(LED7,LOW);
else digitalWrite(LED7,HIGH);
if (bL8==0) digitalWrite(LED8,LOW);
else digitalWrite(LED8,HIGH);
if (bL9==0) digitalWrite(LED9,LOW);
else digitalWrite(LED9,HIGH);
}
0 Comments
Your comment will be posted after it is approved.