WAVEGO-PCA9685

From Waveshare Wiki
Jump to: navigation, search

PCA9685 Controls Servo

Introduction

PCA9685 is an LED control chip based on IIC bus control for generating 16-channel PWM signals. The frequency and duty cycle of the PWM wave can be freely adjusted at each LED output.
The servo is a position (angle) servo for control systems that require continuous control of angle change and hold.
This chapter mainly introduces how to change the PWM to achieve the effect of controlling the rotation of the servo through the PCA9685. There is a PCA9685 chip on the ESP32, the main control board of this product, and the servo communicates with the ESP32 through GPIO.
Through the study of this chapter, you can basically master how to send PWM signals through the PCA9685 to control the servo rotation.
WAVEGO-PCA9685 01.gif
WAVEGO-PCA9685 02.gif
WAVEGO-PCA9685 03.gif

Principle

  • In this product, the on-board ESP32 controls the PCA9685 module through IIC communication (GPIO32→SDA, GPIO33→SCL), and then the PCA9685 can generate 16-channel PWM pulse signals to control the servo and the rotation angle of the servo can be adjusted by adjusting the duty cycle of the 16-channel PWM pulses generated by the PCA9685.

WAVEGO-PCA968504.png

Servo Number & Position

WAVEGO-PCA968505.png

  • The demos in this tutorial are all implemented with servo #0, so you will need to remove the leg linkage from both servo #0 and servo #1 before running the demos.

Note: The white swing arm does not need to be removed.

Sample Demo

Code

Servo Simple Rotation

WAVEGO-PCA9685 01.gif

  • Download the sample demo and unzip it.
  • Open the sample demo, select the servo simple rotation, and use Arduino IDE to open PCA9685_Servo1.ino.

WAVEGO-PCA968514.png WAVEGO-PCA968515.png

  • Use the USB cable to connect WAVEGO and the computer, select the correct parameters and COM port, and click to upload.

WAVEGO-PCA968506.png

  • When running the demo, rotate the demo by the following commands:
pwm.setPWM(0,0,286);
pwm.setPWM(0,0,386);
  • Full demo codes are shown below:
#include "Servo1.h"        //Import the library function Servo1.h

TwoWire IIC = TwoWire(0);                   //Initialize the IO port of the IIC
Servo1 pwm = Servo1(0x40, IIC);  //Instantiating pwm

#define S_SCL   33                //Define the IO port of the clock cable as GPIO33
#define S_SDA   32                //Define the IO port of the data line as GPIO32

#define LEG0 0
#define LEG1 1

#define SERVO_FREQ 50

void ServoSetup(){                 
  IIC.begin(S_SDA, S_SCL, 26000000);        //Open the IIC channel
  pwm.begin();
  pwm.setOscillatorFrequency(26000000);     
  pwm.setPWMFreq(SERVO_FREQ);            //the refresh rate is 50Hz
  Wire.setClock(100000);               //Modify the IIC clock frequency as 100KHz
  delay(10);
}

void setup() {
  ServoSetup();
  pwm.setPWM(1,0,386);       //In order to prevent the No. 0 servo from being hindered by the No. 1 servo during the swinging process, the No. 1 servo needs to be set to a certain angle to reserve space for the No. 0 servo first.
}

void loop() {
  pwm.setPWM(0,0,286);
  delay(500);
  pwm.setPWM(0,0,386);
  delay(500);
}

Demo Code Analysis

  • The servo communicates with the PCA9685 using the IIC.
TwoWire IIC = TwoWire(0);                   //Initialize the IIC's IO port
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40, IIC);  //Instantiating pwm

#define S_SCL   33                //Define the IO port of the clock line as GPIO33
#define S_SDA   32                //Define the IO port of the data line as GPIO32
  • The function is for enabling the IIC channel and initializing the servo.
