Servo action with FOR loop

I'm pressing a button with a servo and finally have it working OK with the code shown below.

I also tried a version using the FOR loop code from the Sweep sketch, with its additional parameter of an increment value, instead of my simple write() commands. But that involves trial & error to optimise the delay setting in the loop. An unnecessary step in the simple method.

I assume there must be some advantage of the FOR loop method, or Arduino would not have used it in the basic servo demo. Is it just extra flexibility or what?

Code for simple method

/* Aim is to achieve the following sequence of events:
  On power-up of circuit:
  -----------------------
  1. Ensure that the servo's start position places the arm
  close to the CUBE camera's button, ready to press it.

  During void loop(), IF triggered by pin 7 going briefly LOW:
  ------------------------------------------------------------
  2. A small rotation in an anti-clockwise direction.
  3. A delay of 3 s before reversing, which powers up the CUBE.
  4. Two normal presses (i.e. with just a short delay before
  each release) will start the video.
  5. A single normal press after a specified delay will stop
  the video.
  6. The pin 7 trigger is HIGH again by this time. So further
  looping is disabled until another trigger allows.
*/

#include <Servo.h> // Uses code from the Arduino library

Servo myservo;  // "Create servo object to control a servo"

// Define variable 'outPos' and set it. It's the start position,
// before anti-clockwise rotation presses the button.
// I've marked it permanently below the rotor arm.
int outPos = 17;

// Now set the position needed for button to be fully pressed.
// So the angle moved will be 17-7 = a mere 10 degs.
int inPos = 7;

// Define variable for pin that will be used as the low-going
// trigger.
// Ultimately that will come from simple electronics.
const int triggerPin = 7;

// =========================================================================

void setup()
{
  // Attach the servo on pin 9 to the servo object 'myservo'.
  // Min & max values could be added but I've kept it simple.
  myservo.attach(9);

  // Avoid need for a resistor by using INPUT_PULLUP
  // So pin 7 is normally High. When it's taken low, even very
  // briefly, it allows the code within the loop to run.
  pinMode(triggerPin, INPUT_PULLUP);

  // Move to the Start position, with the servo arm ready to push the button.
  // This was established by trial & error.
  // It obviously depends on the arm being in a consistent physical position.
  
  myservo.write(outPos); // Rotates to the start ('Out') position.
}
// Servo arm is now close to face of button.

void loop()
{

  if (digitalRead(triggerPin) == LOW)
  {
    // A momentary LOW triggers the following:
    // Power up by pressing CUBE button for 3 s, say 3100 ms
    // IOW moving the servo a small angle and holding
    // it there for about 3s.

    // Rotates from outPos to inPos
    myservo.write(inPos);

    // Wait for 3 s before reversing
    delay(3200);

    // Return rotation from inPos to outPos
    myservo.write(outPos);
  }

  // The button will therefore have been pressed for 3s and
  // the servo arm will be back at its original position.

}

// As the trigger was only LOW very briefly, it is HIGH again
// by this time. So further looping is now disabled until a
// later trigger allows it.

Code using FOR loop as in Sweep sketch

/* Aim is to achieve the following sequence of events:
  On power-up of circuit:
  -----------------------
  1. Ensure that the servo's start position places the arm
  close to the CUBE camera's button, ready to press it.

  During void loop(), IF triggered by pin 7 going briefly LOW:
  ------------------------------------------------------------
  2. A small rotation in an anti-clockwise direction.
  3. A delay of 3 s before reversing, which powers up the CUBE.
  4. Two normal presses (i.e. with just a short delay before
  each release) will start the video.
  5. A single normal press after a specified delay will stop
  the video.
  6. The pin 7 trigger is HIGH again by this time. So further
  looping is disabled until another trigger allows.
*/

#include <Servo.h> // Uses code from the Arduino library

Servo myservo;  // "Create servo object to control a servo"

// Define variable 'outPos' and set it. It's the start position,
// before anti-clockwise rotation presses the button.
// I've marked it permanently below the rotor arm.
int outPos = 17;

// Now set the position needed for button to be fully pressed.
// So the angle moved will be 17-7 = a mere 10 degs.
int inPos = 7;

// Define variable for pin that will be used as the low-going
// trigger.
// Ultimately that will come from simple electronics.
const int triggerPin = 7;

// Define 'pos' for use with FOR loop as in Sweep sketch
int pos;

// =========================================================================

void setup()
{
  // Attach the servo on pin 9 to the servo object 'myservo'.
  // Min & max values could be added but I've kept it simple.
  myservo.attach(9);

  // Avoid need for a resistor by using INPUT_PULLUP
  // So pin 7 is normally High. When it's taken low, even very
  // briefly, it allows the code within the loop to run.
  pinMode(triggerPin, INPUT_PULLUP);

  // Move to the Start position, with the servo arm ready to push the button.
  // This was established by trial & error.
  // It obviously depends on the arm being in a consistent physical position.

  myservo.write(outPos); // Rotates to the start ('Out') position.
}
// Servo arm is now close to face of button.



void loop()
{

  if (digitalRead(triggerPin) == LOW)
  {
    // A momentary LOW triggers all the following:
    // Rotates anti-clockwise from outPos to inPos, but using the FOR loop as in the Sweep sketch

    for (pos = outPos; pos >= inPos; pos -= 3)
    {
      // goes from 17 to 7 degrees in steps of 1 degree
      myservo.write(pos);

      // I'm unsure how to optimise this setting, a complication of this method.
      delay(10);
    }

    // Wait for 3 s before reversing
    delay(3200);

    for (inPos = 18; pos <= outPos; pos += 3)
    {
      // goes from 7 to 17 degrees, the original start position
      myservo.write(pos);

      // I'm unsure how to optimise this setting, a complication of this method.
      delay(10);
    }
  }
     
}

Terrypin:
I assume there must be some advantage of the FOR loop method, or Arduino would not have used it in the basic servo demo. Is it just extra flexibility or what?

The programmer's convenience?

It's not clear what you want to happen.

...R

I assume there must be some advantage of the FOR loop method, or Arduino would not have used it in the basic servo demo. Is it just extra flexibility or what?

It is not a matter of the for loop having an advantage, rather it is the fact that by using the for loop the servo can move slowly from one extreme to another. Whether that is better than moving at full speed depends on the application. Are you happy for the servo arm to hit the shutter release button of your camera at full speed, for instance ?

The example is probably ment to encourage beginners to play with as many numbers as possible. Both step size and delay per step can be modified and this will allow the user to see the size of the individual steps and how fast they can be performed.

If you want to move from point A to point B at full speed then there is no advantage to the for loop method.

If you want to be able to control the speed the servo moves from A to B then the for loop does it where write(A), delay write(B) doesn't.

Different techniques for different purposes.

Steve

UKHeliBob:
by using the for loop the servo can move slowly from one extreme to another.

For the OP's benefit (you are well aware of this) the slow movement can also be achieved without using FOR.

...R

Hi,
Is this thread associated with this thread?

https://forum.arduino.cc/index.php?topic=643506.0

Tom... :slight_smile:

The OP has opened at least 3, possibly 4 threads in the last couple of days about controlling a servo

Thanks for all the replies and sorry for my delay in responding.

I now understand the distinction, thanks, summarised by @UKHeliBob and @slipstick.

In my case, simulating the pressing of a firm camera button, the simple method is clearly preferable, with delays after each rotation chosen carefully by experiment.

@Robin2
"It's not clear what you want to happen."
Didn't my code comments explain that in detail?

"...the slow movement can also be achieved without using FOR."
How is that achieved please?

Terry, East Grinstead, UK

"...the slow movement can also be achieved without using FOR."
How is that achieved please?

You can use the loop() function to do it by updating the servo position at intervals determined by comparing the time of the previous update with the current time using millis() to do the timing. The advantage is that you can do other things in loop() because the code is not locked into the for loop

See Using millis() for timing. A beginners guide, Several things at the same time and look at the BlinkWithoutDelay example in the IDE.

There is also a library named VarSpeedServo specifically aimed at moving a servo slowly although I have no personal experience of it,

Thanks @UKHeliBob, I’ll explore both of those soon.

Terry

UKHeliBob:
There is also a library named VarSpeedServo specifically aimed at moving a servo slowly although I have no personal experience of it,

I use it quite often and it has worked very well for me. It's non-blocking (unless you use the wait parameter) and a lot easier than trying to write your own Sweep equivalent using millis() directly.

Steve

Thanks Steve, duly installed and looks very handy. Coding for my first project (sequence of camera button presses) is almost finished but I'll experiment with that new function slowmove() later.

Terry, East Grinstead, UK

I wouldn't use slowmove(). That's effectively a legacy function that's just in there so old programs still compile.

Use write(value, speed, wait) instead with it's optional speed and wait parameters.

Steve

I'm having difficulty using the VarSeeedServo library. After reading that "Everything that works with Servo works with VarSpeedServo too," I changed just two lines of code in a successfully working sketch as shown here:

// #include <Servo.h> // Uses code from the Arduino library
// Servo myservo;  // "Create servo object to control a servo"
#include <VarSpeedServo.h> // Uses the VarSpeedServo library
VarSpeedServo myServo;

But on uploading I get "Error compiling for board ArduinolGenuino Uno."

Below is the last part of the full error message file. Largely obscure to me. For example how do I interpret the message about 'multiple libraries'? There is only one occurrence of it on my PC.

And what part is WProgram.h meant to play? The error file correctly says "No such file or directory," but why is it apparently needed and where is it supposed to come from?

Also, after using Sketch > Include Library > Add ZIP Library the new library does appear in the list.

But why does it not appear under Manage Libraries?

ERROR FILE, LAST PART

Detecting libraries used...
"C:\\Program Files (x86)\\Arduino\\hardware\\tools\\avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10810 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\cores\\arduino" "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\variants\\standard" "C:\\Users\\terry\\AppData\\Local\\Temp\\arduino_build_662060\\sketch\\CUBE-ServoPlusLED-varRevision.ino.cpp" -o nul
Alternatives for VarSpeedServo.h: [VarSpeedServo]
ResolveLibrary(VarSpeedServo.h)
  -> candidates: [VarSpeedServo]
"C:\\Program Files (x86)\\Arduino\\hardware\\tools\\avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10810 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\cores\\arduino" "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\variants\\standard" "-IC:\\Users\\terry\\Dropbox\\Electronics\\Arduino\\SKETCHES\\libraries\\VarSpeedServo" "C:\\Users\\terry\\AppData\\Local\\Temp\\arduino_build_662060\\sketch\\CUBE-ServoPlusLED-varRevision.ino.cpp" -o nul
"C:\\Program Files (x86)\\Arduino\\hardware\\tools\\avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10810 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\cores\\arduino" "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\variants\\standard" "-IC:\\Users\\terry\\Dropbox\\Electronics\\Arduino\\SKETCHES\\libraries\\VarSpeedServo" "C:\\Users\\terry\\Dropbox\\Electronics\\Arduino\\SKETCHES\\libraries\\VarSpeedServo\\VarSpeedServo.cpp" -o nul
C:\Users\terry\Dropbox\Electronics\Arduino\SKETCHES\libraries\VarSpeedServo\VarSpeedServo.cpp:56:10: fatal error: WProgram.h: No such file or directory
Alternatives for WProgram.h: []

 #include <WProgram.h>
ResolveLibrary(WProgram.h)

          ^~~~~~~~~~~~

  -> candidates: []compilation terminated.

Terry, East Grinstead, UK

You seem to have managed to find a very old version of VarSPeedServo. WProgram.h was replaced by Arduino.h years ago. Where did you get your version from?

The version I use is from GitHub - netlabtoolkit/VarSpeedServo: Arduino library for servos that extends the standard servo.h library with the ability to set speed, and wait for position to complete

Steve

Thanks. Not sure of my source but now downloaded from your link. I have VarSpeedServo-master.zip, 25 Kb.

Will try it tomorrow morning.

Terry, East Grinstead, UK

Now have two VarSpeedServo libraries!

Have to go out so haven't yet tried the latest one you suggested. Is that its correct name? And I think I should first remove the earlier one, VarSpeedServo. How is that best done please, as I see no 'Remove' or 'Delete' under Manage Libraries?

Terry, East Grinstead, UK

Just delete the original VarSpeedServo folder. Your old error messages will tell you where it is if you're not sure.

Then to keep things simple rename the other folder with -master (which should be in the same 'libraries' folder) to be just VarSpeedServo. When you restart the IDE you should have only one.

I have no idea if there's a more official or better way of handling these libraries. I just go for simple.

Steve

Hi,
Down load the library as a zip and get the "add zip" in "include library" to do ALL the installation.
No need to rename anything, the IDE does it all for you.

Tom... :slight_smile: