Pages: [1]   Go Down
Author Topic: processing2arduino - parsing serial stream  (Read 1016 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello everyone,

I built an application to control a servo motor with moue movements. I mapped X coords to angle of servo motor. Now I want to add Y coords to control another servo motor, and I need a way to parse the serial stream on arduino, in order to distingush what is what.

Any pointer will do....
thanks

C5
Logged

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6255
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

There are lots of ways do to what you want. I assume your x and y values are 16 bit integers. The app I am currently working sends and receives binary packets, so I have distilled the following which may be useful.  
Usage: if(SerialInput() == 'x')
                // do something with xValue;

Code:
// the routine below expect 3 bytes:
// tag - 'x' or 'y' to indicate the meaning of the following value
// msb - the most significant byte of the value
// lsb - lsb of the value
//
// you can define other tags if other more data needs to be sent, but the code below //always expects  exactly two bytes after each tag.

int xValue;
int yValue;


char SerialInput() {
  // returns 'x' if x value received, 'y' if y value, or 0 if nothing

   if(Serial.available() >= 3 ){
          uint8_t      tag = Serial.read();  
          uint8_t      msb = Serial.read();
          uint8_t      lsb = Serial.read();
          unsigned int value = lsb + (msb <<8);
          
          switch(tag) {
             case 'x' : xValue = value; break;         // save the value in the global variable
             case 'y' : yValue = value; break;
             default  : tag = 0;   //not a valid tag
          }
          return tag;  
   }
   return 0;
}

I haven't used processing, but would think the sending code would look something like the following.
 Example usage: SendMessage('x', 300);
Code:
void SendMessage(char tag, int value) {
   Serial.write(tag,byte);
   Serial.write(value >>8 ,byte);
   Serial.write( (byte)value) ;  
}
« Last Edit: January 08, 2008, 01:08:14 pm by mem » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for your reply mem,

I tryed to use your code on arduine, and just to fetch data from serial send command integrated in arduino, and then to print teh results, but I couldn't manage to do it.
Can you help on this one?

This is what is on arduino:

Code:

int xValue;
int yValue;


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

void loop() {

  SerialInput();

  }

char SerialInput() {
  // returns 'x' if x value received, 'y' if y value, or 0 if nothing

   if(Serial.available() >= 3 ){
          uint8_t      tag = Serial.read();  
          uint8_t      msb = Serial.read();
          uint8_t      lsb = Serial.read();
          unsigned int value = lsb + (msb <<smiley-cool;
          
          switch(tag) {
             case 'x' : xValue = value; break;         // save the value in the global variable
             case 'y' : yValue = value; break;
             default  : tag = 0;   //not a valid tag
          }
          return tag;  
         Serial.println(xValue);
         Serial.println(yValue);
   }
   return 0;
}
 

« Last Edit: January 09, 2008, 05:58:36 am by C5 » Logged

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6255
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The routine returns just before you print the values so they are never sent.

You can fix it as follows:
    Before the if(Serial.available() >= 3 ){ statement, add the statment: tag=0 ;
    move the return tag; statement to the end of the routine in place of the return 0;

The posted code would also work if you put the return tag statement after the print statements but the above is clearer.  

When I posted I was thinking that your code would do something like

loop() {
   if(SerialInput() ) {
        Serial.println(xValue);
        Serial.println(yValue);
   }  
}
« Last Edit: January 09, 2008, 07:49:32 am by mem » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello mem,

I can say that something is going on, but it is not clear what.

I'm still trying to control my servo from the arduino serial monitor send command.

The data that arduino is expecting are from 0 to 1023 for x and from 0 to 255 for y, in command like this SendComm("x"+mouseXcoords+"y"+mouseYcoord+/n);
Where I will have for example if the cursor is in the middle,
stream = x512y128
and so on...

To achive this, should I modify your code to do something like this:
if SerialInput == x
read the stream untill SerialInput == y
this input = xValue
else if SerialInput == y
read the stream until /n
this input = yValue

Or do you have any other clue regarding the data types, and teh protocol...

Thanks

C5
Logged

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6255
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

if you are sending the x and y data together then you can simplify the code.  The following assumes 'x' as a header and then both x and y as 16 bit values using two bytes each.  The msb of y will always be zero for now but if your mouse hardware changes you won't have to change the protocol

Code:
int xValue,yValue;

boolean SerialInput() {
  // returns true if valid data received, global x & y variables are updated
  // packets start with the char 'x' and include x and y co-ords
 // protocol consists of 5 bytes  'x', xmsb, xlsb, ymsb, ylsb
 
   boolean result = false ;                // default return code if we dont get a valid packet
   if(Serial.available() >= 5 ){  
         if( Serial.read() == 'x'){  // if true this the start of a packet???                  
            uint8_t      msb = Serial.read();   // get the x data
            uint8_t      lsb = Serial.read();
            xValue = lsb + (msb <<8);           // save the x data
            msb = Serial.read();               // get the y data  
            lsb = Serial.read();
            yValue = lsb + (msb <<8);
            result = true;                      // we have a packet and have updated the global variables
         }
   }    
   return result;
}
 

I am assuming you are using processing and that write(byte) will send a raw byte,

Assuming X and Y are the integer values of the mouse, the protocol assumes  something like:

send('x');
send ((byte)(X / 256));
send ((byte)(X % 256));    //  X mod 256
send((byte)(Y/ 256));
send ((byte)(Y % 256));

If you are using Processing and that doesn't send raw data then we may need a whole new protocol.
BTW, I think Processing needs those casts so it knows that the data is a byte, but I have not actually used Processing myself so am not really sure.
« Last Edit: January 09, 2008, 11:30:08 am by mem » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

mem,

It works, thanks A LOT.

it still needs some fine tuning, but it works. I don't know whay I was complicating it here......

anyway, i'm glad we finished it...I owe you a beer...minimum smiley-wink


C5
Logged

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6255
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Good to hear its working. Have fun. Post the results when you have it finished

Oh, and thanks for the beer  smiley
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello mem,

its been awhile and i forgot to post my code.

here is for future reference, the code works really good, and its super fast.
i implemented some stuff if for example you turn off the system i want my camera calibrated, and some more that i forgot, go tru the code and see for yourself, the messge expected is "X123" if you want X axix and 123 value

cheers

thanks

int servoPinX = 2;     // control pin for X servo motor
int minPulseX = 500;   // minimum servo position
int maxPulseX = 2500;  // maximum servo position
int pulseX = 0;        // amount to pulse the servo

int inputX = 0;
int inputY = 0;

long lastPulseX = 0;    // the time in milliseconds of the last pulse
int refreshTimeX = 20; // the time needed in between pulses

int analogValueX = 0;

int servoPinY = 3;     // control pin for Y servo motor
int minPulseY = 500;   // minimum servo position
int maxPulseY = 2500;  // maximum servo position
int pulseY = 0;        // amount to pulse the servo


long lastPulseY = 0;    // the time in milliseconds of the last pulse
int refreshTimeY = 20; // the time needed in between pulses

int analogValueY = 0;

int xValue = 128;
int yValue = 64;

int input = 0;

void setup() {
    pinMode(servoPinX, OUTPUT); // Set X servo pin as an output pin
    pinMode(servoPinY, OUTPUT); // Set Y servo pin as an output pin
    pulseX = minPulseX; // Set the X motor position value to the minimum
    pulseY = minPulseY; // Set the Y motor position value to the minimum

    Serial.begin(9600); //begin serial communication

}

void loop() {

    char in = SerialInput();

    if(in == 'x'){ //if X received...
        inputX = xValue;

        analogValueX = (inputX*4);      // read the analog input
        pulseX = (analogValueX * 19) / 10 + minPulseX;    // convert the analog value
        // to a range between minPulse
        // and maxPulse.

        // pulse the servo again if rhe refresh time (20 ms) have passed:
        if (millis() - lastPulseX >= refreshTimeX) {
            digitalWrite(servoPinX, HIGH);   // turn the motor on
            delayMicroseconds(pulseX);       // length of the pulse sets the motor position
            digitalWrite(servoPinX, LOW);    // turn the motor off
            lastPulseX = millis();           // save the time of the last pulse
        }
    }
    else if(in == 'y'){
        inputY = yValue;

        analogValueY = (inputY*4);      // read the analog input
        pulseY = (analogValueY * 19) / 10 + minPulseY;    // convert the analog value
        // to a range between minPulse
        // and maxPulse.

        // pulse the servo again if rhe refresh time (20 ms) have passed:
        if (millis() - lastPulseY >= refreshTimeY) {
            digitalWrite(servoPinY, HIGH);   // turn the motor on
            delayMicroseconds(pulseY);       // length of the pulse sets the motor position
            digitalWrite(servoPinY, LOW);    // turn the motor off
            lastPulseY = millis();           // save the time of the last pulse
        }
    }
    else if(in == '0'){
        int inX = 128;

        analogValueX = (inX*4);      // read the analog input
        pulseX = (analogValueX * 19) / 10 + minPulseX;    // convert the analog value
        // to a range between minPulse
        // and maxPulse.

        // pulse the servo again if rhe refresh time (20 ms) have passed:
        if (millis() - lastPulseX >= refreshTimeX) {
            digitalWrite(servoPinX, HIGH);   // turn the motor on
            delayMicroseconds(pulseX);       // length of the pulse sets the motor position
            digitalWrite(servoPinX, LOW);    // turn the motor off
            lastPulseX = millis();           // save the time of the last pulse
        }

        int inY = 64;

        analogValueY = (inY*4);      // read the analog input
        pulseY = (analogValueY * 19) / 10 + minPulseY;    // convert the analog value
        // to a range between minPulse
        // and maxPulse.

        // pulse the servo again if rhe refresh time (20 ms) have passed:
        if (millis() - lastPulseY >= refreshTimeY) {
            digitalWrite(servoPinY, HIGH);   // turn the motor on
            delayMicroseconds(pulseY);       // length of the pulse sets the motor position
            digitalWrite(servoPinY, LOW);    // turn the motor off
            lastPulseY = millis();           // save the time of the last pulse
        }

    }
    else if(! Serial.available()){
        inputX = xValue;

        analogValueX = (inputX*4);      // read the analog input
        pulseX = (analogValueX * 19) / 10 + minPulseX;    // convert the analog value
        // to a range between minPulse
        // and maxPulse.

        // pulse the servo again if rhe refresh time (20 ms) have passed:
        if (millis() - lastPulseX >= refreshTimeX) {
            digitalWrite(servoPinX, HIGH);   // turn the motor on
            delayMicroseconds(pulseX);       // length of the pulse sets the motor position
            digitalWrite(servoPinX, LOW);    // turn the motor off
            lastPulseX = millis();           // save the time of the last pulse
        }
        inputY = yValue;

        analogValueY = (inputY*4);      // read the analog input
        pulseY = (analogValueY * 19) / 10 + minPulseY;    // convert the analog value
        // to a range between minPulse
        // and maxPulse.

        // pulse the servo again if rhe refresh time (20 ms) have passed:
        if (millis() - lastPulseY >= refres
Logged

London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6255
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi C5,

Thanks for sharing, have fun!
Logged

Pages: [1]   Go Up
Jump to: