Delay Functions making my mazebot crazy!?

Hello everyone. My programming for my maze robot (arduino powered (328 chip) with two touch sensors and a rugged shield for the motors) was going good until I got to the delay functions. Then, I noticed that some delays numbers would make my robot go into odd behaviors (like only spinning one wheel), while others would work perfectly :fearful:. What is this from!? My code is posted below, and would be in final format if not for the delay errors :cold_sweat:.

//motor test

#define EN1 3            // Pin 3 is Enable for Driver #1

#define EN2 11           // Pin 11 is Enable for Driver #2

#define DIR1 12          // Pin 12 is Direction for Driver #1

#define DIR2 13          // Pin 13 is Direction for Driver #2


const int buttonPin2 = 7; //left

const int buttonPin = 8; //right

int buttonState = 0;     // variable for reading the buttons
int buttonState2 = 0; 




uint8_t savedPWM = 0;

void pAnalogWrite(uint8_t pwm) { // Parallel analogWrite()

  if (pwm==0) {

    digitalWrite(EN1, LOW); 
    digitalWrite(EN2, LOW);

  } 
  else if (pwm==255) {

    digitalWrite(EN1, HIGH); 
    digitalWrite(EN2, HIGH);

  } 
  else {

    TCCR2A |= _BV(COM2A1) | _BV(COM2B1);

    OCR2A = OCR2B = pwm;

  }

  savedPWM = pwm;

}



void pSetDirection(uint8_t forward) { // 1==forward, 0==reverse

  pAnalogWrite(0); // Turn drivers off while switching direction

  if (forward) {

    digitalWrite(DIR1, HIGH); 
    digitalWrite(DIR2, HIGH);

  } 
  else {

    digitalWrite(DIR1, LOW); 
    digitalWrite(DIR2, LOW);

  }

  pAnalogWrite(savedPWM);  // Restore driver power level

}




void setup() {

  Serial.begin(9600);


  pAnalogWrite(0); // Both motors off for now

  pinMode(EN1, OUTPUT); 
  pinMode(EN2, OUTPUT);

  pinMode(DIR1, OUTPUT); 
  pinMode(DIR2, OUTPUT);

  pinMode(buttonPin, INPUT); //button input    
  pinMode(buttonPin2, INPUT); //button input 


  buttonState = digitalRead(buttonPin);
  buttonState2 = digitalRead(buttonPin2); 

}



void loop() 

{



  buttonState = digitalRead(buttonPin);
  buttonState2 = digitalRead(buttonPin2); 



  if(buttonState2==HIGH)//start on left side
  {    
 delay(5);
 pAnalogWrite(0);
 delay(5);
unsigned currentMillis = millis();

      digitalWrite(EN1, LOW); 
    digitalWrite(EN2, HIGH);
     digitalWrite(DIR1, HIGH); 
    digitalWrite(DIR2, HIGH);
    
    Serial.println("Left is HIGH");
   
    delay(50);
  

if(currentMillis > 200)
{
       
     pSetDirection(0); // back

   pAnalogWrite(255); // 100% power

delay(200);  
       digitalWrite(EN1, LOW); 
    digitalWrite(EN2, HIGH);
     digitalWrite(DIR1, HIGH); 
    digitalWrite(DIR2, HIGH);
    
    delay(200);
}
else;
delay(5);
  }
  
  
  






    if(buttonState==HIGH)//start on left side, then move to right
    {
       delay(5);
 pAnalogWrite(0);
 delay(5);
  pSetDirection(0); // reverse

   pAnalogWrite(255); // 100% power

    Serial.println("Right is HIGH");

    delay(300);
    
  }
  
  
  
  
   if(buttonState==LOW && buttonState2==LOW)
 {
    delay(10);
    
 pAnalogWrite(0);

 delay(10);

 pSetDirection(1); // Foward

   pAnalogWrite(255); // 100% power

    Serial.println("Left is LOW");
    
    delay(100);
    
       digitalWrite(EN1, HIGH);
      digitalWrite(EN2, LOW);
     digitalWrite(DIR1, HIGH); 
    digitalWrite(DIR2, HIGH);
    delay(5);

  }




    if(buttonState==HIGH & buttonState2==HIGH)
  {
 delay(5);
 pAnalogWrite(0);
 delay(5);
    
    pSetDirection(0); // back

  pAnalogWrite(255); // 100% power
    Serial.println("Right and Left are HIGH");

    delay(5);
    
  }
  


}

Can you give an example of one case where varying a delay causes an undesired effect? Without your bot to play with its hard to know where to start analyzing the problem. Show the working code and the change that makes it fail and explain how it fails if that change is made.

My code is posted below, and would be in final format if not for the delay errors

