controlling micro servo

Hi I am trying to control a micro servo without the library. A8 is reading voltage from potential divider and as I rotate the potential divider I expect the servo to rotate with it.

It seems like it would only stop at 5 equally spaced angle e.g. 0, 45, 90, 135 and 180. I have tried the servo library and it was capable of stopping at a more specific angle.

Is the duty cycle between 1-2ms ? I have tried 2ms and it does not stop at 180 and it required higher duty cycle like 4ms to reach 180.

float angle=0.00; //duty cycle
float total=20.00; //PWM period 
float potential;

void setup() {
pinMode(A8, INPUT); //voltage from potential divider
pinMode(8, OUTPUT);  //control signal to servo

}

void loop() {

potential=analogRead(A8);



               
angle = potential*(4/1023.00);




digitalWrite(8,HIGH);
delay(angle);
digitalWrite(8,LOW);
delay(total-angle);


}

Why not use the library?

But anyway with that code your main problem is that you can't use delay() to get short accurate delays. The parameter to it is an integer not a float so 2.00 and 2.99 will end up at exactly the same delay. Try using delayMicroseconds instead.

And servos aren't fussy about the pulse repetition rate so you might as well just use a constant 20ms for the off time.

BTW you might not get 180 degrees anyway. Many/most hobby servos are limited to about 120-150 degrees.

Steve

I don't believe you can control a servo with 0 to 100% PWM like that, the cycle time has to be 20 mS and the on time between 544 and about 2400 uS.

It's working with delayMicroseconds thank you! but it is not as smooth as what I got from the library

You might try this test sketch to determine the end limits and micro values thereof.

/*
 Try this test sketch with the Servo library to see how your
 servo responds to different settings, type a position
 (0 to 180) or if you type a number greater than 200 it will be
 interpreted as microseconds(544 to 2400), in the top of serial
 monitor and hit [ENTER], start at 90 (or 1472) and work your
 way toward zero (544) 5 degrees (or 50 micros) at a time, then
 toward 180 (2400). 
*/
#include <Servo.h>
Servo servo;

void setup() {
  // initialize serial:
  Serial.begin(9600); //set serial monitor baud rate to match
  servo.write(90);
  servo.attach(9);
  prntIt();
}

void loop() {
  // if there's any serial available, read it:
  while (Serial.available() > 0) {

    // look for the next valid integer in the incoming serial stream:
    int pos = Serial.parseInt();
    pos = constrain(pos, 0, 2400);
    servo.write(pos);
    prntIt();
  }
}
void prntIt()
{
  Serial.print("  degrees = "); 
  Serial.print(servo.read());
  Serial.print("\t");
  Serial.print("microseconds =  ");
  Serial.println(servo.readMicroseconds());
}

Lets have a peek at your program.
HowToPostCode

kc15781:
It's working with delayMicroseconds thank you! but it is not as smooth as what I got from the library

As has been asked before;
Why don't you use the servo library?

What you have to realize is that without the library, you trying to do some output timing while you code also has to do other activities.

You code might not get to the part of the code that decides if the servo signal needs to go HIGH or LOW on the exact microsecond you want.

It may be 10 or 15 us late, which means your servo pulse may be 10 or 15us longer or shorter.
The more code you have around it the more inaccuracy in your servo signal because your code has more and more other things to do.

Tom... :slight_smile:

Wrote this and it works but is jittery, I guess because the processor is busy doing other things like Tom said. What’s the reason for not wanting to use the lib?

uint32_t uStime, cycle = 2500, pTime = 1476;
void setup() {
  // initialize serial:
  Serial.begin(9600); //set serial monitor baud rate to match
  pinMode(9,OUTPUT);
}

void loop()
{
    // if there's any serial available, read it:
  while (Serial.available() > 0) {

    // look for the next valid integer in the incoming serial stream:
    int pos = Serial.parseInt();
    pos = constrain(pos, 544, 2400);
    pTime = (pos);
    Serial.println(pTime);
  }
  bitWrite(PORTB,1,micros() - uStime < pTime);
  if(micros() - uStime > cycle)
    uStime += cycle;
}

I want to learn how it operates and by using the library it kind of conceals the whole operation.

How is the code from the library different to my code? Doesn't it execute the code from the top to the bottom?

I believe the lib makes use of a hardware timer to control the pulse width, why not read the code in the files Servo.h and Servo.cpp inside the Servo library.