This page describes using an Arduino to interface with the analog output from a reasonably inexpensive sonar rangefinder. The range finder has a splendid array of features; we only scratch the surface here.
The sensor in question is a MaxBotic LV-MaxSonar EZ20. I bought mine in February 2008 from www.pololu.com for $26 plus a reasonable p&p charge.
First I will show you a really, really basic Arduino program to access the sensor. Then I will expand upon that. There are things in this which may be of interest to you even if you don't have the sensor I am writing about... anything that returns an analog voltage from 0 to 5v (or less) can use the programs.
Initially, all we need is an Arduino and the ultrasonic distance sensor, aka "EZ0". The EZ0 has numerous pads, but we only need to connect wires from the "GND", "5v" and "AN" pads. (They are labeled in the copper traces, if you look closely at the underside of the module.) The maximum likely current demand of the EZ0 is 3mA, so it can be powered from the Arduino. The AN line goes to the analog input of your choice. I'm using AN0, but you only need to change one line at the head of the program to "re-write" it to expect the sensor on a different channel.
Most of what you need to know is explained in the sourcecode that follows. You can skip directly to that, if you wish.
As with all Arduino programs, there are two main functions, "setup" and "loop".
Just before "setup" in the sourcecode, you will see two #defines. These tell the compiler....
I chose "an0" as a way to refer to the first (and in this case only) analog input pin. LEDpin is my reference for the pin on which I have an LED which I will want to turn on and off. Not only are these human-friendly (well, at least geek-friendly) terms for things easier to deal with than "0" and "13", but if someone else is using the program, and for some reason, say, wants to connect the LED to pin 12, then they only need to change the....
#define LEDpin 13
.... line (to #define LEDpin 12), and instantly, all through the program, anywhere that a reference was made to the pin the LED was attached to occurs, that reference has been "revised" to accommodate the programmer's wish to move the LED to pin 12.
Most of the examples I've seen for Arduino code would put the zero and the 13 into variables. This "works", but is less elegant.
Also before the declaration of "setup", I've declared a variable "iAnVal".
Nothing in the declaration of "setup" is essential to the core function of this program, which is to read an analog value, from, as it happens, the MaxBotic ultrasonic range finding unit. However, if the program is to be useful, and if we are to retain our sanity, it needs to tell us what we've read, and it needs to help us see what's happening, 'cause few programs do exactly what they "should" until a few passes through the "write/ test/ edit/ re-write, re-test" cycle. Sigh. So, in "setup", we prepare the system to send "things" out via the built-in serial interface. (That's the Serial.begin line) And we prepare the pin defined by LEDpin to be used for output.
Do take a moment to read the two comments under "N.B." in the sourcecode, in the "setup" declaration.
Once the Arduino is programmed, and told to begin executing that program, first, always, it does whatever is in the "setup" function, which we just discussed. It then goes on to do what's in the "loop" function. In this case, that consists of....
The first pause is there for two reasons. 1) There is no point in reading the analog value as often as the Arduino could. 2) Without this pause, the LED would not be off for a perceptible period of time. The second pass over this pause occurs shortly after the LED is turned off on the first pass through the loop.
"Tell the user what the reading was". In this simple version of the "read sensor" program, the user can't see what the sensor is reporting unless the Arduino is attached to a larger computer, or another output device has been provided. Don't worry.... the next version of the program (farther down the page, after the one below) will "work" without either.
The standard Arduino development environment "talks to" the Arduino over a serial link. That link is usually provided via a USB interface, but the Arduino, and to some extent the big PC driving it, "think" they're "talking" via a serial link. That link is used, for instance, for sending the program to the Arduino.
But! The link can be used for other things. The program below sends back ("up") the serial link the value read from the analog sensor. The "Serial.println(iAnVal)" statement is the one that causes this. The "trick" is knowing how to see (in the usual, human, sense, the information that the Arduino has sent to the big PC. Here's how...
When the Arduino Development Environment program is running in the big computer, it shows as a window with a menu across the top consisting of "File.. Edit.. Sketch.. (etc)". Below that is a row of icons... a triangle to verify the code, a square to stop it, etc. At the right hand end of that line of icons is a rectangle with a little circle above it. Hover your mouse pointer over it, and you will see "Serial Monitor".
After you have written your program and saved it, and "upload to I/O board"ed it, and seen the "Binary sketch size..." message in the panel at the bottom of the Arduino Development Environment program's window, click on the Serial Monitor icon. Once the Arduino has finished the "setup" function (it was taking a while in a Boarduino I was using... not sure why...), then you will see numbers appearing where you once had the "Binary sketch size..." message. These numbers are the readings the Arduino is making of the analog input. They come from the Serial.println line. Put something in front of the ultrasonic ranger, and the numbers will change.
Pretty cool! Here's the simple program that does what I've described. After you've got that into an Arduino and working, come back and look at the material after this, the first program.
/*MaxBotix1simple ver 29 Mar 08 A demonstration of using an analog sensor with an Arduino. While general points arise, the example shows an ultrasonic rangefinder, MaxBotix LV-MaxSonar EZ0, in action. This program is explained in the "How To" at.... http://sheepdogguides.com/arduino/aht1a.htm ================*/ /*First: Create a human-friendly name for the pin on which you have the sensor. Change just the following line if you want to connect your sensor on a different analog input.*/ #define anIn 0 //(no ; here... never is on a "#define" line.) #define LEDpin 13 /*(no ; here) Not "needed"... but helpful if you have an LED and resistor on pin 13. It will be made to "wink" so that you can see that your the program IS executing the "loop" function.*/ int iAnVal; /* declare a variable to store the value coming from the sensor It has not been given an initial value as an assignment is made to the variable before any attempt to read from it.*/ void setup() { /*The two lines here are not "needed" to read the sensor, but they support things which can help you see what is going on as you debug your program*/ Serial.begin(9600);//See note at the Serial.write line. pinMode(LEDpin, OUTPUT); // prepare the pin "LEDpin" for output /*======================================== N.B.: 1) The sensor does some things at each power cycle. For the rest of the time after coming to life, until the next cycle, it will work best if there is only air for at least 14 inches in front of it during the second or two as power is applied. 2) For some reason I haven't tracked down... maybe it has always done it?... but my Arduino is, when I run this program, taking about 8 seconds (from the time I get the message "Binary sketch size....") to start executing the "loop" function. This isn't enough time to be a problem, but you need to know that the pause is happening before you worry that the program isn't running. The "wink" of the LED tells you when "loop" has started running. =========================================*/ } //end of setup void loop() { iAnVal = analogRead(anIn); // read a value from the sensor delay(150); /* Stop the program for a moment. Partly to make the "wink" work, but also as there is no reason to read the sensor as frequently as the Arduino could read it.*/ Serial.println(iAnVal); /*You do not need anything "extra" beyond the normal Arduino Development Tool (my name for the most basic, can't live without it, arduino.exe that you must already have to see things that have been sent to the serial port by using Serial.println In the icons under the menu (menu: "File.. Edit.. Sketch....), at the right hand end, is one that is identified "Serial Monitor" if you hover your mouse pointer over it. Click on this after starting the upload of the program to your Arduino, and things that are sent with Serial.println will appear in the panel at the bottom of the Arduino Development Tool window. For Serial.println to work, you should do a Serial.begin during the "setup" function. ------------------------------------------*/ /*The three following aren't "needed"... they wink the LED so that you can see that the "loop" function is executing.*/ digitalWrite(LEDpin,HIGH); delay(150); digitalWrite(LEDpin,LOW); }
So. That's the simple program. It reads the sensor, and sends the value read to the serial stream, which you can read while the Arduino is attached to your PC, as explained above, and in the comments within the program.
Now for and enhanced version of the program. It is very similar, but, once you add four LEDs to the circuit, the program gives the result from the sensor on a crude 5 value bar graph. (No LED on, 1 on, 2 on, etc.)
The LEDs and their resistors go on pins 9,10,11, and 12, unless you want to change the #defines at the top of the program. Each LED goes from its pin, to its resistor, and that goes to ground. (The "zero volts" connection, or "rail".) Resistor size? Depends a little on the LED, but about 300-800 ohms will probably be okay.
You can jump ahead and read through the code if you wish,
All that's been added to the program bits and pieces setting up the pins for the LEDs as outputs, and defining some constants which will determine when the LEDs turn on. The latter are "Thresh0", "Thresh1", etc. "Thresh" as in "threshold".
Once these things were taken care of, I only had to add the four lines to loop which look like....
if (iAnVal<Thresh0) {digitalWrite(LEDan0,HIGH);} else {digitalWrite(LEDan0,LOW);};
That says: "If the analog value read from the sensor a moment ago is less than the number in "Thresh0", then turn the first LED on, and if it isn't turn the LED off. Pretty simple, really, apart from getting all the semi-colons exactly right!
And now you know about all of the new stuff in the extended version of the first program. Load it to your Arduino, and watch the LED bar graph grow and shrink as you move your hand close to and away from the sensor. Beware: The sensor has pretty good "peripheral" vision, and the bar graph will tell you the closest thing seen by the sensor. If you want to change the distance that causes, say, the second LED to come on or go off, just change the values assigned to the different threshold constants.
Enjoy! Amaze your friends!
/*MaxBotix2simple ver 29 Mar 08 A slightly extended version of the following. The extension requires four LEDs (with resistors), and provides a bar graph to display an indication of the value that the analog sensor is returning. A demonstration of using an analog sensor with an Arduino. While general points arise, the example shows an ultrasonic rangefinder, MaxBotix LV-MaxSonar EZ0, in action. This program is explained in the "How To" at.... http://sheepdogguides.com/arduino/aht1a.htm ================*/ /*First: Create a human-friendly name for the pin on which you have the sensor. Change just the following line if you want to connect your sensor on a different analog input.*/ #define anIn 0 //(no ; here... never is on a "#define" line.) #define LEDpin 13 /*(no ; here) Not "needed"... but helpful if you have an LED and resistor on pin 13. It will be made to "wink" so that you can see that your the program IS executing the "loop" function.*/ int iAnVal; /* declare a variable to store the value coming from the sensor It has not been given an initial value as an assignment is made to the variable before any attempt to read from it.*/ /*New material, part of additions to turn MaxBotix1simple into MaxBotix2simple....*/ #define LEDan0 9 //no ; after any #define #define LEDan1 10 #define LEDan2 11 #define LEDan3 12 #define Thresh0 21 //(no ; here) #define Thresh1 36 //(no ; here) #define Thresh2 51 //(no ; here) #define Thresh3 66 //(no ; here) /*End, this block of new material, part of additions to turn MaxBotix1simple into MaxBotix2simple....*/ void setup() { /*The two lines here are not "needed" to read the sensor, but they support things which can help you see what is going on as you debug your program*/ Serial.begin(9600);//See note at the Serial.write line. pinMode(LEDpin, OUTPUT); // prepare the pin "LEDpin" for output /*======================================== N.B.: 1) The sensor does some things at each power cycle. For the rest of the time after coming to life, until the next cycle, it will work best if there is only air for at least 14 inches in front of it during the second or two as power is applied. 2) For some reason I haven't tracked down... maybe it has always done it?... but my Arduino is, when I run this program, taking about 8 seconds (from the time I get the message "Binary sketch size....") to start executing the "loop" function. This isn't enough time to be a problem, but you need to know that the pause is happening before you worry that the program isn't running. The "wink" of the LED tells you when "loop" has started running. =========================================*/ /*New material, part of additions to turn MaxBotix1simple into MaxBotix2simple....*/ pinMode(LEDan0,OUTPUT); pinMode(LEDan1,OUTPUT); pinMode(LEDan2,OUTPUT); pinMode(LEDan3,OUTPUT); } //end of setup void loop() { iAnVal = analogRead(anIn); // read a value from the sensor /*New material, part of additions to turn MaxBotix1simple into MaxBotix2simple....*/ if (iAnVal<Thresh0) {digitalWrite(LEDan0,HIGH);} else {digitalWrite(LEDan0,LOW);}; if (iAnVal<Thresh1) {digitalWrite(LEDan1,HIGH);} else {digitalWrite(LEDan1,LOW);}; if (iAnVal<Thresh2) {digitalWrite(LEDan2,HIGH);} else {digitalWrite(LEDan2,LOW);}; if (iAnVal<Thresh3) {digitalWrite(LEDan3,HIGH);} else {digitalWrite(LEDan3,LOW);}; /*End, this block of new material, part of additions to turn MaxBotix1simple into MaxBotix2simple....*/ delay(150); /* Stop the program for a moment. Partly to make the "wink" work, but also as there is no reason to read the sensor as frequently as the Arduino could read it.*/ Serial.println(iAnVal); /*You do not need anything "extra" beyond the normal Arduino Development Tool (my name for the most basic, can't live without it, arduino.exe that you must already have to see things that have been sent to the serial port by using Serial.println In the icons under the menu (menu: "File.. Edit.. Sketch....), at the right hand end, is one that is identified "Serial Monitor" if you hover your mouse pointer over it. Click on this after starting the upload of the program to your Arduino, and things that are sent with Serial.println will appear in the panel at the bottom of the Arduino Development Tool window. For Serial.println to work, you should do a Serial.begin during the "setup" function. ------------------------------------------*/ /*The three following aren't "needed"... they wink the LED so that you can see that the "loop" function is executing.*/ digitalWrite(LEDpin,HIGH); delay(150); digitalWrite(LEDpin,LOW); }
As the rabbit used to say, "That's All Folks". I hope it has been clear and helpful. Do please feel free to get in touch (see below.) Word "how you went wrong" would be useful, even if you figured out what the problem was. Maybe I can extend this "How To" note, and save the next person from the nuisance you had.
If you visit 1&1's site from here, it helps me. They host my website, and I wouldn't put this link up for them if I wasn't happy with their service.
Click here to visit editor's Sheepdog Software (tm) freeware, shareware pages.
Click here to visit the homepage of my biggest site.
Click here to visit the homepage of Sheepdogsoftware.co.uk. Apologies if the "?FrmAht" I added to that link causes your browser problems. Please let me know, if so?
Page tested for compliance with INDUSTRY (not MS-only) standards, using the free, publicly accessible validator at validator.w3.org
....... P a g e . . . E n d s .....