Working with TTL UART Sensor Devices

Sensors Insights by Derek Hildreth

Let's look at what's required to read data from a sensor over TTL UART interface and apply it to a simple application. Specifically, we’re going to be using the Maxbotix Ultrasonic Rangefinder (HRLV-MaxSonar EZ1 MB1013) connected to an enclosed TS-7553-V2 single board computer with LCD output.  The principles and most of the source code found here can also be applied generically to other sensors (even RS-232), single board computers, and applications, so enjoy!


Interfacing with a TTL UART Sensor

We start by busting open the enclosure and exposing the headers of the TS-7553-V2, so we can hookup our range sensor.  Referring to the wiring diagram below, you’ll see we only need three wires:  3.3 VDC (pin 19), ground (pin 3), and TTL UART signal (receive only, pin 10).  These all come off of HD1 pin header.

Figure 1

Referring to the HRLV-MaxSonar EZ1 MB1013 Datasheet, we see that the output options include serial, analog voltage, and pulse width.  We’re going to use serial, and even more specifically, we’re going to use TTL level serial, not RS-232.  This means, we need to set the PCB jumper on the bottom of the board with solder.

Figure 2

After we’ve made all the connections, we’re ready to fire up with TS-7553-V2 single board computer and start writing code.  For those of you who want immediate gratification, open a shell and type cat /dev/ttymxc6.  You’ll see a bunch of numbers flying by in your console.  These numbers are the distance in millimeters that the sensor is reporting.  Place your hand over the sensor and watch the values change.  Pretty neat, right?  Okay, moving onto C programming.

In the simplest form, here’s what our code looks like to read data in from the TTL sensor and converting it into something human readable.  You’re going to want to change the port name depending on your system.  For ours, we’re using /dev/ttymxc6.




#include <stdio.h>
#include <math.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

