Arduino Programming for Servo motor

1. Jul 16, 2013

pyroknife

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. Jul 16, 2013

Floid

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))
myservo.write(pos_sin)
}

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

3. Jul 16, 2013

pyroknife

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.

4. Jul 16, 2013

Floid

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)
myservo.write(40*pos_sin)
}

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).

5. Jul 16, 2013

pyroknife

By using this, it is difficult to specify the frequency of operation?

6. Jul 16, 2013

Floid

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.

7. Jul 16, 2013

pyroknife

Okay, thanks a bunch. I'll give this a try.

8. Jul 16, 2013

pyroknife

The abs is not necessary right, for my case?

9. Jul 16, 2013

pyroknife

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?