One of the most common uses of a micro is to read voltages. That is done with
an analogRead statement. The UNO has six analog pins labeled A0-A5. That function
returns a 10 bit number from 0-1023. Typically the count should be between 600 and
750. This prevents you from going over the 5V input limit of the A/D converter. You
often have a lot of noise with the reading. It is best to average a number of readings
to get a good solid number. The following code takes a running average and also serves
to multiply the raw A/D reading into a number representing an engineering unit. Note
the new variables had to be added at the beginning of the program.
For a visual, at so many loops the battery voltage is compared with a set value. The
double && is a logical, it means both statements must be true. You get more blinks as
the voltage gets lower. There is still the single short blink to indicate everything
is OK.
A serial print routine has been added at the end of the program. It sends data at the
199th loop just before the number resets. The line Serial.begin(9600) tells the micro
at what speed to communicate with, 9600 baud. Without this line it will not communicate
with the Serial Monitor in TOOLS. Printing takes time and should be limited in how
much is printed and how often.
Load this program into your computer and save it as an example using these basic functions.
Load it into your micro and do the three following tests:
Jumper A0 to REF......It should read 1023 counts and about 18V.
Jumper A0 to GND......It should read 0 counts and about 0V.
Jumper A0 to D13......It should read 0 counts and about ??V.
Ponder that a while. It will teach you to be careful in what you believe is happening.
In this sample program the voltage is calculated in millivolts. In a 12V system that gives a number of about 13,000 or down to the millivolt. There are two problems with this; (1) with this A/D having a maximum count of 1023 the accuracy is only three digits, more than that is imaginary. (2) With int the number can only go up to 32K. Then it will represent itself as negative. This becomes a problem over 32V. Printing all those digits will have the numbers dancing around. For higher voltages , multiply by a smaller number to give tenths of mv. In printing notice the word (float). That formats the number to TWO decimal places after dividing by a thousand which is a reasonable number.
Averaging can almost give an extra digit of accuracy, but it has a slow response. Sometimes it will be better to use the raw data number when response needs to be fast. I have mixed both in a program. The count up and down examples shown later have a slow response. It is sometimes necessary to add a"clawback" when loads change instantly.
The following POT might be useful while experimenting. Having soldered connections to a pot is more reliable.
http://www.ebay.com/itm/New-Rotary-Potentiometer-Model-Sensor-for-Arduino-UNO-PIC-AVR-MCU-DSP-/282248992879?hash=item41b759d86f:g:IZ8AAOSwA3dYIZmb/*
BASEAS
Turns on the LED for a quick blink, then off for a longer period, repeatedly.
A loop counter counts the number of loops and resets at 200.
This boilerplate code for future programs is in the public domain.
The slash and star indicate multiple lines of comments eliminating
This program blinks about every second to indicate it is running.
A/D reads value on A0 then multiplies and averages it to get voltage in mv.
It blinks more as the voltage lowers and serial data is sent to TOOLS.
*/
// put additional variable names here.
// int means it is an integer -32K to +32K
int blinktime = 0; // define blinktime and set initial value to zero
int rawdata = 0; // A0 A/D data
int battery = 0; // calculated battery voltage
void setup() {
// initialize the digital pin as an output.
// Pin 13 has an LED connected on most Arduino boards.
// if you forget to declare an output pin, it will still
// output a pulse for a machine cycle. Then the pin will
// float. That can drive you nuts when driving a FET, but
// can be really handy at times.
Serial.begin(9600); // setup serial and define baud rate
pinMode(13, OUTPUT); // LED pin declared as an output
}
void loop() { // the { indicates the start of the code body
if (blinktime == 200) blinktime = 0; // reset if high limit is reached
// this is an interesting line. blinktime == 200, The == is a logical statement.
// blinktime = 0 A single = is a mathematical. Confusing these two is easy to do
// and will not always show up as an error. When you have written code that looks
// perfect but doesn't work, look for this.
if (blinktime == 0) digitalWrite(13, HIGH); // set the LED on. It will stay
// on till it is turned off
if (blinktime == 4) digitalWrite(13, LOW); // set the LED off when 4 loops
// are reached. As the program
// increases in size this number
// will have to be reduced
// GET ANALOG DATA AND CONVERT TO BATTERY VOLTAGE IN MILLIVOLTS
rawdata = analogRead (0); // Anolog In. Read the battery voltage PIN #A0 BATTERY
battery = battery - battery / 18; // Subtract one average reading
battery = battery + rawdata; // Add latest A/D reading back
// 3.3V = about 13500 counts or 13.5V
// Display battery condition by number of blinks
// First long blink if battery fully charged
if (blinktime == 60 && battery <= 13750) digitalWrite(13, HIGH); // set the LED on if below set voltage
if (blinktime == 70) digitalWrite(13, LOW); // set the LED off regardless at this time
// Second long blink if battery medium charge
if (blinktime == 90 && battery <= 13200) digitalWrite(13, HIGH); // LED on if below set voltage
if (blinktime == 100) digitalWrite(13, LOW); // LED off regardless at this time
// Third long blink if battery low
if (blinktime == 120 && battery <= 12500) digitalWrite(13, HIGH); // LED on if below set voltage
if (blinktime == 130) digitalWrite(13, LOW); // LED off regardless at this time
// Fourth long blink if battery discharged
if (blinktime == 160 && battery <= 12000) digitalWrite(13, HIGH); // LED on if below set voltage
if (blinktime == 170) digitalWrite(13, LOW); // LED off regardless at this time
// THE FOLLOWING IS THE SCREEN PRINT ROUTINE
if (blinktime == 199) // if on the last count print data
{ // do everything after the { symbol
Serial.print(rawdata); // A/D value
Serial.print(" count "); // space, then count, then some more spaces
Serial.print((float)battery/1000); // battery voltage TO TWO DECIMAL PLACES USING FLOAT
Serial.println("V "); // V for volts, Notice the ln after print. NEW LINE
} // } symbol ends the things to do for this IF
blinktime = blinktime + 1; // add one count to the program loop count
delay(10); // wait for 10 milliseconds. make shorter or longer to suit
} // end of program loop