float read_port(void)
    int fd = 0; /* File descriptor for the port */
    char buffer[6];
    int rangeMm = 0;
    float rangeIn = 0;
    float rangeFt = 0;

    fd = open("/dev/ttymxc6", O_RDONLY | O_NOCTTY);
    if (fd == -1) {
        perror("open_port: Unable to open /dev/ttymxc6 - ");

    int n = read(fd, buffer, sizeof(buffer));

    if (n < 0) {
        fputs("read failed!\n", stderr);

    // Remove the initial "R" at the beginning
    memmove(buffer, buffer + 1, sizeof(buffer + 1) + 1);

    // Remove the newline character at the end of the string
    buffer[strcspn(buffer, "\n")] = 0;

    rangeMm = atoi(buffer);
    rangeIn = rangeMm / 25.4;
    rangeFt = rangeIn / 12;

    printf("%d mm, %.1f in, %.1f ft\n", rangeMm, rangeIn, rangeFt);

    memset(buffer, 0, sizeof(buffer));


int main(void)

    int r = 1;
    while(r) {

        r = read_port();


    return r;


After compiling with gcc test-ttl.c -o test-ttl, you should be able to run it with sudo ./test-ttl.  You should see output similar to this (press Ctrl + C to stop):


debian@ts-imx6ul:~/test-ttl$ sudo ./test-ttl

1458 mm, 57.4 in, 4.8 ft

1582 mm, 62.3 in, 5.2 ft

1581 mm, 62.2 in, 5.2 ft

1581 mm, 62.2 in, 5.2 ft

1581 mm, 62.2 in, 5.2 ft

361 mm, 14.2 in, 1.2 ft

340 mm, 13.4 in, 1.1 ft

300 mm, 11.8 in, 1.0 ft

1487 mm, 58.5 in, 4.9 ft

1492 mm, 58.7 in, 4.9 ft

1588 mm, 62.5 in, 5.2 ft




If everything has gone smoothly, you deserve a pat on the back because you’ve successfully interfaced a single board computer to a TTL sensor!


Example Application - Garage Parking Assistant

When thinking of applications for using a range sensor, one of the first things that came to mind was to use it as a garage parking assistant.  This way, we can finally ditch that dangling tennis ball acting as stop marker!  Instead, we’ll display simple instructions on the LCD screen along with the distance data from the sensor.  We’ll also add some stoplight-esque LEDs for dead simple and intuitive instructions to go, slow down, and stop.


Breadboard Prototype and Testing

Now, let’s build upon the previous section and bring in the LCD screen of the TS-7553-V2 as well as status LEDs.  Here’s what we’re looking at doing (LCD display not shown):

Figure 3

The LEDs are going to be connected to the same GPIO pins that the enclosure keypad is connected to.  So, we're actually going to disconnect the keypad and not use it in this project.  This also means we need to blacklist the gpio_keys kernel module so that we can configure them as outputs in our program (otherwise, we get a permission denied error when trying to export the GPIO pins).  So, use this command to blacklist it:


sudo echo “blacklist gpio_keys” > /etc/modprobe.d/fbdev-blacklist.conf


We’re going to use the Technologic Systems’ provided lcd-display.h library as well as the sysfs gpio library, and finally the cairo/cairo.h graphics library.  Since this becomes slightly more complicated to compile, we’re also going to introduce a Makefile that will make things easier.  So, let’s head to the code repository and review the code.  Come back after you’ve made the jump to the embeddedarm/park-ranger repository and reviewed.

Once you’re ready, clone the repository, change into the project directory, install required cairo library, and then compile and install using the commands (using root or sudo):


git clone

cd park-ranger

apt-get update; apt-get install libcairo2-dev

make && make install


Once you’ve finished here, you should now have a program called park-ranger installed in /usr/local/bin/.  There are just a couple more steps we need to take in order to activate and turn on the LCD screen, so run these commands:


modprobe ts-st7565p-fb



Now, we run it using park-ranger.  You should be seeing some output on both the console and on the LCD screen.  Wave your hand in front of the sensor and see what happens with the green, yellow, and red LEDs and on-screen instructions.

Figure 4


Starting Automatically

Inevitably, we’re going to want our application to startup when the system boots.  So, let’s use the provided park-ranger.service file for startup via systemd.  Install it and then enable it using the commands:


cp park-ranger.service /etc/systemd/system/

systemctl enable park-ranger.service


You can manually kick off the program now using the command:


systemctl start park-ranger.service


End Product Build and Install

Okay, so moving away from the breadboard stage and onto something we can install and use in our garage. I took a piece of ½” oak hobby board and made it into a nice little wall-mountable package that I could mount the TS-7553-V2, LEDs, and range sensor onto.

Figure 5

I chiseled out some spots for the wiring to go and drilled necessary holes for mounting the enclosure, LEDs, and range finder.  A few rubber feet on the back keeps it from wiggling around too much.


Figure 6

Inside the enclosure, I soldered all the wires onto the bottom of the header pins of the TS-7553-V2.  If I were to do it professionally, I would use some IDC socket header connectors, but since this is just a quick and fun project for home, I’m willing to overlook that detail.  Everything was soldered down to a protoboard and then covered in hot glue to secure and protect components (which, in hindsight, was excessive and I wouldn’t do it again).

Finally, I mounted it to the wall and gave it a first test run.  After figuring out what the proper distance was by finding the perfect parking spot and reading the distance on the screen, I modified the code and mounted it for the last time.  Here it is in action:

And, that’s it!  A simple, real-world application for using our TTL UART sensor.


Further Improvements

Here’s a list of things I would do to improve the garage parking assistant:

  • Auto wake for power savings
    • The sensor could be the only thing active, looking for a change in the distance reading, and then turn everything on to help park, and then turn everything off again after some defined time.  A PIR sensor might be the thing to use here.
  • Separate sensor location
    • Placing the sensor in line with the bumper of the vehicle would provide more accurate and solid readings.
  • Use keypad to program distance/fine-tune
    • Perhaps the LEDs could be controlled by another IC using I2C in order to free up the keypad gpio pins again.  Then, we wouldn’t need to hardcode the distance into the C code and recompile.
  • Use inches instead of feet
    • While we could still display the distance in feet, we should be using millimeters or inches in our if else block for better accuracy.
  • Test other range sensors
    • The HRLV-MaxSonar sensor comes in all sorts of varieties with different sensing patterns for different applications.  Test a few and see which works the best.



In reading this article, you should have come away with a bunch of information on how to interface with an TTL UART (or RS-232) sensor device and apply it to a real-world application and feel comfortable in applying these development principles to your own sensor for your project.  Now, go build something amazing and report back to me!




About the author

Derek Hildreth has been working for Technologic Systems in various capacities since 2010, starting as an intern embedded engineer.