Get steering and drive servos to work at the same time

Hello all. The code below should steer the robot using light while it is moving. If I comment out

delay(3000);          //drive for 3 seconds
stopDrive();          //stop
delay(10000);          //pause for 10 seconds

the pan servo will drive and steer correctly. If I put the delay back in, it will not steer. Please help. Thanks.

#include <Servo.h>

// this code uses 2 photoresistors like eyes attached to the panServo to track a light source. 

Servo panServo;
Servo leftDriveServo;
Servo rightDriveServo;

//************************************************************************
int pos = 83;  // Variable to store the servo position for straight ahead. servo is not straight on the robot
//************************************************************************

int inputPhotoLeft = 1; // Easier to read, instead of just 1 or 0.
int inputPhotoRight = 0;
int Left = 0; // Store readings from the photoresistors.
int Right = 0; // Store readings from the photoresistors.
***********************************************************************************************************************************************

void drive() //this is used to make the servos go
{
leftDriveServo.writeMicroseconds(1481);              // 1437   between 500 and 2500 **1382 STOP, 2500 forward fast, 500 reverse fast
rightDriveServo.writeMicroseconds(1270);           // 1332   between 500 and 2500 **1391 STOP, 2500 forward fast, 500 reverse fast
}

void stopDrive() //this is used to stop the servos
{
//******************************************************************************************************************************  
leftDriveServo.writeMicroseconds(1381);              // between 500 and 2500 **1382 = STOP, 2500 forward fast, 500 reverse fast
rightDriveServo.writeMicroseconds(1391);              // between 500 and 2500 **1391 STOP, 500 forward fast, 2500 reverse fast
//******************************************************************************************************************************
}

void steer() //this is used to steer the servos
{
if (Left == (Right))
{
panServo.write(83);
}

// Checks if right is greater than left, if so move to right.

else if (Left < (Right))

{
  
//panServo.attach(8); // Attach servo to pin 8.
if (pos < 93)//was 179
pos++;
panServo.write(pos);
}
// Checks if left is greater than right, if so move to left.
else if (Right < (Left))

{
//panServo.attach(8); // Attach servo to pin 8.
if (pos > 73)
pos -=1 ;
panServo.write(pos);
}
}

void setup()
{
  delay(5000);
panServo.attach(8); // Attach servo to pin 8.
panServo.write(pos); //turn pan servo to center
stopDrive(); //this stops the servo from moving when it is attached to the pin
//leftDriveServo.writeMicroseconds(1382); //this stops the servo from moving when it is attached to the pin
//rightDriveServo.writeMicroseconds(1391); //this stops the servo from moving when it is attached to the pin
leftDriveServo.attach(9); // Attach servo to pin 9.
rightDriveServo.attach(10); // Attach servo to pin 10.
//chkDistanceFwd = 400; //set maximum range for the sonar to keep it from detecting too soon and turning off.
delay(500);        //wait this many milliseconds for everything to set up. WAS 500
Serial.begin(115200);
}

void loop()
{

// Reads the values from the photoresistors to the Left and Right variables.
//panServo.attach(8); // Attach servo to pin 8.
Left = analogRead(inputPhotoLeft);
Right = analogRead(inputPhotoRight);

steer();

// this is the driving delay section each 1000 is 1 second  

drive();              //drive
delay(3000);          //drive for 3 seconds
stopDrive();          //stop
delay(10000);          //pause for 10 seconds

}

The delays stop anything happening until the delay is finished. Does that explain why your problem is happening ?

Yes…but I need some sort of delay to repeat the drive/stop/drive sequence. Should the delay be placed somewhere else in the code or the steer placed somewhere else? Is there another way to replicate the drive/pause/drive sequence?

Thanks.

Should the delay be placed somewhere else

Yes, drop it in the bin. Look at the blink without delay example.

Thanks AWOL. I will take a look and see how to incorporate it.

Just got the robot back and tried the following code. The idea is for the robot to drive and steer for 3 seconds, stop for 10 seconds, then drive and steer for 3 seconds. All this is doing is driving and steering. Can someone help fix this so it will work as required? Thanks.

#include <Servo.h>

long previousMillis = 0;        // will store last time LED was updated

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 1000;           // interval at which to blink (milliseconds)


// this code uses 2 photoresistors like eyes attached to the panServo to track a light source. 

Servo panServo;
Servo leftDriveServo;
Servo rightDriveServo;

//************************************************************************
int pos = 83;  // Variable to store the servo position for straight ahead. servo is not straight on the robot
//************************************************************************

