Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Arduino Programming for Servo motor

  1. Jul 16, 2013 #1
    Hi all. I am working on a project that requires using an arduino microcontroller to control the motion of a servo motor.

    The original code is of the form:
    #include <Servo.h>

    Servo myservo; // create servo object to control a servo
    // a maximum of eight servo objects can be created

    int pos = 0; // variable to store the servo position

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

    void loop()
    for(pos = 0; pos <= 40; 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 15ms for the servo to reach the position
    for(pos = 40; 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 15ms for the servo to reach the position

    but the problem is I don't want the motor's motion to behave linearly (constant increments of the pos variable). My desired motion is a sinusoidal like function.
    Does anyone have any suggestions on how to approach this?
    I am quite new to programming, especially with microcontrollers.
  2. jcsd
  3. Jul 16, 2013 #2
    If you want to keep it taking 40 increments from 0 to 180 and 40 increments from 180 back to 0 then

    for(pos = 0; pos < 80; pos ++)
    float pos_sin = abs(sin(2*PI*pos/80))

    Might want to double check what scaling myservo.write wants, as this is it will get a floating point 0 .. 1 where before you were giving it an integer 0..40
  4. Jul 16, 2013 #3
    Thanks for the reply!
    I actually want the servo motor to go from 0deg to 40deg and back to 0 deg and then repeat. That is what I am calling one full cycle.
  5. Jul 16, 2013 #4
    Well in that case basically just multiply pos_sin * 40 once you calculate it. Also just use PI so that you go from sin(0) -> sin(PI/2) -> sin(PI) which takes you from 0*40 -> 1*40 -> 0*40 (full cycle from 0 to 40 to back again.

    for(pos = 0; pos < 80; pos ++)
    float pos_sin = sin(PI*pos/80)

    Depending on if you want to end on 0 or right before 0 make pos <= 80 instead of pos < 80.

    Also the 80 really has no significance now, you could make it any number depending on the resolution you want (be sure to change it in both places if you did change it).
  6. Jul 16, 2013 #5
    By using this, it is difficult to specify the frequency of operation?
  7. Jul 16, 2013 #6
    Well, the frequency is going to be dependent on how fast the for loop gets called. I left out the delay you had in your original program but if you need it for servo settling time then if you assume each iteration of the loop has a 15ms delay:

    80 increments per cycle (from my code) * 15ms delay = 1.2 seconds to make a fully cycle so you are at a little less than 1Hz operation. If you want to increase / decrease that frequency then you either need to change the increments per cycle or the delay per cycle. So for example if you want to double the frequency cut the increments per cycle in half.

    Like most systems you end up trading resolution (a bunch of increments) for speed. You have to find the happy medium you need.
  8. Jul 16, 2013 #7
    Okay, thanks a bunch. I'll give this a try.
  9. Jul 16, 2013 #8
    The abs is not necessary right, for my case?
  10. Jul 16, 2013 #9
    Out of curiosity, instead of using a for loop, could you just write a sin function and have that drive the motion instead of using a loop?
Share this great discussion with others via Reddit, Google+, Twitter, or Facebook