Module 6. Ultrasonic Range Sensing

Theory

 The HC-SR04 is an inexpensive distance sensor that is easy to work with. It uses two ultrasonic transducers, one acting as a speaker and one serving as a microphone. The left transducer (acting as a speaker) emits a series of high-frequency sound pulses that travels through the air. When they hit a solid surface, these pulses are reflected back towards the module. The right transducer (acting as a microphone) registers this echo. The time required for the sound to make the trip away and back is used to determine how far the sound has traveled, and thus the distance to the obstacle.

Sensor Module

The ultrasonic sensor module makes it easy to get distance data by abstracting out a lot of the work associated with actuating the speaker and recognizing the echoes.

It has a 4 pin interface:

  1. Vcc is power. It is connected to 5V.
  2. GND is ground. It is connected to a ground pin of the microcontroller.
  3. TRIG is the trigger pin. It is connected to a digital pin of the microcontroller.
  4. ECHO is the echo pin. It is also connected to a digital pin of the microcontroller.

In our case, we will connect TRIG and ECHO to the same pin, as this will enable us to use a convenient function in the Arduino-Python library called pulseIn_set .

Getting a distance measurement from the module works like this:

  • When you want to make a distance measurement, send a quick pulse to the sensor on the trigger line.
  • The ultrasonic module will use the speaker to send out a sound-pulse and wait for an echo to come back.
  • When the module detects an echo, it sends a pulse to the microcontroller over the ECHO wire.
  • The time difference between when the trigger pulse was transmitted and when the echo pulse returned can be used to determine how far the sound has traveled (distance = speed * time).

Code

Get Distance Measurements

In your code, you will need to keep track of how long it has taken from the trigger pulse was sent to the echo returns. We could write this functionality manually, but it is easier and more accurate to use a library function called pulseIn_set .

pulseIn_set Function Specification

inputs:

  • pin : pin number for pulse measurement.
  • val : “HIGH” or “LOW”. Pulse is measured when this state is detected.
  • numTrials : number of trials used for average. Default value is 5.

returns:

  • duration : an average of pulse length measurements.

pulseIn_set Operation

This function works as follows:

  1. Set pin to the OUTPUT
  2. Set pin to the opposite logic level of val and wait a little.
  3. Set pin to the logic level of val . For the ultrasonic sensor, this will trigger a distance
  4. Start a
  5. Set pin to the INPUT
  6. When the logic level of pin is pulled to LOW by the ultrasonic sensor, stop the
  7. Repeat steps 1 to 6 numTrials times (if no number specified, use repeat five times).
  8. Average the time from all the numTrials distance measurements, and return this

That is quite a lot going on!

Code

You now know all you need to start writing code to interface with the ultrasonic sensor. It can look something like this:

from Arduino import Arduino 
import time
PIN_SENSE = 12 # pin where ultrasonic sensor is connected
# connect to Arduino - you may need to specify the data rate and PORT_NAME as per module 5, i.e.
PORT_NAME = 'COM3'                   # example of Windows port name 
#PORT_NAME = '/dev/tty.usbserial-1420' # example of Mac port name
board = Arduino('9600', port=PORT_NAME)
print('Connected')

try:

while True:
     # make distance measurement
     pulseTime = board.pulseIn_set(PIN_SENSE, 'HIGH') 
     print(pulseTime)
     time.sleep(1) # delay to keep UART bus for getting overloaded
except KeyboardInterrupt:
     board.close() # close serial connection

By running this program, you should see numbers print to your console in rapid succession.

  • Observe how the numbers change when you point the ultrasonic sensor in different directions.

Calibrating for Distance Measurement

By using a ruler, you can manually determine how far the sound has traveled.

Find a scaling factor that makes the value printed by the Arduino correspond to the distance to an obstacle (and not the time it took the sound to travel out and back as it currently is doing).

Hint: how different is the constant of proportionality you get from this?

Writing to a file

You can use the csv library to write data to a file. This can be very useful for data analysis and will be used in the next module where you use the ultrasonic range finder for conducting an experiment.

from Arduino import Arduino

import time
import csv # new, for writing to file
FILE_NAME = 'pendulum_data.csv' # name of file that data will be written to 
PIN_SENSE = 12                  # pin where ultrasonic sensor is connected
# connect to Arduino 
from Arduino import Arduino
PORT_NAME = 'COM3'                   # example of Windows port name 
#PORT_NAME = '/dev/tty.usbserial-1420' # example of Mac port name 
board = Arduino('9600',port=PORT_NAME) # find and connect microcontroller 
print('Connected')
f = open(FILE_NAME,'a')              # open a file for 'a'ppending 
writer = csv.writer(f,delimiter=',') # prepare for writing to file

# Write data-field titles to file 
writer.writerow(['Time (s)', 'Distance (cm)'])
startTime = time.time() # capture current time as datum

