A video is available that supports this article , click below
Parts List
- Arduino Nano
- OLED screen 128×64 pixels (but you could use smaller) SSD1306 driver
- HC-SR04 ultrasonic sensor
- Some wires and a breadboard
Introduction to Ultrasonic Sensors
These are used to detect objects in front of them by sending out a ultrasonic pulse of sound (sound with a frequency higher than what the human ear can detect) and listening for this sound coming back (after reflecting off the object). There are two main advantages to using ultrasound, firstly you cannot here the sound! and secondly, the higher the frequency then the narrower the beam of sound will be as it leaves and travels through the air. This means we should get spurious return echos from nearby objects. Here’s a picture of one.
How can we detect an objects distance?
The units only send out a sound pulse and listen for it coming back, that’s it, that alone is not enough to work out how far away something is. It would only tell use that something is in front of the sensor but not how far. In order to work out the distance we need to do a small calculation based on how long it took for the sound to travel and return. This is why we need some sort of MCU to control the sensor and to do the calculation. The distance the echo has travelled can be calculated if we
- : Know the speed the sound travels at
- : Know the time it took.
The equation is
Distance= Speed x Time
The speed of sound in air is approximately 330m/s. It has to be approximate as the speed of any sound wave depends on the density of the substance it is travelling through and air density fluctuates slightly on a day to day basis (and indeed with altitude). But for our purposes this approximation is accurate enough. So we know the speed, what about the time, how do we find that out? Because we have a Micro-Controller Unit (MCU) attached to our device it is trivial to get the time. This is the rough sequence of operation :
- MCU triggers Ultrasonic unit to send pulse and starts a timer
- Sound wave travels out and hits an object, reflects (echo’s) back to sensor
- Sensor detects returned sound wave, sends a pulse on its echo pin to MCU
- MCU detects the change in the echo pin, stops timer
- MCU gets time for wave to go and come back by looking at the timer value
We now have the time as well, but be careful the time is the time it took for the sound pulse to travel out to the object and back. We just need the time it took to get to the object, which is, of course half the time taken. The MCU can then calculate the distance by multiplying the speed of sound (330m/s) by the time taken and display this in any way you wish.
Circuit Diagram and Breadboard equivalent (click to enlarge)
Required Libraries
Using the Arduino Libraries Manager (Sketch->Include Library->Manage Libraries…) type “NewPing” into the search bar and install the NewPing library. This library handles all the nitty gritty of sending the pulse, setting timers and watching the echo pin, allowing us to use simple functions to get the distance. Next, to drive the display type in “Adafruit SSD1306” and install this library. Lastly type in “Adafruit graphics” and install the Adafruit graphics library. Your now good to go, the code you need for this project is below, copy and paste into your project and upload to your board.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
// --------------------------------------------------------------------------- // Ultrasonic range finder from XTronical. 15-11-18 // Disclaimer : No liability is undertaken as to suitability or being fit // for any purpose what-so-ever, no warranties offered. // --------------------------------------------------------------------------- #include <NewPing.h> // ultrasound sensor library #include <Adafruit_GFX.h> // for writing text/graphics to screen #include <Adafruit_SSD1306.h> // driver library for oleds with 1306 driver chip #define OLED_Address 0x3C // I2C address of oled, if this doesn't work try 0x3D Adafruit_SSD1306 oled(128,64); // create our screen object setting resolution to 128x64 #define NUM_OF_READINGS 10 // number of readings to take before using highest for display // This gives a less jittery stable value // But at the expense of taking longer to update display // A value of 10 will be 0.5s per update to display #define TRIGGER_PIN 12 // Arduino pin tied to trigger pin on the ultrasonic sensor. #define ECHO_PIN 11 // Arduino pin tied to echo pin on the ultrasonic sensor. NewPing sonar(TRIGGER_PIN, ECHO_PIN); // NewPing setup of pins void setup() { oled.begin(SSD1306_SWITCHCAPVCC, OLED_Address); // init the display } long Distance; // Highest reading in the last samples to display long ThisReading; // and last red current reading void loop() { // Take readings, go with highest, from experimentation the highest from a range // of samples is usaully the correct one with lower values being spurious Distance=0; for(int i=0;i<NUM_OF_READINGS;i++) { delay(50); // Wait 50ms between pings (20 pings/sec). 29ms should be the shortest delay between pings. ThisReading=sonar.ping_cm(); if(ThisReading>Distance) Distance=ThisReading; } // Display result to display oled.clearDisplay(); oled.setTextColor(WHITE); oled.setTextSize(2); oled.setCursor(0,0); oled.print("Distance :"); oled.print(Distance); oled.println("cm"); oled.display(); } |
and that’s it. You may want to make your project more permanent by soldering to strip or perf board and mounting in a suitable box.
Possible Problems
During development of this project it became apparent that the sensors (certainly the ones I was using) were fairly voltage sensitive, they were spec’d for between 4.8 to 5v but would give poor results if the power to the sensor was not rock solid at 5V. If you have this issue all you need do is power the Arduino from a voltage higher than 7V with the power going into the VIN pin of the Nano. A suitable battery back will do this easily (5 pack AA holders giving around 7.5V are available).