Need help servo delay

Hello!

First post here, im spanking new on playing with arduino, and for my project i want to have a servomotor that is going to raise a panel in my car.

the problem i have is that i cant get the servo to stay in place...

i can get it to stay if i just do the servo.write and write the position. but i want to delay, slow down (dont know which is the right expression..) the servo to make it smoother. so the servo dont just snaps into place.

i wrote a code with a switch and used a "for" statement in my "if button HIGH" to make the servo take longer time to reach its position, the problem is that as soon as the servo reaches its position i reset full speed to the starting position, in want it to stay at like 60-90 degrees. until the switch is in "LOW"

its probably a simple solution and im interested in learning what im doing wrong. but i need help!

Hoping someone can explain in arduino baby talk or point me in the right direction to what i need to read to learn the logic in this type of code.

my code:

// C++ code
//

#include <Servo.h>

int button = 0;
int pos = 0;

Servo servo_9;


void setup() {
  pinMode(2, INPUT);
  servo_9.attach(9, 500, 2500);
  
}

void loop() {

  button = digitalRead(2);
  if (button == HIGH)

  {
    for (pos =0; pos <=90; pos +=1) {
      servo_9.write(pos);
      delay(50); 
    
    }
    
  }

  if (button == LOW)

  {
    for (pos =89; pos >=0; pos -=1) {
      servo_9.write(pos);
      delay(50);
    }
    
  }
}

Trace the code with you finger, keeping in mind it has no idea what you want it to do. You may see why it does what you don't want.

A dumb simple fix is to wait whilst the button is HIGH, viz:

void loop() {

  button = digitalRead(2);

  if (button == HIGH)
  {
    for (pos =0; pos <=90; pos +=1) {
      servo_9.write(pos);
      delay(50); 
    }    
  }

// wait while the switch is closed

  while (button == HIGH) {
    button = digitalRead(2);
  }

  button = digitalRead(2);

  if (button == LOW) {
    for (pos =89; pos >=0; pos -=1) {
      servo_9.write(pos);
      delay(50);
    }
  }


// wait while the switch is open

  while (button == LOW) {
    button = digitalRead(2);
  }


}

You see you needa do the same thing after the second servo sweep - hang out waiting for the switch to change back.

I can't test this. This way of doing it will work, but is inflexible and as I said, lame. Look forward to doing it in a different manner and have fun with it in this state.

It should go slow up and stay up when you throw the switch, then go slow down and stay down when you return the switch to normal.

Lemme know it doesn't work; if I haven't passed out from a tryptophan OD I might be able to assemble enough functional brain cells to help.

a7

Ah! I think i follow, in my logic i have tried to make it stop. So i tested break statements and so on. But know that i see it it makes sense. Thank you very much! going to test it as soon as i get the time!

Meanwhile, I lashed it up here and I can say the code below works. See comments //... for what I added and may have changed just a bit.

You will soon realize that:

  • you can't stop the going up or down in midstream
  • you can't do anything else at all during the sweeps

which mayn't matter at this time. When it starts to matter, we here and can help point the way to the microprocessor equivalent of walking and chewing gum at the same time.

# include <Servo.h>

int button = 0;
int pos = 0;

Servo servo_9;

void setup() {
  pinMode(2, INPUT_PULLUP);  //... I used a pushbutton wired to ground
  servo_9.attach(9); //... I have perfect servos, so no , 500, 2500);
}

void loop() {
  button = digitalRead(2);

  if (button == HIGH) {
    for (pos =0; pos <=90; pos +=1) {
      servo_9.write(pos);
      delay(25); //... life too short, sped it up a bit
    }    
  }

//... wait while the switch is closed
  while (button == HIGH) {
    button = digitalRead(2);
  }

  button = digitalRead(2);

  if (button == LOW) {
    for (pos =89; pos >=0; pos -=1) {
      servo_9.write(pos);
      delay(25);
    }
  }

//... wait while the switch is open
  while (button == LOW) {
    button = digitalRead(2);
  }
}

In the early days it is probably best not to get too creative, and def a waste misuse of time trying this or that in the hope that it will help.

I repeat - in this sketch, and your original, tracing the flow with your finger will show you why it does what it does.

Another thing to say early on is that the serial monitor is your friend. You can use Serial.print() and println() statements to show the value of key variables and observe how they inform the flow through your code.

I fogrrot to say welcome to the community.

HTH

a7

1 Like

Again thank you for the help! Much love!

look this over
it monitors the button for a press, toggling a target servo position between a Hi/Lo setting and uses a timer to move the servo toward that target position - corrected

// toggle servo position using button switch

# include <Servo.h>

const byte PinServo = 9;
Servo servo_9;

const byte PinBut   = 2;
      byte butState = 0;

const int PosLo =  0;
const int PosHi = 90;

int  posTarg = 0;
int  pos = 0;
bool posHi;;


const unsigned long MsecPeriod = 25;
      unsigned long msec0;

// -----------------------------------------------------------------------------
void loop ()
{
    // timer
    unsigned long msec = millis ();
    if (msec - msec0 >= MsecPeriod)  {
        msec0 = msec;

        // mov servo toward target position
        if (posTarg > pos)
            pos++;
        else if (posTarg < pos)
            pos--;

        servo_9.write (pos);
    }

    // monitor button press
    byte but = digitalRead (PinBut);
    if (butState != but)  {     // state change
        butState  = but;
        delay (20);             // debounce

        if (LOW == but)  {      // pressed
            if (posHi)  {
                posHi   = false;
                posTarg = PosLo;
            }
            else {
                posHi   = true;
                posTarg = PosHi;
            }
            Serial.print ("but press: pos");
            Serial.println (pos);
        }
    }
}

// -----------------------------------------------------------------------------
void setup ()
{
    Serial.begin (9600);

    pinMode (PinBut, INPUT_PULLUP);  // enable internal pullup
    butState = digitalRead (PinBut);

    servo_9.attach (PinServo); //... I have perfect servos, so no , 500, 2500);
}

Better yet, run it.

Shouldn't increasing MsecPeriod make the servo take longer to sweep?

Or did you leave that flaw in the code as an exercise for the "spanking new" programmer to fix?

a7