AGFRC A20CLS Servo working with physical Servo tester, but not with code

Here are two sketches (first for Uno, second for ESP32 QT Pico Py). The notable part of this is that using a standard cheap digital servo, this works just fine, but with the A20CLS, it doesn't. Do note that I modified the Servo.h and ESP32Servo.h themselves in an attempt to fix the problem. Specifically, I REFRESH_INTERVAL to 3003 (instead of 2000) and DEFAULT_PULSE_WIDTH to 1520 (instead of 1500) in Servo.h. In ESP32Servo.h I changed REFRESH_CPS to 333.

I know that modifying libraries is advised against but I'm pretty sure this is a PWM problem given that the A20CLS works with the physical servo tester and is recieving power normally.

First (Uno):
#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(1); // attaches the servo on pin 1 to the servo object
myservo.write(20);
delay(500);
myservo.write(40);
delay(500);
myservo.write(60);
delay(500);
}

void loop() {
/*
for (pos = 0; pos <= 60; 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
}*/
}

Second (ESP32)

#include <ESP32Servo.h>

Servo myservo; // create servo object to control a servo
// 16 servo objects can be created on the ESP32

int pos = 0; // variable to store the servo position
// Recommended PWM GPIO pins on the ESP32 include 2,4,12-19,21-23,25-27,32-33
// Possible PWM GPIO pins on the ESP32-S2: 0(used by on-board button),1-17,18(used by on-board LED),19-21,26,33-42
// Possible PWM GPIO pins on the ESP32-S3: 0(used by on-board button),1-21,35-45,47,48(used by on-board LED)
// Possible PWM GPIO pins on the ESP32-C3: 0(used by on-board button),1-7,8(used by on-board LED),9-10,18-21
#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
int servoPin = 26;
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
int servoPin = 26;
#else
int servoPin = 26;
#endif

void setup() {
// Allow allocation of all timers
ESP32PWM::allocateTimer(0);
ESP32PWM::allocateTimer(1);
ESP32PWM::allocateTimer(2);
ESP32PWM::allocateTimer(3);
myservo.setPeriodHertz(50); // standard 50 hz servo
myservo.attach(servoPin, 1000, 2000); // attaches the servo on pin 18 to the servo object
// using default min/max of 1000us and 2000us
// different servos may require different min/max settings
// for an accurate 0 to 180 sweep
}

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 positionij
}
for (pos = 180; pos >= 0; 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
}

}

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'

Use code tags (the < CODE/ > icon above the compose window) to make it easier to read and copy for examination

https://forum.arduino.cc/t/how-to-get-the-best-out-of-this-forum

Please post your full sketch, using code tags when you do

Posting your code using code tags prevents parts of it being interpreted as HTML coding and makes it easier to copy for examination

In my experience the easiest way to tidy up the code and add the code tags is as follows

Start by tidying up your code by using Tools/Auto Format in the IDE to make it easier to read. Then use Edit/Copy for Forum and paste what was copied in a new reply. Code tags will have been added to the code to make it easy to read in the forum thus making it easier to provide help.

It is also helpful to post error messages in code tags as it makes it easier to scroll through them and copy them for examination

So then it worked OK when you changed the refresh to 333Hz?
So what is the problem?

And the code works with a cheap servo.

There is nothing about your servo that would require you to modify the library.

Is the microprocessor a 3.3 volt part?

It may be that your whizzy servo needs a logic level shift to closer to the level your tester puts out. Like 5 volts.

a7

It works with a servo tester that physically moves it, but not with the actual code that I need to use for my project.

We need to see your code in a proper format. See @UKHeliBob post on how to do it.

hi, I am working with @tburchett . we are using an ESP32 Pico py, and have been able to get a smaller servo working using this code for PWM control on the ESP32:

#define PWM_PIN 26  // Pin connected to the servo (GPIO 26 for ESP32)

