The code found from this site Arduino Playground - Servo uses a for loop. If you graph the motion of the motor or just by a simple inspection of the 2 for loops, you can tell that the motion resembles that of a saw tooth graph.
My question is is it possible to make this a sinusoidal like motion instead?
The trick is remembering that "sin()" returns the sine of the angle given, but the angle is expressed in radians, not degrees.
There are 2pi radians in 360 degrees.
AWOL:
The trick is remembering that “sin()” returns the sine of the angle given, but the angle is expressed in radians, not degrees.
There are 2pi radians in 360 degrees.
Just to be sure. The following code would give a linear sawtooth-like motion for the servo right?
#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 < 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 15ms for the servo to reach the position
}
for(pos = 180; pos>=1; 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
}
}
Would the following changes (in BOLD) be enough to give the sinusoidal function?
#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 < 180; [b]pos += sin(1))[/b] // 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 = 180; pos>=1; [b]pos-=sin(1)[/b]) // 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
}
}
Arrch:
pos is an int. sin expects radians, which will likely be a float.
oh, I didn’t paste it here.
I changed the code to
#include <Servo.h>
Servo myservo; // create servo object to control a servo
// a maximum of eight servo objects can be created
float 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; [b]pos += sin(pos))[/b] // 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; [b]pos-=sin(pos)[/b]) // 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
}
}
I just need to figure out the constant that goes inside the parenthesis.
Ideally, since sin goes from 0 to 1 to 0 to -1 to 0.
Could ‘pos’ equal (180 * (1 + (sin(?/(whatever resolution wanted*))/2) ).
*How many "steps from 0 to 180 wanted.
Or do I need to go back to sleep before trying to remember trig/calculus?
EDIT/ADDENDUM:
Or, could do it “manually”, using arrays. Fill an array with calculated values of (180 * (sin(?/(n, n-1, n-2…n-n))) ). Then increment/decrement by the elements of array. Not the prettiest method, but should work.
Lots of people have done this for fading LEDs. Google their code, just replace their “0-255” (PWM for LED brightness) with “0-180” (servo position). (In ALL instances, explicit, and any calculations they made using 0-255.)
I just need to figure out the constant that goes inside the parenthesis.
Has to be a variable, right? SIN of a constant will still be a constant. (I'm seriously asking, because feels like my brain isn't working right.)
....pos =+ ( x * sin(?/(2*pos)) ) ?
Just make sure 2 * pos never equals 0 (undefined)
If pos = 1, sin(?/(21)) = sin(?/2) = 1
If pos = 180, sin(?/(2180)) = sin(?/360) = (practically) 0
x = some factor to speed up / slow down rate of increase / decrease.
(***I'm getting that feeling that I'm missing the obviously much easier solution to this. Feels like college all over again. :~ ) I know this isn't totally correct. But maybe it'll help something click with someone else?
pyroknife:
My question is is it possible to make this a sinusoidal like motion instead?
Yes. Calculate the sin of a value that increases with time. The result will be a sin wave. The frequency of the sin wave will be determined by how quickly your input value increases with time (each 2*pi increase in the input will correspond to one complete cycle on the output). The amplitude of the sin wave will be 1. You would scale and offset this value to produce the range of movement you wanted, for example you could map it to a servo angle in the range 0 .. 180.
float frequency = 4; // Hz
float time = millis() / 1000.0;
float value = amplitude * sin(2 * pi * frequency * time); // value is in the range +/- 1
int servoPosition = (int) (value + 1) * 180;
IMO it would be sensible to use the approach demonstrated in the blink without delay example sketch to update the position at regular intervals so that the output performed a sinusoidal movement - no loops or delays required.
So, you're saying one cycle (2 pi radians, remember) maps to a displacement of zero to 40 "degrees" and back to zero?
How long does a cycle take?
(Trying to nudge you in the right direction here)
Be aware that the sin() function is slow on an Arduino - not much cpu hardware. If performance matters, use a table lookup instead. The table simply an array with sin values. Array index is the angle. You probably can avoid floating point entirely.
AWOL:
So, you’re saying one cycle (2 pi radians, remember) maps to a displacement of zero to 40 “degrees” and back to zero?
How long does a cycle take?
(Trying to nudge you in the right direction here)