Controlling servo motor with arduino

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?

Yes.
Use the sin function or a lookup table.

AWOL:
Yes.
Use the sin function or a lookup table.

Is there anyway you can provide a rough code on how this is done?
I am new to the arduino and to coding.
I tried searching on google, but had no luck.

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.

I would still use a for loop right?

pyroknife:
I would still use a for loop right?

Yes.

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 
  } 
}

pyroknife:
Would the following changes (in BOLD) be enough to give the sinusoidal function?

Nope.

sin(1) is a constant. You're not looking to add a constant, else it becomes linear.

Arrch:

pyroknife:
Would the following changes (in BOLD) be enough to give the sinusoidal function?

Nope.

sin(1) is a constant. You're not looking to add a constant, else it becomes linear.

Sin(pos).

pos is an int. sin expects radians, which will likely be a float.

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.

pyroknife — What’s the 40? I’m not claiming it’s wrong. I just don’t understand it.

Idea. Just spit-balling here. Awaiting confirmation/feedback.

What if it looked something like this -

for(pos=0; pos <180; pos += (sin(2?/180)) )
   {
        write position, etc.....
   }

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? :sleeping:

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(?/(2
180)) = 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.

1ChicagoDave:
pyroknife — What's the 40? I'm not claiming it's wrong. I just don't understand it.

I want the servo to rotate from 0deg to 40deg and back to 0deg. That is what I am defining as a cycle.

It sounds like specifying a frequency just became a lot harder with a sin() function?

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.

Be aware that the sin() function is slow on an Arduino

but compared to any servo you can afford, it'll be plenty fast enough.

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)

I was thinking of using something like this:

void loop() 
{ 
  for(pos = 0; pos <= 40; pos ++)
  {
    float pos_sin = sin(PI*pos/40);
    myservo.write(40*pos_sin);
  }

And does that do what you want?