int inputPhotoLeft = 1; // Easier to read, instead of just 1 or 0.
int inputPhotoRight = 0;
int Left = 0; // Store readings from the photoresistors.
int Right = 0; // Store readings from the photoresistors.

//***********************************************************************************************************************************************
int lightThreshold = 100; //sets light threshold to prevent accidental activation...the higher the number, the more light required to activate it
//***********************************************************************************************************************************************

void drive() //this is used to make the servos go
{
leftDriveServo.writeMicroseconds(1481);              // 1437   between 500 and 2500 **1382 STOP, 2500 forward fast, 500 reverse fast
rightDriveServo.writeMicroseconds(1270);           // 1332   between 500 and 2500 **1391 STOP, 2500 forward fast, 500 reverse fast
}

void stopDrive() //this is used to stop the servos
{
//******************************************************************************************************************************  
leftDriveServo.writeMicroseconds(1381);              // between 500 and 2500 **1382 = STOP, 2500 forward fast, 500 reverse fast
rightDriveServo.writeMicroseconds(1391);              // between 500 and 2500 **1391 STOP, 500 forward fast, 2500 reverse fast
//******************************************************************************************************************************
}

void steer() //this is used to steer the servos
{
if (Left == (Right))
{
panServo.write(83);
}

// Checks if right is greater than left, if so move to right.
//else if (Left < (Right+20))

else if (Left < (Right))
// +20 is the deadzone, so it wont jiggle back and forth.
{
  
//panServo.attach(8); // Attach servo to pin 8.
if (pos < 93)//was 179
pos++;
panServo.write(pos);
}
// Checks if left is greater than right, if so move to left.
else if (Right < (Left))
// +20 is the deadzone, so it wont jiggle back and forth.
{
//panServo.attach(8); // Attach servo to pin 8.
if (pos > 73)
pos -=1 ;
panServo.write(pos);
}
}

void setup()
{
  delay(5000);
panServo.attach(8); // Attach servo to pin 8.
panServo.write(pos); //turn pan servo to center
stopDrive(); //this stops the servo from moving when it is attached to the pin
//leftDriveServo.writeMicroseconds(1382); //this stops the servo from moving when it is attached to the pin
//rightDriveServo.writeMicroseconds(1391); //this stops the servo from moving when it is attached to the pin
leftDriveServo.attach(9); // Attach servo to pin 9.
rightDriveServo.attach(10); // Attach servo to pin 10.
delay(500);        //wait this many milliseconds for everything to set up. WAS 500
Serial.begin(115200);
}

