Arduino Distance Sensor Software Sketch
Arduino Distance Sensor Software Sketch
Copy the code sketch below, paste it into your Arduino programming software and load it into your Arduino to run the distance sensor project.
You must also download the timerOne library from http://code.google.com/p/arduino-timerone/downloads/detail?name=TimerOne-v9.zip&can=2&q=
Install the library using the guide http://arduino.cc/en/Guide/Libraries
This is where the magic happens...
The main code blocks of the sketch are:
Library include files
Two libraries are included with the #include directive. They both pull in definitions and give your sketch information regarding the liquid crystal display and the Timer 1 driver respectively.
The liquid crystal library was installed by default when you installed the Arduino software on your computer.
As the Arduino starts up various constants and variables are defined. First the control pins for the trigger and echo signals of the HC-SR04 are designated. These must match the actual connections between your boards.
#define trigPin 12
An id is then assigned to the interrupt generated from the echo signal.
#define echo_int 0
Timer one is set to time out every 50 uS and a tick counter allows the routine to measure a 200 mS duration after which a new trigger pulse is initiated.
#define TIMER_US 50
'tick_counts' is defined as a variable rather than a constant so that it can be adjusted on the fly if we need to later.
The variables required to measure the duration of the echo pulse are defined and initialized to zero.
volatile long echo_start = 0;
Next we define 16 distance ranges to characterize the echo signal distance. One range or zone for each column on the 16 character display.
#define RANGES 16
A variable holds the current distance found in cm.
volatile int range_cm;
The LCD display module allows us to define up to eight special characters over and above the built in character set. These are used for the mini bargraph characters of the distance sensor graphic.
Each of the special characters 'bar0'-'bar7' consists of an array of eight bytes. One byte for each row of the character. The least significant five bits each correspond to a pixel in the character row
The setup() function is called by the Arduino start up code once during the reset sequence. Any necessary initialisation can be done here.
The I/O pins that we are going to use are set as 'INPUT' or 'OUTPUT' as appropriate. The timer is initialised and interrupt routines attached to interrupts so that the routines will be executed when the interrupts fire.
The LCD begin() routine is called to initialise the LCD display.
The USB virtual serial port is initialised so that we can use it for debugging the software when needed.
Next the distance zones array is initialised by calculating equally spaced zones from the 'MAX_ZONE' value in uS.
To complete the setup the special LCD characters are created and stored in the LCD module then a rough scale in cm is printed to the second row of the display.
Note that we are not going to use the keyboard of the LCD in this project but we may well come back to it in a later exercise.
After setup() is complete the loop() function is called. As it's name suggests it will execute to the end then start again at the top forever or until it is powered off or reset. This is where we make the device accessible to the outside world and do things that are not time critical.
All the critical stuff in this project is done in the interrupt routines leaving only the display to be handled in the main loop.
I decided to update the display twice a second so the first thing that loop() does is test a timer to see if it has been at least 500mS since the last update.
If the timer triggers then the LCD display is updated after sending some diagnostic information to the serial monitor port.
As a general rule you should always build some diagnostics of some sort into your software because it can often be invaluable when you find that your code doesn't work in the way that you intended. Printing information to the serial monitor is an easy and quick method of debugging your programs.
The display is generated by writing one of the special bargraph characters to each of the 16 positions. The actual character written is determined by the corresponding value from the 'range_hits' array.
The range_hits array contains one counter for each character. The value of the counter is an indication of how often a distance reading in the corresponding range has been detected recently.
The resulting display is a line of bargraphs that indicate various objects seen by the sensor.
Timer Interrupt Routine
The timerIsr() function is called when the timer times out every 50uS. For now it simply calls the trigger_pulse() function which deals with the timing of the pulse on the trigger output pin.
Each time the routine is called it decrements the counter by subtracting 1 until it reaches zero where it is reset and 'state' is set to '1' to start the pulse output.
The pulse output is generated every 200mS by the simple finite state machine in the trigger_pulse function.
The state machine is normally in state '0' but is set to state '1' when the timer times out. While in state '1' the trigger output pin is set 'HIGH' which produces a +5v level on the trigger pin. The state is then immediately set to '2' and the function exits.
The next time the interrupt routine calls trigger_pulse() 50uS later, the code in state '2' of the state machine sets the trigger pin 'LOW' which sends the output level to 0v. The state is then set to '0', the normal or idle state.
That is how this function generates a trigger pulse of 50uS duration which is comfortably in excess of the minimum 10uS required by the HC-SR04 module.
Echo Interrupt Routine
The second interrupt routine deals with the echo pulse coming back from the HC-SR04 module. It's called 'echo_interrupt()' and it measures the duration of the echo in micro seconds.
The echo interrupt is set to trigger whenever the level on the echo input pin changes state either from low to high or from high to low.
The first job is to determine which end of the pulse has just triggered the routine and this is done by testing the level on the pin. If it is high then this must be the start of the pulse and if it is low then it must be the end of the pulse.
Depending on which end of the pulse we are at the 'echo_start' and 'echo_end' variables are set to the start and end times of the pulse in micro seconds. When the end of the pulse is detected the 'echo duration' is calculated from the difference between end and start times and the distance in centimeters is then calculated by dividing by 58.
When the echo duration has been calculated it is sorted into the appropriate range or zone.
The corresponding element of the 'range_hits' array is increased by 3 and all other elements decreased by 1. The effect of this is to provide persistence to the display. The relative height of each bargraph is an indication of how strong the echo is from objects at different distances.
When you have connected it up, installed the TimerOne library and downloaded the sketch from the website to the Arduino you should have a working ultrasonic distance sensor.
Point the sensor at the objects of interest and watch the echos pop up on the display.
|Now subscribe to our newsletter and don't miss a thing|