Sketch with 'if' , 'for' , 'else if' - why doesn't it work?

Summary - I have a sketch that I've used successfully for weeks that contains some 'if' , 'else if' code. When I modified it by adding two 'for' statements following the 'if' and the 'else if' things went sideways on me. That modified code does not work as I expected. I'm hoping someone on the forum can educate me about what I did wrong and what I can do to make it work as I intended.
Wiring detail - I have a spdt toggle switch connected to digital inputs on an UNO. Common on the toggle switch is connected to ground on the UNO; toggle pin that I call Tog1UpPin is connected to pin 0 on the UNO; toggle pin that I call Tog1DnPin is connected to pin 1 on the UNO. The UNO is connected to a PCA9685 servo driver. I have a servo that I call ServoA connected to pin 0 on the PCA9685.
Sequence of operation - With Tog1UpPin thrown, ServoA rapidly moves to a fixed point of rotation (280) AND HOLDS THAT POSITION. With Tog1DnPin thrown, ServoA rapidly moves to a fixed point of rotation (300) AND HOLDS THAT POSITION. As I throw the toggle between the Up and Dn positions, the servo responds and holds it appropriate position until toggle thrown in the opposite direction.
The Fast sketch - The sketch described above is shown below. It's the first of two sketches. I'll name it "Fast sketch".

I decided to try to modify my Fast sketch to slow down the speed of the servo as it moves from 300 to 280 and back. This is where things fell apart for me.

Modified sketch which I call "Slow sketch" sequence of operation - Same as sequence of operation of Slow sketch except servo speed reduced to 1 step every 30 ms. To accomplish this I added the statement for(pos=300;pos>=280;pos-=1) after the 'if' statement and for(pos=280;<=300; pos+1) after the 'else if' statement.
The modified sketch - This sketch (Slow sketch) is the second sketch shown below.
How the Slow sketch functions - With the Tog1UpPin thrown, the servo slowly moves to position 280, then rapidly returns to position 300, then slowly moves to position 280, then rapidly returns to position 300. The servo will continue this 'cycling' pattern until Tog1DnPin is thrown. When Tog1DnPin is thrown, the servo stops and no longer responds.
FINALLY, MY QUESTION - Thank you for having the patience to continue. Why doesn't the servo in Fast sketch respond exactly as it does in Slow sketch, with the exception being the speed of response?

Thank you for your patience in reading my long post and for any suggestions you can offer.
Regards
Rick

FAST SKETCH

[code]
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

Adafruit_PWMServoDriver pwm=Adafruit_PWMServoDriver();


int Tog1UpPin=0;
int Tog1DnPin=1;
int ServoA=0;

bool Tog1UpPinstatus;
bool Tog1DnPinstatus;

void setup() {
pwm.begin();
pwm.setPWMFreq(60);
pinMode (Tog1UpPin,INPUT_PULLUP);
pinMode (Tog1DnPin,INPUT_PULLUP);
Tog1UpPinstatus=digitalRead(Tog1UpPin);
Tog1DnPinstatus=digitalRead(Tog1DnPin);
}

void loop() {
Tog1UpPinstatus=digitalRead(Tog1UpPin);  // Toggle switch in the UP position
Tog1DnPinstatus=digitalRead(Tog1DnPin);  // Toggle switch in the DOWN position



if (Tog1UpPinstatus==LOW)            
{ 
 
  pwm.setPWM(ServoA,0,280);
  
}

else if (Tog1DnPinstatus==LOW) 
{ 
 
 pwm.setPWM(ServoA,0,300);
 
}

}
[/code]
``


``
SLOW SKETCH

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm=Adafruit_PWMServoDriver();

int Tog1UpPin=0;
int Tog1DnPin=1;
int ServoA=0;
int pos=0;

bool Tog1UpPinstatus;
bool Tog1DnPinstatus;

void setup() {
pwm.begin();
pwm.setPWMFreq(60);
pinMode (Tog1UpPin,INPUT_PULLUP);
pinMode (Tog1DnPin,INPUT_PULLUP);
Tog1UpPinstatus=digitalRead(Tog1UpPin);
Tog1DnPinstatus=digitalRead(Tog1DnPin);
}

void loop() {
Tog1UpPinstatus=digitalRead(Tog1UpPin);  // Toggle switch in the UP position
Tog1DnPinstatus=digitalRead(Tog1DnPin);  // Toggle switch in the DOWN position


if(Tog1UpPinstatus==LOW)
{
 for(pos=300;pos>=200;pos-=1)
{
  pwm.setPWM(ServoA,0,pos);
delay (30);
}
}
else if(Tog1DnPinstatus==LOW)
{
  for(pos=200;pos>=300;pos+=1)
{
pwm.setPWM(ServoA,0,pos);
delay (30);
}
}
}

Double check the condition

Your problem is that the loop function er, loops so your for loops run over and over, which explains the behavior you observe.

Get rid of the for loops. Check your switches and see where you want the servo to end up. If pos isn't where it should be, increment or decrement it as appropriate, tell the servo the new position and delay a bit. The loop function will take care of the necessary repetition.

Here is your code with the exact same functionality as you have coded it but with additional debug-output to the serial-monitor that makes visible what your program is doing.

So open the serial monitor adjust baudrate to 115200

then upload this version and watch the serial output
You will see numbers of pos similar to those

22:12:21.626 -> Setup-Start
22:12:21.860 -> "0:Top of loop" pos=0
22:12:22.094 -> "0:Top of loop" pos=0
22:12:22.375 -> "0:Top of loop" pos=0
22:12:22.608 -> "0:Top of loop" pos=0
22:12:22.877 -> "0:Top of loop" pos=0
22:12:23.112 -> "0:Top of loop" pos=0
22:12:23.348 -> "0:Top of loop" pos=0
22:12:23.582 -> "1:Up-button pressed" Tog1UpPinstatus=0
22:12:23.582 -> "pos-=" pos=300
22:12:23.864 -> "pos-=" pos=291
22:12:24.146 -> "pos-=" pos=282
22:12:24.426 -> "pos-=" pos=273
22:12:24.660 -> "pos-=" pos=264
22:12:24.940 -> "pos-=" pos=255
22:12:25.220 -> "pos-=" pos=246
22:12:25.500 -> "pos-=" pos=237
22:12:25.781 -> "pos-=" pos=228
22:12:26.015 -> "pos-=" pos=219
22:12:26.297 -> "pos-=" pos=210
22:12:26.576 -> "pos-=" pos=201
22:12:26.623 -> "0:Top of loop" pos=199
22:12:26.904 -> "0:Top of loop" pos=199
22:12:27.139 -> "0:Top of loop" pos=199
22:12:27.375 -> "0:Top of loop" pos=199
22:12:27.652 -> "0:Top of loop" pos=199
22:12:27.872 -> "0:Top of loop" pos=199

as long as the for-loop is running your code can not execute your if-conditions
and that is the reason why your code reacts so slow

But you have a loop running with exact that name loop

void loop itself is looping all the time
and with the help of if-conditions and some boolean flags you can create the same functionality which will be very responsive

pictute taken from this Arduino Programming Course

image

Here is the demo-version of your code with debug-output

#define dbg(myFixedText, variableName) \
        Serial.print( F(#myFixedText " "  #variableName"=") ); \
        Serial.println(variableName); 
// usage: dbg("1:my fixed text",myVariable); 
// myVariable can be any variable or expression that is defined in scope

#define dbgi(myFixedText, variableName,timeInterval) \
  do { \
    static unsigned long intervalStartTime; \
    if ( millis() - intervalStartTime >= timeInterval ){ \
      intervalStartTime = millis(); \
      Serial.print( F(#myFixedText " "  #variableName"=") ); \
      Serial.println(variableName); \
    } \
  } while (false);
// usage: dbgi("2:my fixed text",myVar,myInterval); 
// myVar can be any variable or expression that is defined in scope
// myInterval is the time-interval which must pass by before the next
// print is executed


#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

int Tog1UpPin = 3;
int Tog1DnPin = 4;
int ServoA = 5;
int pos = 0;

bool Tog1UpPinstatus;
bool Tog1DnPinstatus;

void setup() {
  Serial.begin(115200);
  Serial.println( F("Setup-Start") );

  pwm.begin();
  pwm.setPWMFreq(60);
  pinMode (Tog1UpPin, INPUT_PULLUP);
  pinMode (Tog1DnPin, INPUT_PULLUP);
  Tog1UpPinstatus = digitalRead(Tog1UpPin);
  Tog1DnPinstatus = digitalRead(Tog1DnPin);
}

void loop() {
  dbgi("0:Top of loop",pos,250);
  Tog1UpPinstatus = digitalRead(Tog1UpPin); // Toggle switch in the UP position
  Tog1DnPinstatus = digitalRead(Tog1DnPin); // Toggle switch in the DOWN position

  if (Tog1UpPinstatus == LOW)
  {
    dbg("1:Up-button pressed",Tog1UpPinstatus);
    for (pos = 300; pos >= 200; pos -= 1)
    {
      dbgi("pos-=",pos,250);
      pwm.setPWM(ServoA, 0, pos);
      delay (30);
    }
  }
  else if (Tog1DnPinstatus == LOW)
  {
    dbg("2:Down-button pressed",Tog1UpPinstatus);
    for (pos = 200; pos >= 300; pos += 1)
    {
      dbgi("3:pos+=",pos,250);
      pwm.setPWM(ServoA, 0, pos);
      delay (30);
    }
  }
}

Now make a first attempt to use the looping of loop for your purposes. It is very likely that it will not run immediately but it is important that you start thinking about it.

best regards Stefan

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.