ESP32 Servo SG90 issue

Hi, I have multiple SG90 servos and when uploading the below code it does not rotate 180 degrees but spins multiple 360 degrees in both directions. I bought them from AliExpress Servo g9. I've created a video and placed it on YouTube Click to view video (I've only just uploaded it so give YouTube time if it doesn't load).

Any help will be appreciated. Thanks in advance.

Here's the code I've used.

#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 = 17;
#elif defined(CONFIG_IDF_TARGET_ESP32C3)
int servoPin = 7;
#else
int servoPin = 33;
#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 position
	}
	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
	}
}

Unfortunately you bought the wrong ones

You have not bought servos

What you bought are continuous rotation "servos". You cannot control the angle that they turn to, only their direction of rotation and speed

Found a solution of sorts.I used this site to get ideas Drone Bot Workshop. I had to install the library from the site. It uses a value of 0 (fast clockwise) to 93 (slow clockwise) giving various speeds from fast to slow 0-93. I've found values 94-100 stops the motor. Counter clockwise is 101 (slow) to 180 (fast). I've just butchered the WiFi version down to it's basics that I can work with.
I have delays of 1000ms between actions but I've found that the clockwise turn is slightly longer than the counter clockwise. Further investigation and a look at the library functions will be needed. There are functions such as readMicroseconds and writeMicroseconds which could come in handy if they do what I think they do. I don't want to go down the path of reed switches or microswitches. If anyone has sample code which uses the library from this site Github ESP32Servo Lib to get accurate angles it would be appreciated. i.e. on a clock from 8-4 (twenty to - twenty past). I'll probably need to use a reed switch and magnet to to home it initially, but I just need accurate angles from the servos I bought.

Here's what I'm using for the initial testing. I'm not sure what the 'allocateTimer' does yet also.

#include <ESP32Servo.h>

Servo myservo;  // create servo object to control a servo

// Servo GPIO pin
static const int servoPin = 33;

void setup() {
  // Allow allocation of all timers for servo library
  ESP32PWM::allocateTimer(0);
  ESP32PWM::allocateTimer(1);
  ESP32PWM::allocateTimer(2);
  ESP32PWM::allocateTimer(3);

  // Set servo PWM frequency to 50Hz
  myservo.setPeriodHertz(50);

  // Attach to servo and define minimum and maximum positions
  // Modify as required
  myservo.attach(servoPin, 500, 2400);

  // Start serial
  Serial.begin(115200);

  //Stop motor
  myservo.write(99);
}

void loop() {
  // Move servo into position
  myservo.write(93);//Clockwise slow
  delay(1000);
  myservo.write(99);//Stop
  delay(1000);
  myservo.write(101);//Counter Clockwise slow
  delay(1000);
  myservo.write(99);//Stop
  delay(1000);
}

Please describe exactly what you want the servo movements to be in terms of angles. Your "solution" will not work well in the medium to long term. Apart from anything else the rotation speed will depend on the load put on the servo

Just a basic cat laser toy. I've thrown a video of it on YouTube here It's scheduled to be released at 23:00 GMT. Take a look. I've used random numbers for delays and seems to work OK. I'm going to reduce the sketch by putting the movement in a single function, passing the Write value and the delay. That should shorten it. Here's the code I've used:-

#include <ESP32Servo.h>

Servo myservo;  // create servo object to control a servo
Servo myservo2;  // create servo object to control a servo

// Servo GPIO pin
static const int servoPin = 33;
static const int servoPin2 = 25;

void setup() {
  // Allow allocation of all timers for servo library
  ESP32PWM::allocateTimer(0);
  ESP32PWM::allocateTimer(1);
  ESP32PWM::allocateTimer(2);
  ESP32PWM::allocateTimer(3);

  // Set servo PWM frequency to 50Hz
  myservo.setPeriodHertz(50);
  myservo2.setPeriodHertz(50);

  myservo.write(99);
  myservo2.write(99);
  // Attach to servo and define minimum and maximum positions
  // Modify as required
  myservo.attach(servoPin, 500, 2400);
  myservo2.attach(servoPin2, 500, 2400);

  // Start serial
  Serial.begin(115200);

  //Stop motor
  myservo.write(99);
  myservo2.write(99);
}

void loop() {

  int BaseRandomNumber = random(2, 1000); 
  int TiltRandomNumber = random(2, 1000); 
  // Move servo into position
  myservo.write(93);  //Clockwise slow
  myservo2.write(93);  //Clockwise slow
  delay(1000);

  myservo.write(99);  //Stop
  myservo2.write(99);  //Stop
  delay(BaseRandomNumber);
  myservo.write(101);  //Counter Clockwise slow
  myservo2.write(101);  //Counter Clockwise slow
  delay(BaseRandomNumber);
  myservo.write(99);  //Stop
  myservo2.write(99);  //Stop
  delay(BaseRandomNumber);

  myservo.write(70);  //Clockwise slow
  myservo2.write(70);  //Clockwise slow
  delay(TiltRandomNumber);
  myservo.write(99);  //Stop
  myservo2.write(99);  //Stop
  delay(TiltRandomNumber);
  myservo.write(130);  //Counter Clockwise slow
  myservo2.write(130);  //Counter Clockwise slow
  delay(TiltRandomNumber);
  myservo.write(99);  //Stop
  myservo2.write(99);  //Stop
  delay(TiltRandomNumber);
}

Do yourself a favour and buy some real servos

It's a challenge. I love challenges :rofl:

Look on AliExpress and recommend some. I need accurate servos and you seem to know what you are talking about.

For your application, ie a cat laser toy, you do not need precision, so just about any 9 gram servo will be good enough as long as they are actually servos and not continuous rotation electronically controlled motors

I am not going to recommend any from Ali because I don't trust their descriptions. You would probably be better off paying a little more and buying from Ebay from a seller based in the UK. Before buying, message them and make absolutely sure that you know what you are buying. Even better would be to go to a local model shop in or around where you live and buy from there

1 Like