Use DYP-A01 ultrasonic distance sensor in Elixir
Tags: elixir, nerves, ultrasonic, raspberrypi
Published: 2021-09-01 12:42:13

[にほんご](https://qiita.com/mnishiguchi/items/dd2fbf53a8b32b0984fb)

The other day I played with [DYP-A01 ultrasonic distance sensor](https://www.adafruit.com/product/4664) on my [Nerves](https://www.nerves-project.org/)-powered [Raspberry Pi](https://www.raspberrypi.org/). Here is my note.

[![](https://cdn-shop.adafruit.com/1200x900/4664-03.jpg)](https://www.adafruit.com/product/4664)

## 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](https://www.nerves-project.org/) 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](https://elixir-slackin.herokuapp.com/) when I got stuck. People are nice and kind in the community.

- [Nerves documentation](https://hexdocs.pm/nerves/getting-started.html)
- [Nerves • Elixir School](https://elixirschool.com/en/lessons/specifics/nerves/)

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

- [Nerves Livebook firmware](https://github.com/fhunleth/nerves_livebook)
- [Nerves example firmware collection](https://github.com/nerves-project/nerves_examples)

In the following YouTube videos, [Frank Hunleth](https://twitter.com/fhunleth?lang=en), a co-author of the Nerves Project, talks about Nerves for beginners.

- [Elixir in Embedded Systems using Nerves Livebook](https://youtu.be/P_xryjmG35I) (YouTube)
- [Elixir Wizards Live: Frank and the Wizards](https://youtu.be/qp56tIEnYH4) (YouTube)

## Hardware used

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

|                                                                                |                                                                                                                     |
| ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| [DYP-A01 ultrasonic distance sensor](https://www.adafruit.com/product/4664)    | ![](https://cdn-shop.adafruit.com/970x728/4664-04.jpg)                                                              |
| [USB to TTL Serial Cable](https://www.adafruit.com/product/954)                | ![](https://cdn-shop.adafruit.com/970x728/954-02.jpg)                                                               |
| [Jumper wires](https://www.google.com/search?q=jumper+wires&tbm=isch)          | ![](https://cdn-shop.adafruit.com/970x728/1956-02.jpg)                                                              |
| [Raspberry Pi 4](https://www.raspberrypi.org/products/raspberry-pi-4-model-b/) | ![](https://www.raspberrypi.org/homepage-9df4b/static/raspberry-pi-4-labelled-2857741801afdf1cabeaa58325e07b58.png) |
| [Raspberry Pi Zero W (with Headers)](https://www.sparkfun.com/products/15470)  | ![](https://cdn.sparkfun.com//assets/parts/1/4/0/5/9/15470-Raspberry_Pi_Zero_WH-01.jpg)                             |

## 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](https://www.adafruit.com/product/4664).

> 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.

![](https://cdn-shop.adafruit.com/970x728/954-02.jpg)

![20210831_173325](https://user-images.githubusercontent.com/7563926/131585666-806f64b5-4f76-49e0-875d-9f12a48427c0.jpg)
![20210831_173120](https://user-images.githubusercontent.com/7563926/131585661-4fdbd79a-7b2a-4bd1-87f6-024e6119f01a.jpg)

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](https://cdn-shop.adafruit.com/product-files/4664/4664_datasheet.pdf).

| DYP-A01               | USB to TTL Serial Cable |
| --------------------- | ----------------------- |
| Red (3.3-5V)          | Red (5V)                |
| Black (Ground)        | Black (Ground)          |
| 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                 |
| White (TX / Transmit) | GPIO 15 (RX / Receive) |

[Raspberry Pi pinout](https://pinout.xyz/pinout/uart)

## Elixir program

I package the necessary code as Elixir library [dypa01](https://hex.pm/packages/dypa01). It can be installed by adding `dypa01` to your list of dependencies in your firmware's `mix.exs` file:

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

## Find serial port name

First shell into your Nerves-powered Raspberry Pi.

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

```elixir
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`.

```elixir
iex> 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.

```elixir
# 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}}
```