I followed some YouTube videos on how to modify servos for Continuous Rotation and applied it to my mini SG90 servos. I am using the Cheapest unbranded servos, but this should work with other brands. Keep the pot in place and use a servo tester to center the servos when you are ready to glue the pot. I then tried to use the PCA9685 boards to control them. Using the example code from Adafruit's PCA9685 PWM Servo Library, I came up with the following code to get max speed in both directions without going too far unnecessarily.
I am using SERVOMIN, SERVOCENTER, SERVOMAX, and NUMSERVOS to get the values for each servo through the Serial Terminal. I set the serial terminal to 57,600kbaud and used some delay defines to slow things down a bit.
Here is my code, file name "PCA9685-ContRot-Servo-SG90.ino", I hope this will help out others that may be having difficulties getting SG90 servos to work in Continuous Rotation mode on these modules.
Enjoy, Jorge!
I am using SERVOMIN, SERVOCENTER, SERVOMAX, and NUMSERVOS to get the values for each servo through the Serial Terminal. I set the serial terminal to 57,600kbaud and used some delay defines to slow things down a bit.
Here is my code, file name "PCA9685-ContRot-Servo-SG90.ino", I hope this will help out others that may be having difficulties getting SG90 servos to work in Continuous Rotation mode on these modules.
Code:
/*
* PCA9685 Continuous Rotation Servo Test and Calibration for SG90 Mini Servos
* By: Jorge Joaquin Pareja https://Hanger18.Altervista.org
*
* This code is written to help you determine proper values for SERVOMIN, SERVOCENTER, and SERVOMAX for
* use in your own code, when using the mini SG90 servos modified for continuous rotation with the PCA9685
*
* *************************
* Memory output from Arduino IDE 1.8.15 :
* *************************
* Memory Usage on Teensy 4.1:
* FLASH:
* Code: 17704
* Data: 3928
* Headers: 9084
* Free for files: 8095748
*
* RAM1:
* Variables: 12992
* Code: 14864
* Padding: 17904
* Free for local variables: 478528
*
* RAM2:
* Variables: 12384
* Free for malloc/new: 511904
*
* Using library Wire at version 1.0 in folder: C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Wire
* Using library Adafruit_PWM_Servo_Driver_Library at version 2.4.0 in folder: C:\Users\%USERNAME%\Documents\Arduino\libraries\Adafruit_PWM_Servo_Driver_Library
*
* *************************
*
* NOTES:
* The process for Modifying the un-branded mini SG90 clear blue servos was challenging.
* It is important to use a known accurate servo tester with a good neutral position to
* ensure the servo pot is centered after modifications. Glue the potentiometer once
* the center position is found while the tester is still powering the servo. Dabbing
* a drop of Gel Type Super Glue with a toothpick can slightly nudge the pot a tad off
* center so it will need to be on, and adjusted, until it dries. 10 to 15 min
*
* This type of servo, once modified and centered, has a value of about 315 for center
* using Adafruit_PWMServoDriver and my SERVOCENTER define. The SERVOMIN define is set
* to 265, and the SERVOMAX define is set to 375. This gives about 40 to 60 speed
* settings in either direction from SERVOCENTER.
*/
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h> // install from library manager by searching "Adafruit PWM" or from " https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library "
// See notes in Adafruits PWM Servo Library's examples from the Servo example for more options
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
#define SERVO_FREQ 50
uint8_t servonum = 0;
/*
* My Modificates below this line
*/
// Change these settings to suit your particular servo if the defaults do not work for you
#define SERVOMIN 265 // Adjust for maximum speed in clockwise position
#define SERVOCENTER 315 // Adjust for stopping the rotation
#define SERVOMAX 375 // Adjust for maximum speed in counter-clockwise position
#define NUMSERVOS 1 // How many servos you are testing on the PCA9685, 1 to 16 (code will automaticaly subtract one to get the servonum variable)
#define WAITDELAY 1000 // incase you want to slow things down if you add serial terminal code
#define QUICKDELAY 25 // for keeping a servo value slow enough so we can see it
void setup() {
Serial.begin(57600);
Serial.println("16 channel Servo test, with " + String(NUMSERVOS) + " servos attached");
pwm.begin();
pwm.setOscillatorFrequency(27000000);
pwm.setPWMFreq(SERVO_FREQ); // Analog servos run at ~50 Hz updates
delay(100);
} // END setup()
void loop() {
///////////////////////////////////////////////////////////////////////////////////////
// Counter Clockwise
// Ramp-up to SERVOMAX
for (uint16_t pulselen = SERVOCENTER; pulselen < SERVOMAX; pulselen++)
{
pwm.setPWM(servonum, 0, pulselen);
Serial.println("Servo: " + String(servonum) + ", Pulse Length: " + String(pulselen));
delay(QUICKDELAY);
}
// Ramp-down to SERVOCENTER
for (uint16_t pulselen = SERVOMAX; pulselen > SERVOCENTER; pulselen--)
{
pwm.setPWM(servonum, 0, pulselen);
Serial.println("Servo: " + String(servonum) + ", Pulse Length: " + String(pulselen));
delay(QUICKDELAY);
}
///////////////////////////////////////////////////////////////////////////////////////
// Clockwise
// Ramp-down to SERVOMIN
for (uint16_t pulselen = SERVOCENTER; pulselen > SERVOMIN; pulselen--) {
pwm.setPWM(servonum, 0, pulselen);
Serial.println("Servo: " + String(servonum) + ", Pulse Length: " + String(pulselen));
delay(QUICKDELAY);
}
// Ramp-up to SERVOCENTER
for (uint16_t pulselen = SERVOMIN; pulselen < SERVOCENTER; pulselen++) {
pwm.setPWM(servonum, 0, pulselen);
Serial.println("Servo: " + String(servonum) + ", Pulse Length: " + String(pulselen));
delay(QUICKDELAY);
}
///////////////////////////////////////////////////////////////////////////////////////
delay(WAITDELAY); // let the servo wait this long before testing the next servo if any
servonum++;
if (servonum > (NUMSERVOS - 1)) servonum = 0; // Test the next servo if NUMSERVOS is greater than 1
} // END loop()
Enjoy, Jorge!