Arduino Programming for Servo motor

Click For Summary

Discussion Overview

The discussion revolves around programming an Arduino microcontroller to control the motion of a servo motor, specifically aiming to achieve a sinusoidal motion rather than linear increments. Participants explore coding approaches and mathematical functions to implement this desired behavior.

Discussion Character

  • Exploratory
  • Technical explanation
  • Mathematical reasoning

Main Points Raised

  • One participant shares initial code for controlling a servo motor and expresses a desire for non-linear motion, specifically a sinusoidal function.
  • Another participant suggests using a sine function to achieve the desired motion, providing a code snippet that calculates the position based on the sine of an angle.
  • A participant clarifies their intention to have the servo move between 0 degrees and 40 degrees, indicating that this range defines one full cycle.
  • Further suggestions include multiplying the sine output by 40 to scale the motion appropriately and using PI to define the sine function's range.
  • Concerns are raised about specifying the frequency of operation, with discussions on how the loop's speed and delay impact the frequency of the servo's motion.
  • Another participant notes that the absolute value function may not be necessary for their specific case.
  • A question is posed about the possibility of using a sine function directly to drive the motion without a loop.

Areas of Agreement / Disagreement

Participants have not reached a consensus on the best approach to implement the sinusoidal motion, and multiple suggestions and methods are being explored. The discussion remains unresolved regarding the optimal coding strategy and the implications of frequency adjustments.

Contextual Notes

Participants mention the importance of delay for servo settling time and the trade-off between resolution and speed, indicating that adjustments to increments or delays will affect the frequency of operation. There is also a note about the arbitrary nature of the number of increments used in the sine calculation.

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?
 

Similar threads

  • · Replies 5 ·
Replies
5
Views
4K
  • · Replies 8 ·
Replies
8
Views
7K
Replies
1
Views
4K
  • · Replies 2 ·
Replies
2
Views
3K
  • · Replies 4 ·
Replies
4
Views
4K
  • · Replies 3 ·
Replies
3
Views
7K
Replies
1
Views
2K
  • · Replies 85 ·
3
Replies
85
Views
10K
  • · Replies 1 ·
Replies
1
Views
3K
  • · Replies 8 ·
Replies
8
Views
2K