// PWM frequency, 50 Hz is typically used for servos (20 ms pulse width cycle)
#define PWM_FREQUENCY 50  // 50 Hz for 20ms cycle
#define PWM_RESOLUTION 8  // 8-bit resolution (0-255)
#define PWM_CHANNEL 0  // Use channel 0

void setup() {
  // Initialize serial communication for debugging
  Serial.begin(115200);

  // Set up PWM on GPIO 26
  ledcSetup(PWM_CHANNEL, PWM_FREQUENCY, PWM_RESOLUTION);
  ledcAttachPin(PWM_PIN, PWM_CHANNEL);
}

void loop() {
  // Move the servo to 0 degrees
  int pwmValue = map(0, 0, 180, 0, 255);  // Convert degrees to PWM range (0-255)
  ledcWrite(PWM_CHANNEL, pwmValue);
  Serial.println("Servo at 0 degrees");
  delay(1000);  // Wait for 1 second

  // Move the servo to 90 degrees
  pwmValue = map(90, 0, 180, 0, 255);  // Convert degrees to PWM range
  ledcWrite(PWM_CHANNEL, pwmValue);
  Serial.println("Servo at 90 degrees");
  delay(1000);  // Wait for 1 second

  // Move the servo to 180 degrees
  pwmValue = map(180, 0, 180, 0, 255);  // Convert degrees to PWM range
  ledcWrite(PWM_CHANNEL, pwmValue);
  Serial.println("Servo at 180 degrees");
  delay(1000);  // Wait for 1 second
}

however, when the frequency is changed to 333, or 330, or 250, or any other frequency, and the signal wire is connected to the servo signal input, the servo doesn't do anything. We are also pretty sure that the servo uses 330hz because it says it on the manufacture datasheet, and also we connected an uno to our servo tester (which is able to drive the servo) and it read 330hz. In all instances, the servo is independently powered through a separate 5V power supply, and squeaking from the servo is present whenever it is powered. to clarify, our servo works perfectly with the servo tester. I would think that maybe the servo needs 5v logic, which would be strange because I've never encountered that before. unfortunately I don't have a MOSFET to bring the signal wire up to 5v, and I'm not that good with electronics so I don't know any other way to do this. i just thought maybe I can connect the servo tester signal to a potentiometer, and see at what voltage the servo will stop receiving signal. I am really at a loss for ideas here, if anyone can provide any information or help that would be greatly appreciated.

Also I'm not quite sure of the rule of this forum, I dont think that this should be a seperate thread, because I am working with @tburchett , so please inform me if that is the case.

By all means contribute to this topic if you and @tburchett are working together but will one of you please post your sketch using code tags as requested

There would be nothing strange about the servo requiring 5V if that is the voltage that it is specified to work at. It should not, however, need the PWM frequency to be modified. Why did you change it ?

When the servo is powered is powered independently have you connected the GNDs of the two power supplies to provide a common reference for signal levels ?

1 Like

I thought it was strange because i was able to drive other servos using the 3.3V logic from the board. Here is the code I used to drive the small, 3.3v servo with:

#include <ESP32Servo.h>

Servo myServo;  // Create a Servo object

#define SERVO_PIN 26  // Use GPIO 26 (can be changed to another PWM-capable pin)

void setup() {
  Serial.begin(115200);

  // Attach the servo to the specified pin
  myServo.attach(SERVO_PIN);
}

void loop() {
  // Sweep from 0 to 180 degrees
  for (int angle = 0; angle <= 180; angle++) {
    myServo.write(angle);  // Move servo to the current angle
    Serial.print("Servo at ");
    Serial.print(angle);
    Serial.println(" degrees");
    delay(20);  // Delay for smooth movement
  }

  // Sweep from 180 back to 0 degrees
  for (int angle = 180; angle >= 0; angle--) {
    myServo.write(angle);  // Move servo to the current angle
    Serial.print("Servo at ");
    Serial.print(angle);
    Serial.println(" degrees");
    delay(20);  // Delay for smooth movement
  }
}

