I was searching for a way to exchange data between an Arduino/ArduPilot and a Java application. There are already several solutions to do this but none of them really met my requirements. So I decided to write a library that implements a mechanism called serialization/deserialization. The now called SimpleSerialization library allows you to define a data structure (or object) that will be converted into a stream which then can be sent via a serial connection.DownloadsThe distribution: SimpleSerialization-1.0.zipThe project page: code.google.com/p/simpleserialization.What you can do with it- debug an Arduino application in a very convenient way- remote control an Arduino- setup a hardware-in-the-loop simulation- and moreAn example SimpleSerialization application could be to feed an Arduino with GPS data at 5Hz and attitude data at 30Hz. In return the Arduino would send the calculated actuator commands back at a rate of 10Hz. All this data would be exchanged via a single serial connection.Requirements- an Arduino or ArduPilot- a serial connection from a PC to the Arduino- and additional 2KB of flash memory when used with the ArduPilot- the Arduino IDE- a Java IDE (e.g. Processing or Eclipse)
The SimpleSerialization library is part of my UAV Playground project where I explore various aspects of UAVs like microcontrollers, simulators and remote controlled model airplanes.
And if you are planning to define more than one class whose instances you want to send via SimpleSerialization, then make sure you set different pre- and postamble values for them. Have a look at the Timer class of the MultipleData example where it is shown how this is done (setPreamble and setPostamble).
This is not necessary if you are using multiple instances of the same class (Message: message1, message2).
Jaron, recently tried to use your SimpleSerialization with my own data structure but I am having some issues. I constructed my classes based off of your examples/source but I still have a few questions. I have posted my source code below, can you tell me what I am doing wrong ? Also can you explain the
Project goal: turn on and off two LEDS using a processing based interface and arduino
Arduino Code:
#include
#include "Message.h"
int greenLedPin = 7;
int redLedPin =8;
long connectionSpeed = 9600;
Message incomming;
Message outgoing;
long R_status=0;
long G_status = 0;
/*
* This is the callback function that is called whenever the data is updated.
*/
void dataUpdate(SerializationData *data)
{
Message.h :
/*
* This is the declaration of the Message class whose instance (object) is going
* to be serialized and sent via the serial connection.
*
*/
#ifndef _MESSAGE_H
#define _MESSAGE_H
#include "SimpleSerialization.h"
class Message : public SerializationData {
public:
int getDataSize();
void readData(SerializationInputStream& input);
void writeData(SerializationOutputStream& output);
char* getTitle() { return message; };
void setTitle(char *message) { strcpy(this->message, message); };
int getData() { return pi; }
void setData(int pi) { this->pi = pi; }
private:
char message[32];
int pi;
};
#endif /* _MESSAGE_H */
Message.cpp:
/*
* This is the definition of the Message class whose instance (object) is going
* to be serialized and sent via the serial connection.
*/
#include "Message.h"
int Message::getDataSize() {
int size = SerializationTypes::SIZEOF_INTEGER + strlen(message);
size += SerializationTypes::SIZEOF_FLOAT;
return size;
}
void Message::readData(SerializationInputStream& input) {
input.readString(message);
pi = input.readInteger();
}
Processing Side:
/*
* Replace "COM4" with the serial port your Arduino is connected to.
* Replace 115200 with the baud rate your Arduino communicates.
*
* A very simple example that sends an integer value to the Arduino when the
* mouse is pressed or released. The Arduino then turns an LED on or off.
* Have a look at the Arduino SwitchLed example to see how the value is received.
*/
Message.java:
/*
* This is the Message class whose instance (object) is going to be deserialized
* from the data that was sent via the serial connection.
*/
import jaron.simpleserialization.*;
public class Message extends SerializationData {
private String message = "";
private int pi;
public String getTitle() {
return message;
}
public void setTitle(String message) {
this.message = message;
}
public int getData() {
return pi;
}
public void setData(int pi) {
this.pi = pi;
}
public int getDataSize() {
int size = SerializationTypes.SIZEOF_STRING + message.length();
size += SerializationTypes.SIZEOF_FLOAT;
return size;
}
public void readData(SerializationInputStream input) {
message = input.readString();
pi = input.readInteger();
}
public void writeData(SerializationOutputStream output) {
output.writeString(message);
output.writeInteger(pi);
}
}
You're welcome Bryan. I haven't done a hardware-in-the-loop simulation yet but the SimpleSerialization library is another step forward to an autonomous flight. Next I will start to implement some of the autopilot code from the UAVsim on an Arduino/ArduPilot and that's where the SimpleSerialization is becoming helpful.
I don't hesitate because I think that we'll see some interesting developments in UAV hardware in the near future. For example the Arduino Mega based ArduPilot that will better fit my style of programming.
Jaron,
Thank you for your UAV Playground! I got it running this week and the UAVsim will be a big help in learning the effects of PID tuning. I want to try your SimpleSerialization next for hardware-in-the-loop simulation. Have you done this yet for your autopilot and tailess UAV?
I'm using the hardware serial port but from a software architecture's point of view it would be very easy to switch to any other serial interface or device. I wasn't very lucky with the soft serial approach.
Comments
This is not necessary if you are using multiple instances of the same class (Message: message1, message2).
if(((Message *)data)->getTitle() == "red_Set")
with
if(strcmp(((Message *)data)->getTitle(), "red_Set") == 0)
and
else if (((Message *)data)->getTitle()== "green_Set")
with
else if (strcmp(((Message *)data)->getTitle(), "green_Set") == 0)
Have a look at this example: SimpleSerialization-Example-ToggleLEDs.zip
Project goal: turn on and off two LEDS using a processing based interface and arduino
Arduino Code:
#include
#include "Message.h"
int greenLedPin = 7;
int redLedPin =8;
long connectionSpeed = 9600;
Message incomming;
Message outgoing;
long R_status=0;
long G_status = 0;
/*
* This is the callback function that is called whenever the data is updated.
*/
void dataUpdate(SerializationData *data)
{
if(((Message *)data)->getTitle() == "red_Set")
{
if (((Message *)data)->getData() == 1)
{
digitalWrite(redLedPin, HIGH);
R_status = 1;
}
else
{
digitalWrite(redLedPin, LOW);
R_status = 0;
}
// outgoing.setTitle("red_Status");
// outgoing.setData(R_status);
}
else if (((Message *)data)->getTitle()== "green_Set")
{
if (((Message *)data)->getData() == 1)
{
digitalWrite(greenLedPin, HIGH);
G_status = 1;
}
else
{
digitalWrite(greenLedPin, LOW);
G_status = 0;
}
}
}
void setup()
{
pinMode(greenLedPin, OUTPUT);
pinMode(redLedPin, OUTPUT);
incomming.setUpdateCallback(&dataUpdate);
SimpleSerialization.begin(connectionSpeed);
SimpleSerialization.addDeserializableData(&incomming);
}
void loop() {
SimpleSerialization.processInput();
}
Message.h :
/*
* This is the declaration of the Message class whose instance (object) is going
* to be serialized and sent via the serial connection.
*
*/
#ifndef _MESSAGE_H
#define _MESSAGE_H
#include "SimpleSerialization.h"
class Message : public SerializationData {
public:
int getDataSize();
void readData(SerializationInputStream& input);
void writeData(SerializationOutputStream& output);
char* getTitle() { return message; };
void setTitle(char *message) { strcpy(this->message, message); };
int getData() { return pi; }
void setData(int pi) { this->pi = pi; }
private:
char message[32];
int pi;
};
#endif /* _MESSAGE_H */
Message.cpp:
/*
* This is the definition of the Message class whose instance (object) is going
* to be serialized and sent via the serial connection.
*/
#include "Message.h"
int Message::getDataSize() {
int size = SerializationTypes::SIZEOF_INTEGER + strlen(message);
size += SerializationTypes::SIZEOF_FLOAT;
return size;
}
void Message::readData(SerializationInputStream& input) {
input.readString(message);
pi = input.readInteger();
}
void Message::writeData(SerializationOutputStream& output) {
output.writeString(message);
output.writeInteger(pi);
}
Processing Side:
/*
* Replace "COM4" with the serial port your Arduino is connected to.
* Replace 115200 with the baud rate your Arduino communicates.
*
* A very simple example that sends an integer value to the Arduino when the
* mouse is pressed or released. The Arduino then turns an LED on or off.
* Have a look at the Arduino SwitchLed example to see how the value is received.
*/
import jaron.simpleserialization.*;
import processing.serial.*;
String serialPort = "COM8";
int connectionSpeed = 9600;
SerializationSerialConnection conn;
Message mess;
int r_status=0;
int g_status =0;
void setup() {
// The Processing setup
size(200, 200);
frame.setTitle("LED Control");
// Initialize the serialization
conn = new SerializationSerialConnection(this, serialPort, connectionSpeed);
PFont font;
font = loadFont("text.vlw");
textFont(font);
background(0);
mess = new Message();
}
void draw() {
stroke(255,255,255);
if(g_status == 0)
{
fill(255,255,255);
}
else
{
fill(0,255,0);
}
String s = "Green LED";
rect(100,5,50,50);
text(s,100,70);
if(r_status == 0)
{
fill(255,255,255);
}
else
{
fill(255,0,0);
}
s = "Red LED";
rect(5,5,50,50);
text(s,5,70);
}
void mousePressed() {
// If the mouse is pressed then send 1 to the Arduino
if(mouseX > 5 && mouseX < 55 && mouseY > 5 && mouseY < 55)
{
if(r_status ==1)
{
r_status = 0;
}
else
{
r_status = 1;
}
mess.setTitle("red_Set");
mess.setData(r_status);
conn.write(mess);
delay(10);
//conn.read();
}
else if((mouseX > 100 && mouseX < 150) && (mouseY > 5 && mouseY < 55))
{
if(g_status ==1)
{
g_status = 0;
}
else
{
g_status = 1;
}
mess.setTitle("green_Set");
mess.setData(g_status);
conn.write(mess);
delay(10);
//conn.read();
}
}
Message.java:
/*
* This is the Message class whose instance (object) is going to be deserialized
* from the data that was sent via the serial connection.
*/
import jaron.simpleserialization.*;
public class Message extends SerializationData {
private String message = "";
private int pi;
public String getTitle() {
return message;
}
public void setTitle(String message) {
this.message = message;
}
public int getData() {
return pi;
}
public void setData(int pi) {
this.pi = pi;
}
public int getDataSize() {
int size = SerializationTypes.SIZEOF_STRING + message.length();
size += SerializationTypes.SIZEOF_FLOAT;
return size;
}
public void readData(SerializationInputStream input) {
message = input.readString();
pi = input.readInteger();
}
public void writeData(SerializationOutputStream output) {
output.writeString(message);
output.writeInteger(pi);
}
}
I don't hesitate because I think that we'll see some interesting developments in UAV hardware in the near future. For example the Arduino Mega based ArduPilot that will better fit my style of programming.
Thank you for your UAV Playground! I got it running this week and the UAVsim will be a big help in learning the effects of PID tuning. I want to try your SimpleSerialization next for hardware-in-the-loop simulation. Have you done this yet for your autopilot and tailess UAV?