WAVEGO-PCA9685

来自Waveshare Wiki
跳转至: 导航搜索

PCA9685控制舵机

简介

  • PCA9685是一款基于IIC总线控制,用于产生16路PWM信号的LED控制芯片,每一路LED输出端均可自由调节PWM波的频率和占空比。
  • 舵机是一种位置(角度)伺服器,适用于需要连续控制角度变化并保持的控制系统。
  • 本章主要介绍如何通过PCA9685改变PWM达到控制舵机转动的效果,在本产品的主控板ESP32上搭载有PCA9685芯片,舵机通过GPIO与ESP32通信。
  • 通过本章的学习,您可以基本掌握如何通过PCA9685发送PWM信号控制舵机转动。

舵机转动.gif 舵机角度控制.gif 舵机步进操作.gif

原理

  • 在本产品中,板载ESP32通过IIC通信(GPIO32→SDA,GPIO33→SCL)控制PCA9685模块,然后PCA9685可以产生16路PWM脉冲信号控制舵机,通过调节PCA9685产生的16路PWM脉冲的占空比可调节舵机转动角度。

图片3.png

舵机编号及位置图示

WAVEGO舵机.jpg

  • 该教程中的例程都用0号舵机实现,因此在运行例程前需要将0号舵机和1号舵机上的腿部连杆都拆卸下来。

注:白色摆臂不需要拆下来。

示例程序

舵机控制例程

代码

舵机简单转动

舵机转动.gif

  • 下载示例程序并解压。
  • 企业微信截图 1665216224860.png
  • 打开示例程序,选择舵机简单转动并用Arduino IDE打开PCA9685_Servo1.ino。
  • 企业微信截图 16652164373582.png 企业微信截图 16652164788084.png
  • 用USB将WAVEGO和电脑连接,选择正确的参数和端口,上传程序。
  • 企业微信截图 16652167496826.png
  • 程序运行时,通过
    pwm.setPWM(0,0,286);
    pwm.setPWM(0,0,386);
    转动舵机。
  • 完整代码如下:
  • #include "Servo1.h"        //导入库函数Servo1.h
    
    TwoWire IIC = TwoWire(0);                   //初始化IIC的IO口
    Servo1 pwm = Servo1(0x40, IIC);  //实例化pwm
    
    #define S_SCL   33                //定义时钟线的IO口为GPIO33
    #define S_SDA   32                //定义数据线的IO口为GPIO32
    
    #define LEG0 0
    #define LEG1 1
    
    #define SERVO_FREQ 50
    
    void ServoSetup(){                 
      IIC.begin(S_SDA, S_SCL, 26000000);        //打开IIC通道
      pwm.begin();
      pwm.setOscillatorFrequency(26000000);     
      pwm.setPWMFreq(SERVO_FREQ);            //刷新频率为50Hz
      Wire.setClock(100000);               //修改IIC的时钟频率为100KHz
      delay(10);
    }
    
    void setup() {
      ServoSetup();
      pwm.setPWM(1,0,386);       //为防止0号舵机摆动过程被1号舵机阻碍,需先将1号舵机设置到一定的角度给0号舵机预留空间
    }
    
    void loop() {
      pwm.setPWM(0,0,286);
      delay(500);
      pwm.setPWM(0,0,386);
      delay(500);
    }

代码解析

  • 舵机与PCA9685使用IIC通信。
    TwoWire IIC = TwoWire(0);                   //初始化IIC的IO口
    Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40, IIC);  //实例化pwm
    
    #define S_SCL   33                //定义时钟线的IO口为GPIO33
    #define S_SDA   32                //定义数据线的IO口为GPIO32
  • 函数功能为打开IIC通道,初始化舵机。
    void ServoSetup(){                 
      IIC.begin(S_SDA, S_SCL, 26000000);        //打开IIC通道
      pwm.begin();
      pwm.setOscillatorFrequency(26000000);
      pwm.setPWMFreq(SERVO_FREQ);             //刷新频率为50Hz
      Wire.setClock(100000);                  //修改IIC的时钟频率为100KHz
      delay(10);
    }
  • servoID为舵机编号,填入对应的舵机编号控制对应舵机,通过改变pwm转动舵机,pwm的取值为86~484,角度控制有对应角度及计算方法。
  • 面向摆臂一侧,随着pwm值的增大,舵机摆臂做逆时针旋转。
  • 为了防止0号舵机摆动过程中被1号舵机阻碍,需要将1号舵机设置摆动到一定位置确保0号舵机不会被阻碍。
  • pwm.setPWM(servoID, 0, pwm);

程序运行效果

  • 0号舵机摆臂在45度范围内左右摆动。

舵机转动.gif

舵机角度控制

