Reading data from a DXL360 digital level onto your computer

There are some digital levels on the market that are really nice tools to have for a variety of purposes. I grabbed a DXL360 and am really happy with it so far. When I wanted to do an angle vs. time calibration measurement of my Barn Door Startracker over 10s of minutes, I really wanted to get the data from the level into a computer so I could plot and process it a bit.

The level has a USB port but the manual suggests that an optional attachment is required to get it into a computer, at least for this model. However, the manual also states that data comes out of it in RS232 format. I bet I could read that data with some more generic equipment that I have sitting around. And it turned out to be easy. This post shows how I did it.

First, I cut a USB cable in half to tap into the level. As a check, I hooked the data lines up to my oscilloscope. I was greeted with a binary bitstream that changed pleasantly as I rotated the level. Looks promising.

Next, I just plugged the data cables into my extraordinarily useful Adafruit FT232H breakout board, which is basically a universal attachment for these kinds of things. I love this chip. In this case I just plugged the TX line (white in my cable) to the UART RX line on the chip (D1) and GND to GND.

To test it, I just followed Adafruit’s instructions to open up a `screen` session on my (linux) laptop. I was immediately greeted with and ASCII stream of data in a meaningful format. The FT232H starts up in its UART serial mode by default which is exactly what I needed for this device. Yay: this is an easy project.

Since I didn’t need any advanced features of this chip for this project, I didn’t need to use the Adafruit library or anything. I just wrote a bit of Python 3 code to parse the data:

"""
Digital Level Reader.

Reads DXL360 digital level measurements coming in over the serial port.

Data comes in via UART, converted to USB with a FT232H or equiv.
Format is X+0000Y+0000

Original Purpose: Calibrate/verify star-tracking barn-door camera mount.
By: Nick Touran
"""
import serial
import re
import time


DEV = '/dev/ttyUSB0'
BAUD = 9600
MSG_LENGTH = 12


def read():
    with serial.Serial(DEV, BAUD, timeout=1) as port:
        # sync up when you find an 'X' character
        char = b''
        while char != b'X':
            char = port.read()
        port.read(MSG_LENGTH - 1)  # toss one datum since X was consumed
        start = time.time()
        seconds = 0.0
        # now read continuously and process into floats
        while True:
            datum = port.read(MSG_LENGTH).decode()
            match = re.search('X([+-]\d\d\d\d)Y([+-]\d\d\d\d)', datum)
            if not match:
                raise ValueError('Level did not provide valid data. Check connection.')
            x, y = match.groups()
            x = int(x) * 0.01
            y = int(y) * 0.01
            seconds = time.time() - start
            print('{:<10.1f} {: 6.2f} {: 6.2f}'.format(seconds, x, y))
            yield (seconds, x, y)

if __name__ == '__main__':
    read()

This code creates a generator that you iterate over very simply for whatever application you need. For my calibration stuff, the plotting code looks like this:

 

import matplotlib.pyplot as plt

import level


def measure(duration_in_seconds=20):
    t, x, y = [], [], []


    for seconds, xi, yi in level.read():
        t.append(seconds)
        x.append(xi)
        y.append(yi)
        if seconds > duration_in_seconds:
            break

    plt.plot(t, x, '.')
    plt.xlabel('Time (s)')
    plt.ylabel('Angle (degrees)')
    plt.title('Level data')
    plt.grid(alpha=0.3)
    plt.show()

That just reads some data and then plots it, like this:Sweeeeeet.

Coupling a computer to this level really makes it an even more awesome and useful instrument.

Update: I open-sourced this software as part of the startracker project on github.

One thought on “Reading data from a DXL360 digital level onto your computer”

Leave a Reply

Your email address will not be published. Required fields are marked *