void ServoSetup(){                 
  IIC.begin(S_SDA, S_SCL, 26000000);        //Enabling the IIC channel
  pwm.begin();
  pwm.setOscillatorFrequency(26000000);
  pwm.setPWMFreq(SERVO_FREQ);             //The refreshing rate is 50Hz
  Wire.setClock(100000);                  //Modify the IIC clock frequency as 100KHz
  delay(10);
}

The servoID is the servo number, fill in the corresponding servo number to control the corresponding servo, and rotate the servo by changing the PWM, the value of PWM is 86~484, the angle control has the corresponding angle, and the calculation method.
Facing the swing arm side, the servo swing arm does a counterclockwise rotation as the value of PWM increases.
In order to prevent the No. 0 servo from being obstructed by the No. 1 servo during the swinging process, it is necessary to set the No. 1 servo to swing to a certain position to ensure that the No. 0 servo will not be obstructed.

pwm.setPWM(servoID, 0, pwm);

Demo Running Effect

  • The No. 0 servo swing arm swings from side to side within a 45-degree range.

WAVEGO-PCA9685 01.gif

Servo Angle Control

WAVEGO-PCA9685 02.gif

  • Select Servo Angle Control and open PCA9685_Servo2.ino with the Arduino IDE.

WAVEGO-PCA9685 Angle.png
WAVEGO-PCA9685 Angle02.png

  • Connect the WAVEGO to the PC with the USB cable, select the correct parameters and COM port, and upload the demo.

WAVEGO-PCA968506.png

  • In this demo, the code to realize the rotation of the servo is the same as the code for the simple rotation of the servo, the difference is that in this demo there is an introduction to how to control the servo angle with pwm.

The complete code is as follows:

#include "Servo1.h"        //Import the the header file Servo1.h

TwoWire IIC = TwoWire(0);                   //Initialize the IIC's IO port
Servo1 pwm = Servo1(0x40, IIC);  //Instantiating pwm

#define S_SCL   33                //Define the IO port of the clock line as GPIO33
#define S_SDA   32                //Define the IO port of the data line as GPIO32

#define LEG0 0
#define LEG1 1

#define SERVO_FREQ 50

void ServoSetup(){                 
  IIC.begin(S_SDA, S_SCL, 26000000);        //Enable the IIC channel
  pwm.begin();
  pwm.setOscillatorFrequency(26000000);     
  pwm.setPWMFreq(SERVO_FREQ);      //The refresh rate is 50Hz
  Wire.setClock(100000);         //Modify the IIC clock frequency is 100KHz
  delay(10);
}

void setup() {
  ServoSetup();
  pwm.setPWM(1,0,386);       //In order to prevent the No. 0 servo from being hindered by the No. 1 servo during the swinging process, the No. 1 servo needs to be set to a certain angle to reserve space for the No. 0 servo first.
}

void loop() {
  pwm.setPWM(0,0,86);        //Servo 0 swings to 0 degrees.
  delay(1000);
  pwm.setPWM(0,0,186);        //Servo 0 swings to 45 degrees.
  delay(1000);
  pwm.setPWM(0,0,286);        //Servo 0 swings to 90 degrees.
  delay(1000);
  pwm.setPWM(0,0,386);        //Servo 0 swings to 135 degrees.
  delay(1000);
  pwm.setPWM(0,0,484);        //Servo 0 swings to 180 degrees.
  delay(1000);  
}

Demo Analysis

  • Servo control generally requires a 20ms time base pulse, and the high-level part of this pulse is generally the angle control pulse part in the range of 0.5ms to 2.5ms. The PCA9685 uses a 12-bit register to control the PWM duty cycle, and the value of the register is calculated using the following method:
Pulse High Time Angle Theotical pwm Actual pwm
0.5ms 0 Degree 0.5/20*(2^12-1)=102 86
1.0ms 45 Degrees 1.0/20*(2^12-1)=205 186
1.5ms 90 Degrees 1.5/20*(2^12-1)=307 286
2.0ms 135 Degrees 2.0/20*(2^12-1)=410 386
2.5ms 180 Degrees 2.5/20*(2^12-1)=512 484

