3. MiniBit distance sensor
3.1. HC_SR04P
Output a 10µs (µs = microsecond) High signal to Trigger input to start the detection.
Measure the length of pulse received on Echo output to determine distance
Distance is pulse time * speed of sound / 2
The speed of sound is about 343m/s or 34300cm/s or 0.0343 cm/µs (centimeter per microsecond).
Note
µs
.µ
, which represents 1/1000000, one millionth.utime
library us
is used instead of µs
.Warning
Some objects might not be detected by ultrasonic sensors:
Some objects are shaped or positioned in such a way that the sound wave bounces off the object away from the Ultrasonic sensor.
Some objects are too small to reflect enough of the sound wave back to the sensor to be detected.
Some objects can absorb the sound wave all together (cloth, carpet).
3.2. Ultrasound timing
3.3. Trigger pulse
write_digital(1)
, for 10us, then it is set low, write_digital(0)
.utime.sleep_us(10)
.DSP = pin15
, in CAPITALS, can be used to set the pin to be used by the sensor.import utime
DSP = pin15
DSP.write_digital(1)
utime.sleep_us(10)
DSP.write_digital(0)
Once the wave is returned, after being reflected by an object, the Echo pin goes high for a particular amount of time which will be equal to the time taken for the wave to return back to the sensor.
The first step is to record the last low timestamp for Echo (pulse_start
) e.g. just before the return signal is received and the pin goes high. A while loop is used to repetitively update the pulse_start time, while read_digital() == 0
, until the read_digital() value is no longer 0. This gives the pulse_start time for when read_digital() changes to 1.
while DSP.read_digital() == 0:
pulse_start = utime.ticks_us()
Once a signal is received, the value changes from low (0) to high (1), and the signal will remain high for the duration of the Echo pulse. Then it will go low again.
The second step is to record the last high timestamp for Echo (pulse_end). e.g. just before the return signal is received and the pin goes low. A while loop is used to repetitively update the pulse_end time, while read_digital() == 1
, until the read_digital() value is no longer 1. This gives the pulse_end time for when read_digital() changes to 0.
while DSP.read_digital() == 1:
pulse_end = utime.ticks_us()
The duration of the pulse is then calculated using pulse_duration = pulse_end - pulse_start
.
Since the distance to the object is half of the distance traveled by the pulse to and back from the object, the distance can be calculated using distance = speed x time / 2. The speed is 0.0343 cm/µs. 0.01715 is used instead since 0.0343 / 2 = 0.01715.
pulse_duration = pulse_end - pulse_start
distance = int(0.01715 * pulse_duration)
3.4. Distance to an object
- distance()
Returns the distance, in cm, to an object.
distance
, returns the distance to an object, in cm.from microbit import *
import utime
DSP = pin15
def distance():
DSP.write_digital(1) # Send 10us Ping pulse
utime.sleep_us(10)
DSP.write_digital(0)
while DSP.read_digital() == 0: # ensure Ping pulse has cleared
pulse_start = utime.ticks_us()
while DSP.read_digital() == 1: # wait for Echo pulse to return
pulse_end = utime.ticks_us()
try:
pulse_duration = pulse_end - pulse_start
except ValueError:
pulse_duration = 0
else:
pulse_duration = 0
distance = int(0.01715 * pulse_duration)
return distance
while True:
d = distance()
display.scroll(d, delay=60)
sleep(1000)
distance() < 50
, measures the distance to objects and if the distance is less than 50cm it spins the buggy to the right for 0.1 second and checks again.from microbit import *
import utime
LMF = pin12
LMB = pin8
RMF = pin16
RMB = pin14
DSP = pin15
def distance():
DSP.write_digital(1) # Send 10us Ping pulse
utime.sleep_us(10)
DSP.write_digital(0)
while DSP.read_digital() == 0: # ensure Ping pulse has cleared
pulse_start = utime.ticks_us()
while DSP.read_digital() == 1: # wait for Echo pulse to return
pulse_end = utime.ticks_us()
try:
pulse_duration = pulse_end - pulse_start
except NameError:
pulse_duration = 0
except:
pulse_duration = 0
else:
pulse_duration = pulse_end - pulse_start
distance = int(0.01715 * pulse_duration)
return distance
def scale(from_value, from_min, from_max, to_min, to_max):
return int(((from_value - from_min) / (from_max - from_min)) * (to_max - to_min) + to_min)
def speed_scaled(speed=2):
return scale(speed, 0, 10, 0, 1023)
def stop():
LMF.write_digital(0)
LMB.write_digital(0)
RMF.write_digital(0)
RMB.write_digital(0)
def forwards(speed=2, duration=None):
analog_speed = speed_scaled(speed)
LMF.write_analog(analog_speed)
LMB.write_digital(0)
RMF.write_analog(analog_speed)
RMB.write_digital(0)
def backwards(speed=2, duration=None):
analog_speed = speed_scaled(speed)
LMF.write_digital(0)
LMB.write_analog(analog_speed)
RMF.write_digital(0)
RMB.write_analog(analog_speed)
def spin_right(speed=2, duration=None):
analog_speed = speed_scaled(speed)
LMF.write_analog(analog_speed)
LMB.write_digital(0)
RMF.write_digital(0)
RMB.write_analog(analog_speed)
while True:
forwards(speed=2, duration=100)
# check for obstacle and spin
d = distance()
# display.scroll(d, delay=40)
if d < 50:
while d < 50:
spin_right(speed=2, duration=100)
d = distance()
# display.scroll(d, delay=40)
Tasks
Write code to drive the buggy forwards until it measures an object 30cm in front and then stops.
Write code to drive the buggy forwards until it measures an object 20cm in front and then it stops for 500ms, goes backwards for 500ms, then spins until no object is detected within 20cm, then goes forwards and repeats.