Hardly. Your random indenting and over use of white space makes your code too hard for me to read. I gave up.

MarkT: Can you give an example of one case where varying a delay causes an undesired effect? Without your bot to play with its hard to know where to start analyzing the problem. Show the working code and the change that makes it fail and explain how it fails if that change is made.

For instance, in the code below if I changed the delay (300) to anything greater the robot would go backwards (even when the sensor was not HIGH). If it is not HIGH it should go forwards like I programmed it.

    if(buttonState==HIGH)//start on left side, then move to right
    {
       delay(5);
 pAnalogWrite(0);
 delay(5);
  pSetDirection(0); // reverse

   pAnalogWrite(255); // 100% power

    Serial.println("Right is HIGH");

    delay(300); //bad delay
    
  }

PaulS:

My code is posted below, and would be in final format if not for the delay errors

Hardly. Your random indenting and over use of white space makes your code too hard for me to read. I gave up.

I prefer my spaces white ]:D. Anyways, I think the issue may just be in the loop itself, so you can just look over that smaller section if you want.

I prefer my spaces white

And I prefer my indentation less stochastic.

    unsigned currentMillis = millis();

Do you mean “unsigned long”?

  if(currentMillis > 200)
      {
      pSetDirection(0); // back
      pAnalogWrite(255); // 100% power
      delay(200);  
      digitalWrite(EN1, LOW); 
      digitalWrite(EN2, HIGH);
      digitalWrite(DIR1, HIGH); 
      digitalWrite(DIR2, HIGH);
      delay(200);
      }
    else;
  delay(5);

What is the point of the “else” there?

Then, I noticed that some delays numbers would make my robot go into odd behaviors (like only spinning one wheel), while others would work perfectly …

Perhaps re-code to get rid of the delays?

The delays are what make the robot back up for a certain time when a trigger is switched. The else was put in to try and fix the odd behaviors (does not help).

Do I need to add "long" before millis()? The point of the value is to record the time that the sensor is HIGH for. If it is LOW, then the time is lost and will restart when the sensor is HIGH.

I prefer my spaces white

I do to. There's a big difference between

void loop()
{
   buttonState = digitalRead(somePin);
   if(buttonState == HIGH)
   {
      // Do something
   }
}

and

void loop()



{





   buttonState = digitalRead(somePin);










   if(buttonState == HIGH)

   {



      // Do something

   }

}

One is easy to read. One is not. Your code is the latter.

I still need my issue solved. Here is the code corrected (without too many spaces).

//motor test

#define EN1 3            // Pin 3 is Enable for Driver #1

#define EN2 11           // Pin 11 is Enable for Driver #2

#define DIR1 12          // Pin 12 is Direction for Driver #1

#define DIR2 13          // Pin 13 is Direction for Driver #2


const int buttonPin2 = 7; //left

const int buttonPin = 8; //right

int buttonState = 0;     // variable for reading the buttons
int buttonState2 = 0; 




uint8_t savedPWM = 0;

void pAnalogWrite(uint8_t pwm) { // Parallel analogWrite()

  if (pwm==0) {

    digitalWrite(EN1, LOW); 
    digitalWrite(EN2, LOW);

  } 
  else if (pwm==255) {

    digitalWrite(EN1, HIGH); 
    digitalWrite(EN2, HIGH);

  } 
  else {

    TCCR2A |= _BV(COM2A1) | _BV(COM2B1);

    OCR2A = OCR2B = pwm;

  }

  savedPWM = pwm;

}



void pSetDirection(uint8_t forward) { // 1==forward, 0==reverse

  pAnalogWrite(0); // Turn drivers off while switching direction

  if (forward) {

    digitalWrite(DIR1, HIGH); 
    digitalWrite(DIR2, HIGH);

  } 
  else {

    digitalWrite(DIR1, LOW); 
    digitalWrite(DIR2, LOW);

  }

  pAnalogWrite(savedPWM);  // Restore driver power level

}




void setup() {

  Serial.begin(9600);


  pAnalogWrite(0); // Both motors off for now

  pinMode(EN1, OUTPUT); 
  pinMode(EN2, OUTPUT);

  pinMode(DIR1, OUTPUT); 
  pinMode(DIR2, OUTPUT);

  pinMode(buttonPin, INPUT); //button input    
  pinMode(buttonPin2, INPUT); //button input 


  buttonState = digitalRead(buttonPin);
  buttonState2 = digitalRead(buttonPin2); 

}



void loop() 

