One of the most interesting and useful features of the Arduino is the ease with which you can attach and read a huge variety of sensors. Which brings us to how to read those sensors. While every sensor is different, the vast majority will report back a reading as a partial voltage. If you have a sensor measuring something, say how light / dark it is on a 5v system like the Arduino, then you might expect the following.
Full Dark 0v
25% Light 1.25v
50% Light 2.5v
75% Light 3.75v
100% Light 5v
With every possible voltage in between as the light level creeps up or down. The returned signal then is Analog in nature.
What analog means is that a signal can have an infinite number of states, it can always be just a little more or a little less. The problem here is that the Arduino is a Digital device. It expects a single discrete answer, yes or no, on or off, high or low. It has no maybe, sorta, or middle.
This was allowed for when the Arduino was designed by using some special internal circuitry that is attached to just some of the pins. If you examine the Arduino you will note that there are labels on the pins that divide them into groups.
In particular the group labeled as “Analog In” can accept an analog reading when used with the following command.
analogRead( )
This command will tell the arduino to check the voltage on one of the analog in pins, and convert it to a digital number. For example, the command analogRead(A3) will tell the Arduino to check the pin A3, and return a number from 0 to 1023 based on the 0 to 5v scale. Our previous light based sensor example then, would give the following results.
Full Dark = 0
25% Light = 254
50% Light = 511
75% Light = 767
100% Light = 1023
This isn’t an actual Analog input, because that would require an infinite number of possibilities, but by chopping it up into 1024 possible results, we can fake it so good that it no longer matters.
The Arduino can also fake an Analog output, but once again, only on specially designated pins, and only within certain steps.
When writing an analog output the Arduino uses only pins 2 through 13. You will see them marked as a group PWM on the board. This stands for Pulse Width Modulation. The idea is very simple, the Arduino pulses, or turns on and off, the pin so fast that it appears to be a partial voltage. If I wanted a 2.5v output then I would want the relative amount of ON time to OFF time to be 50%. If I wanted a lower voltage, I would need less on time and more off time. There are 256 available levels of output, and they are 0 through 255
The command is
analogWrite( )
For example, if I want to put an output of 50% or 2.5v on pin 6, then I would choose a number in the middle of that scale and write the following. analogWrite(6, 127)
So why would I want this? Two reasons, 1, because some things use this as a signal. An excellent example are RC servos, which use that PWM signal to determine what position to move to. Change the signal, and the servo moves. Reason 2, many simple devices need a specific voltage or a variable input. This can be used to speed control a motor, or to dim an LED.
In order to write a useful bit of code to demonstrate these we will need one additional concept.
Basically, we need a place to store the numbers from the analogRead and a place to put numbers for the analogWrite. There are different types of data storage available, but we are going to use the simplest. It is called int, and it stands for integer. It can basically be used like X in algebra, it stands for whatever is stored in it, and can be used in place of a number anywhere in the code. It can be used to store ONLY whole numbers from -2,147,483,648 to 2,147,483,647. That’s a big enough range that you shouldn’t exceed the limits. If you do, it just cuts off the extra and stores whats left causing bad data or an error, you’ve been warned. It also cuts off partial numbers. If you try to store 3.6, then it stores 3 and drops the .6 entirely.
To use it, you must first set it up before the setup section by giving it a name. In this example we’ll set up two int called Innie and Outtie. The commands then would be :
int Innie = 0
int Outtie = 0
The 0 in this example tells it to go ahead and assign them a value of 0. This is extremely good practice in programming. If you leave off the “= 0” then it still works, but the value is going to be whatever random thing got left in storage from previously. This can wreak havoc on your program’s execution.
We’re gonna need some wiring to run this on. For an output, we’ll have an LED setup in pin 6, and for an input we’ll use the potentiometer in the kit (see video) on pin A3.
Let’s put it all together then.
int Innie = 0; //creates Innie and assigns it 0
int Outtie =0; //creates Outtie and assigns it 0
voidsetup( ) {
}
void loop( ) {
Innie = analogRead (A3); //this reads pin A3 and assigns a 0-1023 to the int Innie
Outtie = Innie/2; //this is simple math, it cuts the number in Innie in half to scale it down to the range of 0-255 and puts it in Outtie
analogWrite(6, Outtie); // this sets pin 6 to a PWM whose strength is between 0-255 based on the number in Outtie
}
EDIT; As a very observant @Locutus pointed out I should have divided by 4, not 2. These are the little mistakes that trip up all programmers. Details details details.
Arduino / Programming Chatter Thread - #9 by Locutus