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.
- Elixir in Embedded Systems using Nerves Livebook (YouTube)
- Elixir Wizards Live: Frank and the Wizards (YouTube)
Hardware used
Here is a list of what I used in my experiment.
- DYP-A01 ultrasonic distance sensor
- USB to TTL Serial Cable
- Jumper wires
- Raspberry Pi 4
- Raspberry Pi Zero W (with Headers)
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.
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-A01 | USB 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-A01 | Raspberry Pi |
Red (3.3-5V) | 5V |
Black (Ground) | Ground |
Orange (RX / receive) | - |
White (TX / Transmit) | GPIO 15 (RX / Receive) |
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}}