- Project

Ultrasonic Sonar


Here’s how I used an HC-SR04 ultrasonic sensor to make a radar system, similar to that used on automobile parking sensors.

Project Overview
In this project we’ll demonstrate how sound waves emitted from a sensor can be used to detect objects up to several metres away. Here we’ll use this to simulate a car parking sensor, but you could also use it to steer a robot car. The HC-SR04 is a low cost sensor that emits a ultrasonic sound wave when triggered; it then measures how long it takes for an echo of that sound to return to the device, generating an ‘echo’ pulse which an Arduino can read. The device consists of a small circuit board, with a 4-pin male connector, two transducers for sending ‘T’ and receiving ‘R’ the sound waves, and a crystal resonator for accurate timing. As you will see, it is very easy to use and costs less than £2.



In the circuit diagram to the right we have connected each of the six LED’s to an Arduino output using 270 ohm resistors. The buzzer is a low power piezoelectric type, so it can be driven directly from an output. The HC-SR04 sensor requires 5 volts power and separate ‘trigger’ output and ‘echo’ input pins.

This design makes no use of the analogue inputs, but takes power from that side of the UNO pcb.

The completed project is based on using an Arduino UNO, an HC-SR04, six LED’s a buzzer and a small piece of breadboard. All of these components have been mounted on a piece of hardboard to form a simple demonstrator. As the circuitry is low current, the unit can be powered from either the USB socket or an external 7.2v supply, in the form of batteries or a wall charger

Using a suitable reflective target, such as a piece of stiff cardboard, as this approaches the sensor the code progressively illuminates the string of LED’s and increases the cadence of tones from the buzzer. When the target is very close to the sensor, all LED’s are illuminated and a permanent tone is delivered by the buzzer.



Design Files
The following files can be downloaded to help you complete this project. Each has a hyper-link and an associated description. Depending on how your web browser is configured the links will either open the files directly into the browser or offer them as downloads.

Circuit Diagram - a drawing of what is seen in the view above. Use it as a guide to wiring up your project.
Parts list - the things you will need and budget prices.
Physical Templates - drawings produced in Ms PowerPoint. Ensure that they do print at the correct size, if used directly on hardboard.
Software Code - the all important Arduino .ino file which runs the project. See comments below on coding.


Sketch: The code for this project is shown on the right. At power-up or RESET the code runs through a simple power-up routine which illuminates the six LEDs and beeps the buzzer. It doesn’t take long and it gives confidence that none of the connections have come loose in transit.

To check loop timing I normally connect an oscilloscope to pin 13 and drive this pin HIGH and LOW. You can remove this from the code if you wish.

// ###########################################################
//  UNO Demo Board v0.1 Beta
//  Released:  18/07/2015
//  Author:  TechKnowTone
// ###########################################################
    This program will simulate a simple sonar system, demonstrating
    the use of piezoelectric accoustic transducers. The effective
    distance measured by the sensor will be used to control the beep
    from a buzzer and a simple strip of LED, going from green to red.
    Sensor reading are taken once every 100 milliseconds.
    In POST run a pattern through the LED's
    Then read distance sensor and set bar graph accordingly
    Set buzzer frequency to match
// Declare and initialise global variables
#define pinTime0 13 // scope trigger pin

int buzzCnt = 0;  // buzzer off counter
int buzzMax = 9000;  // max buzzer delay in 10ms perdiods
int buzzPin = 6;  // buzzer pin
long duration = 0;  // measured time delay from echo response
long echoMax = 5000;  // max pulse timeout 5 ms
int echoPin = 4;   // ultrasonic echo pin
unsigned long interval = 10000; // loop delay interval
unsigned long lastMicros; // record of last micros() reading
int ledBarVal = 0; // value from 0 - 6
int ledPin[] = {7,8,9,10,11,12};  // pin assignments
int loopCnt = 500;  // loop counter in 10ms steps
int modeState = 1;  // default mode from reset
int potPin = 0;  // analogue input for potentiometer
int potVal = 0;  // value read from analogue i/p 0 - 1023
int trigPin = 5;   // ultrasonic trigger pin

