Use DYP-A01 ultrasonic distance sensor in Elixir

The other day I played with DYP-A01 ultrasonic distance sensor on my Nerves-powered Raspberry Pi. Here is my note.

Long story short

  • I wrote an Elixir program that enables us to communicate with an ultrasonic sensor through serial ports on Raspberry Pi.
  • I was able to measure distance connecting an ultrasonic sensor to:
    • UART Rx pin on Raspberry Pi Zero
    • UART Rx pin on Raspberry Pi 4
    • USB port on Raspberry Pi 4

Nerves firmware

I use Nerves to build firmware for my Raspberry Pi.

I am not going to talk about Nerves firmware here, it is a platform for building firmware in Elixir programming language. There are good resources out there.

I personally started Nerves by reading Nerves official documentation. Then I asked questions on #nerves channel in Elixir Slack when I got stuck. People are nice and kind in the community.

Here are some example firmware projects that you can do experiment with.

In the following YouTube videos, Frank Hunleth, a co-author of the Nerves Project, talks about Nerves for beginners.

Hardware used

Here is a list of what I used in my experiment.

Wiring

Wiring can be done through either USB or GPIO pins.

USB

I purchased DYP-A01 ultrasonic distance sensor and USB to TTL Serial Cable based on what I read in Adafruit's catalog.

This sensor has UART output, so it can connect to a microcontroller or microcomputer with a TTL serial port. You can also connect it to a computer using a USB-to-serial adapter and read data from the operating system's COM or serial port device.

At first I had no idea how I am supposed to connect them together. While the USB cable has four wires coming our of it, at the end of the sensor's cable is one connector. After a while, I learned that I could use jumper wires to connect them.

20210831_173325 20210831_173120

In my case, thankfully the wires are nicely color-coded, which makes the wiring easy. For this particular sensor, one wire is unneeded because we transmit no signal from our Raspberry Pi to the sensor. We just receive the signals that is sent periodically from the sensor, which is called "UART auto output" in the sensor's data sheet.

DYP-A01USB to TTL Serial Cable
Red (3.3-5V)Red (5V)
Black (Ground)Black (Ground)
Orange (RX / receive)-
White (TX / Transmit)White (RX / receive)

GPIO pins

Alternatively we can connect the sensor through GPIO pins on Raspberry Pi.

DYP-A01Raspberry Pi
Red (3.3-5V)5V
Black (Ground)Ground
Orange (RX / receive)-
White (TX / Transmit)GPIO 15 (RX / Receive)

Raspberry Pi pinout

Elixir program

I package the necessary code as Elixir library dypa01. It can be installed by adding dypa01 to your list of dependencies in your firmware's mix.exs file:

def deps do
  [
    {:dypa01, "~> 0.1"}
  ]
end

Alternatively Mix.install/2 at runtime in IEx:

❯ iex

iex> Mix.install([{:dypa01, "~> 0.1"}])

Find serial port name

First shell into your Nerves-powered Raspberry Pi.

You can list all serial ports that are currently attached by running:

iex> Circuits.UART.enumerate
%{
  "ttyAMA0" => %{},
  "ttyS0" => %{},
  "ttyUSB0" => %{
    description: "CP2102 USB to UART Bridge Controller",
    manufacturer: "Silicon Labs",
    product_id: 60000,
    serial_number: "0001",
    vendor_id: 4292
  }
}

You can find the default Nerves serial port for UART in /boot/config.txt.

cmd "cat /boot/config.txt | grep tty"
# Enable the UART (/dev/ttyS0)
0

In my case, I found out that my Rasperry Pi Zero uses ttyAMA0 and my Rasperry Pi 4 uses ttyS0 for UART.

Measure distance

Once the serial port name is found, it is easy to read distance data from the ultrasonic distance sensor.

# Start a gen server for interacting with a DYP-A01 sensor on port ttyAMA0
iex> {:ok, pid} = DYPA01.start_link(port_name: "ttyAMA0")
{:ok, #PID<0.1407.0>}

# Measure the current distance
iex> DYPA01.measure(pid)
{:ok, %DYPA01.Measurement{distance_mm: 1680, timestamp_ms: 321793}}