try:

     while True:
          # make distance measurement
          pulseTime = board.pulseIn_set(PIN_SENSE, 'HIGH') 
          distance = pulseTime * 0.034 / 2; # in cm

          # write list of data to file 
          currentTime = time.time()-startTime data = [currentTime, distance]
          writer.writerow(data) # write data to file print('time = %5.2f   distance = %5.1f' % tuple(data))
   
          time.sleep(1) # delay to keep UART bus for getting overloaded

     # press ctrl+c while the console is active to terminate the program 
     except KeyboardInterrupt:
          board.close() # close serial connection
          f.close()     # close file gracefully when program is terminated

Exercises

  • How fast can you get the sensor to measure data? By reducing the delay too much, you may find that the sensor stops working. You can observe the TX and RX LEDs on the Nano to see the UART activity.
  • Make the program print the values to the screen only occasionally.
  • Add the LED, and set up a circuit that lights up whenever the sensor finds something that is getting too close.

Modules

  1. Buying Parts
  2. Preparing the Arduino
  3. Setting up Python on your PC
  4. Learning Python
  5. Arduino for Data Collection
  6. Ultrasonic Range Sensing
  7. Pendulum Experiment

 

Updated 2020-05-19  CEW

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Sensor Module

 

The ultrasonic sensor module makes it easy to get distance data by abstracting out a lot of the work associated with actuating the speaker and recognizing the echoes.

 

It has a 4 pin interface:

 

PWR is power. It is connected to 5V.

GND is ground. It is connected to a ground pin of the microcontroller.

TRIG is the trigger pin. It is connected to a digital pin of the microcontroller. ECHO is the echo pin. It is connected to a digital pin of the microcontroller.

In our case, we will connect TRIG and ECHO to the same pin, as this will enable us to use a convenient function in the Arduino-Python library called pulseIn_set .

 

Getting a distance measurement from the module works like this:

 

When you want to make a distance measurement, send a quick pulse to the sensor on the trigger line. The ultrasonic module will use the speaker to send out a sound-pulse and wait for an echo to come back. When the module detects an echo, it sends a pulse to the microcontroller over the ECHO wire.

The time difference between when the trigger pulse was transmitted and when the echo pulse returned can be used to determine how far the sound has traveled (distance = speed * time).

 

 

Code

Get Distance Measurements

 

In your code, you will need to keep track of how long it has taken from the trigger pulse was sent to the echo returns. We could write this functionality manually, but it is easier and more accurate to use a library function called pulseIn_set .

 

pulseIn_set Function Specification

 

inputs:

pin : pin number for pulse measurement.

val : “HIGH” or “LOW”. Pulse is measured when this state is detected.

numTrials : number of trials used for average. Default value is 5. returns:

duration : an average of pulse length measurements.

 

pulseIn_set Operation

 

This function works as follows:

 

  1. Set pin to the OUTPUT
  2. Set pin to the opposite logic level of val and wait a little.
  3. Set pin to the logic level of val . For the ultrasonic sensor, this will trigger a distance
  4. Start a
  5. Set pin to the INPUT
  6. When the logic level of pin is pulled to LOW by the ultrasonic sensor, stop the
  7. Repeat steps 1 to 6 numTrials times (if no number specified, use repeat five times).
  8. Average the time from all the numTrials distance measurements, and return this

 

That is quite a lot going on!

 

Code

 

You now know all you need to start writing code to interface with the ultrasonic sensor. It can look something like this:

 

 

from Arduino import Arduino import time

 

PIN_SENSE = 12 # pin where ultrasonic sensor is connected

 

# connect to Arduino board = Arduino() print(‘Connected’)

 

 

try:

 

while True:

# make distance measurement

pulseTime = board.pulseIn_set(PIN_SENSE, ‘HIGH’) print(pulseTime)

 

time.sleep(1) # delay to keep UART bus for getting overloaded

 

 

except KeyboardInterrupt:

board.close() # close serial connection

 

 

By running this program, you should see numbers print to your console in rapid succession.

 

Observe how the numbers change when you point the ultrasonic sensor in different directions.

 

 

Calibrating for Distance Measurement

 

By using a ruler, you can manually determine how far the sound has traveled.

Find a scaling factor that makes the value printed by the Arduino correspond to the distance to an obstacle (and not the time it took the sound to travel out and back as it currently is doing).

 

Hint: how different is the constant of proportionality you get from this?

 

Writing to file

 

You can use the csv library to write data to a file. This can be very useful for data analysis and will be used in the next module where you use the ultrasonic range finder for conducting an experiment.

 

from Arduino import Arduino import time

import csv # new, for writing to file

 

FILE_NAME = ‘pendulum_data.csv’ # name of file that data will be written to PIN_SENSE = 12                  # pin where ultrasic sensor is connected

 