{



  buttonState = digitalRead(buttonPin);
  buttonState2 = digitalRead(buttonPin2); 



  if(buttonState2==HIGH)//start on left side
  {    
    delay(5);
    pAnalogWrite(0);
    delay(5);
    unsigned currentMillis = millis();

    digitalWrite(EN1, LOW); 
    digitalWrite(EN2, HIGH);
    digitalWrite(DIR1, HIGH); 
    digitalWrite(DIR2, HIGH);

    Serial.println("Left is HIGH");

    delay(50);


    if(currentMillis > 200)
    {

      pSetDirection(0); // back

      pAnalogWrite(255); // 100% power

      delay(200);  
      digitalWrite(EN1, LOW); 
      digitalWrite(EN2, HIGH);
      digitalWrite(DIR1, HIGH); 
      digitalWrite(DIR2, HIGH);

      delay(200);
    }
    else;
    delay(5);
  }









  if(buttonState==HIGH)//start on left side, then move to right
  {
    delay(5);
    pAnalogWrite(0);
    delay(5);
    pSetDirection(0); // reverse

    pAnalogWrite(255); // 100% power

    Serial.println("Right is HIGH");

    delay(300);

  }




  if(buttonState==LOW && buttonState2==LOW)
  {
    delay(10);

    pAnalogWrite(0);

    delay(10);

    pSetDirection(1); // Foward

    pAnalogWrite(255); // 100% power

    Serial.println("Left is LOW");

    delay(100);

    digitalWrite(EN1, HIGH);
    digitalWrite(EN2, LOW);
    digitalWrite(DIR1, HIGH); 
    digitalWrite(DIR2, HIGH);
    delay(5);

  }




  if(buttonState==HIGH & buttonState2==HIGH)
  {
    delay(5);
    pAnalogWrite(0);
    delay(5);

    pSetDirection(0); // back

    pAnalogWrite(255); // 100% power
    Serial.println("Right and Left are HIGH");

    delay(5);

  }



}

Here is the code corrected

You missed a bit : unsigned currentMillis = millis();

drewtoby: Then, I noticed that some delays numbers would make my robot go into odd behaviors (like only spinning one wheel), while others would work perfectly

The delay themselves are probably not the issue, it's your (lack of) logic.

drewtoby: and would be in final format if not for the delay errors

Your definition of final format must be completely different from mine. and I agree with the others: putting 4 or 5 spaces makes for a ton of unnecessary scrolling.

drewtoby: ```  buttonState = digitalRead(buttonPin);  buttonState2 = digitalRead(buttonPin2); }

void loop() {  buttonState = digitalRead(buttonPin);  buttonState2 = digitalRead(buttonPin2);

What's the point of reading the buttons in setup() if it is the first thing that happens in loop()?

drewtoby: unsigned currentMillis = millis();

Like the others pointed out you certainly didn't mean "unsigned" and probably meant "unsigned long". However, what's the point of this code? The only other place you look at currentMillis is here:

drewtoby: if(currentMillis > 200) {           pSetDirection(0); // back

This is where your logic flawed. millis() is constantly counting up. millis() (and by definition currentMillis) will almost always be greater than 200, since it will probably take about 200 ms to get that if-statement. You must have meant to compare it other event in the past? Note, you delay 400ms inside of the if-statement that checks to see if 200ms has passed since the processor was reset. What's the point of that?

So how you think your code is complete, is beyond me. I don't see any logical path to what you are doing. You've thrown together (seemingly) random pieces of code and are surprised it isn't working how you expected?

drewtoby: Here is the code corrected (without too many spaces).

Put every { and } on a separate line, with matching pairs indented by the same amount.

Delete any blank line which is adjacent to a { or }.

Then your code will be at least half readable.

Why are you doing all that parallel output stuff?

I have a rugged motor shield attached to my arduino.

I have a rugged motor shield attached to my arduino.

So? You aren't listening.

drewtoby: I still need my issue solved. Here is the code corrected (without too many spaces).

...
  else {

    TCCR2A |= _BV(COM2A1) | _BV(COM2B1);

    OCR2A = OCR2B = pwm;

  }

  savedPWM = pwm;

}

LOL.

Your idea of

"too many"

and mine

obviously differ.

PaulS:

I have a rugged motor shield attached to my arduino.

So? You aren't listening.

I am listening, I was responding to the Parelleling from PeterH.

I am trying to get the robot to count once the sensor is triggered, and stop and reset once the sensor is released. Should changing the variable of Millis() around fix the entire issue? I need it to not count when the sensor is LOW.

Also, the code is not random. The shield can be found here: ruggedcircuits.com/html/rugged_motor_driver.html (which the setup is in my code).

And the loop is for responding to my two seperate touch sensors.

As for my logic in the program, what should I change around if it is not the delays? It was working fine before I added them :cold_sweat:

Thanks

I am listening

You've been asked more than once to remove excess white space. You haven't. Therefore, you aren't listening.