although for some reason that, and the esp32servo example "sweep" are no longer working on the small servo. this could be due to the fact that I fired my esp32 and my servo and I am using a new pair, but I'm not sure how that would create an issue.

I changed the frequency because it was my original hypothesis to why I could not drive the big servo. I looked at the manufacturer datasheet, and that said the refresh rate was 333hz. I also tried connecting the grounds and it did not help, although that was a few hours ago and I think I may have accidentally connected the ESP32 ground to the 5V power, which would be what fried it. strangely, on the fired esp32, I can still connect and run code, but the pins all read 1V on my multimeter.

Do you have any suggestions of what else I could try/test? it seems like the best thing to do is to find a way to step up the signal to 5v.

Here is the sketch we were using to run the small servo on, which we were trying to run the big servo on by switching the freqeuncy to 330hz.

#define PWM_PIN 26  // Pin connected to the servo (GPIO 26 for ESP32)

// PWM frequency, 50 Hz is typically used for servos (20 ms pulse width cycle)
#define PWM_FREQUENCY 50  // 50 Hz for 20ms cycle
#define PWM_RESOLUTION 8  // 8-bit resolution (0-255)
#define PWM_CHANNEL 0     // Use channel 0

void setup() {
  // Initialize serial communication for debugging
  Serial.begin(115200);

  // Set up PWM on GPIO 26
  ledcSetup(PWM_CHANNEL, PWM_FREQUENCY, PWM_RESOLUTION);
  ledcAttachPin(PWM_PIN, PWM_CHANNEL);
}

void loop() {
  // Sweep the servo from 0 to 180 degrees
  for (int angle = 0; angle <= 180; angle++) {
    int pwmValue = map(angle, 0, 180, 0, 255);  // Convert degrees to PWM range (0-255)
    ledcWrite(PWM_CHANNEL, pwmValue);           // Set PWM value to move the servo
    Serial.print("Servo at ");
    Serial.print(angle);
    Serial.println(" degrees");
    delay(20);  // Add a short delay for smoother movement
  }

  // Sweep the servo back from 180 to 0 degrees
  for (int angle = 180; angle >= 0; angle--) {
    int pwmValue = map(angle, 0, 180, 0, 255);  // Convert degrees to PWM range (0-255)
    ledcWrite(PWM_CHANNEL, pwmValue);           // Set PWM value to move the servo
    Serial.print("Servo at ");
    Serial.print(angle);
    Serial.println(" degrees");
    delay(20);  // Add a short delay for smoother movement
  }
}

Hi, @blitio

Can you please post a link to the data/spec sheet of that servo?

Have you tried 50Hz, which is the "standard" PWM frequency?

  • Frequency:
    The pulses occur at a frequency of 50 Hz (20 milliseconds period).
  • Pulse Width:
  • A pulse width of 1 millisecond typically corresponds to the servo's minimum position (e.g., 0 degrees).
  • A pulse width of 2 milliseconds typically corresponds to the servo's maximum position (e.g., 180 degrees).
  • A pulse width of 1.5 milliseconds typically corresponds to the servo's neutral position (e.g., 90 degrees).

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

i cant find where i got it, but a link to a picture of it is here: 711-OQ8yv-S6-L-2-1 hosted at ImgBB — ImgBB

also the same 333hz is on this page when you scroll to the bottom: A20CLS_Micro Servo_PRODUCTS_ AGF-RC Electronic Technology Co., Ltd-AGF-RC Electronic Technology Co., Ltd

yes, we have, and the problem we think is likely too low logic voltage

@blitio - tell @tburchett to put the code in a code block.

Well, the stated servo is a digital servo. It runs at a higher frequency than the standard hobby servo.

Hi,
For all to see;

Have you got and oscilloscope to view the signal?

Tom.... :smiley: :+1: :coffee: :australia:

For debugging use the Uno since it outputs 5V. Use the unmodified servo library

Don't use pin 0 or 1
Make sure the servo ground wire is connected to the Uno and power supply

Try the sweep example.

2 Likes