# connect to Arduino board = Arduino() print(‘Connected’)

 

f = open(FILE_NAME,’a’)              # open a file for ‘a’ppending writer = csv.writer(f,delimiter=’,’) # prepare for writing to file

 

# Write data-field titles to file writer.writerow([‘Time (s)’, ‘Distance (cm)’])

 

startTime = time.time() # capture current time as datum

 

 

try:

 

while True:

# make distance measurement

pulseTime = board.pulseIn_set(PIN_SENSE, ‘HIGH’) distance = pulseTime * 0.034 / 2; # in cm

 

# write list of data to file currentTime = time.time()-startTime data = [currentTime, distance]

 

writer.writerow(data) # write data to file print(‘time = %5.2f                      distance = %5.1f’ % tuple(data))

 

time.sleep(1) # delay to keep UART bus for getting overloaded

 

 

# press ctrl+c while the console is active to terminate the program except KeyboardInterrupt:

board.close() # close serial connection

f.close()     # close file gracefully when program is terminated

 

 

 

Exercises

 

How fast can you get the sensor to measure data? By reducing the delay too much, you may find that the sensor stops working. You can observe the TX and RX LEDs on the Nano to see the UART activity.

Make the program print the values to the screen only occasionally.

Add the LED, and set up a circuit that lights up whenever the sensor finds something that is getting too close.

 

Next: Module 4: Pendulum Experiment

 

7. Pendulum Experiment

This module is an experiment where we use the ultrasonic distance sensor to collect data from a pendulum undergoing damped simple harmonic motion.

 

Experimental setup and procedure

 

The setup for this experiment requires a few parts. The most important thing is that the pendulum is aimed squarely at the large, flat surface on the pendulum at all times during the oscillations. This means it is important that you do not make the amplitude of the oscillations too large.

 

Equipment

 

Cardboard String

Hole-punch Mass

Stand for suspending the pendulum Box or similar for the sensor to sit on

 

Setup

 

  1. Cut out a rectangle in cardboard that is about 5 cm by 10
  2. Use a hole-punch to make three holes in it. Two holes are in the upper left and right corner for attaching the string, and one is at the bottom center for suspending the
  3. Tie a string through the top
  4. Hang the string on the stand so that it will not
  5. Position the ultrasonic sensor so that it points directly at the cardboard cutout as the pendulum

 

Code

Use the code you developed during the last module to measure the distance and print it to a file. The code below can also be used as a starting point, including a fairly accurate time to distance calibration.

 

from Arduino import Arduino import time

import csv

 

FILE_NAME = ‘pendulum_data.csv’       # name of file that data will be written to PIN_SENSE = 12                                    # pin where ultrasic sensor is connected

 

# connect to Arduino board = Arduino() print(‘Connected’)

 

f = open(FILE_NAME,’a’)                           # open a file for ‘a’ppending writer = csv.writer(f, delimiter=’,’, newline=”) # prepare for writing to file

 

# Write data-field titles to file writer.writerow([‘Counter’, ‘Time (s)’, ‘Distance (cm)’])

 

counter = 0             # to count how many data-points we have collected startTime = time.time() # capture current time as datum

 

 

try:

 

while True:

counter = counter + 1 # increment counter

 

# make distance measurement

pulseTime = board.pulseIn_set(PIN_SENSE, ‘HIGH’, 1) distance = pulseTime * 0.034 / 2; # in cm

 

# write list of data to file

writer.writerow([counter, time.time()-startTime, distance])

 

# print to console every 10 iterations. % is modulo operator if counter % 10 == 0:

print(distance)

 

time.sleep(0.01) # delay to keep UART bus for getting overloaded

 

# press ctrl+c while the console is active to terminate the program except:

board.close()   # close board connection

f.close()       # close file gracefully when program is terminated

 

 

 

Procedure

 

  1. Excite the pendulum so that it starts oscillating. Make sure it moves about 10 cm away from the equilibrium position in either direction.
  2. Start the Python program to collect data.
  3. Wait for the oscillations to die down before stopping data-collection. 20 seconds of data will be more than enough, but you can collect for longer if you want to.
  4. Change the name of the file that data is being printed to if you are going to redo the experiment. This makes it easy to see which data-points corresponds to which runs of the

 

Data Analysis

 

For analyzing the data, we can continue using Spyder to write and run code. Another tool designed explicitly for this type of work is known as Jupyter Notebook .

 

You can install and launch Jupyter from the Anaconda Navigator in the same way you have been using Spyder.

 

The following instructions have been written using a Jupyter notebook that you can open and copy code from, or that you can download and use as a starting point for your work.

 

Data Analysis in Jupyter Notebooks

 

Google is your friend. As a starting point, you can take a look at these links:

 

how to download a files from GitHub how to use Jupyter

Leave a Reply