Optimizing serial reception with XBee

Hello all,

Could someone please help me optimize my code if needed.
I’m not good at coding in C.
I want to command a Sabertooth Dual 25A Motor Drive and 2 servo’s (for the movement of a little camera) from my Windows PC with Xbee wireless (Set at Baudrate 57600) to a Arduino Mega via a Microsoft compatible gamepad (one stick for the cam and one stick for the motor) .
From the PC side i have no problems with my Delphi app.
I think its the Arduino code my problem.
I managed to tweak the settings to a point that it works reasonnably but i am still not satisfied.
When i move the sticks slowly i get a decent response from the Arduino Mega but if i move the stick faster the servo’s seem to freeze.
I think its something todo with the reception of my command codes being messed up.
I use 5 chars for the commands the first char being for the destination “Camera or Motor” the second char being the direction “Forward Backwards, Left or Right” the last three chars are 3 digits from 000 to 255 for the value to be send.
To limit the number of bytes to be send i do not send a end of command character , should I ?
This is my command reception procedure :

boolean recvCommand(char &d,char &c,int &v)
{
  char serin = ' ';
  d = ' ';
  c = ' ';
  v = 0;
  char charspeed[4];
  int index = 0;
  if (Serial2.available())
  {
    while (Serial2.available() > 0)
    {
      serin = Serial2.read();
      // check if command received is a valid character
      if (serin == 'M' || serin == 'C')
      {
        d = serin;
      }    
      else if (serin == 'V' || serin == 'H')
      {
        c = serin;
      }  
      // get speed value here
      else if (serin >= '0' && serin <= '9') // is this an ascii digit between 0 and 9?
      {
        charspeed[index] = serin;
        index++;
      }  
      charspeed[3] = 'o';
      v = atoi(charspeed);
      //delay(5);
    }
    return 1;
  }
  else
  {
     return 0; 
     v = 0;
  } 
}

This is my execute command procedure :

void exCommand(char d,char c,int v)
{
  String s1,s2;
  constrain(v,0,255);
  boolean busy = false;
  if (v >= 0 && v < 256)
  {
    anglev = map(v,0,255,0,180);
    angleh = map(v,0,255,0,180);
    if (d == 'M')     // recieved command for motor (speed = value)
    {
      busy = true;
      constrain(v,0,255);
      s1 = "Motor:";
       switch (c)
       {
       case  'V' :   // Forward-Backward
         s2 =  "For-Back";
         //Serial.print(s);
         // todo : command the actual movement here
         myServomv.write(anglev);
         //delay(5);
         //analogWrite(s1Pin,v);
         break;
       case 'H' :    // Left-Right 
         s2 =  "Left-Right";
         //Serial.print(s);
         // todo : command the actual movement here
         myServomh.write(angleh);
         //delay(5);
         //analogWrite(s2Pin,v);
         break;     
        
       default:
         // dest not valid 
         ;
       }  
       lcd.clear();
       lcd.setCursor(0,0);
       lcd.print(s1 + s2);
       lcd.setCursor(0,1);
       lcd.print("Speed: ");
       lcd.setCursor(7,1);
       lcd.print(v);
       busy = false;
      
    }
    else if (d == 'C' && busy == false)   // received command for camera (movement = value)
    {  
       constrain(v,0,255);
       
       s1 = "Cam:";
       
       switch (c)
       {
       case  'V' : //  Up-Down
         s2 =  "Up-Down";
         //Serial.print(s);
         // todo : command the actual movement here
         myServocv.write(anglev);
         //delay(5);
         break;
    
       case 'H' :     // Left-Right
         s2 =  "Left-Right";
         //Serial.print(s);
         // todo : command the actual movement here
         myServoch.write(angleh);
         //delay(5);
         break;     
    
       default:
         // dest not valid 
         ;
       }  
       lcd.clear();
       lcd.setCursor(0,0);
       lcd.print(s1 + s2);
       lcd.setCursor(0,1);
       lcd.print("Move: ");
       lcd.setCursor(6,1);
       lcd.print(v);
    } 
  }  
}

And my Loop

void loop()
{
  if (recvCommand(dest,command,value)) 
  {
    exCommand(dest,command,value);
  }
  else  // no command received can update info
  {
    getInfo(voltage,velocity,temperature);
    sendInfo(voltage,velocity,temperature);
  }  
}

I have a few questions :slight_smile:

How Could i optimize my code ?
I intent to also send a few values (bytes) every second to the PC , should i be better of using a second pair of Xbee’s for this ?
The mega has 4 hardware serial ports.

The Sabertooth motor controller has 3 different methods of accepting input to drive the motors.
Analog, RC Mode , or serial messages.
What would be the best mode ?

      charspeed[3] = 'o';
      v = atoi(charspeed);

The atoi() function expects a NULL terminated array of chars. The chars in the array are supposed to be digits from '0' to '9'. Why are you not NULL terminating the array? Why are you inserting a non-digit in the array?

I use 5 chars for the commands the first char being for the destination "Camera or Motor" the second char being the direction "Forward Backwards, Left or Right" the last three chars are 3 digits from 000 to 255 for the value to be send.

If you really want to speed up the transfer of data, you will will send three bytes - the destination, 'C' or "M', the direction, 'F' or 'B', and the value (as a byte).

The sending three characters and conversion to and from a numeric value takes time.

To limit the number of bytes to be send i do not send a end of command character , should I ?

Not necessarily. But, it you receive 'C', 'M', 'F', or 'B', you should set index to 0.

    anglev = map(v,0,255,0,180);
    angleh = map(v,0,255,0,180);

Which operates at a higher frequency - the Arduino or your PC? Do the computations on the faster machine.

      constrain(v,0,255);

Constraining v after mapping it seems silly.

Well , i changed the 3 digits to one byte and displaced the map function calls to my PC.
The response is already much much better.

Thanks very much.

Please bare with me , this is my first Arduino program , or should i say sketch. :slight_smile: