Pages: [1]   Go Down
Author Topic: Using the sensorbox firmware with Flash  (Read 710 times)
0 Members and 1 Guest are viewing this topic.
Brooklyn, NY, USA
Offline Offline
Full Member
***
Karma: 0
Posts: 115
arduino for all
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

 
Quote
I didn't understand how pd handles the incoming data
how do you register an object in pd to a specific imput from Arduino?

pd is already based on streams of data, AKA dataflow, so this firmware makes Arduino output the data as fast as it can read it in a stream.  Then changing modes, (input, output, PWM, pulseIn) are done using commands, which are like events.

Quote
how do you do something like this
val1 = analogRead(pin5)
val2 = digitalRead(pin6)

In a program like Flash that is event-based (like most programming languages), I think I would make an interface similar to how you would get mouse coordinates: send data only when it changes, and then make events for each change.  But that would probably be quite a bit of work.  

A simple idea for the analogIns would be to make a function that write the value to a variable whenever it receives data from the serial port, then analogRead() would just output that variable.  Digital reading is trickier since you are likely going to be using buttons with that.  Then its really like an event.  If you just poll it with something like digitalRead(), then you might miss a button press.

Quote
Quote
To start read data from Arduino, you wait for the cycle marker byte: 255. Then you are at the top of the cycle. The next byte is digital pins 0-6, then digital pins 7-14. Then comes byte pairs for each analogIn, which are reassembled to make the 10-bit value. To send digital data to Arduino, its just a 3 byte cycle, 255 for the marker, one by for digital pins 0-6 and the next byte for pins 7-13.

I can understand if you serialize the data coming from Arduino
so that Arduino sends a long "string" or byte-cycle like  
255   0 0 0 0 0 0   0 0 0 0 0 0    ?-? ?-? ?-? ?-? ?-?
where
- 255 is the starting cycle marker  
- 6 bytes for digital pin 1->6
- 6 bytes for digital pin 7->14
- 5 pairs(?-?) what do they look like (I have to test it yet)
 

This is complicated, I did this to make the data format as compact as possible.  But its not too bad to use once you get the hang of it.  You have to think in terms of bits here.  For example, for each byte on the serial port, the 8th bit is used to mark that byte as data or commands.  If the 8th bit is 0, that byte is data (0-127 is the range of values then).  If the 8th bit is 1, that byte is a command (128-255).

Its actually like this (each element is a byte):



255 pin0-6 pin7-13 aIn0-high aIn0-low aIn1-high aIn1-low aIn2-high aIn2-low


pin0-6 is one byte, 8 bits.  The first 7 bits are mapped to digital input pins 0 thru 6.  The 8th bit is always 0.

pin7-13 is one byte, 8 bits.  The first 7 bits are mapped to digital input pins 7 thru 13.  The 8th bit is always 0.

So for these you need to use bit-wise operators to get each pin's value from the byte.  For this you would use the bitwise AND: & (note, its not &&).  To get the value of the first bit, you would do (inputByte & 1), for the second (inputByte & 2), for the third (inputByte & 4).  The second argument is 2 to the power of X, where X is the bit position.  Basically, its like an array of bits.  So the first bit is (inputByte & (2^0)), so like arrays, the first element is 0.



The analog values also use bitwise techniques to fit 10-bits of data into two separate 8-bit bytes.  With the analog data, I just use the first 7-bits and set the 8th bit to 0, to mark that byte as data and not a command.

I build these bytes like this:
    printByte(analogData >> 7);  // bitshift the big stuff into the output byte
    printByte(analogData % 128);  // mod by 32 for the small byte

The first one, I take the 16-bit int analogData, and use a >> "right-shift" bitwise operator.  This literally moves the bits to the right.  So I move the values over 7 bits, so I am now getting the top 7-bits of analogData and output that as a byte.

Then I use % "modulo" 128 to get the bottom 7-bits of analogData and output that as a byte.

Then on the host side, I have to reassemble those two values into a 14-bit value.  That is easy: for the first byte, the high byte, I multiply it by 128 (2^7), then I add the second byte.  Voila.  You know have 14-bits of resolution sent in 8-bit chunks.



This may seem quite complicated, but it has a number of benefits: the data cycle is always two bytes at a time, so you don't have to deal with variable data length.  Plus its super compact, so it sends data as quickly as possible.  But yes, it makes the programming more complicated.  That's why I want to see easy-to-use objects written for other languages, so people don't have to think about these low-level details, but can reap the benefits of really fast data transfer.
Logged

