Slowing down an RC servo

I am trying to write a sketch that will slow down a servo in a Radio Control project to make for a more scale like operation. The attached code reads the signal from the RC transmitter then slowly advances until it gets to 180 degrees. This is what I want but it takes the servo to the zero position and starts again. How to I stop it at 180 degrees then wait until the switch is switched off again, then return to zero? No matter what I try, it keeps repeating or doesn't move at all. Tearing out what little hair I have left! I know the break statement has no effect where it is>

Any help much appreciated

#include <Servo.h>
int servoPin = 9;
int signalPin = 7;
int servoPos = 0;
Servo myservo;
unsigned long duration;

void setup() {
  // put your setup code here, to run once:
  
Serial.begin(9600);
myservo.attach(servoPin);
pinMode(signalPin, INPUT);

}

void loop() {

duration = pulseIn(signalPin, HIGH);
delay(1000);
Serial.println(duration);
delay(2000);


if (duration > 1200) {
  for(servoPos=0;servoPos <= 90;servoPos+=1){
    myservo.write(servoPos);
    delay(50);
    Serial.println(servoPos);  
    if (servoPos==180) {
    break;
   delay(250);
}
       
}

}

}

Walk through the loop to understand what it's doing:

First pass, suppose the duration is >1200 so the if() is true and you move your servo.

On the next pass you follow the same logic and the for() executes again. The first thing it will do is write '0' to myservo which will cause it to move back to zero.

A "break" isn't what you need here. Without devoting too much thought, maybe add a true/false flag that indicates the servo has already moved to 180. It's initialized to false and once the servo moves to 180 it is set to true. You check this flag in your if( duration > 1200 ) -- i.e. if( duration > 1200 && flagAlreadyAt180 == false )

Very crudely:

#include <Servo.h>

const uint8_t servoPin = 9;
const uint8_t signalPin = 7;
uint8_t servoPos = 0;

Servo myservo;
unsigned long duration;

uint8_t flagAlreadyAt180;

void setup() 
{ 
    Serial.begin(9600);
    myservo.attach( servoPin );
    pinMode( signalPin, INPUT );

    flagAlreadyAt180 = false;

}//setup

