Sending a single data point from the physical world into media systems is reasonably straight forward. Sending multiple data points can be much more complex. This post outlines a simple strategy for sending multiple data points from Arduino to Processing.
Messages should be structured in a way that sender can format and receiver can parse. As Processing has powerful built in parsing tools ( splitTokens ) we will develop a message structure that reflects these strengths.
NOTE: that Arduino serial is ASCII based and as such, the largest number that can be sent is 255. (there are work-arounds to this — but we will accept this constraint for this example).
Making Connections
This example assumes that you have more than one sensor or input connected to I/O pins and that you have connected your sensors to sequential pins (eg: 3 sensors connected to pins 4,5,6 or 7,8,9). Last, the code indexes off of the lowest pin number of the sequence — eg: 4 in the first example, 7 in the second. You need to indicate the number of sensors and the number of the first sensor pin in the Arduino code (see declarations at top of example file).
Critical Code
Data packets from Arduino will take this form:
START_BYTE sensorData DELIMITER sensorData DELIMITER sensorData DELIMITER END_BYTE
If we define the following:
- START_BYTE = * ( asterisk , ASCII 42 )
- DELIMITER = , ( comma , ASCII 44 )
- END_BYTE = # ( pound, ASCII 35 )
Then the above message structure would give a packet that looks like this:
*data1,data2,data3,dataN,#
By storing the sensor data in an array the code can be structured to loop over all the pins to read and then send the data.
The basic Arduino function that will assemble a packet from an array of data follows:
void sendSensors(){
// built and send package
Serial.print(START_BYTE, BYTE); // send START_BYTE as a BYTE
for (int i = 0; i < MAX_NUMBER_SENSORS; i ++) {
Serial.print(sensors[i], DEC); // send the sensorValues out via USB as a DECimal
Serial.print(DELIMITER, BYTE); // commas separate data
} // end for
Serial.print(END_BYTE, BYTE); // end of message
} // end sendSensors
In Processing we can use the serialEvent() listener to receive the serial stream and parse the incoming message:
void serialEvent( Serial usbPort ){
madeUSBcontact = true ;
String usbString = usbPort.readStringUntil( END_BYTE );
if ( usbString != null ){
usbString = trim( usbString );
int incomingSensorStream[] = int (splitTokens( usbString, TOKENS ));
// this is a hack to get the data from incomingSensorStream (local)
// into sensorData (global)
sensorData = new int[incomingSensorStream.length];
arrayCopy( incomingSensorStream , sensorData );
} // end if
usbPort.clear(); // dumps buffer before asking for next data point
usbPort.write( '\r' ); // send a carriage return to continue communication
} // end serialEvent