Thursday, July 17, 2008

USB Communication part II

The Arduino can receive string signals from the computer, but the computer has to send them. I have searched high and low for a multi-platform API to connect to a USB device and send strings to it in C++. No luck. Under windows there's CSerial, and Linux has libUSB, but instructions on how to use them are sparse, particularly on Unix/Linux.
So I turned to Python. Python is an interpreted language, useful for rapid prototyping software and scripting. It also has a brilliant USB communications library called pyserial. It also can be embedded in a C++ program. What follows is at best a hack. At worst it's a terrible kludge. Either way it works quite well. Python is installed by default on the Mac OS, so I didn't have to do anything beyond finding the right include directory. You can download it from python.org and pyserial from sourceforge. Using Python to send messages over the USB connection is impressively simple. The test code looks like this:

import serial
import time

ser = serial.Serial('/dev/tty.usbserial',9600)
time.sleep(2)
ser.write('Any message string you want.')
time.sleep(0.1)
ser.write('Another message string')
time.sleep(1.0)


The sleep commands ensure that the serial connection has time to start up (in the first case), and that it has time to transmit before the script ends (in the last case). In between, the connection buffers all the messages you send so the middle sleep isn't technically necessary.

Now I need to insert these commands into a C++ program. Fortunately, this is simple too. If you #include Python.h you gain access the the Python interpreter. I tried several different tutorials for using the various functions in Python.h, but the one that worked the best was the simple "PyRun_SimpleString(char* str);". With that, you can simply create your Python command in a char[] string in C++ and send it off. With that in mind I created the following wrapper class called serialBridge, which encapsulates the python commands including the setup and shutdown.

Here's the code:
serialBridge.h
serialBridge.cpp

And here's how to use it:

#include "iostream"

#include "Python.h"
#include "serialBridge.h"

using namespace std;

int main()
{
rSerial::serialBridge ser;
ser.setObserverStream(&cout);
ser.init("/dev/tty.usbserial",9600);
ser.delay(2.0);

for(int i = 0; i <>
{
ser.sendString("\"#");
ser.delay(1);
ser.sendString("\"~");
ser.delay(1);
}
return 0;
}

No comments: