Mike Chambers

code = joy

Sending Multibyte Numbers from ActionScript to Arduino

with 8 comments

If you follow me on twitter, then you have probably noticed that I have been learning about Flash, physical computing and electronics lately. I started out working with Phidgets, and have recently begun working with the Arduino (Ill write up Flash / Arduino getting started tutorial shortly). I am currently working on a project where I need to send data from Flash to the Arduino, and quickly discovered that it is not as easy as I thought it would be. In this post, I will show an example of how to send multibyte Numbers from ActionScript to Arduino.

When you send data to Arduino over the Serial port, Arduino reads that data byte by byte. Thus, if you want to send a string to the Arduino, you have to read the string byte by byte and reconstruct it which is a bit of a hassle, but nothing too difficult. However, what if you want to send a number? If you just need to send a small whole number (up to 127), then you can simply write the number to the socket:

socket.writeByte(127);

 

and then read the same number in Arduino by reading the byte:

value = Serial.read();
Serial.println(value, DEC); //will send 127

 

However, if you need to send a number larger than 127, then things get a bit tricky. This is because numbers larger than 127 require multiple bytes to send, which means that you cannot simply read in the number on the Arduino side (since you have to read byte by byte). One solution (suggested to my by Thibault Imbert) is to multiply the number by some ratio. This would allow you to represent numbers larger than 127, but at the price of accuracy.

So, after much searching, I found a post on the Arduino forums that shows how to build a float from a byte array using a union. With that code as a guide, I was able to figure out how to send a float from ActionScript to Arduino.

I have uploaded a simple example into my github example code repository. The Flash part of the example is done in Flex and ActionScript, but the ActionScript code is the same regardless of what you are using to build your Flash content.

Note, all of the code in the examples is released under an MIT license.

First, lets look at the Arduino sketch:


//union that we will use
//the construct the float
//from the individual bytes
//sent from Flash / ActionScript
union u_tag {
    byte b[4];
    float ival;
} u;

float value;

void setup()
{
  Serial.begin(9600);
}

void loop()
{  

  //this example assumes only floats / Numbers
  //are being sent. So we just look for data in 4 byte
  //increments
  if(Serial.available() > 3)
  {

    //read the 4 bytes into the union
    u.b[0] = Serial.read();
    u.b[1] = Serial.read();
    u.b[2] = Serial.read();
    u.b[3] = Serial.read();

    //retrieve the float value of the union
    //(based on the bytes passed in)
    value = u.ival;

    //send the reconstructed float back to the Serial
    //flash
    Serial.print(value, DEC);

    //write out a null byte, (the Flash Socket
    //class looks for this)
    Serial.print(0, BYTE);
  }

}

 

Now, lets look at how we send the Number from ActionScript:


private function onApplicationComplete():void
{
	//only allow numbers, period and minus sign
	numberInput.restrict = ".0-9\\-";

	socket = new Socket()
	socket.addEventListener(Event.CONNECT, onConnect);
	socket.addEventListener(Event.CLOSE, onClose);
	socket.addEventListener( IOErrorEvent.IO_ERROR, onIOError );
	socket.addEventListener( SecurityErrorEvent.SECURITY_ERROR, onSecurityError );
	socket.addEventListener( ProgressEvent.SOCKET_DATA, onSocketData );

	//disable until we connect
	this.enabled = false;

	//this is important! If you dont set this to
	//little endian, then Arduino wont understand
	//the bytes
	socket.endian = Endian.LITTLE_ENDIAN;

	socket.connect(SERVER_ADDRESS, PORT);
}

private function onSendClick():void
{
	//get the number that the user input
	var out:Number = Number(numberInput.text);

	//write it as a float to the server.
	//this is important.
	socket.writeFloat(out);

	//if number is too big, then it will overflow on
	//the Arduino, and probably come back as 0.00000
}

 

Again, you can download the complete example from my GitHub repository.

A couple of things to take note of. Notice that we set the Endianness of the socket to LITTLE_ENDIAN. This is necessary for Arduino to be able to understand the number we are sending.

Second, notice that we send the number by calling socket.writeFloat. I initially tried writeInt, but ActionScript ints are 4 bytes, where the Arduino int is 2. Thibault suggested I send the number using writeShort, but that also did not work.

Basically, the only way I was able to get it to work, was to use writeFloat. In practice this should not matter, but it is something you should keep in mind.

Now, I am pretty sure it is possible to send other ActionScript multibyte number types using writeInt, writeUnsignedInt and writeShort, since we are just sending raw bytes over the socket. However, I have not figured out how to reconstruct them on the Arduino side yet. If anyone gets additional types working, then post a note in the comments.

UPDATE : I have posted another example that shows how to send ints / shorts from ActionScript to Arduino. You can view the code here.

Being able to easily send multibyte numbers make communication significantly easier, because, now, among other things, we can easily send packets of complex data. Ill leave that for another post though.

If you have any suggestions or corrections, then leave them in the comments.

Written by mikechambers

August 1st, 2010 at 11:03 pm

Posted in General

Tagged with ,

8 Responses to 'Sending Multibyte Numbers from ActionScript to Arduino'

Subscribe to comments with RSS or TrackBack to 'Sending Multibyte Numbers from ActionScript to Arduino'.

  1. Using floats on an Arduino is generally frowned upon. The AVR chip has no FPU, so any floating point manipulation must all be done in software. This is very slow compared to manipulating ints, plus it eats up your valuable program space in order to include the float manipulation libraries.

    David R

    1 Aug 10 at 11:20 pm

  2. @David


    Using floats on an Arduino is generally frowned upon.

    Yeah, I would prefer to send ints or uints, but havent had any luck with it thus far.

    Hopefully, someone who knows more of the C / Arduino side will see the post and might be able to make some suggestions.

    mike chambers

    mesh@adobe.com

    mikechambers

    1 Aug 10 at 11:31 pm

  3. For those in London we have a session on Arduino and AS next month.

    http://www.lfpug.com/26th-august-2010-26082010/

    Tink

    2 Aug 10 at 1:25 am

  4. Hi Mike,
    Can’t wait to see your Flash / Arduino getting started tutorial. I’ve been working with an Arduino lately, but have been mostly sticking with Processing. A straightforwards walkthrough for communicating directly with Flash would be awesome – especially for reading data in from the Arduino Analog inputs. Cheers. Lawrie.

    Lawrie

    2 Aug 10 at 4:06 am

  5. You might have luck sending out a known hex int (like writeUnsignedInt(0xDEADBEEF)) then reading back on the Arduino side. From the hex value you get back it should be easy to infer how things are getting mangled.

    Also, why isn’t there a writeUnsignedChar? Then you could do 0-255. With the existing one, -128..127 should be possible.

    Ben Garney

    2 Aug 10 at 9:22 am

  6. I’m not entirely sure why, but it seems i’m able to send/receive values from 0-255 to and from Arduino with the AS3 Socket using writeByte().

    //ActionScript
    socket.writeByte(int(myInput.text)); // 0-255

    //Sketch
    if (Serial.available() > 0)
    {
    incomingByte = Serial.read();
    Serial.println(incomingByte, DEC);
    }

    sending numbers outside of the 0-255 range are looped, so 256 becomes 0, and -1 becomes 255.

    TheDarkIn1978

    20 Sep 10 at 2:38 am

  7. I managed to read the flash -> arduino serial messages alright and I successfully used the sent values to change the delay of a blinking LED.

    However, this only works if the serial monitor is open (using SerProxy).. if I close the serial monitor window, the output stops (normal), but also the serial read stops receiving any data. any thoughts on this?
    thanks

    Omar

    7 Dec 10 at 8:11 am

  8. Hello Mike:
    I,m lost in a proyect that i can“t finish,need the void() for send a float data via serial from a Arduino and receive it with the funcion of your article.
    I was trying and no find the math.
    Many thanks for all

Leave a Reply