Testing Out an Ultrasonic Sensor (The Posh Way)
This week we’ve got a lesson where we’ve got to test out an ultrasonic sensor using an Arduino Uno board.
We’re going to be doing something similar in our lesson to what we did in the post “Tuning The Distance of an IR Sensor Using Arduino” that I wrote last week in class; only this time (because I’m not in class and I can think straight) I want to integrate the sensor with a thermostat using a thermistor (because the speed of sound is affected by temperature – and why not?).
// Unfortunately I have left my uno board in my locker at uni, so I’m going to have to use this Arduino MEGA board that I have here instead but it’s all the same really.?
Before I set all that up however, I want to make a screen to use (instead of having to use the serial monitor like we did last time) to check readouts in real time on the same board that the sensor will be mounted to (just for fun).
Wiring up the 1602A LCD screen to our Arduino MEGA
Luckily, anything I seem to think of that I want to do is usually pretty easy to find and in this case there is an official Arduino tutorial that shows you how to wire up an LCD screen and rather than send you there I’ll just show you the one I drew myself.
// I followed the official guide about display methods over on the Arduino website. This configuration also changes as the circuit develops so this isn’t the final version.
Uploading the sketch to the arduino MEGA (or whatever)
Now the Arduino is all wired up, it’s simply a matter of uploading the following code to it to get the display to work.
// include the library code:
#include <LiquidCrystal.h>
// initialize digital pins
const int rs = 13, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
void setup() {
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.print("DIGITAL");
lcd.setCursor(0, 1); //Stes new line.
lcd.print("HILLBILLY!!");
}
void loop() {
// Turn off the display:
lcd.noDisplay();
delay(500);
// Turn on the display:
lcd.display();
delay(10000);
}
Sweet, so that’s it! I’ve got my program writing a message to the LCD screen.
Adding a temperature sensor to the circuit
The next thing I want to install onto my board before I begin looking at the sensor is I want to have a thermostat to help my sensor tuning device be a bit more accurate in arduous weather conditions. I’ve got one of these DHT11 humidity and temperature sensors here and I’m going to wire that into the board. I’ve not included a diagram for that as Fritzing doesn’t have the correct part in their library (mine only has 3 pins). One pin is a connection and the other is to ground and the third pin is a data pin that has a resistor going back to the VCC connection with a data pin coming out of that (before the resistor).
For this to work in our Arduino software we need to download the DHT sensor library from Adafruit. To do that go to Sketch > Include > Library > Manage Libraries and search for “DHT sensor library” from Adafruit and install it.
Once we’ve done that (as well as installing the other libraries the installation suggests to us) we can load up the code to read from the sensor by visiting File > Examples > DHT Sensor library > DHTtester.
[su_accordion class=””] [su_spoiler title=”Reveal the DHT11 code >>” open=”no” style=”default” icon=”plus” anchor=”” class=””]
// Example testing sketch for various DHT humidity/temperature sensors // Written by ladyada, public domain #include "DHT.h" #define DHTPIN 2 // what pin we're connected to // Uncomment whatever type you're using! #define DHTTYPE DHT11 // DHT 11 //#define DHTTYPE DHT22 // DHT 22 (AM2302) //#define DHTTYPE DHT21 // DHT 21 (AM2301) // Initialize DHT sensor for normal 16mhz Arduino DHT dht(DHTPIN, DHTTYPE); void setup() { Serial.begin(9600); Serial.println( "DHTxx test!" ); dht.begin(); } void loop() { // Wait a few seconds between measurements. delay(2000); // Reading temperature or humidity takes about 250 milliseconds! // Sensor readings may also be up to 2 seconds 'old' float h = dht.readHumidity(); // Read temperature as Celsius float t = dht.readTemperature(); // Read temperature as Fahrenheit float f = dht.readTemperature( true ); // Check if any reads failed and exit early (to try again). if (isnan(h) || isnan(t) || isnan(f)) { Serial.println( "Failed to read from DHT sensor!" ); return ; } // Compute heat index // Must send in temp in Fahrenheit! float hi = dht.computeHeatIndex(f, h); Serial.print( "Humidity: " ); Serial.print(h); Serial.print( " %\t" ); Serial.print( "Temperature: " ); Serial.print(t); Serial.print( " *C " ); Serial.print(f); Serial.print( " *F\t" ); Serial.print( "Heat index: " ); Serial.print(hi); Serial.println( " *F" ); } |
// The code for this part of the program was quite long so I’ve hidden it from view but you can reveal it by clicking on the link above.
Once we’ve done that and told the code what pin we’re using, we should get a readout in our serial monitor showing us the current temperature in the room.
Making the temperature show up on the LCD screen
The next step is to take the work we did in the start of this post and print our new information to the LCD screen. To do this the original code that we had to print the data to the screen was adapted to include the new information about the temperature sensor and that was now to be printed to the screen. This is the code that I wrote to print celcius to the LCD screen.
#include <LiquidCrystal.h>
#include "DHT.h"
#define DHTPIN 2 // what pin we're connected to
#define DHTTYPE DHT11 // DHT 11
// Initialise DHT sensor for normal 16mhz Arduino
DHT dht(DHTPIN, DHTTYPE);
// Initialise LCD screen
const int rs = 13, en = 11, d4 = 6, d5 = 5, d6 = 4, d7 = 3;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
void setup() {
Serial.begin(9600);
dht.begin();
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
lcd.clear();
}
void loop() {
// Wait a few seconds between measurements.
delay(2000);
// Reading temperature or humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds 'old'
float t = dht.readTemperature();
lcd.setCursor(0,0); // Sets the cursor to col 0 and row 0
lcd.print("Temp: "); // Prints Sensor Val: to LCD
lcd.print(t); // Prints value on Potpin1 to LCD
lcd.setCursor(0,1); // Sets the cursor to col 1 and row 0
delay(10000);
}
Success! The temperature is now printing to the screen. The next and final step is to get the ultrasonic sensor wired up to the circuit and the output of that printing to the LCD screen. At this stage it will just be the raw data coming in from the sensor but we’ll quickly look to convert that data into an accurate distance our sensor is from something (and at a given temperature ?).
Wiring up the HC-SR04 sensor to our circuit
Here’s a photograph of the raw data coming in from the sensor that will be used to configure the distance readings later.
// Note: I deactivated the precalculated solution for the purpose of this exercise from the original code that I got from Arduino.
This is the code that gets us to the point where we can tune the sensor.
[su_accordion class=””] [su_spoiler title=”See the code that takes raw readings for us >>” open=”no” style=”default” icon=”plus” anchor=”” class=””]#include <LiquidCrystal.h> #include "DHT.h" #define DHTPIN 2 // Set the pin for the DHT11 temperature sensor #define DHTTYPE DHT11 // DHT 11 // Initialise DHT sensor for normal 16mhz Arduino DHT dht(DHTPIN, DHTTYPE); // Initialise LCD screen const int rs = 8, en = 7, d4 = 6, d5 = 5, d6 = 4, d7 = 3; LiquidCrystal lcd(rs, en, d4, d5, d6, d7); // Initialise Ultrasonic variables screen const int trigPin = 10; const int echoPin = 9; float duration, distance; void setup() { Serial.begin(9600); dht.begin(); // set up the LCD's number of columns and rows: lcd.begin(16, 2); lcd.clear(); pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); } void loop() { // Wait a few seconds between measurements. delay(2000); //All the code for the HC-SR04 sensor digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); duration = pulseIn(echoPin, HIGH); float t = dht.readTemperature(); lcd.setCursor(0,0); // Sets the cursor to col 0 and row 0 lcd.print( "Temp: " ); lcd.print(t); // Prints to LCD lcd.setCursor(0,1); // Sets the cursor to col 1 and row 0 lcd.print( "Reading: " ); lcd.print(duration); // Prints to LCD delay(1000); } |
Plotting the data and working out the distance of the sensor using our readings
Just like we did in the post “Tuning The Distance of an IR Sensor Using Arduino” I plotted the data (transposed so that I’ve got the output in cm). 82 readings were taken at 10mm intervals and the results recorded and plotted in Excel.
To make use of this temperature sensor that I installed I will need to adjust this new formula slightly to allow for this functionality.
On looking at it, the bit of code (from the library in the Arduino IDE) that I removed (because it made all this a bit harder – why not?) was actually needed for this part so I had to put all the readings, and the pretty graph I just drew behind me and reinstated it.
This is the line of code I’m talking about:
distance = (duration*.0343)
The sensor spits out microsecond values (the time it takes for the sound to hit the wall and bounce back in microseconds). What we need to do is to simply multiply the sensor value by the speed of sound and then divide that by two.
// Note: arduino have provided the speed of sound in their equation but this is a cm/μs value so we need to calculate the speed of sound in m/s and then convert that to a cm/μs reading and replace their value with our dynamic (changes with each reading) value. Bosh!
The equation for the speed of sound is and I’ve got a reading for temperature which is what in the equation is; so if I plug that value into that equation I’ll get a value for the current speed of sound for the temperature in my environment. Next simply convert that meters per second reading into a cm per nanosecond reading and we have our temperature dependant, ultrasonic sensor calibration module complete with LCD output.
This is the final code for the project
#include <LiquidCrystal.h>
#include "DHT.h"
#define DHTPIN 2 // The pin for the DHT11 temperature sensor
#define DHTTYPE DHT11 // DHT 11
// Initialise DHT sensor for normal 16mhz Arduino
DHT dht(DHTPIN, DHTTYPE);
// Initialise LCD screen
const int rs = 8, en = 7, d4 = 6, d5 = 5, d6 = 4, d7 = 3;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
// Initialise Ultrasonic variables screen
const int trigPin = 10;
const int echoPin = 9;
float duration, distance;
void setup() {
Serial.begin(9600);
dht.begin();
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
lcd.clear();
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}
void loop() {
// Wait a few seconds between measurements.
delay(200);
lcd.clear();
//All the code for the HC-SR04 sensor
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
float t = dht.readTemperature();
float vsound = (331.4 + 0.6*t);
float microsound = vsound*pow(10,-4);
distance = (duration*microsound)/2;
lcd.setCursor(0,0); // Sets the cursor to col 0 and row 0
lcd.print("Temp: "); lcd.print(t); // Prints to LCD
lcd.setCursor(0,1); // Sets the cursor to col 1 and row 0
// Prints to LCD
lcd.print("Dist: "); lcd.print(distance); lcd.print("cm");
delay(1000);
}
Well that success brings us to the end of our rather convoluted journey through the ultrasonic sensor. I hope, in amongst all the randomness, you found something to be informative and/or useful.
// I’m going to be posting some more robotics stuff soon ?. Toodles ?.