void loop()
{

// Reads the values from the photoresistors to the Left and Right variables.
//panServo.attach(8); // Attach servo to pin 8.
Left = analogRead(inputPhotoLeft);
Right = analogRead(inputPhotoRight);

steer();

// this is the driving delay section each 1000 is 1 second  

drive();              //drive
  unsigned long currentMillis = millis();
   if(currentMillis - previousMillis > (interval*3))// drive for 3 seconds
   {
    previousMillis = currentMillis;

stopDrive();          //stop
  unsigned long currentMillis = millis();
   if(currentMillis - previousMillis > (interval*10))// stop for 10 seconds
   {
    previousMillis = currentMillis;
    
    drive();              //drive
  unsigned long currentMillis = millis();
   if(currentMillis - previousMillis > (interval*3))// drive for 3 seconds
   {
    previousMillis = currentMillis;

stopDrive();          //stop
  unsigned long currentMillis = millis();
   if(currentMillis - previousMillis > (interval*10))// stop for 10 seconds
   {
    previousMillis = currentMillis;

}
  }}

That code doesn't compile. Before you post the correct code, could you run the auto-format (ctrl-T) tool on it, please?

Sorry about that. Here is the corrected code that compiles and is formatted with autoformat.

#include <Servo.h>

long previousMillis = 0;        // will store last time LED was updated

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 1000;           // interval at which to blink (milliseconds)


// this code uses 2 photoresistors like eyes attached to the panServo to track a light source. 

Servo panServo;
Servo leftDriveServo;
Servo rightDriveServo;

//************************************************************************
int pos = 83;  // Variable to store the servo position for straight ahead. servo is not straight on the robot
//************************************************************************

int inputPhotoLeft = 1; // Easier to read, instead of just 1 or 0.
int inputPhotoRight = 0;
int Left = 0; // Store readings from the photoresistors.
int Right = 0; // Store readings from the photoresistors.

//***********************************************************************************************************************************************
int lightThreshold = 100; //sets light threshold to prevent accidental activation...the higher the number, the more light required to activate it
//***********************************************************************************************************************************************

void drive() //this is used to make the servos go
{
  leftDriveServo.writeMicroseconds(1481);              // 1437   between 500 and 2500 **1382 STOP, 2500 forward fast, 500 reverse fast
  rightDriveServo.writeMicroseconds(1270);           // 1332   between 500 and 2500 **1391 STOP, 2500 forward fast, 500 reverse fast
}

void stopDrive() //this is used to stop the servos
{
  //******************************************************************************************************************************  
  leftDriveServo.writeMicroseconds(1381);              // between 500 and 2500 **1382 = STOP, 2500 forward fast, 500 reverse fast
  rightDriveServo.writeMicroseconds(1391);              // between 500 and 2500 **1391 STOP, 500 forward fast, 2500 reverse fast
  //******************************************************************************************************************************
}

void steer() //this is used to steer the servos
{
  if (Left == (Right))
  {
    panServo.write(83);
  }

  // Checks if right is greater than left, if so move to right.

  else if (Left < (Right))
  {
    if (pos < 93)//was 179
      pos++;
    panServo.write(pos);
  }
  // Checks if left is greater than right, if so move to left.

  else if (Right < (Left))
  {
    //panServo.attach(8); // Attach servo to pin 8.
    if (pos > 73)
      pos -=1 ;
    panServo.write(pos);
  }
}

void setup()
{
  delay(5000);
  panServo.attach(8); // Attach servo to pin 8.
  panServo.write(pos); //turn pan servo to center
  stopDrive(); //this stops the servo from moving when it is attached to the pin
  leftDriveServo.attach(9); // Attach servo to pin 9.
  rightDriveServo.attach(10); // Attach servo to pin 10.
  delay(500);        //wait this many milliseconds for everything to set up. WAS 500
  Serial.begin(115200);
}

void loop()
{

  // Reads the values from the photoresistors to the Left and Right variables.
  Left = analogRead(inputPhotoLeft);
  Right = analogRead(inputPhotoRight);

  steer();

  // this is the driving delay section each 1000 is 1 second  

  drive();              //drive
  unsigned long currentMillis = millis();
  if(currentMillis - previousMillis > (interval*3))// drive for 3 seconds
  {
    previousMillis = currentMillis;

    stopDrive();          //stop
    unsigned long currentMillis = millis();
    if(currentMillis - previousMillis > (interval*10))// stop for 10 seconds
    {
      previousMillis = currentMillis;

      drive();              //drive
      unsigned long currentMillis = millis();
      if(currentMillis - previousMillis > (interval*3))// drive for 3 seconds
      {
        previousMillis = currentMillis;

        stopDrive();          //stop
        unsigned long currentMillis = millis();
        if(currentMillis - previousMillis > (interval*10))// stop for 10 seconds
        {
          previousMillis = currentMillis;

        }
      }
    }
  }
}

Search the forums for state machine code. Your nested if logic isn't going to do what you want - it'll call the stop routine, but immediately afterwards loop will run again and steer and drive, so you'll never notice the stop.

Ok, I have included the blink without delay below but I am confused on how to incorporate the state machine code in my code to replace the delays. Could someone start me out by modifying my first drive part of the code so that it will work using state machine code? I will keep looking too. Thanks.

/* Blink without Delay

 Turns on and off a light emitting diode(LED) connected to a digital  
 pin, without using the delay() function.  This means that other code
 can run at the same time without being interrupted by the LED code.

 The circuit:
 * LED attached from pin 13 to ground.
 * Note: on most Arduinos, there is already an LED on the board
 that's attached to pin 13, so no hardware is needed for this example.


 created 2005
 by David A. Mellis
 modified 8 Feb 2010
 by Paul Stoffregen

 This example code is in the public domain.


 http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
 */

// constants won't change. Used here to 
// set pin numbers:
const int ledPin =  13;      // the number of the LED pin

// Variables will change:
int ledState = LOW;             // ledState used to set the LED
long previousMillis = 0;        // will store last time LED was updated

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 1000;           // interval at which to blink (milliseconds)

void setup() {
  // set the digital pin as output:
  pinMode(ledPin, OUTPUT);      
}

void loop()
{
  // here is where you'd put code that needs to be running all the time.

  // check to see if it's time to blink the LED; that is, if the 
  // difference between the current time and last time you blinked 
  // the LED is bigger than the interval at which you want to 
  // blink the LED.
  unsigned long currentMillis = millis();

  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED 
    previousMillis = currentMillis;   

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
  }
}

Think of your problem as a series of state transitions (going from stationary to moving forwards, going from moving forewards to turning right etc), with a length of time associated with each. When the length of time has expired OR something more important has happened, then it is time to change state. Changing state should take very little time at all, and should set up the pause associated with the new state.

I modified it to what I thought would work but it just turns on and does not stop after 3 seconds. How do I address the drive servos? I tried to write their states as was done to the LED but had to comment out those statements because they were not declared and I could not figure out what needed to be fixed.

#include <Servo.h>

long previousMillis = 0;        // will store last time LED was updated

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 1000;           // interval at which to blink (milliseconds)
int leftDriveServoState = LOW;
int rightDriveServoState = LOW;

// this code uses 2 photoresistors like eyes attached to the panServo to track a light source. 

Servo panServo;
Servo leftDriveServo;
Servo rightDriveServo;

//************************************************************************
int pos = 83;  // Variable to store the servo position for straight ahead. servo is not straight on the robot
//************************************************************************

int inputPhotoLeft = 1; // Easier to read, instead of just 1 or 0.
int inputPhotoRight = 0;
int Left = 0; // Store readings from the photoresistors.
int Right = 0; // Store readings from the photoresistors.

//***********************************************************************************************************************************************
int lightThreshold = 100; //sets light threshold to prevent accidental activation...the higher the number, the more light required to activate it
//***********************************************************************************************************************************************

void drive() //this is used to make the servos go
{
  leftDriveServo.writeMicroseconds(1481);              // 1437   between 500 and 2500 **1382 STOP, 2500 forward fast, 500 reverse fast
  rightDriveServo.writeMicroseconds(1270);           // 1332   between 500 and 2500 **1391 STOP, 2500 forward fast, 500 reverse fast
}

void stopDrive() //this is used to stop the servos
{
  //******************************************************************************************************************************  
  leftDriveServo.writeMicroseconds(1381);              // between 500 and 2500 **1382 = STOP, 2500 forward fast, 500 reverse fast
  rightDriveServo.writeMicroseconds(1391);              // between 500 and 2500 **1391 STOP, 500 forward fast, 2500 reverse fast
  //******************************************************************************************************************************
}

void steer() //this is used to steer the servos
{
  if (Left == (Right))
  {
    panServo.write(83);
  }

  // Checks if right is greater than left, if so move to right.

  else if (Left < (Right))
  {
    if (pos < 93)//was 179
      pos++;
    panServo.write(pos);
  }
  // Checks if left is greater than right, if so move to left.
  
  else if (Right < (Left))
  {
    //panServo.attach(8); // Attach servo to pin 8.
    if (pos > 73)
      pos -=1 ;
    panServo.write(pos);
  }
}

void setup()
{
  delay(5000);
  panServo.attach(8); // Attach servo to pin 8.
  panServo.write(pos); //turn pan servo to center
  stopDrive(); //this stops the servo from moving when it is attached to the pin
  leftDriveServo.attach(9); // Attach servo to pin 9.
  rightDriveServo.attach(10); // Attach servo to pin 10.
  delay(500);        //wait this many milliseconds for everything to set up. WAS 500
  Serial.begin(115200);
}

void loop()
{

  // Reads the values from the photoresistors to the Left and Right variables.
  //panServo.attach(8); // Attach servo to pin 8.
  Left = analogRead(inputPhotoLeft);
  Right = analogRead(inputPhotoRight);

  steer();

  // this is the driving delay section each 1000 is 1 second  

///  drive();              //drive
  unsigned long currentMillis = millis();
  if(currentMillis - previousMillis > (interval*3))// if current minus previus is less than 3 seconds, drive for 3 seconds
  {
    previousMillis = currentMillis;
    
        if (leftDriveServoState == LOW && rightDriveServoState == LOW)
        drive();              //drive
    else
      stopDrive(); 
      
      ///   write(leftDriveServo, leftDriveServoState);
     ///    write(rightDriveServo, rightDriveServoState);
    
/*      stopDrive();          //stop
    unsigned long currentMillis = millis();
    if(currentMillis - previousMillis > (interval*10))// stop for 10 seconds
    {
      previousMillis = currentMillis;
      
        drive();              //drive
      unsigned long currentMillis = millis();
      if(currentMillis - previousMillis > (interval*3))// drive for 3 seconds
      {
        previousMillis = currentMillis;
        
          stopDrive();          //stop
        unsigned long currentMillis = millis();
        if(currentMillis - previousMillis > (interval*10))// stop for 10 seconds
        {
          previousMillis = currentMillis;
        }
      }*/
    //}
  }
}