void setup() {
  // put your setup code here, to run once:
  pinMode(buzzPin, OUTPUT);
  digitalWrite(buzzPin, LOW);
  pinMode(echoPin, INPUT);
  pinMode(ledPin[0], OUTPUT);
  pinMode(ledPin[1], OUTPUT);
  pinMode(ledPin[2], OUTPUT);
  pinMode(ledPin[3], OUTPUT);
  pinMode(ledPin[4], OUTPUT);
  pinMode(ledPin[5], OUTPUT);
  pinMode(pinTime0, OUTPUT);
  pinMode(trigPin, OUTPUT);
  lastMicros = micros();  // sync loop timer

void loop() {
  // put your main code here, to run repeatedly:
  sonar();  // main function
  // main loop delay is interval = 10 ms
  digitalWrite(pinTime0, LOW);
  while (micros() - lastMicros < interval) {
    // do nothing
  } lastMicros = micros();
  // output pulse for scope trigger
  digitalWrite(pinTime0, HIGH);
  if (buzzCnt == 0) {digitalWrite(buzzPin, LOW);}  // turn buzzer off every 10 ms cycle

// ----------------------------------------------------------------------

void driveLedLevel(int zL) {
  // drive LEDs as a bar graph in range 0 to 6;
  if (zL >= 1) {digitalWrite(ledPin[0], HIGH);}
  else {digitalWrite(ledPin[0], LOW);}
  if (zL >= 2) {digitalWrite(ledPin[1], HIGH);}
  else {digitalWrite(ledPin[1], LOW);}
  if (zL >= 3) {digitalWrite(ledPin[2], HIGH);}
  else {digitalWrite(ledPin[2], LOW);}
  if (zL >= 4) {digitalWrite(ledPin[3], HIGH);}
  else {digitalWrite(ledPin[3], LOW);}
  if (zL >= 5) {digitalWrite(ledPin[4], HIGH);}
  else {digitalWrite(ledPin[4], LOW);}
  if (zL >= 6) {digitalWrite(ledPin[5], HIGH);}
  else {digitalWrite(ledPin[5], LOW);}

// ----------------------------------------------------------------------

void driveLedRow(int zL0, int zL1, int zL2, int zL3, int zL4, int zL5) {
  // drive all LEDs ON/OFF depending on pattern specified
  if (zL0 == 1) {digitalWrite(ledPin[0], HIGH);}
  else {digitalWrite(ledPin[0], LOW);}
  if (zL1 == 1) {digitalWrite(ledPin[1], HIGH);}
  else {digitalWrite(ledPin[1], LOW);}
  if (zL2 == 1) {digitalWrite(ledPin[2], HIGH);}
  else {digitalWrite(ledPin[2], LOW);}
  if (zL3 == 1) {digitalWrite(ledPin[3], HIGH);}
  else {digitalWrite(ledPin[3], LOW);}
  if (zL4 == 1) {digitalWrite(ledPin[4], HIGH);}
  else {digitalWrite(ledPin[4], LOW);}
  if (zL5 == 1) {digitalWrite(ledPin[5], HIGH);}
  else {digitalWrite(ledPin[5], LOW);}

// ----------------------------------------------------------------------

void flashBuzz() {
  // flash all LED's ON for 10 ms then OFF
  // buzzer sounds during flash period
  digitalWrite(buzzPin, HIGH);
  digitalWrite(buzzPin, LOW);

// ----------------------------------------------------------------------

void sonar() {
  if (buzzCnt >= buzzMax) {
    // turn the buzzer on for 10ms
    digitalWrite(buzzPin, HIGH);
    buzzCnt = 0;
  if (loopCnt >= 9) {
    // read the sensor every 100 ms
    loopCnt = 0;
    int zMax = 2000;
    if (duration <= 200) {duration = zMax;}
    if (duration >= zMax) {duration = zMax;}
    Serial.print("Echo = ");
    ledBarVal = (8 * (zMax-duration+100))/zMax;
    if (ledBarVal > 6) {ledBarVal = 6; buzzCnt = 1;}
    Serial.print("   Bar = ");
    Serial.print("   Distance = ");
    Serial.print(duration / 58.0, 1);
    buzzMax = 10 + ((6-ledBarVal) * 20);
    if (ledBarVal == 0) {buzzMax = 20000;}  // turn buzzer off if LEDs are off

// ----------------------------------------------------------------------

void runPOST() {
  // run a pattern through the LEDs to confirm they are workling
  for (int zC = 0; zC <20; zC++) {Serial.println("");}
  Serial.print("Starting POST routine...");
  int zDel = 500;
  for (int zL = 0; zL <3; zL++) {
    driveLedRow(1,1,1,1,1,1); delay(zDel);
    driveLedRow(0,0,0,0,0,0); delay(zDel);
  zDel = 100;
  for (int zL = 0; zL < 3; zL++) {
    driveLedRow(1,0,0,0,0,0); delay(zDel);
    driveLedRow(0,1,0,0,0,0); delay(zDel);
    driveLedRow(0,0,1,0,0,0); delay(zDel);
    driveLedRow(0,0,0,1,0,0); delay(zDel);
    driveLedRow(0,0,0,0,1,0); delay(zDel);
    driveLedRow(0,0,0,0,0,1); delay(zDel);
    driveLedRow(0,0,0,0,1,0); delay(zDel);
    driveLedRow(0,0,0,1,0,0); delay(zDel);
    driveLedRow(0,0,1,0,0,0); delay(zDel);
    driveLedRow(0,1,0,0,0,0); delay(zDel);
  driveLedRow(1,0,0,0,0,0); delay(zDel);
  Serial.println("Entering Mode ...");

// ----------------------------------------------------------------------

void trigSen() {
  // trigger the distance sensor and get a reading
  // The ultrasonic PING is triggered by a HIGH pulse of 2 or more microseconds.
  digitalWrite(trigPin, LOW);
  digitalWrite(trigPin, HIGH);
  digitalWrite(trigPin, LOW);
  // A high pulse of duration in microseconds from the sending
  // of the ping to the return of its echo from something.
  duration = pulseIn(echoPin, HIGH, echoMax);

// ----------------------------------------------------------------------




Need more?
If you feel that I haven’t included enough information to allow you to tackle a project of this type then send me an email explaining what you need. Or if you just want to give me some general feedback on this site, or to suggest projects what I might include which would be interesting to you, I’d be pleased to hear from you.