void loop() 
{
    duration = pulseIn(signalPin, HIGH);
    delay(1000);
    Serial.println(duration);
    delay(2000);


    if (duration > 1200 && flagAlreadyAt180 == false ) 
    {
        for(servoPos=0;servoPos <= 90;servoPos+=1)
        {
            myservo.write(servoPos);
            delay(50);
            Serial.println(servoPos); 
       
        }//if

        flagAlreadyAt180 = true;

    }//if

}//loop
  for(servoPos=0;servoPos <= 90;servoPos+=1){
    myservo.write(servoPos);
    delay(50);
    Serial.println(servoPos); 
    if (servoPos==180) {

How likely is it that servoPos will ever equal 180 when the for loop stops at 90 ?

UKHeliBob:

  for(servoPos=0;servoPos <= 90;servoPos+=1){

myservo.write(servoPos);
   delay(50);
   Serial.println(servoPos);
   if (servoPos==180) {



How likely is it that servoPos will ever equal 180 when the for loop stops at 90 ?

Apologies, it was at 180, I reduced it to save time!

If you mean that the for loop goes from 0 to 180 then why test for a value of 180 inside it because you the servo will be at 180 when it ends anyway

in the library-manager there is a lib called ControlledServo which has functions for slow moving a servo

best regards Stefan

And there's always the good old VarSpeedServo library that has a speed parameter in the write() command. Very easy to use.

Steve

Thank you all for your input, I now have several solutions. Problem solved!

Blackfin:
Walk through the loop to understand what it's doing:

First pass, suppose the duration is >1200 so the if() is true and you move your servo.

On the next pass you follow the same logic and the for() executes again. The first thing it will do is write '0' to myservo which will cause it to move back to zero.

A "break" isn't what you need here. Without devoting too much thought, maybe add a true/false flag that indicates the servo has already moved to 180. It's initialized to false and once the servo moves to 180 it is set to true. You check this flag in your if( duration > 1200 ) -- i.e. if( duration > 1200 && flagAlreadyAt180 == false )

Very crudely:

#include <Servo.h>

const uint8_t servoPin = 9;
const uint8_t signalPin = 7;
uint8_t servoPos = 0;

Servo myservo;
unsigned long duration;

uint8_t flagAlreadyAt180;

void setup()
{
    Serial.begin(9600);
    myservo.attach( servoPin );
    pinMode( signalPin, INPUT );

flagAlreadyAt180 = false;

}//setup

void loop()
{
    duration = pulseIn(signalPin, HIGH);
    delay(1000);
    Serial.println(duration);
    delay(2000);

if (duration > 1200 && flagAlreadyAt180 == false )
    {
        for(servoPos=0;servoPos <= 90;servoPos+=1)
        {
            myservo.write(servoPos);
            delay(50);
            Serial.println(servoPos);
     
        }//if

flagAlreadyAt180 = true;

}//if

}//loop

I thought I had cracked it and added to the code to go from 180 degrees back to zero and this is what happens
operate the switch on the RC transmitter - ON
the servo moves up to 180 degrees and stops
operate the switch on the RC transmitter - OFF
the servo moves back to 0 then flips to max and starts to count down from 255!
As far as I can see from the code, the flag should stop anything happening! Am I missing something obvious? I have a solution using another library but would like to understand why I can't get this method to work!

#include <Servo.h>

const uint8_t servoPin = 9;
const uint8_t signalPin = 7;
uint8_t servoPos = 0;

Servo myservo;
unsigned long duration;

uint8_t flagAlreadyAt180;

void setup()
{
  Serial.begin(9600);
  myservo.attach( servoPin );
  pinMode( signalPin, INPUT );
  servoPos = 0;
  flagAlreadyAt180 = false;

}//setup

void loop()
{
  duration = pulseIn(signalPin, HIGH);
  delay(1000);
  Serial.println(duration);
  delay(2000);
  Serial.println(flagAlreadyAt180);

  if (duration > 1200 && flagAlreadyAt180 == false )
  {
    for (servoPos = 0; servoPos <= 180; servoPos += 1)
    {
      myservo.write(servoPos);
      delay(50);
      Serial.println(servoPos);

    }//if

    flagAlreadyAt180 = true;

  }//if

  if (duration < 1200 && flagAlreadyAt180 == true ) 
    {
        for(servoPos = 180;servoPos >= 0;servoPos-=1)
        {
            myservo.write(servoPos);
            delay(50);
            Serial.println(servoPos); 
       
        }//if

        flagAlreadyAt180 = false;


    }
    }//loop
    for (servoPos = 180; servoPos >= 0; servoPos -= 1)

Once servoPos goes beyond zero it will become 255
Change the code to stop it going beyond 0

    for (servoPos = 180; servoPos > 0; servoPos -= 1)

UKHeliBob:

    for (servoPos = 180; servoPos >= 0; servoPos -= 1)

Once servoPos goes beyond zero it will become 255
Change the code to stop it going beyond 0

    for (servoPos = 180; servoPos > 0; servoPos -= 1)

Thanks for that, now the only thing wrong is that on power up, the servo goes to the midpoint despite the line in the void setup - servoPos=0;

Please post your code as it is now

You might add a

myservo.write(servoPos);

in setup() after that initialization to actually set the servo there.

Blackfin:
You might add a

myservo.write(servoPos);

in setup() after that initialization to actually set the servo there.

That did the trick, many thanks!

UKHeliBob:
Please post your code as it is now

Apologies, the reason I did not post the full code was that I thought it might be frowned upon posting the full code each time.
Blackfin has solved the issue. Many thanks for taking the time to help, it is much appreciated.

I thought it might be frowned upon posting the full code each time.

Just the opposite. Posting the full code allows any changes to be seen in context without need to refer to and copy from previous posts. It is also not unknown for posters to have changed other parts of their code too without mentioning it