舵机角度控制.gif

  • 选择舵机角度控制并用Arduino IDE打开PCA9685_Servo2.ino。
  • 企业微信截图 16652164506241.png 企业微信截图 16652164969197.png
  • 用USB将WAVEGO和电脑连接,选择正确的参数和端口,上传程序。
  • 企业微信截图 16652175966866(1).png
  • 在该程序中,实现舵机转动的代码和舵机简单转动的代码一样,不同的是在这个程序中有介绍到如何用pwm控制舵机角度。
  • 完整代码如下:
  • #include "Servo1.h"        //导入头文件Servo1.h
    
    TwoWire IIC = TwoWire(0);                   //初始化IIC的IO口
    Servo1 pwm = Servo1(0x40, IIC);  //实例化pwm
    
    #define S_SCL   33                //定义时钟线的IO口为GPIO33
    #define S_SDA   32                //定义数据线的IO口为GPIO32
    
    #define LEG0 0
    #define LEG1 1
    
    #define SERVO_FREQ 50
    
    void ServoSetup(){                 
      IIC.begin(S_SDA, S_SCL, 26000000);        //打开IIC通道
      pwm.begin();
      pwm.setOscillatorFrequency(26000000);     
      pwm.setPWMFreq(SERVO_FREQ);      //刷新频率为50Hz
      Wire.setClock(100000);         //修改IIC的时钟频率为100KHz
      delay(10);
    }
    
    void setup() {
      ServoSetup();
      pwm.setPWM(1,0,386);       //为防止0号舵机摆动过程被1号舵机阻碍,需先将1号舵机设置到一定的角度给0号舵机预留空间
    }
    
    void loop() {
      pwm.setPWM(0,0,86);        //0号舵机摆到0度
      delay(1000);
      pwm.setPWM(0,0,186);        //0号舵机摆到45度
      delay(1000);
      pwm.setPWM(0,0,286);        //0号舵机摆到90度
      delay(1000);
      pwm.setPWM(0,0,386);        //0号舵机摆到135度
      delay(1000);
      pwm.setPWM(0,0,484);        //0号舵机摆到180度
      delay(1000);  
    }

代码解析

  • 舵机的控制一般需要一个20ms的时基脉冲,该脉冲的高电平部分一般为0.5ms~2.5ms范围内的角度控制脉冲部分。PCA9685采用12位的寄存器来控制PWM占比,寄存器的值用以下方法计算:
    脉冲高电平时间 角度 理论pwm 实际pwm
    0.5ms 0度 0.5/20*(2^12-1)=102 86
    1.0ms 45度 1.0/20*(2^12-1)=205 186
    1.5ms 90度 1.5/20*(2^12-1)=307 286
    2.0ms 135度 2.0/20*(2^12-1)=410 386
    2.5ms 180度 2.5/20*(2^12-1)=512 484
    实际使用中存在误差,在本产品的舵机中测得pwm取值为86~484。

程序运行效果

  • 舵机摆臂依次摆动到0度、45度、90度、135度、180度,到达180度后又重新回到0度不停循环。

舵机角度控制.gif

舵机步进操作

舵机步进操作.gif

  • >选择舵机角度控制并用Arduino IDE打开PCA9685_Servo3.ino,用USB将WAVEGO和电脑连接。
  • 企业微信截图 16652164639056.png 企业微信截图 16652165127635.png
  • 选择正确的参数和端口,上传程序。
  • 企业微信截图 16652177503367.png
  • 在该程序中,定义了新的变量offset,该变量作为偏移值令pwm在到达484前不停+1,以实现步进操作。
  • 完整代码如下:
  • #include "Servo1.h"        //导入库函数Servo1.h
    
    TwoWire IIC = TwoWire(0);                   //初始化IIC的IO口
    Servo1 pwm = Servo1(0x40, IIC);  //实例化pwm
    
    #define S_SCL   33                //定义时钟线的IO口为GPIO33
    #define S_SDA   32                //定义数据线的IO口为GPIO32
    
    #define SERVO_FREQ 50
                 
    #define LEG0 0
    #define LEG1 1               
    
    //设置舵机摆臂初始位置
    int Position = 86;
    
    //初始化舵机                                    
    void ServoSetup(){                 
      IIC.begin(S_SDA, S_SCL, 26000000);        //打开IIC通道
      pwm.begin();
      pwm.setOscillatorFrequency(26000000);       
      pwm.setPWMFreq(SERVO_FREQ);             //刷新频率为50Hz
      Wire.setClock(100000);                   //修改IIC时钟频率为100KHz
      delay(10);
    }
    
    //转动舵机摆臂
    void servoDebug(byte servoID, int offset){   
      if(Position<=484){              //原pwm小于等于484时开始步进操作
        Position += offset;           //舵机在原来的位置上摆动offset
        pwm.setPWM(servoID, 0, Position);  //令指定舵机摆动到指定位置
      }else{
        Position  = 86;
        pwm.setPWM(servoID,0,Position);
      }
    }
    
    void setup() {
      ServoSetup();
      pwm.setPWM(1,0,386);      //为防止0号舵机摆动过程被1号舵机阻碍,需先将1号舵机设置到一定的角度给0号舵机预留空间      
      pwm.setPWM(0,0,86);       //初始化舵机摆臂位置
    }
    
    void loop() {
        servoDebug(0,1);       //0号舵机以偏移量1步进
        delay(50);             //系统暂停50ms
    }

代码解析

  • 判断pwm是否小于等于484,为真时执行步进操作。
    Position += offset;
    pwm.setPWM(servoID, 0, Position)
    为假时则执行else语句将pwm值重置为86。
    void servoDebug(byte servoID, int offset){   
      if(Position<=484){              //原pwm小于等于484时开始步进操作
        Position += offset;           //舵机在原来的位置上摆动offset
        pwm.setPWM(servoID, 0, Position);  //令指定舵机摆动到指定位置
      }else{
        Position  = 86;               //原pwm大于或等于484时将pwm重置为86,并将舵机转到0度位置
        pwm.setPWM(servoID,0,Position);
      }
    }

程序运行效果

  • 舵机摆臂从0度开始摆动,以偏移值为1进行pwm不断+1的步进操作。

舵机步进操作.gif

总结

  • 通过本章可知,通过改变PCA9685发出的PWM信号可以对舵机进行控制。

全部章节