Solved:time lag as encoders control the mouse via Arduino serial communication

Can you provide one or two sentences that describe what each of your functions is supposed to do.

...R

Absolutely. Sorry for the confusion. The comments on the main function of code have been added to the relevant lines.

const int switchPin = 2;
const int mouseButton = 3;
const int ledPin = 13;

int value = 0;

boolean mouseIsActive = false;
int prevSwitchState = HIGH;
int prevButtonState = LOW;

int toggle = 0;
int flag = 0;

int f;
int t=0;

int f_prev = 0;
int t_prev = 0;
// dont forget to change back 
int datain_Byte[6];
int th;
int fi;
int z;

void setup()
{
  pinMode(switchPin,INPUT);
  pinMode(ledPin,OUTPUT);
  Serial.begin(115200);
  Serial1.begin(115200);
  Mouse.begin();
  while(!Serial);
}

void loop()
{
  mouseActiveFcn(); // a push button controls the power to the Arduino.
  dataReading(); // get data from robot encoder. The data consists game selection integer z, 
                 //finger rotation angle, thumb rotation angle. Because the Arduino define integer
                 // as 2 bytes. Each piece of data consists of six bytes.
                 
                 // a physical control box has button to turn on and off the arduino.
                 // If it is on, mouseIsActive == true, the following lines will be
                 // executed. 
  if (mouseIsActive == true){
    if (z == 1 ){ // z is the integer that is generated by robot computer which 
                  // selects the game people like to play. 
      if(value==1){ // value = 1 incidates that the encoder data from robot comes in. Then
                    // Arduino takes control of game computer mouse. If value = 0, the computer mouse
                    // plays the game. 
        angryBirdGame(); // Arduino mouse is activated from map function
      }
      angryBirdMouseButton(); // Arduino controls the mouse key hold and release
    }
  }
//    
    if( z== 2){ // the same logic with z = 1;
      if(value==1){
        bubbleShootGame(); // Arduino mouse is activated from map function
      }
      clickMouse(); // Arduino activates the mouse key click function
    }
       
  }

  
  void mouseActiveFcn(){
    int switchState = digitalRead(switchPin);
  if (switchState != prevSwitchState) {
    if (switchState == LOW) {
      mouseIsActive = !mouseIsActive;
      digitalWrite(ledPin, mouseIsActive);
    }
  }
   prevSwitchState = switchState;
   delay(10);
  }
  
  void dataReading()
  {
            if(Serial1.available()>5) {
      
      for (int n = 0; n < 6; n++)
      {
        datain_Byte[n] = Serial1.read();
        value = 1;
      }
          z = 256*datain_Byte[1] + datain_Byte[0];
          f = (256*datain_Byte[3] + datain_Byte[2]);
          t = (256*datain_Byte[5] + datain_Byte[4]);
          Serial.println(z);
         // Serial.println(f);
         // Serial.println(t);
          //Serial.println();
          f_prev = f;
          t_prev = t;     
      }
          else {
            value = 0;
            f = f_prev;
            t = t_prev;
          }

    
  }
  
  
  void angryBirdGame(){
   
       th = map(t,0,130,28,13);
       fi = map(f,0,480,70,88);
       Mouse.move(th, fi, 0); 
  }
  
  void angryBirdMouseButton(){
       int buttonState = digitalRead(mouseButton);
       if (buttonState == HIGH && prevButtonState == LOW) {
     // if the mouse is not pressed, press it:
     toggle++;
     if(toggle == 1)
     {
     if(t < 5 && f < 6){
       if (!Mouse.isPressed(MOUSE_LEFT)) {
         Mouse.press(MOUSE_LEFT); 
       }
     //Serial.println(toggle);  
     }
     else
     { toggle = 0;
     //Serial.println(toggle); 
     }
   }
   else if(toggle == 2)
   {
     // else the mouse button is not pressed:
     // if the mouse is pressed, release it:
     if (Mouse.isPressed(MOUSE_LEFT)) {
       Mouse.release(MOUSE_LEFT); 
     }
     toggle = 0;
   }
   }

   prevButtonState = buttonState;  
  }
  
  void bubbleShootGame(){
       th = map(t,0,180,80,0);
       fi = map(f,0,480,100,0);
       Mouse.move(th, fi, 0);
  }
  
  void clickMouse(){
     int buttonState = digitalRead(mouseButton);
   if (buttonState == HIGH && prevButtonState == LOW) {
     Mouse.click();
   }
   prevButtonState = buttonState;
   delay(10);
  }
  
  
  void generalMove(){
       th = map(t,0,7,0,120);
       fi = map(f,0,17,0,120);
       Mouse.move(th, fi, 0);
     int buttonState = digitalRead(mouseButton);
   if (buttonState == HIGH && prevButtonState == LOW) {
     Mouse.click();
   prevButtonState = buttonState;
   }
   delay(10);
  }
  
  void holdMouse(){
     int buttonState = digitalRead(mouseButton);
   if (buttonState == HIGH && prevButtonState == LOW) {
     // if the mouse is not pressed, press it:
     toggle++;
     if(toggle == 1)
       if (!Mouse.isPressed(MOUSE_LEFT)) {
         Mouse.press(MOUSE_LEFT); 
       }  
   }
   else if(toggle == 2)
   {
     // else the mouse button is not pressed:
     // if the mouse is pressed, release it:
     if (Mouse.isPressed(MOUSE_LEFT)) {
       Mouse.release(MOUSE_LEFT); 
     }
     toggle = 0;
   }
   prevButtonState = buttonState;
   delay(10);
   }

Your code formatting is very poor. It has taken me a long time to make it readable. Use the autoformat option in the Arduino IDE.

I notice that you have a test

    if (mouseIsActive == true){
        if (z == 1 )

but the corresponding if (z == 2) is NOT within the If (mouseIsActive
(Very obvious with proper formatting)

Might that be the problem?

...R

Robin2,

Thanks a lot for the help. Sorry for the very formatting and for taking your quite long time to spot that. You just taught me a lesson on the importance of formatting. Yes, that should be inside the IF condition of MouseActive =true as well. However, the issue still persists. When I select z =2, the mapping range gets bigger. As I move faster and faster of my robot, the cursor movement on the game computer starts delaying and eventually the cursor stops the move. And then I check the serial monitor of Z output from Arduino. Z is not 2 anymore. It becomes some random number like 727, or -22207 and as such.

const int switchPin = 2;
const int mouseButton = 3;
const int ledPin = 13;

int value = 0;

boolean mouseIsActive = false;
int prevSwitchState = HIGH;
int prevButtonState = LOW;

int toggle = 0;
int flag = 0;

int f;
int t=0;

int f_prev = 0;
int t_prev = 0;
// dont forget to change back 
int datain_Byte[6];
int th;
int fi;
int z;

void setup()
{
  pinMode(switchPin,INPUT);
  pinMode(ledPin,OUTPUT);
  Serial.begin(115200);
  Serial1.begin(115200);
  Mouse.begin();
  while(!Serial);
}

void loop()
{
  mouseActiveFcn(); // a push button controls the power to the Arduino.
  dataReading(); // get data from robot encoder. The data consists game selection integer z, 
  //finger rotation angle, thumb rotation angle. Because the Arduino define integer
  // as 2 bytes. Each piece of data consists of six bytes.

  // a physical control box has button to turn on and off the arduino.
  // If it is on, mouseIsActive == true, the following lines will be
  // executed. 
  if (mouseIsActive == true){
    if (z == 1 ){ // z is the integer that is generated by robot computer which 
      // selects the game people like to play. 
      if(value==1){ // value = 1 incidates that the encoder data from robot comes in. Then
        // Arduino takes control of game computer mouse. If value = 0, the computer mouse
        // plays the game. 
        angryBirdGame(); // Arduino mouse is activated from map function
      }
      angryBirdMouseButton(); // Arduino controls the mouse key hold and release
    }
  //    
  if( z== 2){ // the same logic with z = 1;
    if(value==1){
      bubbleShootGame(); // Arduino mouse is activated from map function
    }
    clickMouse(); // Arduino activates the mouse key click function
  }
  }

}


void mouseActiveFcn(){
  int switchState = digitalRead(switchPin);
  if (switchState != prevSwitchState) {
    if (switchState == LOW) {
      mouseIsActive = !mouseIsActive;
      digitalWrite(ledPin, mouseIsActive);
    }
  }
  prevSwitchState = switchState;
  delay(10);
}

void dataReading()
{
  if(Serial1.available()>5) {

    for (int n = 0; n < 6; n++)
    {
      datain_Byte[n] = Serial1.read();
      value = 1;
    }
    z = 256*datain_Byte[1] + datain_Byte[0];
    f = (256*datain_Byte[3] + datain_Byte[2]);
    t = (256*datain_Byte[5] + datain_Byte[4]);
    Serial.println(z);
    // Serial.println(f);
    // Serial.println(t);
    //Serial.println();
    f_prev = f;
    t_prev = t;     
  }
  else {
    value = 0;
    f = f_prev;
    t = t_prev;
  }


}


void angryBirdGame(){

  th = map(t,0,130,28,13);
  fi = map(f,0,480,70,88);
  Mouse.move(th, fi, 0); 
}

void angryBirdMouseButton(){
  int buttonState = digitalRead(mouseButton);
  if (buttonState == HIGH && prevButtonState == LOW) {
    // if the mouse is not pressed, press it:
    toggle++;
    if(toggle == 1)
    {
      if(t < 5 && f < 6){
        if (!Mouse.isPressed(MOUSE_LEFT)) {
          Mouse.press(MOUSE_LEFT); 
        }
        //Serial.println(toggle);  
      }
      else
      { 
        toggle = 0;
        //Serial.println(toggle); 
      }
    }
    else if(toggle == 2)
    {
      // else the mouse button is not pressed:
      // if the mouse is pressed, release it:
      if (Mouse.isPressed(MOUSE_LEFT)) {
        Mouse.release(MOUSE_LEFT); 
      }
      toggle = 0;
    }
  }

  prevButtonState = buttonState;  
}

void bubbleShootGame(){
  th = map(t,0,180,80,0);
  fi = map(f,0,480,100,0);
  Mouse.move(th, fi, 0);
}

void clickMouse(){
  int buttonState = digitalRead(mouseButton);
  if (buttonState == HIGH && prevButtonState == LOW) {
    Mouse.click();
  }
  prevButtonState = buttonState;
  delay(10);
}


void generalMove(){
  th = map(t,0,7,0,120);
  fi = map(f,0,17,0,120);
  Mouse.move(th, fi, 0);
  int buttonState = digitalRead(mouseButton);
  if (buttonState == HIGH && prevButtonState == LOW) {
    Mouse.click();
    prevButtonState = buttonState;
  }
  delay(10);
}

void holdMouse(){
  int buttonState = digitalRead(mouseButton);
  if (buttonState == HIGH && prevButtonState == LOW) {
    // if the mouse is not pressed, press it:
    toggle++;
    if(toggle == 1)
      if (!Mouse.isPressed(MOUSE_LEFT)) {
        Mouse.press(MOUSE_LEFT); 
      }  
  }
  else if(toggle == 2)
  {
    // else the mouse button is not pressed:
    // if the mouse is pressed, release it:
    if (Mouse.isPressed(MOUSE_LEFT)) {
      Mouse.release(MOUSE_LEFT); 
    }
    toggle = 0;
  }
  prevButtonState = buttonState;
  delay(10);
}

What do you see when you print the raw values of f and t ?

How about meaningful names for f, t and z

Have you any idea how many "hits" my text editor gets when I ask it to find "t"

...R

nice point, Robin2. Attached is revised code. Let me know if anything else needs to be rewritten. Thanks a lot for the critics.

const int switchPin = 2;
const int mouseButton = 3;
const int ledPin = 13;

int value = 0;
boolean mouseIsActive = false;
int prevSwitchState = HIGH;
int prevButtonState = LOW;
int toggle = 0;
int flag = 0;
int fingerAngle= 0; //fingerAngle from encoder
int thumbAngle =0;//thumbAngle from encoder
int fingerAngle_prev = 0; // previous finger angle from encoder
int thumbAngle_prev = 0; // previous thumb angle from encoder
int datain_Byte[6];
int thumbAngle_pixel = 0; // thumb angle mapped to pixels on game computer screen
int fingerAngle_pixe = 0; // finger angle mapped to pixels on game computer screen
int gameSelection = 0; //gameSelection

void setup()
{
  pinMode(switchPin,INPUT);
  pinMode(ledPin,OUTPUT);
  Serial.begin(115200);
  Serial1.begin(115200);
  Mouse.begin();
  while(!Serial);
}

void loop()
{
  mouseActiveFcn(); // a push button controls the power to the Arduino.
  dataReading(); // get data from robot encoder. The data consists game selection integer z, 
  //finger rotation angle, thumb rotation angle. Because the Arduino define integer
  // as 2 bytes. Each piece of data consists of six bytes.

  // a physical control box has button to turn on and off the arduino.
  // If it is on, mouseIsActive == true, the following lines will be
  // executed. 
  if (mouseIsActive == true){
    if (gameSelection == 1 ){ // z is the integer that is generated by robot computer which 
      // selects the game people like to play. 
      if(value==1){ // value = 1 incidates that the encoder data from robot comes in. Then
        // Arduino takes control of game computer mouse. If value = 0, the computer mouse
        // plays the game. 
        angryBirdGame(); // Arduino mouse is activated from map function
      }
      angryBirdMouseButton(); // Arduino controls the mouse key hold and release
    }
    //    
    if( gameSelection== 2){ // the same logic with z = 1;
      if(value==1){
        bubbleShootGame(); // Arduino mouse is activated from map function
      }
      clickMouse(); // Arduino activates the mouse key click function
    }
  }

}


void mouseActiveFcn(){
  int switchState = digitalRead(switchPin);
  if (switchState != prevSwitchState) {
    if (switchState == LOW) {
      mouseIsActive = !mouseIsActive;
      digitalWrite(ledPin, mouseIsActive);
    }
  }
  prevSwitchState = switchState;
  delay(10);
}

void dataReading()
{
  if(Serial1.available()>5) {

    for (int n = 0; n < 6; n++)
    {
      datain_Byte[n] = Serial1.read();
      value = 1;
    }
    gameSelection = 256*datain_Byte[1] + datain_Byte[0];
    fingerAngle = (256*datain_Byte[3] + datain_Byte[2]); //current finger angle
    thumbAngle  = (256*datain_Byte[5] + datain_Byte[4]); //current thumb angle
    Serial.println(gameSelection);
    fingerAngle_prev = fingerAngle;
    thumbAngle_prev = thumbAngle;     
  }
  else {
    value = 0;
    fingerAngle = fingerAngle_prev;
    thumbAngle = thumbAngle_prev;
  }


}


void angryBirdGame(){

  thumbAngle_pixel = map(thumbAngle,0,130,28,13); //this function maps the thumb angle from encoder to the game computer pixel setting
  fingerAngle_pixel = map(fingerAngle,0,480,70,88);
  Mouse.move(thumbAngle_pixel, fingerAngle_pixel, 0); 
}

void angryBirdMouseButton(){
  int buttonState = digitalRead(mouseButton);
  if (buttonState == HIGH && prevButtonState == LOW) {
    // if the mouse is not pressed, press it:
    toggle++;
    if(toggle == 1)
    {
      if(thumbAngle_pixel < 5 && fingerAngle_pixel < 6){
        if (!Mouse.isPressed(MOUSE_LEFT)) {
          Mouse.press(MOUSE_LEFT); 
        } 
      }
      else
      { 
        toggle = 0;
      }
    }
    else if(toggle == 2)
    {
      // else the mouse button is not pressed:
      // if the mouse is pressed, release it:
      if (Mouse.isPressed(MOUSE_LEFT)) {
        Mouse.release(MOUSE_LEFT); 
      }
      toggle = 0;
    }
  }

  prevButtonState = buttonState;  
}

void bubbleShootGame(){
  thumbAngle_pixel = map(thumbAngle,0,180,80,0);
  fingerAngle_pixel = map(fingerAngle,0,480,100,0);
  Mouse.move(thumbAngle_pixel, fingerAngle_pixel, 0);
}

void clickMouse(){
  int buttonState = digitalRead(mouseButton);
  if (buttonState == HIGH && prevButtonState == LOW) {
    Mouse.click();
  }
  prevButtonState = buttonState;
  delay(10);
}


void holdMouse(){
  int buttonState = digitalRead(mouseButton);
  if (buttonState == HIGH && prevButtonState == LOW) {
    // if the mouse is not pressed, press it:
    toggle++;
    if(toggle == 1)
      if (!Mouse.isPressed(MOUSE_LEFT)) {
        Mouse.press(MOUSE_LEFT); 
      }  
  }
  else if(toggle == 2)
  {
    // else the mouse button is not pressed:
    // if the mouse is pressed, release it:
    if (Mouse.isPressed(MOUSE_LEFT)) {
      Mouse.release(MOUSE_LEFT); 
    }
    toggle = 0;
  }
  prevButtonState = buttonState;
  delay(10);
}

By the way, when I comment out the game playing part in my code like map() and the mouse.move()function, the z always gives me the correct way I need. No matter how fast I move my robot. The another thing is, when I select the angry bird game with z = 1, the mouse cursor control seems fine even when I move the robot swiftly. I assume that is because the mapped range for the angry bird game is small not large. But the mapped range when z = 2 is quite large.

void angryBirdGame(){ //z=1

  thumbAngle_pixel = map(thumbAngle,0,130,28,13); //this function maps the thumb angle from encoder to the game computer pixel setting
  fingerAngle_pixel = map(fingerAngle,0,480,70,88);
  Mouse.move(thumbAngle_pixel, fingerAngle_pixel, 0); 
}

void bubbleShootGame(){ //z=2
  thumbAngle_pixel = map(thumbAngle,0,180,80,0);
  fingerAngle_pixel = map(fingerAngle,0,480,100,0);
  Mouse.move(thumbAngle_pixel, fingerAngle_pixel, 0);
}

The Arduino website mentioned about the fact that the Arduino microcontroller can not take the encoder with high speed and high resolution. But my case is a little different. The Encoder is not directly connected to my Arduino Leonardo. The encoder is connected to the robot computer and I wire my Arduino Leonardo RX TX (serial1) to RS232 of robot computer to get encoder data sent in.

I know I am only picking at little pieces but I don't have a sufficient sense of the whole to do anything else

        gameSelection = 256*datain_Byte[1] + datain_Byte[0];
        fingerAngle = (256*datain_Byte[3] + datain_Byte[2]); //current finger angle
        thumbAngle  = (256*datain_Byte[5] + datain_Byte[4]); //current thumb angle
        Serial.println(gameSelection);
        fingerAngle_prev = fingerAngle;
        thumbAngle_prev = thumbAngle;

I suspect you should have the last pair of lines BEFORE the top line. In other words, save the old value before you get the new value.

The new names are much better :slight_smile:

...R

PS, spend an hour or two writing a Python program to get the habit of good code formatting. In Python precise formatting is essential.

Robin2,

Thanks a lot again for the comment. Yeah, I might need to move the last two lines at the very top to save the old values first. I was actually thinking about learning good formatting habit by picking on some other language. And I have finally found where the problem is . It is inside my Datareading() function. I should use while(Serial1.available()>5) instead of if(Serial1.available()>5). I got the hint somewhere else talking about the different between while loop and if statement for sending data from serial1 to serial. Using if statement in the case will easily cause buffer overflow since only 1 pack of data will send out every time no matter how much data comes in. On the other hand, while loop will send out any data which comes into the buffer.

void dataReading()
{
  if(Serial1.available()>5) { // I should use while loop here. Certainly I need to modify some other 
                                      // places in this part of code.                               

    for (int n = 0; n < 6; n++)
    {
      datain_Byte[n] = Serial1.read();
      value = 1;
    }
    gameSelection = 256*datain_Byte[1] + datain_Byte[0];
    fingerAngle = (256*datain_Byte[3] + datain_Byte[2]); //current finger angle
    thumbAngle  = (256*datain_Byte[5] + datain_Byte[4]); //current thumb angle
    Serial.println(gameSelection);
    fingerAngle_prev = fingerAngle;
    thumbAngle_prev = thumbAngle;     
  }
  else {
    value = 0;
    fingerAngle = fingerAngle_prev;
    thumbAngle = thumbAngle_prev;
  }

Glad to hear it is working.

I wonder should you use both IF and WHILE like this

if(Serial1.available()>5) { 
  while(Serial1.available > 0) {

It does nothing if there are five or fewer characters, but then it reads all that there is.

You might want to look at the examples in serial input basics which read from the serial buffer in the background until all the data has been received.

...R

sure. I am looking at the link now and it is very comprehensive. Great work, Robin2.

Robin2,

Again the link is quite informative. a question to your exemplary code in Serialinput link. How should I operate the serial monitor to see the parsed message of "This is a test, 1234, 45.3". When I upload the code and then open the serial monitor, there is no any text coming out. Should I type This is a test, 1234, 45.3, and then hit Send.
Thanks a lot.

// simple parse demo
char receivedChars[] = "This is a test, 1234, 45.3" ;

char messageFromPC[32] = {0};
int integerFromPC = 0;
float floatFromPC = 0.0;

char recvChar;
char endMarker = '>';
boolean newData = false;


void setup() {
	Serial.begin(9600);
	Serial.println("<Arduino is ready>");
	
	parseData();
	showParsedData();
}


void loop() {

}

	
void parseData() {

    // split the data into its parts
    
  char * strtokIndx; // this is used by strtok() as an index
  
  strtokIndx = strtok(receivedChars,",");      // get the first part - the string
  strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
  
  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  integerFromPC = atoi(strtokIndx);     // convert this part to an integer
  
  strtokIndx = strtok(NULL, ","); 
  floatFromPC = atof(strtokIndx);     // convert this part to a float

}


void showParsedData() {
	Serial.print("Message ");
	Serial.println(messageFromPC);
	Serial.print("Integer ");
	Serial.println(integerFromPC);
	Serial.print("Float ");
	Serial.println(floatFromPC);
}

You don't need to enter any data in the Serial Monitor. Try pressing the reset button on the Arduino (assuming it is NOT a Leonardo) while the Serial Monitor is open.

The code only runs once when the Arduino restarts.

The parse example simulates the situation where you had used one of the other examples to put data into receivedChars[]

Do let me know if you can't get it to work

...R

I See. Thanks. Sorry, unfortunately, I am trying with my Leonardo board. It didn't work that way somehow.

33chen:
I See. Thanks. Sorry, unfortunately, I am trying with my Leonardo board. It didn't work that way somehow.

Change the code to this and it will print out every two seconds (I hope).

// simple parse demo
char receivedChars[] = "This is a test, 1234, 45.3" ;

char messageFromPC[32] = {0};
int integerFromPC = 0;
float floatFromPC = 0.0;

char recvChar;
char endMarker = '>';
boolean newData = false;


void setup() {
	Serial.begin(9600);
	Serial.println("<Arduino is ready>");
	
	
}


void loop() {

        parseData();
	showParsedData();
        delay(2000);

}

	
void parseData() {

    // split the data into its parts
    
  char * strtokIndx; // this is used by strtok() as an index
  
  strtokIndx = strtok(receivedChars,",");      // get the first part - the string
  strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
  
  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  integerFromPC = atoi(strtokIndx);     // convert this part to an integer
  
  strtokIndx = strtok(NULL, ","); 
  floatFromPC = atof(strtokIndx);     // convert this part to a float

}


void showParsedData() {
	Serial.print("Message ");
	Serial.println(messageFromPC);
	Serial.print("Integer ");
	Serial.println(integerFromPC);
	Serial.print("Float ");
	Serial.println(floatFromPC);
}

Hopefully also another example of the convenience of using functions.

...R

It works. I can see the output from Serial monitor. Just curious: my results look like this. Is there something else I should change as well? Thanks.

Message This is a test
Integer 0
Float 0.00
Message This is a test
Integer 0
Float 0.00
Message This is a test
Integer 0
Float 0.00

Thanks for pointing that out. I learn new stuff every day. It happens that the strtok() function alters the array receivedChars[] by replacing the commas with \0.

That means that it only works properly the first time. And, because I was just testing it in setup() I had not been aware of that.

On your Leonardo you may not have seen the first printout.

This version should work repeatedly.

// simple parse demo
char receivedChars[] = "This is a test, 1234, 45.3" ;
char tempChars[32];        // temporary array for use by strtok() function

char messageFromPC[32] = {0};
int integerFromPC = 0;
float floatFromPC = 0.0;

char recvChar;
char endMarker = '>';
boolean newData = false;
byte dLen = 0;


void setup() {
    Serial.begin(9600);
    Serial.println("<Arduino is ready>");
}


void loop() {

        // this is necessary because strtok() alters the array
        //   in this case replacing commas with \0
    strcpy(tempChars, receivedChars);
    parseData();
    showParsedData();
    delay(2000);
}

    
void parseData() {

    // split the data into its parts
    
  char * strtokIndx; // this is used by strtok() as an index

  strtokIndx = strtok(tempChars,",");      // get the first part - the string
  strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
  
  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  integerFromPC = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); 
  floatFromPC = atof(strtokIndx);     // convert this part to a float

}


void showParsedData() {
    Serial.print("Message ");
    Serial.println(messageFromPC);
    Serial.print("Integer ");
    Serial.println(integerFromPC);
    Serial.print("Float ");
    Serial.println(floatFromPC);
}

I will add a note to my serial input basics Thread.

Thanks again.

...R

yeah. It works. This is great. Thank you, Robin2.

Senior Chen,

(I realize this post is three years old).

It seems you might be utilizing some type of potentiometers for position-acquisition. If that is accurate it seems you might be acquiring analog voltage correlations of your "definite" position upon what seems to be two axes, or ranges of motion, encoding it digitally via your robot's hardware, decoding it with your arduino code, reincoding it into relative position data, which is used for your mouse function. Could there be a more (application-dependent) streamlined process to do so by bypassing the robot's means of ADC and running your sensors directly to your Arduino's analog inputs for processing via on-board ADC? Not sure if this would save any time three years ago, but just curious.

Thanks man.

Bill.