Ultrasonic distance sensors

In the lab we have ultrasonic sensors available that measure distance using the time of flight of sound.

These sensors use two pins to communicate, a trigger pin and an echo pin.

A measurement is started by a falling edge on the trigger pin, which triggers the sending of an ultrasonic pulse.

After sending the pulse the echo pin will be high until an echo is received.

The distance to an obstacle can then be calculated from the duration of the echo pulse and the speed of sound in air.

         5V ────┐   ┌────────────────────────────
Trigger         │   │
         0V     └───┘

         5V        ┌────────────────┐
Echo               │                │
         0V ───────┘                └────────────

To connect the 5V ultrasonic sensor to the 3.3V microcontroller we need basic level shifting.

The following connections need to be made:

  • Sensor GND to microcontroller GND
  • Sensor VCC to microcontroller 5V
  • Sensor TRIG to microcontroller D6

And one of the following to convert voltage levels:

  • Voltage divider

             ┌──────┐   D5     ┌──────┐
     ECHO ───┤ 10kΩ ├────┴─────┤ 15kΩ ├─── GND
             └──────┘          └──────┘
    
  • Diode

            C   A
     ECHO ───┤⯇├── D5
    

The code snipped below contains a function that, when called, performs a single distance measurement and calls the function passed as the db_done when the measurement is done.

A single argument is passed to the function:

  • nil if no echo was received
  • A number giving the measured distance in meters
function measure_distance(cb_done)
    local timeout = tmr.create()
    local echo_start = nil

    function on_timeout(t)
        -- Stop waiting for an interrupt and
        -- report failure
        gpio.trig(5)
        cb_done(nil)
    end

    function on_echo(level, when, evcount)
        -- Measure the time between the pin going high
        -- and going low to calculate time of flight
        if level == gpio.HIGH then
            echo_start= when
        else
            timeout:unregister()
            gpio.trig(5)

            local tof = when - echo_start
            local distance = tof / 2 * 343e-6

            cb_done(distance)
        end
    end

    -- When the echo ouput does not change
    -- for 200ms no echo was detected
    timeout:alarm(210, tmr.ALARM_SINGLE, on_timeout)

    -- Pin 5 is connected to the echo pin setup
    -- interrupts to measure the length of the pulse
    gpio.mode(5, gpio.INT, gpio.PULLUP)
    gpio.trig(5, "both", on_echo)

    gpio.mode(6, gpio.OUTPUT)
    -- Trigger a measurement by pulsing
    -- pin 6 high and then low for 20us
    gpio.serout(6, gpio.HIGH, {20, 20}, 1, 0)
end

Task: Call the function once a second and print the measured distance

TODO: Actually test this with the required voltage divider resistors/diodes