First foray into hardware programming and it turns out trying to get Arduino data into Flash is trickier than expected. A couple of options seem to be available:
1) Using a third party lib such as as3glue which takes the hassle out of making the two platforms communicate.
or
2) Awkwardly handle the serial transmissions manually with attention to buffering all the received data.
The first approach is straightforward to get up and running thanks to this post on KasperKamperman.com or see here. The second approach needs more thought in order to ensure all data is received correctly. If you want to be able to data from the Arduino without using an extra library, read on.
In AS3 we use the Socket class with the readUTFBytes() method and socketData event to get the information from serial. You can the Socket class documentation in the AS3 reference here. The socketData event fires when data is sent to the socket. But the event can be fired multiple times meaning data is often split up and needs to be reconstructed in Flash to get the correct variables. This has been noted in this post by iestyn, who also mentions that AS2 behaves more predictably. As this is probably a fairly standard buffering issue for hardware programming it is presumably applicable across a range of platforms.
In this demo the Arduino writes data to the serial and Flash reads it and stores it in an array called values. The values array is periodically output using a timer. The data is just an integer counter so it easy to see when the data is correctly received by Flash (i.e. in the correct order and without missing values).
Download the zip of the Arduino to Flash code here.
Note: You must correctly configure SerProxy by editing the SerProxy.cfg to be set to the right COM port (in my case 5333). Make sure the AS3 is using the same port number in the Socket constructor.
To run the demo:
1.) Upload the Arduino code
2.) Start SerProxy.exe
3.) Compile the Flash
I’ve used Flash CS3 Pro (Flash 9) and a Arduino Duemilanove (arduino-0018).
The Arduino code:
//MapToPixel.com
//31 July 2010
//Prints an incremental counter values to the Serial
//port separated by commas "," with an "e" to
//signify the end of the line. Uploading this to the
//Arduino and monitoring the serial port should
//give something like:
//1,2,3e4,5,6e7,8,9e10,11,12e13,14,15e16,17,18e
int count = 0;
void setup()
{
Serial.begin( 9600 );
}
void loop()
{
count = count + 1;
Serial.print( count );
//Use a comma to so the data can be split
Serial.print( "," );
//And again...
count = count + 1;
Serial.print( count );
Serial.print( "," );
//Once more...
count = count + 1;
Serial.print( count );
//But this time print an E to signify the end of the line
Serial.print( "e" );
delay( 500 );
}
The AS3 code:
import flash.events.*;
import flash.net.Socket;
import flash.utils.Timer;
import flash.events.TimerEvent;
trace("Starting Arduino to Flash demo...");
var socket:Socket = new Socket("localhost",5333);
var count:int = 0;
//lineBefore is a temporary store of an incomplete data line found in the buffer not yet saved to the final values list
var lineBefore:String;
//buffer used to store data from socket
var buffer:String;
socket.addEventListener(ProgressEvent.SOCKET_DATA, socketBufferHandler);
//Global storage of final values
var values:Array = new Array();
function socketBufferHandler(event:ProgressEvent):void {
var eol:Number;
//Read the socket data into the buffer
buffer = socket.readUTFBytes(socket.bytesAvailable);
//Sometimes the socket maybe emtpy so first check it's not null
if (buffer != null) {
//Now check if the end of line flag is present in this data string
eol = buffer.indexOf('e');
if (eol == -1) {
//The end of line flag was not found...
//so save this buffer data to a global variable so we can access it later
lineBefore = buffer;
} else {
//The end of line flag was found...
//so substring the data to get the values before the end of line flag
var buff2 = buffer.substring( 0, eol);
//Can now start to think about saving the data...
//but we need to check if there is any data left from a previous firing of this event handler (i.e. stored in lineBefore)
if (lineBefore == null) {
//No outstanding data to save from previous event handler
//Save this to the global array of data
values[count] = buff2;
count++;
} else {
//There is some outstanding data from before. Save this data as well as the new stuff
values[count] = lineBefore + buff2;
count++;
//Now set lineBefore to null to ensure it is not used again (results in duplicates of data)
lineBefore = null;
}
//Set buffer to null to make sure it's clear for the next event
buffer = null;
}
//trace(values.length);
}
//trace(values[values.length-1]);
} //End socketBufferHandler
var myTimer:Timer = new Timer(2000, 1000);
myTimer.addEventListener(TimerEvent.TIMER, timerHandler);
myTimer.addEventListener(TimerEvent.TIMER_COMPLETE, completeHandler);
function timerHandler(e:TimerEvent):void{
trace("values are \n" + values);
}
function completeHandler(e:TimerEvent):void {
trace("timer complete");
}
myTimer.start();