Servo speed control with ps2 contoller, xbee and a traxxas RC car...

So my friend gave me his Traxxas remote control car about a month ago and I thought it would be really cool to get it to run using a PS2 controller. I was able to use Bill Porter’ s library (http://www.billporter.info/playstation-2-controller-arduino-library-v1-0/) and two xbee radios. So having little knowledge of the arduino I set out to make it happen.
I got the car running and I am able to send data and move left and right using one analog stick and forwards, backwards with the other. But I wanted to have a little more control of the rear servo. (the analog stick is really sensitive).
So for the last few days I have been looking and trying to write some code that would allow me to hold down the “X” button and count up from 90 to 179 and the the “o” button and count down from 89 - 0. What I got kind of work, but I need to be able to control the speed at which the loop loops. The problems start to happen when I send data and do other things it start to slow down and the loop will not loop fast enough. Any ideas/help will be greatly welcome, and I also have issues once im done holding the button down. ie getting the servo back to 90 and or just starting over.

sorry for the grammar,spell…
Thanks Tom.

/*
Data sending is as follows
255 = rev
254 = forward
253 = left and right 
252 = all stop
*/

//PS2 Contoller 
#include <PS2X_lib.h>
//LCD Libary
#include <LiquidCrystal.h>

//Declare Varables
//fermware versions
char ConVer[] = {"oct17d"};
//PS2 
PS2X ps2x; 
byte vibrate, type;
int error;
//LCD
LiquidCrystal lcd(12, 11, 10, 4, 3, 2);

  int RX; 
  int RY;
  byte LX;
  int LY;
  int all_stop = 90;
/*speed timer*/
  boolean button_state = false;             // button_state sets the button pressed or not pressed
  //fwd/rec limits
  byte fwd_max = 179;
  byte fwd_min = 91;
  byte rev_max = 0;
  byte rev_min = 89;
  byte still = 90;
  //timing
  unsigned long previous_millis = 0;
  unsigned long current_millis;
  //spd
  byte fwd = 91;
  byte rev = 89;
/*MENU*/
  int interval = 60;
  int rssiPin = 9; 
  byte rssiDur;
/*start program and seial connection*/
void setup()
{  
  Serial.begin(9600);                        //open data port/start sending data over xbee 
    error = ps2x.config_gamepad(8,6,7,5, true, true);      //(clock, command, attention, data, Pressures?, Rumble?) returns 0 when found 1 if not found
      if(error == 0)
      {
        lcd.begin(16,2);
        lcd.setCursor(0, 0);
        lcd.print("Found Controller");  //displays on the lcd if the contoler is found
        lcd.setCursor(0, 1);
        lcd.print("PS2_Ver: ");   //displays version of controller   
        lcd.print(ConVer);
          delay(750);
      }
      else if(error >= 1)
          lcd.print("Not Found");  
            delay(1000);
            
      lcd.clear();
 pinMode(9,INPUT);      
}
void loop()
{
ps2x.read_gamepad();          //reads controller for the duration of the loop
/*ALL STOP 
  if(ps2x.Button(PSB_PINK))                                //failsafe
  {
    Serial.write(252);
    lcd.print("ALL STOP");
    delay(50);
    lcd.clear();
    return;
  }
  */
/*MENU*/
menu();
/*FORWARD*/
if(ps2x.Button(PSB_BLUE))
  {

    drive_fwd();   
        
  }
else if(ps2x.ButtonReleased(PSB_BLUE))
  {
    fwd = still;
    LX = 90;
  }
/*REV*/
if(ps2x.Button(PSB_RED))
  {
    
    drive_rev();   

  }
else if(ps2x.ButtonReleased(PSB_RED))
  {
    rev = still;
    LX = 90;
  }
        Serial.write(254);   
        Serial.write(fwd);
        LX =  map(ps2x.Analog(PSS_LX),0,255,0,179);
        Serial.write(253);
        Serial.write(LX);
}

/*This is the start of the controls*/
/****control fwd via "x" button*****/
void drive_fwd()
{
               //reads x button state
current_millis = millis();                            // take current time
unsigned long time_lap = current_millis - previous_millis; // gives  different between time 
  if(time_lap > interval) 
  {
    previous_millis = current_millis;                    //saves the last time you steped up servo speed 

        fwd++;
        constrain(fwd, still,fwd_min);

    if(fwd < fwd_min)
        fwd = still;
    else if(fwd >= fwd_max)
        fwd = fwd_max;
 
 lcd.setCursor(0, 1);
 lcd.print(fwd);
 
  }
}
/*control rev via "o" button*/
void drive_rev()
{
  
              //reads x button state
current_millis = millis();                            // take current time
unsigned long time_lap = current_millis - previous_millis; // gives  different between time 
  if(time_lap > interval) 
  {
    previous_millis = current_millis;                    //saves the last time you steped up servo speed 

        rev--;
        constrain(rev, still,rev_max);
        
    if(rev > rev_min)
        rev = still;
    else if(rev <= rev_max)
        rev = rev_max;
 
 lcd.setCursor(4, 1);
 lcd.print(rev);

  }
}

/*ANOLOG STICKS*//*STEARING
void sticks() 
{    
  left stick
        lcd.setCursor(0, 0);
       // lcd.print("L");
     LY =  ps2x.Analog(PSS_LY); // reading left Y axis 
      constrain(LY,0,179);
      //  lcd.setCursor(1, 0);
        lcd.print("Y");
        lcd.print(LY);
        
     // reading left X axis and contrains it to serial output
        lcd.setCursor(0, 0);
        lcd.print("X");
        lcd.print(LX);
        delay(100);
        lcd.clear();
right stick        ;
       // lcd.setCursor(0, 1);
     //   lcd.print("R");
      RY =  ps2x.Analog(PSS_RY); // reading RIGHT Y axis 
      constrain(RY,0,179);
       // lcd.setCursor(1, 1);
        lcd.print("Y");
        lcd.print(RY);
      RX =  ps2x.Analog(PSS_RX); // reading RIGHT X axis 
      constrain(RX,0,179);
      //  lcd.setCursor(7, 1);
        lcd.print("X");
        lcd.print(RX);
}        

Menu*/

void menu()
{
if (ps2x.Button(PSB_PAD_UP))                    //changes acceleration and contains it with 2-10 seconds 
    {
      interval = constrain(interval - 1, 10, 60);
      delay(100);
    }
if (ps2x.Button(PSB_PAD_DOWN))
    {
      interval = constrain(interval + 1, 10, 60);
      delay(100);
    }
int interval_percent = map(interval, 10, 60, 99, 10);
  
  lcd.setCursor(10,1);
  rssiDur = pulseIn(rssiPin, LOW, 200);
  lcd.print(rssiDur);
  lcd.setCursor(13, 1);
  lcd.print("%");
  lcd.print(interval_percent);
}

What I got kind of work, but I need to be able to control the speed at which the loop loops.

Which loop? I hope you are not referring to the loop() function.

        constrain(fwd, still,fwd_min);

    if(fwd < fwd_min)
        fwd = still;
    else if(fwd >= fwd_max)
        fwd = fwd_max;

I think you need to go re-read what the constrain function does, and how it works.

void drive_fwd()
{
               //reads x button state

No, it doesn’t.

void drive_rev()
{
  
              //reads x button state

No, it doesn’t. And that blank line is unnecessary. However, one BETWEEN functions would really help readability.

Any ideas/help will be greatly welcome

Tools + Auto Format is desperately needed.

Those delay()s are not helping you.

I am looking at this loop and the drive rev loop.

void drive_fwd()
{
current_millis = millis();                            // take current time
unsigned long time_lap = current_millis - previous_millis; // gives  different between time 
  if(time_lap > interval) 
  {
    previous_millis = current_millis;                    //saves the last time you steped up servo speed 

        fwd++;
        constrain(fwd, still,fwd_min);

    if(fwd < fwd_min)
        fwd = still;
    else if(fwd >= fwd_max)
        fwd = fwd_max;
 
 lcd.setCursor(0, 1);
 lcd.print(fwd);
 
  }
}

what to you mean BETWEEN the functions ( and that was a line of code that I had gotten rid of)

Code:
void drive_rev()
{

//reads x button state
No, it doesn’t. And that blank line is unnecessary. However, one BETWEEN functions would really help readability.

void fun1()
{
}
// This is BETWEEN two functions, where a blank line improves readability.
void fun2()
{
}

Thank for your help I will defiantly change some of my format, and the constrain function make a lot more sense now. Its doing what i want in one single line. I should be able to get some better looking code. I will post later when i have a change to go through it.

So in case anyone was interested in doing something similar to this here what I have so far and it seems to work pretty well. I am continuously tweaking it.

/*PS2 Controller */
#include <PS2X_lib.h>
PS2X ps2x; 
byte vibrate, type;
int error;
//LCD Libary
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 10, 4, 3, 2);
//versions
char ConVer[] = {"oct20a"};
/*DATA TRAN***   id  ***  number****/
const char start_number = '<';
char id;
byte fwd_rev;
byte lft_rgt;
const char end_number = '>';
/*RSSI*/
int rssiPin = 9; 
unsigned long rssiDur;
/*forward and rev limits*/
byte fwd_max = 179;
byte fwd_min = 91;
byte rev_max = 0;
byte rev_min = 89;
byte still = 90;
/*Timing*/
int interval = 60;
unsigned long previous_millis = 0;
unsigned long current_millis;
/*stearing*/
byte LX;

/*****Start Program*****/
void setup()
{  
  Serial.begin(115200);                        //open data port/start sending data over xbee 
  error = ps2x.config_gamepad(8,6,7,5, true, true);      //(clock, command, attention, data, Pressures?, Rumble?) returns 0 when found 1 if not found
  if(error == 0)
  {
    lcd.begin(16,2);
    lcd.setCursor(0, 0);
    lcd.print("Found Controller");  //displays on the lcd if the contoler is found
    lcd.setCursor(0, 1);
    lcd.print("PS2_Ver: ");   //displays version of controller   
    lcd.print(ConVer);
    delay(750);
  }
  else if(error >= 1){
    lcd.print("Not Found");  
    delay(1000);
  }            
  lcd.clear();
  pinMode(9,INPUT);      
}
void loop(){
  ps2x.read_gamepad();          //reads controller for the duration of the loop
  /*MENU*/
  menu();
  /*prints serial data and lcd date*/
  prints();  
  /*FORWARD*/
  if(ps2x.Button(PSB_BLUE)) {
  fwd_rev = drive_fwd(fwd_rev); 
  prints(); 
  }
  else if(ps2x.ButtonReleased(PSB_BLUE)) {
    fwd_rev = still;
    prints(); 
  }
  else if(ps2x.Button(PSB_RED)) {
  fwd_rev = drive_rev(fwd_rev);
   prints(); 
  }
  else if(ps2x.ButtonReleased(PSB_RED)){
    fwd_rev = still;  
    prints(); 
  }else{
    /*prints serial data and lcd date*/
  prints();} 
  }

/*Prints lcd and serial data*/
void prints(){
  //info
  LX =  map(ps2x.Analog(PSS_LX),0,255,0,179);
  rssiDur = pulseIn(rssiPin, LOW, 200);
  //serial prints
  Serial.print('d');            //d is drive eventual 'id'
  Serial.print(fwd_rev);      //prints drive speed


  Serial.print('s');          // s is stearing 
  Serial.print(LX);          //prints stearing

  //lcd prints
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(fwd_rev);
  lcd.setCursor(4,0);
  lcd.print(LX);
  //rssi prints to lcd 
  lcd.setCursor(10,1);
  lcd.print(rssiDur);
  /*print speed % (currently not working)
   lcd.setCursor(13, 1);
   lcd.print("%");
   int interval_percent = map(interval, 10, 60, 99, 10);
   lcd.print(interval_percent);
   */
  delay(50);
}
/*loops while x is being pressed and adds up from 90 to 179*/
byte drive_fwd(byte fwd){
  current_millis = millis();                            // take current time
  unsigned long time_lap = current_millis - previous_millis; // gives  different between time 
  if(time_lap > interval) {
    previous_millis = current_millis;                    //saves the last time you steped up servo speed 
    fwd++;
    fwd = constrain(fwd, fwd_min,fwd_max);
    fwd_rev = fwd;
     return fwd;
  }
   // new
}
/*loops while o is being pressed and subtracts from 89 to 0*/
byte drive_rev(byte rev){
  current_millis = millis();                            // take current time
  unsigned long time_lap = current_millis - previous_millis; // gives  different between time 
  if(time_lap > interval) 
  {
    previous_millis = current_millis;                    //saves the last time you steped up servo speed 
    rev--;
    rev = constrain(rev, rev_max,rev_min);
    fwd_rev = rev;
    return rev;
  }
 //new
}
/*this is the m,enu basic for not but i want it to be
 something that can be acsessed by pressing select and used for tuning*/
void menu(){
  if (ps2x.Button(PSB_PAD_UP)) {                   //changes acceleration and contains it with ~~ 2-10 seconds 
    interval = constrain(interval--, 10, 60);
  }
  if (ps2x.Button(PSB_PAD_DOWN)){
    interval = constrain(interval++, 10, 60);
  }
}
/*Car_Recievere*/
#include <Servo.h>
// the possible states of the state-machine
typedef enum {  none, got_d, got_s } states;

// current state-machine state
states state = none;
// current partial number
unsigned int currentValue;
// servos
Servo fwd_rev;
Servo lft_rgt;
void setup ()
{
  Serial.begin (9600);
  fwd_rev.attach(10);
  lft_rgt.attach(11);
  state = none;
}  // end of setup

void processRPM (const unsigned int value)
{
  Serial.print ("d = ");
  Serial.println (value * 16.67);
  fwd_rev.writeMicroseconds(value * 16.67);
  
} // end of processRPM

void processSpeed (const unsigned int value)
{
  // do something with speed 
  Serial.print ("s = ");
  Serial.println (value);
   lft_rgt.write(179 - value);
} // end of processSpeed


void handlePreviousState ()
{
  switch (state)
  {
  case got_d:
    processRPM (currentValue);
    break;
  case got_s:
    processSpeed (currentValue);
    break;

  }  // end of switch  

  currentValue = 0; 
}  // end of handlePreviousState

void processIncomingByte (const byte c)
{
  if (isdigit (c))
  {
    currentValue *= 10;
    currentValue += c - '0';
  }  // end of digit
  else 
  {

    // The end of the number signals a state change
 handlePreviousState ();

    // set the new state, if we recognize it
    switch (c)
    {
    case 'd':
      state = got_d;
      break;
    case 's':
      state = got_s;
      break;
    default:
      state = none;
      break;
    }  // end of switch on incoming byte
  } // end of not digit  
  
} // end of processIncomingByte

void loop ()
{
  if (Serial.available ())
    processIncomingByte (Serial.read ());

  // do other stuff in loop as required
  
}  // end of loop