Go Down

Topic: Solved:time lag as encoders control the mouse via Arduino serial communication (Read 4529 times) previous topic - next topic

33chen

Hell folks,

I need your insight and help. I am working on a project to use the data from two encoder to control the mouse cursor in my PC. The two encoder data from a hand robot: one records my finger range of motion data, one records my thumb range of motion data. Two encoder data send out from the robot computer via RS232 and logic level convertor to my Arduino Leonardo. And Leonardo is connected to another computer where the encoder data controls the mouse cursor to play game. One encoder data controls the x coordinate, another controls the y coordinate.

My problem lies here. The two encoder data directly correspond to the fingers and thumb movement data. When fingers and thumb move at a moderate speed, the mouse cursor moves in a kind of synchronized manner (by naked eye standard). When fingers and thumb move faster, there is quite obvious delay in the mouse cursor movement, although there is no encoder data lost while Arduino and game computer process the data. In other words, the mouse cursor will follow the same movement done by fingers and thumb, but is quite a delay response. And moreover, when fingers and thumb move even faster to a certain level, the mouse cursor movement starts going wild and seems to me that there is kind of overflow problem happening to Arduino. And it also seems to me this problem is non versatile since it persists even after I reloads the code and turn off and on Arduino. But the problem usually disappears after I restart my game computer.

Hope anyone shares some insight  and idea on it. Thanks a lot in advance. The arduino code is attached here. In the code, f and t are defined to be the encoder data of fingers and the encoder data of thumb.
Code: [Select]

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;

float f1;
float t1;

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();
  dataReading();
   
  if (mouseIsActive == true){
   
    switch(z){
    case 1:{
      while(z == 1){
      dataReading();
      if(value == 1){
      angryBirdGame();
      }
      angryBirdMouseButton();
      mouseActiveFcn();
      if(z != 1 || mouseIsActive == false){
        break;
      }
    }
    }
   
    case 2: {
      while (z == 2){
      dataReading();
      if(value == 1){
      bubbleShootGame();
      }
      clickMouse();
      mouseActiveFcn();
      if(z != 2 || mouseIsActive == false){
        break;
      }
    }
    }
 
    case 3:{
      while (z == 3){
      dataReading();
      if(value == 1){
      bowlingGame();
      }
      mouseActiveFcn();
      if (z != 3 || mouseIsActive == false){
        break;
      }
      }
       
   }
   case 4:{
     while (z == 4){
       dataReading();
       if(value == 1){
         shoppingGame();
       }
       clickMouse();
       mouseActiveFcn();
       if (z != 4 || mouseIsActive == false){
         break;
       }
     }
   }
   case 5:{
     while (z == 5){
       dataReading();
       if(value == 1){
         golfGame();
       }
       clickMouse();
       mouseActiveFcn();
       if (z != 5 || mouseIsActive == false){
         break;
       }
     }
   }
   
   case 6: {
     while (z == 6){
       dataReading();
       if(value == 1){
       panggame();
       }
       mouseActiveFcn();
       if (z != 6 || mouseIsActive == false){
         break;
       }
     }
   }
       
   default:{
     while(1){
       dataReading();
       generalMove();
       mouseActiveFcn();
          if( z == 1 ){
     break;
   }
     else if (z == 2){
       break;
     }
     else if (z == 3) {
       break;
     }
     else if (z == 4) {
       break;
     }
     else if (z == 5) {
       break;
     }
     else if (z == 6){
       break;
     }
     else if (mouseIsActive == false){
       break;
     }
     }
   
    }
    }
     
   delay(10);
  }
  }

 
  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])/10;
          t = (256*datain_Byte[5] + datain_Byte[4])/10;
          //Serial.println(f);
          //Serial.println(t);
          f_prev = f;
          t_prev = t;     
      }
          else {
            value = 0;
            f = f_prev;
            t = t_prev;
          }

   
  }
 
 
  void angryBirdGame(){
       //th = map(t,0,20,38,22);
       th = map(t,0,18,28,13);
       //fi = map(f,0,42,70,90);
       fi = map(f,0,48,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,18,80,0);
       fi = map(f,0,48,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 shoppingGame(){
    th = map(t,0,18,115,0);
    fi = map(f,0,48,108,0);
    Mouse.move(th,fi,0);
  }
 
  void golfGame(){
     th = map(t,0,7,65,60);
     fi = map(f,0,17,95,100);
       Mouse.move(th, fi, 0);
       //delay(10);
  }
 
  void panggame(){
    Serial.write(t);
    Serial.write(f);
    //delay(100);
  }
   
 
  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);
   }

Robin2

I suspect you need to reorganize your program.

Just call dataReading() once in each iteration of loop() and don't use WHILE anywhere so that loop() can repeat as quickly as possible. Ditto for mouseActiveFcn() - and maybe for others.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

33chen

Robin2, thanks a lot again for the quick suggestion. Just curious what does you mean by "Ditto for"? Sorry I am not quite savvy for internet slang. Thanks.

Ji

Robin2

Sorry. Ditto is much older slang than the internet. It just means "the same"

...R
Two or three hours spent thinking and reading documentation solves most programming problems.


33chen

hi Robin2,

Just want to update the progress. Based on the suggestion, I chopped off those unnecessary while loops and other stuff. The revised code is attached below. The problematic phenomenon still persists. Again in the code, the integer z represents the selection of games. When z = 1, it gets into angrybird game. At the same time, I open the serial monitor to see how z is updated. As I gently move my finger and thumb robot, I can see the value of z stays at 1. As I move my fingers and thumb robot faster and faster, the z value stays at 1. The mouse map for z =1 is very small. However, when I select z == 2 from my robot computer, as I move the fingers and thumb robot faster and faster, the z reaches to -22784 and stays there, and my finger and thumb robot lost the control of robot. the mouse map for z = 2 almost covers my computer screen. Thereafter, no data from encoder come to the Arduino as TX LED is not on anymore. The computer that controls the fingers and thumb robot sends the z value as int16.

Do you think there is something to do with the function MAP i used in the code. It seems to me when I map to a larger range, and as I move the robot faster and faster, the Arduino can't process the input correctly anymore. Please let me know what you think. Thanks a lot.

Code: [Select]
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;

float f1;
float t1;

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();
  dataReading(); 
  if (mouseIsActive == true){
    if (z == 1 ){
      if(value==1){
        angryBirdGame();
      }
      angryBirdMouseButton();
    }
   
    if( z== 2){
      if(value==1){
        bubbleShootGame();
      }
      clickMouse();
    }
  delay(20);
   }
       
  }

 
  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,20,38,22);
       th = map(t,0,130,28,13);
       //fi = map(f,0,42,70,90);
       fi = map(f,0,480,70,88);
      // Serial.println(th);
       //Serial.println(fi);
       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);
   }

Robin2

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

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

33chen

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

Code: [Select]
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);
   }
   

Robin2

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

Code: [Select]
   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
Two or three hours spent thinking and reading documentation solves most programming problems.

33chen

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.

Code: [Select]
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);
}

Robin2

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
Two or three hours spent thinking and reading documentation solves most programming problems.

33chen

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

Code: [Select]
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);
}

33chen

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.

Code: [Select]

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.

Robin2

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

Code: [Select]
       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 :)

...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.
Two or three hours spent thinking and reading documentation solves most programming problems.

33chen

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.

Code: [Select]

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;
  }

Go Up