There are errors in actual use, and the PWM is measured to take values of 86~484 in the servo of this product.

Demo Running Effect

  • The servo swing arm swings to 0 degree, 45 degrees, 90 degrees, 135 degrees, 180 degrees, and then back to 0 degree after reaching 180 degrees.

WAVEGO-PCA9685 02.gif

Servo stepping operation

WAVEGO-PCA9685 03.gif

  • Select Servo Angle Control and open PCA9685_Servo3.ino with Arduino IDE, and connect WAVEGO to the computer with USB.

WAVEGO-PCA9685 20.png
WAVEGO-PCA9685 21.png

  • Select the correct parameters and COM port, and then upload the demo.

WAVEGO-PCA968506.png

  • In this demo, the new variable Offset is defined, and this variable is used as an offset value to cause the PWM to keep +1 until it reaches 484 for stepping operations.
  • The full demo code is shown below:
#include "Servo1.h"        //Import the library function Servo1.h

TwoWire IIC = TwoWire(0);                   //Initialize the IIC's IO port
Servo1 pwm = Servo1(0x40, IIC);  //Instantiating pwm

#define S_SCL   33                //Define the IO port for the clock cable as GPIO33
#define S_SDA   32                //Define the IO port for the data cable as GPIO32

#define SERVO_FREQ 50
             
#define LEG0 0
#define LEG1 1               

//Setting the initial position of the servo swing arm
int Position = 86;

//Initialize the servo                              
void ServoSetup(){                 
  IIC.begin(S_SDA, S_SCL, 26000000);        //Enable the IIC channel
  pwm.begin();
  pwm.setOscillatorFrequency(26000000);       
  pwm.setPWMFreq(SERVO_FREQ);             //The refresh rate is 50Hz
  Wire.setClock(100000);                   //Modify the IIC clock frequency as 100KHz
  delay(10);
}

//Rotate the servo swing arm
void servoDebug(byte servoID, int offset){   
  if(Position<=484){              //Start stepping operation when original PWM is less than or equal to 484
    Position += offset;           //The servo swings in the original position offset
    pwm.setPWM(servoID, 0, Position);  //Make the specified servo swing to the specified position.
  }else{
    Position  = 86;
    pwm.setPWM(servoID,0,Position);
  }
}

void setup() {
  ServoSetup();
  pwm.setPWM(1,0,386);      //In order to prevent the No. 0 servo from being hindered by the No. 1 servo during the swinging process, the No. 1 servo needs to be set to a certain angle to reserve space for the No. 0 servo first.      
  pwm.setPWM(0,0,86);       //Initialize servo swing arm position
}

void loop() {
    servoDebug(0,1);       //Servo #0 steps in offset 1.
    delay(50);             //System pause 50ms
}

Demo Code Analysis

  • Determine whether pwm is less than or equal to 484, when true, execute the step operation:
Position += offset;
pwm.setPWM(servoID, 0, Position)

If false, an else statement is executed to reset the pwm value to 86.

void servoDebug(byte servoID, int offset){   
  if(Position<=484){              //Start stepping operation when original pwm is less than or equal to 484
    Position += offset;           //The servo swings in the original position offset
    pwm.setPWM(servoID, 0, Position);  //Make the specified servo swing to the specified position.
  }else{
    Position  = 86;               //Reset the pwm to 86 when the original pwm is greater than or equal to 484 and turn the servo to the 0-degree position
    pwm.setPWM(servoID,0,Position);
  }
}

Demo Running Effect

  • The servo pendulum arm swings from 0 degrees, with an offset value of 1 for pwm constant +1 step operation.

WAVEGO-PCA9685 03.gif

Summary

  • As can be seen in this chapter, the servo can be controlled by changing the PWM signal from the PCA9685.