Brooklyn, NY, USA
Offline Offline
Full Member
***
Karma: 0
Posts: 115
arduino for all
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, I had to continue this in a new post since its quite long

Quote
in this case is a bit easyer
there is only one object that listens to the incoming data and then dispatches the different information
to whoever is listening...or they simply pull the data from the dataset...
it could create some asyncronous computation but I'm not sure
I fear that it can be a mess to code for the user...but i'll give it a try
 
in the end of the day it would be great to code in Actionscript something like
// read analog value
val = Arduino.pin0.value
//set digital value
Arduino.pin6.value = HI;
//set action
Arduino.pin9.pulseTo(someValue)
 
in fact the pulsing could be handled internally by Flash with no problems and just sending single digitalWrites at the specified rate..that could be really cool...and doing FFT inside flash  Shocked  Cool
 
What I fear is that the architecture would ask the user to code more or less the same things inside Flash that he would do in Arduino...I can see almost no point in that

I think the key for the digital inputs is to make events like mouse button presses, then have the arduino firmware and matching flash object handle the generation of these events.  Maybe the firmware itself should only send the digital input information whenever it receives a change.  But I wonder if that would reduce the flexibility of what you can do then.

 
Quote
it could be great if you could explain on the wiki a bit better the "string" that has to be SENT TO Arduino to set commands and the "string" that is RECEIVED FROM Arduino..
give some examples, it would make it easier.

I am not 100% sold on the current design, so I'd like to hear suggestions for how to improve it.  But here are some examples of how it currently works:

commands to send to arduino


setting PWM
(2 bytes: pin, value)
set pin 9 - (230 x) where x = 0-255
set pin 10 - (231 x) where x = 0-255
set pin 11 - (232 x) where x = 0-255

example: 232 128 sets pin10/PWM1 to do half time PWM


setting how many analogIns to read
(1 byte: how many pins + 240)
0 analogIns - 240
1 analogIns - 241
2 analogIns - 242
3 analogIns - 243
4 analogIns - 244
5 analogIns - 245
6 analogIns - 246

example: 240 turns off analog input
               242 transmits the first two analog inputs


turning on and off digitalinput
(1 byte: on/off + 238)
turn off digital input - 238
turn on digital input - 239




send data to digital output
This uses the same bitmask format as arduino transmits for the digital inputs
(3 bytes: (cycle-marker, pin0-6, pin7-13))

example: 255 1 1 sets all digital output pins LOW, except 0 and 7 are set HIGH
example: 255 0 1 sets all digital output pins LOW, except 7 is set HIGH
example: 255 7 0 sets all digital output pins LOW, except 0, 1, and 2 are set HIGH
Logged

Brooklyn, NY, USA
Offline Offline
Full Member
***
Karma: 0
Posts: 115
arduino for all
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset



Oops, small typo in the examples, it should read like this:

setting PWM  
(2 bytes: pin, value)
set pin 9 - (230 x) where x = 0-255
set pin 10 - (231 x) where x = 0-255
set pin 11 - (232 x) where x = 0-255
 
example: 232 128 sets pin11/PWM2 to do half time PWM
 

Thanks to Ben Bogart for spotting this.
Logged

Brooklyn, NY, USA
Offline Offline
Full Member
***
Karma: 0
Posts: 115
arduino for all
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Things have changed a bit, so I thought I'd write a quick note here about what's changed.  You can see the diff on the source code here:

http://pure-data.cvs.sourceforge.net/pure-data/externals/hardware/arduino/Pd_firmware/Pd_firmware.pde?view=diff&r1=text&tr1=1.9&r2=text&tr2=1.21&diff_format=h

What's changed:

Analog inputs are now reported each with their own header byte so that there can be interruptions when reporting the analog pins (previously, it had to report all analogIns before anything else could report):

/* analog input message format
 * ----------------------
 * 0   analog input marker (160 + pin number reported)
 * 1   high byte from analog input
 * 2   low byte from analog input
 */


the digital bytes have changed order:

/* two byte digital output data format
 * ----------------------
 * 0  get ready for digital input bytes (229)
 * 1  digitalOut 7-13 bitmask
 * 2  digitalOut 0-6 bitmask
 */

You can query the version of the firmware now:

#define REPORT_VERSION          240 // return the firmware version

Send a single byte 240 to Arduino, it will reply with:

/* version report format
 * ----------------------
 * 0  version report header (240)
 * 1  major version
 * 2  minor version
 */



« Last Edit: November 30, 2006, 11:13:51 am by eighthave » Logged

Pages: [1]   Go Up
Jump to: