Go Down

Topic: controlling micro servo (Read 418 times) previous topic - next topic

kc15781

Apr 09, 2018, 09:41 am Last Edit: Apr 09, 2018, 12:45 pm by kc15781
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.

Code: [Select]

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);


}

slipstick

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

outsider

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.

kc15781

#3
Apr 09, 2018, 12:30 pm Last Edit: Apr 09, 2018, 12:38 pm by kc15781
It's working with  delayMicroseconds thank you! but it is not as smooth as what I got from the library

outsider

You might try this test sketch to determine the end limits and micro values thereof.
Code: [Select]
/*
 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());
}

outsider


TomGeorge

#6
Apr 09, 2018, 02:30 pm Last Edit: Apr 09, 2018, 02:36 pm by TomGeorge
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... :)
Everything runs on smoke, let the smoke out, it stops running....

outsider

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?
Code: [Select]

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

kc15781

#8
Apr 09, 2018, 05:39 pm Last Edit: Apr 09, 2018, 05:42 pm by kc15781
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?

outsider

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.

Go Up