Mini Continuous Rotation Servo, SG90, Calibration Code for PCA9685 - Completed

japreja

Active member
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.

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!
 
Back
Top