servo motors explicate function

Thread Starter

fredric58

Joined Nov 28, 2014
252
hey all. i posted a question, but I am entirely unable to find it no matter the search I do. Just converted to google chrome so that might be the matter, I don't really know. I would like to make a servo go in these steps. 60 degrees, stop, 45 degrees, stop, 180 degrees, stop (DELAY) for a minute or 2. The "Arduino example" uses a "for " loop (Artduino examples/servo). Can you stack "for" loops? (per say the example) I am rather limited right now do to delivery dates/supply chains......
Code:
void loop() {
  for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
    // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15 ms for the servo to reach the position
  }
  for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15 ms for the servo to reach the position
  }
}
I have learned how to change the degrees, I have learned how to change the time it takes to get to the degree. But I can't find anything in tutorials that has statements for turn 60 degrees, stop, turn 45 degrees, stop, turn 180 degrees, DELAY for a couple minutes. And repeat.......Without the ability to compose it at the moment, I am guessing an "else" statement would be required? turn 60 degrees "else"turn 45 degrees......????? Thanks, Fred
 

Thread Starter

fredric58

Joined Nov 28, 2014
252
The "loop" swings back and forth. 180 degrees to 180 degrees. I simply want to interrupt the "loop" and change the degrees. to (3) different degrees and pause........then repeat. Thanks, Fred
 

djsfantasi

Joined Apr 11, 2010
9,156
The "loop" swings back and forth. 180 degrees to 180 degrees. I simply want to interrupt the "loop" and change the degrees. to (3) different degrees and pause........then repeat. Thanks, Fred
You certainly can stack for loops. You need three. One to turn 60 degrees. Then use a delay statement to pause. A second to turn 45 degrees (is this 45 additional degrees or back to a 45 degree position?). Then a second delay. Then a third for loop to position the servo at 180 degrees.

After this sequence, what do you want to do? Repeat the sequence possibly? In this case, the loop() section on an Arduino automatically gets executed again. Just don’t forget a pause after the third for loop.
 

Thread Starter

fredric58

Joined Nov 28, 2014
252
Dj, you are correct! you can stack them. BUT! you have to put the delay at the beginning of the loop. If you put it at the end, say a 5 minute delay, the servo will go really REALLY slow (5 Minutes long) to make the last 180 degree sweep. I put the delay at the beginning of the loop and it works as anticipated. So, from what I have learned you can't "pause after the return of the third (180 degree). That pause just make the servo return at a very slow rate (5minutes) You have to start at the beginning of the loop with delay....execute loop and back to delay. Now, the delay is the amount of time it takes to make the transition from 45. 60 or 180 going either way. Can you make a recommendation as to how to go from 0 to 45, then from 45 to 60,, then from 60 to 180?
Code:
void loop() {
     delay(60000);
  for (pos = 0; pos <= 60; pos += 1) { // goes from 0 degrees to 60 degrees
    // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15 ms for the servo to reach the position
  }
  for (pos = 60; pos >= 0; pos -= 1) { // goes from 60 degrees to 0 degrees
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15 ms for the servo to reach the position
  }
  for (pos = 0; pos <= 45; pos += 1) { // goes from 0 degrees to 45 degrees
    // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15 ms for the servo to reach the position
  }
  for (pos = 45; pos >= 0; pos -= 1) { // goes from 45 degrees to 0 degrees
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15 ms for the servo to reach the position
  }
  for (pos = 0; pos <= 90; pos += 1) { // goes from 0 degrees to 90 degrees
    // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15 ms for the servo to reach the position
  }
  for (pos = 90; pos >= 0; pos -= 1) { // goes from 90 degrees to 0 degrees
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15 ms for the servo to reach the position // from here we go back to the loop with the delay 60000 (at the beginning of void) between execution of the next cycle.
  }
}
Thanks if you have any ideas, Fred
 

Ya’akov

Joined Jan 27, 2019
9,069
If I understand what you are trying to do (and I am not sure that I do), you need to put your pauses for each chunk of the move between the } of the previous for loop and the for of the next for loop, not inside the previous loop.

Once a for loop executes, it moves to the next line after its closing brace, and that should be your delay—including the two minute delay you want after the full execution. It would be after the final for loop and before the closing } for the loop().
 

djsfantasi

Joined Apr 11, 2010
9,156
What Ya’akov said.

Exactly what I was going to say. In retrospect, my wording was vague. When I said “then use a delay statement to pause”, I meant “after” the for loop. As Ya’akov described more clearly…
between the } of the previous for loop and the for of the next for loop, not inside the previous loop.
 

Thread Starter

fredric58

Joined Nov 28, 2014
252
GOT IT! Thanks for taking the time to input. That makes sense. What I am trying to do is basically learn to control servos. I'm getting there slowly. I "think" I can figure out the next part. It's late, will try it tomorrow.


Code:
void loop() {
     delay(60000);
  for (pos = 0; pos <= 30; pos += 1) { // goes from 0 degrees to 30 degrees (pos <= 30; pos += 1) is the variable?
                                                               // in steps of 1 degree
    myservo.write(pos);                         // tell servo to go to position in variable 'pos'
    delay(15);                                          // waits 15 ms for the servo to reach the position
  }
delay(1000);                                         // delay you spoke of goes after close } of the for loop?  

  for (pos = 30; pos <= 60; pos += 1) { // it's "AT" 30 so it goes from 30 degrees to 60 degrees? then i                                                                                                            //can do "AT" 60 to 90 with delays between? etc etc.
    myservo.write(pos);                         // tell servo to go to position in variable 'pos' (which is 60)
    delay(15);                                          // waits 15 ms for the servo to reach the position
  }
delay(1000);  after for } close ?
Hope that makes sense? Thanks again. Have a great weekend, Fred
 

Ya’akov

Joined Jan 27, 2019
9,069
GOT IT! Thanks for taking the time to input. That makes sense. What I am trying to do is basically learn to control servos. I'm getting there slowly. I "think" I can figure out the next part. It's late, will try it tomorrow.
Something that you should learn to do is create functions when code is repeated. In this case you should really have a function that does the moving and call it with parameters for at least the position start and stop, and you could also add step size like:

sweepServo Function:
//
// DISCLAIMER: This code is untested, it was typed directly into the code block editor and while I didn’t see any problems when I reviewed it, it  could contain typos or other errors that prevent it from running as presented. It is provided as an example of what to do.

// other housekeeping and setup code
// ...

const SERVO_SWEEP_DELAY = 1000; // constant for delay between sweeps segments, set it in one place, change it easily

void loop() {  // much neater main loop logic, easy to foillow

  sweepServo( 0, 30, 1 );
  sweepServo( 30, 90, 1 );
  sweepServo( 90, 180, 1 );
  sweepServo( 180, 90, 1 );
  sweepServo( 90, 30, 1 );
  sweepServo( 30, 0, 1 );

}

void sweepServo(int servoStartPosition, int servoEndPosition, int servoStepDegrees) { // assign the passed parameters to variables

  int servoPosition;
  servoPosition = servoStartPosition; // set the start position according to the parameter passed

  for (servoPosition = 0; servPosition <= servoEndPosition; servoPosition += servoStepDegrees) { // use the other two parameters passed
                                    
    myServo.write(servoPosition); // by convention, use camelCase (not myservo but myServo, I changed this, change it everywhere)
    delay(15); // this could be a constant, like SERVO_SETTLE_DELAY, do this if you find yourself tuning it                                   

   }
  delay(SERVO_SWEEP_DELAY);    //use the constant set at the beginning of the program
}
 

Thread Starter

fredric58

Joined Nov 28, 2014
252
Mr. Ya’akov, Wow! Talk about simplifying something. That’s an incredible concept that I definitely need to study. It is one of, if not the BEST tutorials I have ever received in years. Extremely to the point with comments that are not so overly complicated, that it is very easy for me to understand. I almost understand it without doing any research.....I'm about to implement it and play with it to see what I can accomplish. I truly appreciate you taking the time to share your knowledge with me. I am truly amazed! As far as your "Tenents", that's POWERFUL, an amazing choice of words and EXTREMELY WELL SAID! Thanks for your help with my project, Fred
 

Beau Schwabe

Joined Nov 7, 2019
155
This section of Code ....
C-like:
  servoPosition = servoStartPosition; // set the start position according to the parameter passed

  for (servoPosition = 0; servPosition <= servoEndPosition; servoPosition += servoStepDegrees) { // use the other two parameters passed
                                    
    myServo.write(servoPosition); // by convention, use camelCase (not myservo but myServo, I changed this, change it everywhere)
    delay(15); // this could be a constant, like SERVO_SETTLE_DELAY, do this if you find yourself tuning it                                   

  }
Should read more like ...

C-like:
  for (MovePosition = servoStartPosition; MovePosition <= servoEndPosition; MovePosition += servoStepDegrees) { // use the other two parameters passed
                                    
    myServo.write(MovePosition); // by convention, use camelCase (not myservo but myServo, I changed this, change it everywhere)
    delay(15); // this could be a constant, like SERVO_SETTLE_DELAY, do this if you find yourself tuning it                                   

  }
 

Ya’akov

