Servo library problem

I am using an Arduino Uno Wifi rev 2 with a CNC shield. One of the operations is to move a servo through 120 degrees and back. The problem I have, is that sometimes the servo works faultlessly. However, on other occasions I can hear a ticking sound and the servo doesn't move. By changing out the servo for one of the same brand and spec, I get a faultless movement. I change back and sometimes it works and sometimes it doesn't. Both servos are brand new. Can this be the Servo,h library causing the issue?

I think there is a connection problem. May be due to loose wiring.

I have checked multiple times, however you may be right. It could be inside the servo.
Thank you.

I think you are right. I took the back off and fired it up and it works every time. Possibly a wet solder joint. Thank you very much

I thought it might be a connection inside the servo, however after running a soldering iron over the connections and putting the servo back together, I am still having this randomness. Is there another library I could use with the Arduino Uno Wifi that I can try which would eliminate a software issue?

You have proven that it is not the library, by swapping servos and one servo always has the fault.

What servo are you using?
Can you please post a link to data/specs, where you purchased the servos?

I'm suspecting you have got the cheap SG90 servos with plastic gears.

Tom... :grinning: :+1: :coffee: :australia:

Hello paymentupfront

We need some additional information.

Post your sketch, well formated, with well-tempered comments and in so called code tags "< code >" and a detailed circuit diagram to see how we can help.
Have a nice day and enjoy coding in C++.

... or you could try

servo.attach(pin, min, max);

Where min = 1000 and max = 2000 for a generic SG90 servo.

If using

servo.attach(pin);

Here, the default min = 544, max = 2400 could be beyond the mechanical limits, therefore ...

How are you powering the servo?

It could also be a gear issue, i had that with one of mine. The plastic gears were stripped by the metal ones. You would have to take apart the servo and then replace the broken geara with new ones from another motor.

excellent work. The servo works faultlessly. Here is the code I changed to have a min and max values. Thank you dlloyd `void moveServo(int fromPos, int toPos, int duration, int min, int max) {
int increment = 1;
int delayTime = duration / abs(toPos - fromPos);

if (toPos < fromPos) {
increment = -1;
}

for (int pos = fromPos; pos != toPos; pos += increment) {
pos = constrain(pos, min, max); // Constrain the position within the min and max values
myservo.write(pos);
delayMicroseconds(delayTime);
}

toPos = constrain(toPos, min, max); // Constrain the final position within the min and max values
myservo.write(toPos);
delayMicroseconds(delayTime); // Add a small delay at the end for stability
}
`

Glad you've got it working.

Just to mention, all you needed to do is use servo.attach(pin, min, max); in setup. The library internally uses constrain for both the write() and writeMicroseconds() functions.

Thank you. I am a novice and any help is greatly appreciated. I will be needing assistance later on as the project matures. I hope to operate the arduino via blue tooth or wifi and run a printer program. Would you be interested in working on a project?
Peter

Hi,
What this points out is that the servos that you have, have the ability to physically move more or less than 0 to 180, even though being signaled to go 0 to 180.
Not all the one brand/model are the same.

Glad you got them working properly rather than having to purchase more precise servos.

Tom... :grinning: :+1: :coffee: :australia:

Thank you everyone. Here are the specifications.

