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.
Jaron, sorry to keep bothering you but I am continually being hung up by things. Below I have attached some code and the support files. Running this causes the Arduino to reboot every time it gets to the serA.write(&navData); line. What am I doing wrong here ?
}
void setupNav()
{
navD.setTitle("navD");
navD.set_Speed(speeD);
navD.setLat(lat);
navD.setLon(100.23);
navD.setHeading(heading);
navD.setAlt(alt);
navD.setSatNum(sat_num);
navD.setCurrentWaypoint(current_way);
navD.setDisToWaypoint(dist_toWay);
navD.setMode(mode);
}
/* This is the callback function that is called whenever the data is updated.
*/
void navUpdate(SerializationData *data)
{
debug.println("Nav data received");
if(strcmp(((navData *)data)->getTitle(),"navData") ==0)
{
debug.print("Mode set to: ");
debug.println(((navData *)data)->getMode());
}
}SimpleSerialization.hSimpleSerialization.cppnavData.h
I didn't realize that you where trying to make an instance of an instance (SimpleSerialization) in your previous post. That's the reason why 1. doesn't work.
In 2. you are doing it correctly by instantiating the SerializationSerialConnection class. I can compile that without errors in a 0015 and a 0016 version of the Arduino IDE. What version are you using?
You could recompile the SimpleSerialization library:
- quit the Arduino IDE
- delete the file arduino-00xx\hardware\libraries\SimpleSerialization-1.0\SimpleSerialization.o
- start the Arduino IDE
If all that doesn't help you could comment out the line 147 of the SimpleSerialization.h file:
//extern SerializationSerialConnection SimpleSerialization;
But the you couldn't use the predefined SimpleSerialization object anymore, which is no problem at all if you create your own instances of the SerializationSerialConnection class.
After reviewing the code again I too see no problem however I am still stuck trying to declare multiple instances. Below are two examples that I have tried and the errors that go along with them.
1. #include "SimpleSerialization.h"
SimpleSerialization serA;
error: 'SimpleSerialization' does not name a type In function 'void setup()':
2. #include "SimpleSerialization.h"
SerializationSerialConnection serA;
error: 'SerializationSerialConnection SimpleSerialization()' redeclared as different kind of symbolC:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\build22550.tmp\/SimpleSerialization.h:147: error: previous declaration of 'SerializationSerialConnection SimpleSerialization'
I can see a reason for either of these errors, maybe you can .....
I haven't tried it yet but I don't see any reason why this shouldn't work. I've tried to keep the examples as simple as possible and that's why I didn't show the initialization with a different port.
It's nice to see people digging into the code and using the undocumented features!
Is it possible to declare multiple instances of the SimpleSerialization each pointing at a separate serial port. Forgive the extra stuff in the code...
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);
}
}
Comments
Also I forgot the cpp file for navDatanavData.cpp
#include
#include "debugData.h"
#include "navData.h"
#include "servoData.h"
#include "waypointData.h"
#include
//used for debugging
int rxPin = 2;
int txPin = 3;
SoftwareSerial debug = SoftwareSerial(rxPin, txPin);
//packet types
//debugData debugD;
navData navD;
//servoData servoD;
//waypointData wayD;
//serial connection
SerializationSerialConnection serA;
// navData fields
char title[32];
float speeD;
float lat;
float lon;
float heading;
int alt;
int sat_num;
int current_way;
int dist_toWay;
int mode;
void setup()
{
//used for debugging
pinMode(rxPin, INPUT);
pinMode(txPin, OUTPUT);
debug.begin(9600);
//set update callback
navD.setUpdateCallback(&navUpdate);
//wayD.setUpdateCallback(&waypointUpdate);
//servoD.setUpdateCallback(&servoUpdate);
// setup serial port
serA.begin(&Serial,9600);
serA.addDeserializableData(&navD);
// serA.addDeserializableData(&wayD);
debug.println("Program starting");
}
void loop() {
// read in from serial port
if(Serial.available() > 0)
{
debug.println("recieved Data");
serA.processInput();
}
//xbee and ground station
//serB.processInput(); //ardupilot
// writing
speeD = 100.9;
lat = 88.9;
lon= 100.23;
heading = 180.1;
alt = micros();
sat_num = 2;
current_way= 4;
dist_toWay= 200;
mode = 0;
setupNav();
debug.println("Attempting to send data");
serA.write(&navD); // causes reboot
debug.println("Data Sent");
delay(1000);
}
void setupNav()
{
navD.setTitle("navD");
navD.set_Speed(speeD);
navD.setLat(lat);
navD.setLon(100.23);
navD.setHeading(heading);
navD.setAlt(alt);
navD.setSatNum(sat_num);
navD.setCurrentWaypoint(current_way);
navD.setDisToWaypoint(dist_toWay);
navD.setMode(mode);
}
/* This is the callback function that is called whenever the data is updated.
*/
void navUpdate(SerializationData *data)
{
debug.println("Nav data received");
if(strcmp(((navData *)data)->getTitle(),"navData") ==0)
{
debug.print("Mode set to: ");
debug.println(((navData *)data)->getMode());
}
}SimpleSerialization.hSimpleSerialization.cppnavData.h
In 2. you are doing it correctly by instantiating the SerializationSerialConnection class. I can compile that without errors in a 0015 and a 0016 version of the Arduino IDE. What version are you using?
You could recompile the SimpleSerialization library:
- quit the Arduino IDE
- delete the file arduino-00xx\hardware\libraries\SimpleSerialization-1.0\SimpleSerialization.o
- start the Arduino IDE
If all that doesn't help you could comment out the line 147 of the SimpleSerialization.h file:
//extern SerializationSerialConnection SimpleSerialization;
But the you couldn't use the predefined SimpleSerialization object anymore, which is no problem at all if you create your own instances of the SerializationSerialConnection class.
After reviewing the code again I too see no problem however I am still stuck trying to declare multiple instances. Below are two examples that I have tried and the errors that go along with them.
1. #include "SimpleSerialization.h"
SimpleSerialization serA;
error: 'SimpleSerialization' does not name a type In function 'void setup()':
2. #include "SimpleSerialization.h"
SerializationSerialConnection serA;
error: 'SerializationSerialConnection SimpleSerialization()' redeclared as different kind of symbolC:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\build22550.tmp\/SimpleSerialization.h:147: error: previous declaration of 'SerializationSerialConnection SimpleSerialization'
I can see a reason for either of these errors, maybe you can .....
Thank You
Zachary R Long
It's nice to see people digging into the code and using the undocumented features!
Is it possible to declare multiple instances of the SimpleSerialization each pointing at a separate serial port. Forgive the extra stuff in the code...
Thanks
EX:
SimpleSerialization serA;
SimpleSerialization serB;
void setup()
{
navD.setUpdateCallback(&navUpdate);
wayD.setUpdateCallback(&waypointUpdate);
servoD.setUpdateCallback(&servoUpdate);
serA.begin(&Serial,9600);
serB.begin(&Serial1,9600);
serA.addDeserializableData(&navD);
serA.addDeserializableData(&wayD);
serB.addDeserializableData(&navD);
serB.addDeserializableData(&servoD);
}
void loop() {
// read in from serial port
serA.processInput(); //xbee
serB.processInput(); //ardupilot
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);
}
}
-
1
-
2
of 2 Next