Arduino Programming for Servo motor

AI Thread Summary
The discussion focuses on programming an Arduino to control a servo motor with a sinusoidal motion instead of linear increments. The original code was modified to use a sine function to achieve the desired motion from 0 to 40 degrees and back. Participants suggested scaling the sine output appropriately and adjusting the loop increments to control the frequency of the motion. It was noted that the frequency of operation depends on the loop's execution speed and the delay used. The conversation also touched on the possibility of using a sine function directly instead of a loop for smoother motion control.
pyroknife
Messages
611
Reaction score
4
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.
 
Engineering news on Phys.org
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
 
Floid said:
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)
}

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.
 
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).
 
Floid said:
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)
}
By using this, it is difficult to specify the frequency of operation?
 
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.
 
Floid said:
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.

Okay, thanks a bunch. I'll give this a try.
 
The abs is not necessary right, for my case?
 
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?
 
Back
Top