Joined Jan 27, 2019
9,069
This section of Code ....
C-like:
  servoPosition = servoStartPosition; // set the start position according to the parameter passed

  for (servoPosition = 0; servPosition <= servoEndPosition; servoPosition += servoStepDegrees) { // use the other two parameters passed
                                   
    myServo.write(servoPosition); // by convention, use camelCase (not myservo but myServo, I changed this, change it everywhere)
    delay(15); // this could be a constant, like SERVO_SETTLE_DELAY, do this if you find yourself tuning it                                  

  }
Should read more like ...

C-like:
  for (MovePosition = servoStartPosition; MovePosition <= servoEndPosition; MovePosition += servoStepDegrees) { // use the other two parameters passed
                                   
    myServo.write(MovePosition); // by convention, use camelCase (not myservo but myServo, I changed this, change it everywhere)
    delay(15); // this could be a constant, like SERVO_SETTLE_DELAY, do this if you find yourself tuning it                                  

  }
Yup, editing error (the code block dialog is a lousy code editor, I really should write the code in my usual code editor and paste it).

But, this is what was meant:

C-like:
  // servoPosition = servoStartPosition; set the start position according to the parameter passed

  for (servoPosition = servoStartPosition ; servoPosition <= servoEndPosition; servoPosition += servoStepDegrees) { // use the other two parameters passed
                                   
    myServo.write(servoPosition); // by convention, use camelCase (not myservo but myServo, I changed this, change it everywhere)
    delay(15); // this could be a constant, like SERVO_SETTLE_DELAY, do this if you find yourself tuning it                                  

  }
That should be right, but it is very late and I have been driving for about 12 hours, so, subject to revision due to peer review.
 

Thread Starter

fredric58

Joined Nov 28, 2014
252
What I discovered. I implemented "functions" as described and it 1/2 way works. On line 28 in the #8 post. If I change delay(15); to slow down the spin, to say delay(100); it slows down and you can almost see each degree as it slowly turns. BUT! it only slows the servo down when it is going in a clockwise direction. When it turns to counter clockwise it is as if it is still set to the delay(15); and it jumps back very quickly. I think the delay would remain the same in either direction???
 

Thread Starter

fredric58

Joined Nov 28, 2014
252
It doesn't act right. I'm SURE I have made some mistakes....It compiles OK, but something just isn't right



Code:
/* Sweep
  by BARRAGAN <http://barraganstudio.com>
  This example code is in the public domain.

  modified 8 Nov 2013
  by Scott Fitzgerald
  https://www.arduino.cc/en/Tutorial/LibraryExamples/Sweep
*/

#include <Servo.h>
Servo myServo;  // create servo object to control a servo // twelve servo objects can be created on most boards
int servoPosition = 0;    // variable to store the servo
int servoStartPosition;
int MovePosition;
const(SERVO_SWEEP_DELAY) = 1000;    //use the constant set at the beginning of the program



void setup() {
  myServo.attach(9);  // attaches the servo on pin 9 to the servo object


}

void loop() {  // much neater main loop logic, easy to foillow

  sweepServo( 0, 180, 1 );
  sweepServo( 180, 90, 1 );
  sweepServo( 90, 180, 1 );
  sweepServo( 180, 90, 1 );
  sweepServo( 90, 30, 1 );
  sweepServo( 30, 0, 1 );
  delay(100);
}

void sweepServo(int servoStartPosition, int servoEndPosition, int servoStepDegrees) { // assign the passed parameters to variables

  int servoPosition;
  servoPosition = servoStartPosition; // set the start position according to the parameter passed

  for (MovePosition = servoStartPosition; MovePosition <= servoEndPosition; MovePosition += servoStepDegrees) { // use the other two parameters passed
                                    
    myServo.write(MovePosition); // by convention, use camelCase (not myservo but myServo, I changed this, change it everywhere)
    delay(15); // this could be a constant, like SERVO_SETTLE_DELAY, do this if you find yourself tuning it

  }
  delay(SERVO_SWEEP_DELAY);    //use the constant set at the beginning of the program
}
 

Thread Starter

fredric58

