16路12位PWM信号发生器 PCA 9685
先对单个舵机尝试一下,了解一下PWM

20ms周期 = 频率为50Hz


单个舵机例程1:
非常简单的舵机例子,实现效果是使得电机转动:
#include
#define PIN_SERVO 10 Servo myservo; void setup() {
myservo.attach(PIN_SERVO); } void loop() {
myservo.write(0); delay(1000); myservo.write(80); delay(1000); myservo.write(160); delay(1000); myservo.write(80); delay(1000); myservo.write(0); delay(1000); }
单个舵机例程2:
#include
#define PIN_SERVO 9 int i=0; Servo myservo; void setup() {
myservo.attach(PIN_SERVO); } void loop() {
for(i=0;i<160;i++) {
myservo.write(i); delay(30); } for(i=160;i>0;i--) {
myservo.write(i); delay(30); } delay(1000); }
主要参数以及引脚定义:

- 电压:舵机供电5-7v,接受高一点的电压。
- 逻辑电路电压:3-5V
- 通信接口:使用i2c通信,就是SCL、SDA引脚
7位的I2C地址为:0x40 + A5:A0,A5到A0如果不做任何处理的话是0,想要把哪一位置1就把那个引脚焊到一起。另外用i2cdetect检测出还有一个0x70地址一直存在,这是一个通用地址,可以给所有从机下达指令。
- OE反使能脚:这个引脚低电平使能,不接的话模块内部默认已经接地使能了,所以正常使用可以不接。
- 工作频率:40-1000HZ
接线图:

注意!!!下面例子需要用到外部库文件,如果你IDE没有
,那么下载这个并放在安装路径的文档—arduino-libraries路径下面
,那么下载这个并放在安装路径的文档—arduino-libraries路径下面
例子程序1
/* This is an example for our Adafruit 16-channel PWM & Servo driver Servo test - this will drive 16 servos, one after the other 这是我们的Adafruit 16通道PWM和伺服驱动器的一个例子,驱动16个伺服电机 Pick one up today in the adafruit shop! ------> http://www.adafruit.com/products/815 These displays use I2C to communicate, 2 pins are required to interface. For Arduino UNOs, thats SCL -> Analog 5, SDA -> Analog 4 这些显示器使用I2C进行通信,需要2个引脚。 接口。对于ARDUINO UNOS,这是SCL->模拟5,SDA - >模拟4 / #include
#include
// called this way, it uses the default address 0x40 以这种方式调用,它使用默认地址0x40。 Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); // you can also call it with a different address you want //Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x41); //也可以用不同的地址调用它 /* Depending on your servo make, the pulse width min and max may vary, you want these to be as small/large as possible without hitting the hard stop for max range. You'll have to tweak them as necessary to match the servos you have!*/ /*根据你的伺服制作,脉冲宽度最小和最大可能变化,你想要这些尽可能小大而不碰到 硬停止,对于最大范围。你必须调整它们以匹配你的伺服系统!*/ #define SERVOMIN 150 // this is the 'minimum' pulse length count (out of 4096) //这是“最小”脉冲长度计数(在4096)中 #define SERVOMAX 600 // this is the 'maximum' pulse length count (out of 4096) //这是“最大”脉冲长度计数(在4096中) // our servo # counter //uint8_t servonum = 0; void setup() {
Serial.begin(9600); Serial.println("16 channel Servo test!"); pwm.begin(); pwm.setPWMFreq(60); // Analog servos run at ~60 Hz updates 模拟伺服在60赫兹更新下运行 } // you can use this function if you'd like to set the pulse length in seconds // e.g. setServoPulse(0, 0.001) is a ~1 millisecond pulse width. its not precise! //如果您想以秒为单位设置脉冲长度,则可以使用此函数。 //例如SET伺服脉冲(0,0.001)是一个1毫秒的脉冲宽度。它不是 void setServoPulse(uint8_t n, double pulse) {
double pulselength;//精度浮点数 pulselength = ; // 1,000,000 us per second 每秒100万 pulselength /= 60; // 60 Hz Serial.print(pulselength); Serial.println(" us per period"); pulselength /= 4096; // 12 bits of resolution 12位分辨率 Serial.print(pulselength); Serial.println(" us per bit"); pulse *= 1000; pulse /= pulselength; Serial.println(pulse); pwm.setPWM(n, 0, pulse); } void loop() {
// Drive each servo one at a time //Serial.println(servonum); //每次驱动一个伺服驱动器 //串行打印(伺服); for (uint16_t pulselen = SERVOMIN; pulselen < SERVOMAX; pulselen++) {
pwm.setPWM(0, 0, pulselen); pwm.setPWM(1, 0, pulselen); pwm.setPWM(2, 0, pulselen); pwm.setPWM(3, 0, pulselen); pwm.setPWM(4, 0, pulselen); pwm.setPWM(5, 0, pulselen); pwm.setPWM(6, 0, pulselen); pwm.setPWM(7, 0, pulselen); pwm.setPWM(8, 0, pulselen); pwm.setPWM(9, 0, pulselen); pwm.setPWM(10, 0, pulselen); pwm.setPWM(11, 0, pulselen); pwm.setPWM(12, 0, pulselen); pwm.setPWM(13, 0, pulselen); pwm.setPWM(14, 0, pulselen); pwm.setPWM(15, 0, pulselen); } delay(500); for (uint16_t pulselen = SERVOMAX; pulselen > SERVOMIN; pulselen--) {
pwm.setPWM(0, 0, pulselen); pwm.setPWM(1, 0, pulselen); pwm.setPWM(2, 0, pulselen); pwm.setPWM(3, 0, pulselen); pwm.setPWM(4, 0, pulselen); pwm.setPWM(5, 0, pulselen); pwm.setPWM(6, 0, pulselen); pwm.setPWM(7, 0, pulselen); pwm.setPWM(8, 0, pulselen); pwm.setPWM(9, 0, pulselen); pwm.setPWM(10, 0, pulselen); pwm.setPWM(11, 0, pulselen); pwm.setPWM(12, 0, pulselen); pwm.setPWM(13, 0, pulselen); pwm.setPWM(14, 0, pulselen); pwm.setPWM(15, 0, pulselen); } delay(500); }
例子程序2:
#include
#include
// called this way, it uses the default address 0x40 Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); // our servo # counter //uint8_t servonum = 0; void setup() {
Serial.begin(9600); Serial.println("16 channel Servo test!"); pwm.begin(); pwm.setPWMFreq(50); // Analog servos run at ~50 Hz updates模拟伺服运行在50赫兹更新 } void loop() {
//setServoPulse(0, 0.001); //setServoPulseMS(1, 50); pwm.setPin(0,0,0); pwm.setPin(1,4096,0); pwm.setPin(2,(0.5/20.0)*4096,0); }
IDE自带例程:
/* This is an example for our Adafruit 16-channel PWM & Servo driver PWM test - this will drive 16 PWMs in a 'wave' Pick one up today in the adafruit shop! ------> http://www.adafruit.com/products/815 These displays use I2C to communicate, 2 pins are required to interface. For Arduino UNOs, thats SCL -> Analog 5, SDA -> Analog 4 Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! Written by Limor Fried/Ladyada for Adafruit Industries. BSD license, all text above must be included in any redistribution 这是我们的AdfRuIT 16通道PWM和伺服驱动器的一个例子。 PWM测试-这将驱动16个波姆斯在“波” 今天在AdfRuIT商店挑选一个! ------HTTP://www. AdAfRuIT.COM/PROSTS/815 这些显示器使用I2C进行通信,需要2个引脚。 接口。对于ARDUINO UNOS,这是SCL->模拟5,SDA - >模拟4 ADAFRUIT投入时间和资源来提供这个开源代码, 请通过购买支持AdfRuIT和开源硬件 来自AdfRuIT的产品! 由Limor Fray/Lajayad撰写的AdfuRIT产业。 BSD许可证,以上所有文本必须包含在任何再分配中 */ #include
#include
//以这种方式调用,它使用默认地址0x40。 // called this way, it uses the default address 0x40 Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); // you can also call it with a different address you want //Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x41); //你也可以用不同的地址称呼它。 //ADAFRUITIGPWM伺服驱动器PWM=ADAFRUITIGPWM伺服驱动器(0x41); void setup() {
Serial.begin(9600); Serial.println("16 channel PWM test!"); // if you want to really speed stuff up, you can go into 'fast 400khz I2C' mode // some i2c devices dont like this so much so if you're sharing the bus, watch // out for this! //如果你真的想加快速度,你可以进入“快速400千赫I2C”模式。 //一些I2C设备不太喜欢这个,所以如果你在共享公共汽车,请注意。 //为了这个! pwm.begin(); pwm.setPWMFreq(1600); // This is the maximum PWM frequency这是最大PWM频率 // save I2C bitrate uint8_t twbrbackup = TWBR; // must be changed after calling Wire.begin() (inside pwm.begin()) //保存I2C比特率 //必须在调用Word.No.2之后更改(内部PWM(开始)) TWBR = 12; // upgrade to 400KHz!升级到400千赫! } void loop() {
// Drive each PWM in a 'wave' //在“波”中驱动每个PWM for (uint16_t i=0; i<4096; i += 8) {
//i=i+8 for (uint8_t pwmnum=0; pwmnum < 16; pwmnum++) {
pwm.setPWM(pwmnum, 0, (i + (4096/16)*pwmnum) % 4096 ); //%求余数 x = 7 % 5; //x=2,余数为2,如果i=8,pwmnum=2,(8+256*2)=520,520%4096 } } }
基础知识:
上面有出现uint8_t uint16_t,那它们是什么?其实很简单:
编程语言不扎实看一下字节定义:
B就是Byte,也就是字节;b是bit的缩写,b就是bit,也就是比特位(bit)。B与b不同,注意区分,KB是千字节,Kb是千比特位。 8bit(比特位)=1Byte(字节); 1024Byte(字节)=1KB(千字节); 1024KB(千字节)=1MB(兆字节); 1MB(兆字节)=1024KB(千字节)=1024*1024B(字节)=B(字节); 1024MB=1GB; 1024GB=1TB;

_t的意思到底表示什么?
进阶学习:
从例子中模仿,从库函数中掌握!
setPWMFreq(freq)
setPWM(channel, on, off)
4096这个数到底是什么?
这居然是最高阅读量的Blog,开始写的有点迷惑,今天抽点时间优化一下结构,后面会继续优化,博主也不是完全掌握,有任何疑问评论区见,大家共同学习,如果有帮到你,记得点赞噢!——2018年10月11日13点32分编辑
2019年1月19日,插播一波,如果感兴趣的童鞋们可以加入技术交流群~

完。
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/229415.html原文链接:https://javaforall.net
