RS232 Telemetry Viewer

While developing my balancing robot I needed to visualize certain variables. Being able to monitor angles, velocities and feedback loop factors made it easier to tune the control loop and verify the correct functioning of my sensors. I wrote the program in Java, utilizing the Swing and RXTX libraries.

Current values for each data point are shown with the sliders and text labels. Clicking on a data point will bring up a new window that shows the history of that data point in the form of a line graph. Multiple line graph windows can be used to track the history of several items at once.

The source code can be downloaded as a zip file, or accessed through my RS232 Telemetry Viewer repository on GitHub. To run the code you will need to install the RXTX library.

The code is split into eight classes: Main, Database, TelemetryGUI, ConfigurationLoader, SerialConfigPanel, SerialPortListener, BallPanel and LineGraph. The TelemetryGUI class has two inner classes: TelemetryGroup and TelemetryItem.

Main simply creates an instance of the Database and TelemetryGUI classes.

Database is used to store the history of values for each data point.

TelemetryGUI configures the main window and creates an instance of the ConfigurationLoader to read the configuration text file and make the corresponding panels. A BallPanel is used to visualize the robot's pitch and yaw angles. A SerialConfigPanel shows the available serial ports and baud rates, and allows the user to establish a connection with the selected port.

SerialPortListener is used to spawn a new thread that monitors the RS232 link, interprets incoming text, and populates the database with new values.

LineGraph is a window that shows the recent history of an item in the form of a constantly updating line graph.

Here's a video clip of me testing an early version of this program with my robot back in December 2013:

Balancing Robot Firmware

I'm releasing the firmware for my balancing robot into the public domain. Use it however you wish. The code is rather specific to my choice in microcontroller and sensors, but it might still be helpful to those working on their own robots.

Most of the work takes place in two files: main.c and isrs.c.

The main() function does all of the initialization work, then enters an infinite loop that constantly streams telemetry data out via RS232.

The interrupt service routines in isrs.c are where all of the “real work” is done. That's where the new values from all sensors are read, steering and throttle commands are received from the CC2500-based 2.4GHz transmitter, and the motor PWM values are adjusted based on a PID control loop.

I have amassed a small collection of reusable code while working on various projects with the STM32F0 microcontroller. This collection of code is not polished enough for sharing, but since it was used in this project I am including it anyway. It's in the /f0lib/ directory and should be used with caution. Be sure to read the function implementations before reusing the code in your own projects. The code in /f0lib/ was only written with my particular use cases in mind.

The firmware can be downloaded as a zip file, or accessed through my Balancing Robot repository on GitHub. Have fun!

Video clips and more photos are in my previous post from May 18th.

Balancing Robot

Over a year ago I started to work on a small balancing robot. Between learning more about communication protocols and feedback loops I also had periods of schoolwork that kept me from this hobby. In the end my little robot was balancing on his own and I could send steering and throttle commands wirelessly.

This project marked many firsts for me. It was the first time I made use of my microcontroller's I2C, UART and ADC peripherals. It was the first time I heard about PID control loops. It was also the first time I used an RF module to communicate wirelessly.

As I progressed I took several photos and video clips when milestones were met.

During the planning stage I selected a 3-axis gyro and a 3-axis accelerometer. I settled on STM's L3GD20 and LSM303DLHC devices. I laid out and etched a breakout board for them, then wrote a little Hello World test to draw bar graphs for the gyro readouts.

I decided to use a pair of RC hobby servos to power the robot. I removed the feedback potentiometers and modified the output gears to allow for continuous rotation. Some steering wheels from RC hobby transmitters were initially used as the wheels. The robot frame was constructed with some brass square tubing cut to length and soldered together. A gimbal was used for steering and throttle inputs since I didn't want to dive into the 2.4GHz module's lengthy datasheet until the end.

The wheels quickly proved to be a problem. While they had great traction, their diameter was far too small. The robot could easily drift a little too much, and the servos at full power couldn't spin fast enough to overcome the drifting.

I went with larger diameter wheels, making it much easier for the robot to balance:

The robot was actually drivable at this point. I added optical wheel encoders to make it easier to sense when the robot started to drift off course. Without the encoders the robot could drift if the driving surface wasn't perfectly level. By now the little guy was a mess of breakout boards, flying wires and extensions.

To clean up the mess I designed and etched a PCB specifically for this robot. I incorporated dual H-Bridges on the PCB to give better control over the motors. Previously I had just generated servo signals and let the servos' PCBs control the motors. This mostly worked, but as the servo PCBs came up to temperature the signal center point would drift slightly. This meant that after about a minute of use the robot would effectively have a bit of steering and throttle applied.

I finished by designing and etching a PCB for the transmitter. That was shown in my earlier post about solder masks. A little tuning of the PID control loop brought everything together and I was done. I'll post the firmware in a few days after doing the last bits of clean up and documentation.

Using the RXTX Java Library

There are several libraries for Java that add support for serial ports, and a few months ago I settled on the RXTX library. Recently their web site disappeared and looking back at the code releases it became apparent that development halted a couple years ago. A few groups are still maintaining packages for the library, and people still use it, so I'll post my installation and helloworld notes.

Archive.org has a mirror of the old RXTX web site:
http://web.archive.org/web/20130117073055/http://rxtx.qbang.org/wiki/index.php/Main_Page

Installation

A Linux installation is trivial since RXTX is in the package repositories:

$ sudo apt-get install librxtx-java

An OS X installation is not so easy. Binaries are available from the official RXTX web site, but they are outdated and not compatible with modern versions of OS X. Compiling from source isn't hard, but there are a few changes that must be made along the way. Assuming you already have Java installed, you'll need to install libtool via Homebrew because the stock libtool supplied by Apple won't work.

Install Homebrew, then install libtool:

$ ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)" $ brew install libtool

Download the RXTX 2.2pre2 source and extract the archive. Then edit the configure file, modifying the JAVAINCLUDEDIR line:

Before: JAVAINCLUDEDIR=$JPATH/../../../Headers After: JAVAINCLUDEDIR=/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers

(Make sure the path is valid. It may be different if you installed a different version or distribution of Java than I did.)

Run the configure script:

$ ./configure

Assuming that completed successfully, edit the LIBTOOLC line in the Makefile:

Before: LIBTOOLC = $(GLIBTOOL) --mode=compile $(CC) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(VERBOSE_IOEXCEPTIONS) -c After: LIBTOOLC = $(GLIBTOOL) --tag=CC --mode=compile $(CC) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(VERBOSE_IOEXCEPTIONS) -c

Compile and copy the resulting files into place:

$ make $ cp RXTXcomm.jar /Library/Java/Extensions/ $ cp i386-apple-darwin13.0.0/librxtxSerial.jnilib /Library/Java/Extensions/

Simple Example

The official RXTX wiki has some good examples. Below is an adaption I made with the explicit goal of being short and to the point. See the official examples for better error handling and other use cases.

The following class has two methods: Use getSerialPorts() to get a List<String> of detected serial ports. Then call establishConnection() to make a connection and create the input/output streams. For example, calling establishConnection("/dev/ttyUSB0", 9600); would connect to /dev/ttyUSB0 with a 9600 8N1 configuration. I also setup a Scanner to make it trivial to parse incoming data.

import gnu.io.*; import java.io.*; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.Scanner; public class SerialTest { private SerialPort rs232; private OutputStream rs232ostream; private InputStream rs232istream; private Scanner rs232scanner; public List getSerialPorts() { List list = new ArrayList(); @SuppressWarnings("unchecked") Enumeration ports = CommPortIdentifier.getPortIdentifiers(); while(ports.hasMoreElements()) { CommPortIdentifier port = ports.nextElement(); if(port.getPortType() == CommPortIdentifier.PORT_SERIAL) list.add(port.getName()); } return list; } public Boolean establishConnection(String port, int baudRate) { try { rs232 = (SerialPort) CommPortIdentifier.getPortIdentifier(port).open("Test App", 2000); // app name, timeout rs232.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); rs232ostream = rs232.getOutputStream(); rs232istream = rs232.getInputStream(); rs232scanner = new Scanner(rs232istream); System.out.println("Connected to " + port + " at " + baudRate + " baud."); return true; } catch (Exception e) { System.err.println("Error setting up serial communications with port " + port + "."); System.err.println(e.getClass().toString()); return false; } } // add code that makes use of the input or output streams after calling establishConnection() }

Macro Lens Extension Tubes

My Canon 100mm f/2.8 macro lens takes some great photos but sometimes I want a nearly microscope level of magnification. I found a set of extension tubes that come as a three pack: 13mm, 21mm and 31mm. They can be used individually or stacked. My first shots are below.

100mm lens without any extension tubes:

100mm lens with 13mm extension:

100mm lens with 13mm and 21mm extensions:

100mm lens with 13mm, 21mm and 31mm extensions:

< Prev  3  Next >