Hi dlloyd. seems like I might have jumped the gun. When I came in the following day [without changing anything] both servos did not work. I uploaded an earlier servo sweep code and both servos worked seamlessly. What am I doing wrong? I am hoping you can help. Power supply is 24V 15A. The servos are listed in the above post. Here is the code that works with the servo `/* Sweep
by BARRAGAN http://barraganstudio.com
This example code is in the public domain.

modified 8 Nov 2013
by Scott Fitzgerald
https://www.arduino.cc/en/Tutorial/LibraryExamples/Sweep
*/
#include <Servo.h>

Servo myservo; // create servo object to control a servo
// twelve servo objects can be created on most boards

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() {
delay(5); //stops the shuttering at the begining of the stroke.
for (pos = 0; pos <= 145; 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(5); // waits 15 ms for the servo to reach the position
}
for (pos = 145; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(5); // waits 15 ms for the servo to reach the position

}
}
Here is the code that I am having trouble with#include <Servo.h>
// in this code the servo has a min and max because one servo did not perform correctly and now it does.
// Define pin numbers
#define EN_PIN 8
#define X_DIR_PIN 5
#define X_STP_PIN 2
#define Y_DIR_PIN 6
#define Y_STP_PIN 3
#define Z_DIR_PIN 7
#define Z_STP_PIN 4
#define BTN_PIN 11
#define SERVO_PIN 9 // Change = connected Pin2 to Z+ on the CNC shield
#define Y_MS_PIN 10

// TMC2208
int delayTime = 160; // Delay between each pause (us)
int zStps = 1000; // Sets the printer band width, i.e., width of ink cartridge
bool isMoving = false; // Flag to keep track if the stepper is moving

Servo myservo;

void step(boolean dir, byte dirPin, byte stepperPin, int steps) {
digitalWrite(dirPin, dir);
delay(0.001); // Changes speed of motor

for (int i = 0; i < steps; i++) {
digitalWrite(stepperPin, HIGH);
delayMicroseconds(delayTime);
digitalWrite(stepperPin, LOW);
delayMicroseconds(delayTime);
}
}
void moveServo(int fromPos, int toPos, int duration, int min, int max) {
int increment = 1;
int delayTime = duration / abs(toPos - fromPos);

if (toPos < fromPos) {
increment = -1;
}

for (int pos = fromPos; pos != toPos; pos += increment) {
pos = constrain(pos, min, max); // Constrain the position within the min and max values
myservo.write(pos);
delayMicroseconds(delayTime);
}

toPos = constrain(toPos, min, max); // Constrain the final position within the min and max values
myservo.write(toPos);
delayMicroseconds(delayTime); // Add a small delay at the end for stability
}

void setup() {
pinMode(X_DIR_PIN, OUTPUT);
pinMode(X_STP_PIN, OUTPUT);
pinMode(Y_DIR_PIN, OUTPUT);
pinMode(Y_STP_PIN, OUTPUT);
pinMode(Z_DIR_PIN, OUTPUT);
pinMode(Z_STP_PIN, OUTPUT);
pinMode(BTN_PIN, INPUT_PULLUP); // Set the button pin as input with pull-up resistor
pinMode(EN_PIN, OUTPUT);
digitalWrite(EN_PIN, LOW);
pinMode(Y_MS_PIN, INPUT_PULLUP);

myservo.attach(SERVO_PIN); // Specify servo pin

// Home the machine
while (digitalRead(Y_MS_PIN) == HIGH) {
// Move Y stepper away from the microswitch (Normally Open)
digitalWrite(Y_DIR_PIN, LOW); // Reverse direction
digitalWrite(Y_STP_PIN, HIGH);
delayMicroseconds(delayTime);
digitalWrite(Y_STP_PIN, LOW);
delayMicroseconds(delayTime);
}

// Slowly move Y stepper until microswitch is Normally Closed
while (digitalRead(Y_MS_PIN) == HIGH) {
digitalWrite(Y_DIR_PIN, HIGH); // Move towards the microswitch
digitalWrite(Y_STP_PIN, HIGH);
delayMicroseconds(delayTime);
digitalWrite(Y_STP_PIN, LOW);
delayMicroseconds(delayTime);
}

// Check that Servo is at 0 degrees
if (myservo.read() != 0) {
myservo.write(0);
delay(1000);
}

// Move Z stepper 6400 steps and stop
for (int i = 0; i < 6400; i++) {
step(false, Z_DIR_PIN, Z_STP_PIN, 1);
}
step(false, Z_DIR_PIN, Z_STP_PIN, 0);

// Move servo to 115 degrees and back to 0 degrees
myservo.write(115);//set the travel distance of the servo arm
delay(1000);
myservo.write(0);
delay(1000);

// Reverse Z stepper 2000 steps and stop
for (int i = 0; i < 2000; i++) {
step(true, Z_DIR_PIN, Z_STP_PIN, 1);
}
step(true, Z_DIR_PIN, Z_STP_PIN, 0);
}

void loop() {
// Read the button state
bool buttonState = !digitalRead(BTN_PIN); // Invert the button state, as we're using a Normally Open button

if (buttonState && !isMoving) {
// Button has been pressed, move the Z motor continuously until the button is released
isMoving = true;

while (buttonState) {
  // Move the Z motor one step at a time
  step(false, Z_DIR_PIN, Z_STP_PIN, 1);

  // Read the button state
  buttonState = !digitalRead(BTN_PIN); // Invert the button state, as we're using a Normally Open button
}

// Stop the Z motor
step(false, Z_DIR_PIN, Z_STP_PIN, 0);

// Move the servo to 0 degrees
myservo.write(0);
delay(1000);
// Move the servo to 115 degrees
myservo.write(115);
delay(1000);
// Move the servo back to 5 degrees
myservo.write(0);


isMoving = false;
  // Reverse Z stepper 2000 steps and stop
  delay(1000); // Delay to allow servo to return to 5 degrees

for (int i = 0; i < 2000; i++) {
step(true, Z_DIR_PIN, Z_STP_PIN, 1);
}
step(true, Z_DIR_PIN, Z_STP_PIN, 0);
}
}

`
I hope you can help.
Peter

Hi,
To add code please click this link;

Thanks.. Tom.. :grinning: :+1: :coffee: :australia:

Here's what I've noticed with your code and with the Servo library.

In the Servo library ServoTimers.h, lines 29-31:

//#define USE_TIMERB1        // interferes with PWM on pin 3
#define USE_TIMERB2        // interferes with PWM on pin 11
//#define USE_TIMERB0        // interferes with PWM on pin 6

In your code:

#define BTN_PIN 11
pinMode(BTN_PIN, INPUT_PULLUP); // Set the button pin as input with pull-up resistor

I think the Servo Library using TIMERB2 would interfere with your BTN_PIN.
Changing the timer would interfere with pin 3 or 6 which you are already using, so I would just change the BTN_PIN to another pin that's free.

The library's issue #103 Attach with Min Max bug could possibly create problem with a Servo with limited movement range.

Can't help much further as I don't have the hardware.

Thank you, I tried it but still had problems. Finally I added a different delay and called it int servoDelayTime and it worked. Well, given the history... I hope it still works tomorrow. Thank you so much for your help.
Peter

Hi guys
I'm glad to hear that you found a solution by adding a different delay and renaming it as "int servoDelayTime.