Simple Code to Remote Control Motors

Hi,

I build a 4WD robot. I also built a remote control, in which I have 4 buttons on a breadboard, and each one tells the robot to go in all the basic directions (fwd, back, left, right).

My code on the robot is rather simple, but I'm curious if I've written it effectively. As it is written now, it seems that after I send it a letter - which correlates to a certain direction the wheels should spin, I'm following every command telling the motors to "release".

It seems like there would be a better way to write that code, so that if it doesn't get another command, then it should release all motors. Additionally, it seems that if I give it a forward one, and then send it a left one, it should stop the forward one, and then proceed to the next command.

Code I'm referring to is under void loop().

Any ideas?

/*****

* Slave Xbee Remote 
   - receives data from remote controller

* Notes about this code:
   - This code is on the Leonard board.  Therefore, use "Serial1."
       when wiring code, as opposed to the UNO which uses "Serial."

* This codes will have the robot turn in place when commanded to       

*****/

#include <AFMotor.h>  // AF Motor shield library

const int speed = 100; // percent of maximum speed
int pwm;

int incomingByte;      // a variable to read incoming serial data into


// define wheels (individual)

  // front wheels
  AF_DCMotor Motor_Left_Front(4, MOTOR34_1KHZ); // motor 4
  AF_DCMotor Motor_Right_Front(3, MOTOR34_1KHZ); // motor 3

  // rear wheels
  AF_DCMotor Motor_Left_Rear(1, MOTOR12_64KHZ); // motor 1
  AF_DCMotor Motor_Right_Rear(2, MOTOR12_64KHZ); // motor 2


//*****MOTOR FUNCTIONS  
      
  // Forward, Backward, Release
  
void Drive_State(int DRIVE_STATE)
{
  
  if (DRIVE_STATE == FORWARD)
    {Serial1.println("FORWARD");}
    
    else if (DRIVE_STATE == BACKWARD)
      {Serial1.println("BACKWARD");}

    else  
      {Serial1.println("RELEASE");}

  
      // front wheels
      Motor_Left_Front.run(DRIVE_STATE);
      Motor_Right_Front.run(DRIVE_STATE);
      
      // rear wheels
      Motor_Left_Rear.run(DRIVE_STATE);
      Motor_Right_Rear.run(DRIVE_STATE);
  
      delay(10);
}

// TURN LEFT
void Left_Turn(void)
{
    Serial1.println("LEFT TURN");
    
    // front wheels
    Motor_Left_Front.run(BACKWARD);
    Motor_Right_Front.run(FORWARD);
    
    // rear wheels
    Motor_Left_Rear.run(BACKWARD);
    Motor_Right_Rear.run(FORWARD);
    
    delay(10);    
}

// TURN RIGHT
void Right_Turn(void)
{
    Serial1.println("RIGHT TURN");
    
    // front wheels
    Motor_Left_Front.run(FORWARD);
    Motor_Right_Front.run(BACKWARD);
    
    // rear wheels
    Motor_Left_Rear.run(FORWARD);
    Motor_Right_Rear.run(BACKWARD);
    
    delay(10);   
}

void setup() 
{
  Serial1.begin(9600);           // set up Serial library at 9600 bps

// scale percent into pwm range
pwm = map(speed, 0, 100, 0, 255);  // takes range of 0-255 and maps it to 0-100 for variable 'speed'
                                   // actual pwm value is define as const at beginning of code
                                   
// front wheels
Motor_Left_Front.setSpeed(pwm);
Motor_Right_Front.setSpeed(pwm);

// rear wheels
Motor_Left_Rear.setSpeed(pwm);
Motor_Right_Rear.setSpeed(pwm);

}

void loop() 
{

   if (Serial1.available() > 0)   // see if there's incoming serial data:
    {
      incomingByte = Serial1.read(); // read the oldest byte in the serial buffer:
    }
      {
        if (incomingByte == 'F')  // FORWARD
          {
           // digitalWrite(ledPin, HIGH);
           Serial1.flush();  // is this needed?
           Drive_State(FORWARD);    // forward
           Drive_State(RELEASE);    // stop 
          } 
      
         else if (incomingByte == 'B')  // BACKWARD
          {
           // digitalWrite(ledPin, HIGH);
          Serial1.flush();  // is this needed?
           Drive_State(BACKWARD);   // backward  
           Drive_State(RELEASE);    // stop 
          } 
          
        else if (incomingByte == 'L')  // spin LEFT
          {
           // digitalWrite(ledPin, HIGH);
          Serial1.flush();  // is this needed?
             Left_Turn();
             Drive_State(RELEASE);    // stop          
          } 
          
        else if (incomingByte == 'R')  // spin RIGHT
          {
           // digitalWrite(ledPin, HIGH);
           Serial1.flush();  // is this needed?
           Right_Turn();
           Drive_State(RELEASE);    // stop 
          } 
      }

}

It seems that every IF section contains Drive_State(RELEASE); so why not take it out of the IF sections and just put it once at the end of all of them.

...R

That is a good suggestion. I did that, and added an IF statement, so that I'm not constantly pinging the motors when no signal is received.

Or do you think it's unnecessary, and just use the "Drive_State(RELEASE); // stop" statement as is?

     else
      {
        if (value == true)  // done so not always pinging motors
        {
            Drive_State(RELEASE);    // stop 
            value = false;
        }
      }

Also, I noticed I have the following under each command. Is it ok, or would it run better placing it at the end before the IF statement closure upon receiving a RC signal? Just not sure how the code is being interpreted.

  Serial1.flush();  // is this needed?

serial.flush() is very poorly named because its role changed somwhere during Arduino evolution. It is only relevant if you are sending data from the Arduino and its purpose is to cause the code to wait until all the data in the ougoing buffer has been sent. In other words it should really be called serial.delayUntilOutBufferEmpties().

Long story short - delete it.

It is rarely any use for anything.

...R