Joined Nov 28, 2014
252
What I am trying to accomplish is. I have a servo with a 180 degree sweep. I want to make it go from 0 to 30, "remember" where itself is. go from 30 to 60 (remember where itself is. go from 60 to 90, then.....maybe 90 to 60 then 60 to 180. it seems to always go back to zero and sometimes it just sits there. and the clockwise speed is never the same as the counter clockwise. This is my first attempt to understand "functions". I can write it out line by line, but there's a lotta lines and every time I want to change something I have to go through each line. "functions" seems totally more streamlined way to do this. all help is greatly appreciated, thanks all, Fred
 

Thread Starter

fredric58

Joined Nov 28, 2014
252
int servoPosition;
servoPosition = servoStartPosition;

it starts at zero.......

is it possible that this should be "current servo position"? The start position is (0) but once it moves to say 90 degrees, that's no longer the current start position? 90 degrees would be the current start position? so ??? "start at 90, go to 120 degrees......and I don't see a (minus) for going backwards. is that something I will need to take into consideration?
 

Ya’akov

Joined Jan 27, 2019
9,069
When the servoSweep() function is called it passes three parameters like:

servoSweep(0, 30, 1);

which are, in order, assigned to servoStartPosition, servoEndPosition, and servoStepDegrees. So the call above would result starting at 0°, ending at 30°, and stepping 1° at time. The next call should be:

servoSweep(30, 60, 1);

This will result in starting at 30°, ending at 60°, and stepping 1°. It follows that:

servoSweep(60, 90, 1);
servoSweep(90, 130, 1);
servoSweep(120, 150, 1);
servoSweep(150, 180, 1);

would sweep 30° at a time, from 0° to 180°. To sweep back, reversing the order of the same calls would do the same thing in the other direction.

Use any numbers you want, just know that nothing “remembers” where the servo is. The only thing that decides where the servo will start is the first parameter in the call to the function.

If you wanted to, you could write it to simply do the pattern algorithmically. But this way you have fine control over the positions and can make adjustments.

I hope this is more clear.
 

MrChips

Joined Oct 2, 2009
30,707
This is an example where a properly drawn flow chart is better than 1000 words.
Draw a flow chart that uses no programming or coding language. Just plain English.
 

djsfantasi

Joined Apr 11, 2010
9,156
Code:
It doesn't act right. I'm SURE I have made some mistakes....It compiles OK, but something just isn't right
What do you mean by “slows down the spin”? Are to trying to slow the time it takes for a move from start to end? Or for the delays after the move to change?

The problem occurs in your for statement. You have used the += operator… but that only goes in one direction. And by incrementing versus decrementing, the servo will snap at the end as the loop won’t count the way you think it will.

You need to check if the end position is less than the start position and make sure that servoStepDegrees is negative. Or pass a negative value when going backward. Whichever is easier to you.

Code:
void loop() {  // much neater main loop logic, easy to foillow

  sweepServo( 0, 180, 1 );
  sweepServo( 180, 90, -1 );
  sweepServo( 90, 180, 1 );
  sweepServo( 180, 90, -1 );
  sweepServo( 90, 30, -1 );
  sweepServo( 30, 0, -1 );
  delay(100);

}
 

Thread Starter

fredric58

Joined Nov 28, 2014
252
POST # 13 LINE 44. If this number is increased the servo will move slower from say 30 to 60 degrees. the other delay, delay(SERVO_SWEEP_DELAY); is the time between sweeps.



This makes more sense to me
Code:
void loop() {                // much neater main loop logic, easy to follow

  sweepServo( 0, 180, 1 );
  sweepServo( 180, 90, -1 );  // a negative call, the "speed and "delay" are irrelevant at the moment, that I can control. It's just                                                     // that darn "Snap back to (0) that's annoying me" I'll give this a try tomorrow when I'm not so                                                           // frustrated. Since most of my projects are "repetitive actions" ya'lls input is really appreciated.
                                               // and by using functions it is so easy to change everything globally. 
  sweepServo( 90, 180, 1 );
  sweepServo( 180, 90, -1 );
  sweepServo( 90, 30, -1 );
  sweepServo( 30, 0, -1 );
  delay(100);

}
Thank you again for sharing your knowledge, Fred
 

Beau Schwabe

Joined Nov 7, 2019
155
Here is a basic flow chart that takes into account direction polarity if the Start position is less than or greater than then End position.

The code is blocking, which is how the original code was written, but this can evolve to non-blocking with a more advanced next level "dispatching mode" flowchart implementation.

As is, for "blocking":
- Node 02 would have a Delay(15) or (20) and you would remove "Start Period Timer (20ms)" from Node 07.

For a "dispatch mode" flowchart conducive to "non-blocking":
- The Node reference is a variable Index pointer.
- Each Node does NOT call the next node in the flow but can change the Index pointer.
- Each Node returns to the main program where a dispatcher (If Index pointer is this then go to a corresponding Node).
This can be greatly simplified with the use of "switch case" and "goto" statements. Even though the goto statement is frowned upon, the use of it in this circumstance is an exception.
- This way with more complex designs you can have multiple flowcharts, each with their own Index Pointer, that interdigitate
their Node States.
- Node 02 simply looks for elapsed time to either count down or count up depending on how you write the code.
- Node 07 grabs a new starting point for the Period Counter with "Start Period Timer (20ms)" that Node 02 can reference.

Servo.PNG
 
Top