Asynchronous, Event-Driven UART in C++ for BeagleBone Black

In C++, IoT by timfanelliLeave a Comment

I just posted the first iteration of Serialzzz, a C++ library which provides asynchronous, event-driven I/O for interacting with UART devices on BeagleBone Black. 

Today’s code drop is just the very first functional, initial pass – and is not production ready by any means! But it’s definitely enough to get you up and running quickly… it is geared towards C++ Object Oriented developers, who would otherwise struggle with the C I/O libraries necessary to perform serial I/O. The library provides a SerialComm object, which raises an event containing a message received on the UART. To listen for the event, simply inherit from the SerialCommListener class, and override the “handleMessage” method. SerialComm also provides a method to write messages to the UART, and is thread-safe.

The next code drop will expose UART settings such as baud rate, width, parity, and stop bits. This initial pass is hard-coded to 9600 BAUD 8N1, though it is very simple to change.

You’ll find the source on github, here: https://github.com/zombiebabylabs/serialzzz.

Using it is pretty simple, here’s a quick example to get you started… first we create a class that extends zbl::SerialCommListener:

// ConsoleOutputListener.h
#ifndef CONSOLEOUTPUTLISTENER_H_
#define CONSOLEOUTPUTLISTENER_H_

#include "serialzzz/SerialCommListener.h"

class ConsoleOutputListener 
  : public zbl::SerialCommListener 
{
public:
     ConsoleOutputListener();
     virtual ~ConsoleOutputListener();

     // Override handleMessage, print message to standard out.
     virtual void handleMessage( const char * const message );
};

#endif /* CONSOLEOUTPUTLISTENER_H_ */
// ConsoleOutputListener.cpp
#include "ConsoleOutputListener.h"
#include <iostream>
using namespace std;

ConsoleOutputListener::ConsoleOutputListener() {
}

ConsoleOutputListener::~ConsoleOutputListener() {
}

void ConsoleOutputListener::handleMessage( const char * const message ) {
	cout << message << endl;
}
#endif /* CONSOLEOUTPUTLISTENER_H_ */

And then we define a quick main program, which will spend 5 minutes listening on the serial port, displaying any incoming messages to the cout stream.

// main.cpp
#include <iostream>
#include <unistd.h>
#include "serialzzz/SerialComm.h"
#include "serialzzz/SerialCommListener.h"
#include "ConsoleOutputListener.h"

using namespace zbl;
using namespace std;
int main() {
	SerialCommListener *listener = new ConsoleOutputListener();
	SerialComm *comm = new SerialComm("/dev/ttyO1");

	comm->registerSerialCommListener( listener );
	comm->openPort();

	sleep(300);

	comm->closePort();
	delete comm;
	delete listener;

	return 0;
}

Update I just added lambda support to Serialzzz, and you can now register callbacks for asynchronous message handling like so:

	SerialComm *comm = new SerialComm("/dev/ttyO1");
	comm->registerCallBack(
		[](const char * const msg)
		{
		     cout << msg << endl;
		}
	);

registerCallBack accepts a function<void( const char * const )> argument, and you can add as many as you need.

Both callbacks and listeners will be invoked, and I am leaving both in place for now, as I’m not convinced the SerialCommListener base class won’t be simpler for Java programmers adopting C++ on the BeagleBone. My preference is the callback, but I see value in both.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.