I'm using the Servo library to control a 360 degree servo and making use of the writeMicroseconds() function, which for the most part works pretty well.
The problem is, after the sketch loops a few times through (where the motor rotates forward, then back again to it's original starting position), it's not quite aligned in the same position as where it started from. It's like it overshoots a fraction of a millimeter each time through the loop and then it compounds over time. Is there a way to correct this to be more precise each and every time? Or perhaps a way to have the servo "reset" back to it's starting position after a few loops?
(Not looking for someone to write the code for me, just point me in the right direction)
I think I saw a sketch that used a flagging method to determine the position of the servos shaft (25% of the way forward, 50% of the way forward, 75% etc.)
Could I use a flagging type system to perhaps slow the servo down once it gets to say 75% to its determined position in efforts to make it more precise?
Is this even a thing?
//Code is made for a 360 degree angle servo motor
#include <Servo.h>
#include <ezButton.h>
#include <Adafruit_INA219.h>
Servo Servo1;
ezButton Button1A(2); // Create an ezButton object attached to pin 2
ezButton Button1B(3); // Create an ezButton object attached to pin 3
Adafruit_INA219 ina219;
bool Pressed = false;
//---------------
void setup()
{
Serial.begin(115200);
Servo1.attach(9); // Servo motor attached to pin 9
Button1A.setDebounceTime(50); // Set button debounce time to 50 milliseconds
Button1B.setDebounceTime(50); // Set button debounce time to 50 milliseconds
ina219.begin(); // Start the INA219 DC current module
uint32_t currentFrequency; // Part of the INA219
}
//---------------
void loop()
{
Button1A.loop(); // MUST call the loop() function first
Button1B.loop(); // MUST call the loop() function first
int btnState1A = Button1A.getState();
int btnState1B = Button1B.getState();
if (Button1A.isReleased() && (Pressed == false))
{
Servo1.writeMicroseconds(2000);
float current_mA = 0; // Start measuring servo motor current
current_mA = ina219.getCurrent_mA();
Serial.print("Current: ");
Serial.print(current_mA); Serial.println(" mA");
Serial.println("");
delay(500);
Servo1.writeMicroseconds(1500);
Pressed = true;
}
if (Button1B.isReleased() && (Pressed == true))
{
Servo1.writeMicroseconds(1000);
float current_mA = 0; // Start measuring servo motor current
current_mA = ina219.getCurrent_mA();
Serial.print("Current: ");
Serial.print(current_mA); Serial.println(" mA");
Serial.println("");
delay(500);
Servo1.writeMicroseconds(1500);
Pressed = false;
}
}
Most 360 degree (or "continuous") servos are not intended for positioning. Post a link to the one you have.
There exist positioning servos that will perform more than one full rotation. Or, you could add a shaft encoder to a continuous servo, and develop a PID controller to position the shaft angle.
A continuous servo has had its feedback mechanism disconnected. A continuous servo is no longer a servo, it is merely a gear motor that can have its direction and speed controlled by a servo signal. Positioning with any precision or repeatability is no longer possible.
I think I saw a sketch that used a flagging method to determine the position of the servos shaft (25% of the way forward, 50% of the way forward, 75% etc.)
Don't know what that means. What is a flagging system? Like limit switches?
@jremington Could you possibly post a link to a "positioning servo" for me? I'm not seeing anything obvious on Google regarding them.
@groundFungus I have a 180 degree servo as well, but seeing as it doesn't travel it's full 180 degrees (but rather approx 120 degrees) I can't use it for my application. Out of curiosity, would a 180 degree servo give me precision every-time?
Flagging system: Let me try to do some digging and see if I can find the code I was referring to this for you sir.
Look for sail winch servos.
1 Like
In addition to sail winch servos, there are continuous servos with position feedback, like this one: Pololu - Parallax Feedback 360° High-Speed Servo
I assume that in your original post, there is no load on the servo shaft. I think you will notice that as soon as a load is applied to the servo shaft, the timing scheme no longer works.
1 Like
Thank you for the suggestion @groundFungus. Unfortunately the sail winch servos I was finding only rotate in one direction.
Otherwise it would have been a great solution!
Huh? Check again on that sail winch servo.
@jremington Your solution seems ideal with the Parallax Feedback 360 degree servo.
I'm really glad I asked this great community! Keep it up guys.
Just a thought - but could you maybe use a stepper instead? Assuming the stepper is not mechanically loaded so it mis-steps, you should know how many pulses are needed for 360 degrees (it is often 200 steps). You still have to determine it's position at power up but a simple microswitch (and 'zerioing code) could help you determine it's zero position.
Thank you for the replay @bezelsanddisplays. That's a good thought.
Steppers can be "microstepped" so that you can have 6400 or more steps per revolution depending on the driver capability.
@jremington I just got a Parallax Feedback 360 Servo in today. It's seemingly very accurate; able to stop at the same angle/degree every single time! This is perfect!! I haven't yet tested it under load, but from what I'm seeing thus far, I'm impressed.
Thank you again for the recommendation!
Cool! Glad to help.
There is not much in the way of working Arduino examples for the servo, so others may find it useful if you could post yours.
Completes 1 cycle (Once forward/once backward) x10 times then stops.
#include <Wire.h>
#include "FeedBackServo.h"
#define FEEDBACK_PIN 2 //Servo1 - Define feedback signal pin (Yellow wire)
#define SERVO_PIN 3 //Servo1 - Define control pin (White wire)
FeedBackServo Servo1 = FeedBackServo(FEEDBACK_PIN); //Servo1 - Set feedback signal pin number
int Cycle = 0;
void setup()
{
Serial.begin(115200); //Baud rate
Servo1.setServoControl(SERVO_PIN); //Set servo control pin number
Servo1.setKp(1.0);
}
void loop()
{
if (Cycle <= 9) //Adjust this number for the amount of cycles you want
{
Serial.print("Cycle #"); //Prints to the serial monitor which cycle it's currently on
Serial.println(Cycle);
//SERVO1 START POSITION
Servo1.rotate(220, 3); //Change "220" to whatever degree angle you want your starting angle to be. Change the "3" to how close you want the motor's angle to get before it stops - this is set to +-3 degrees of "220"
Serial.print("Forward Angle: ");
Serial.println(Servo1.Angle());
delay(5000);
//SERVO1 END POSITION
Servo1.rotate(325, 3);
Serial.print("Backward Angle: ");
Serial.println(Servo1.Angle());
Serial.println();
delay(5000);
Cycle = Cycle + 1;
}
}
Sorry for the late response @jremington I just saw your message now
Thanks, but where can users find the library you used, FeedbackServo.h?