DEU 发表于 2016-4-2 21:47:00

求各路大神支招:Arduino UNO驱动PCA9685的程序

最近在搞一个Arduino UNO 控制的机器手的物品交接,但是买来的PCA9685还是没能够玩转,求大神支招,帮我看看程序,提提意见。


无论你有什么想法或者看法,请留言告诉我,有我能解决的,一定回复,做出来了会发一个完整的帖子,跟大家分享心得。



下面是我找的资料。

这个是我在官网上下载的压缩包里的 servo 示例 程序:

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

// called this way, it uses the default address 0x40                                             //官方PCA9685的初始地址是0x40,我也找到有说初始地址是0x80,板子上写的是                                             
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40);                //1+A5 A4 A3 A2 A1 A0+RW, RW是Read和Write,但是我更倾向于0x40,理由是
// you can also call it with a different address you want                                    // 读写位RW不算,其他是0100 0000,如果RW算,是1000 0000,那问题就是
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x41);             //I2C的读写位R,W。《以上是我的个人观点》
// 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 SERVOMIN150 // this is the 'minimum' pulse length count (out of 4096)       //定义舵机的最大最小脉冲宽度
#define SERVOMAX600 // this is the 'maximum' pulse length count (out of 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

yield();
}

// 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!


void setServoPulse(uint8_t n, double pulse) {
double pulselength;

pulselength = 1000000;   // 1,000,000 us per second
pulselength /= 60;   // 60 Hz
Serial.print(pulselength); Serial.println(" us per period");
pulselength /= 4096;// 12 bits of resolution
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(servonum, 0, pulselen);
}

delay(500);
for (uint16_t pulselen = SERVOMAX; pulselen > SERVOMIN; pulselen--) {
    pwm.setPWM(servonum, 0, pulselen);
}

delay(500);

servonum ++;
if (servonum > 15) servonum = 0;
}



这个是压缩包里的<Adafruit_PWMServoDriver.h>文件


#ifndef _ADAFRUIT_PWMServoDriver_H
#define _ADAFRUIT_PWMServoDriver_H

#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif


#define PCA9685_SUBADR1 0x2                                 
#define PCA9685_SUBADR2 0x3
#define PCA9685_SUBADR3 0x4

#define PCA9685_MODE1 0x0
#define PCA9685_PRESCALE 0xFE

#define LED0_ON_L 0x6
#define LED0_ON_H 0x7
#define LED0_OFF_L 0x8
#define LED0_OFF_H 0x9

#define ALLLED_ON_L 0xFA
#define ALLLED_ON_H 0xFB
#define ALLLED_OFF_L 0xFC
#define ALLLED_OFF_H 0xFD


class Adafruit_PWMServoDriver {
public:
Adafruit_PWMServoDriver(uint8_t addr = 0x40);
void begin(void);
void reset(void);
void setPWMFreq(float freq);
void setPWM(uint8_t num, uint16_t on, uint16_t off);
void setPin(uint8_t num, uint16_t val, bool invert=false);

private:
uint8_t _i2caddr;

uint8_t read8(uint8_t addr);
void write8(uint8_t addr, uint8_t d);
};

#endif



官网上说打开 示例servo 文件,按照图接线就可以实现舵机的180度摆动,可是我按照图接线并外接电源共地,舵机并没有实现180度摆动,用示波器检测PWM端口,显示出并没有PWM波。



官网:https://learn.adafruit.com/16-channel-pwm-servo-driver/hooking-it-up


zoologist 发表于 2016-4-2 22:07:23

你找个i2c 地址扫描的程序确定一下这个设备的 I2c地址吧

code-AR 发表于 2016-4-3 18:02:11

板子上面有设置地址的,那个一系列的焊盘

DEU 发表于 2016-4-3 21:17:20

code-AR 发表于 2016-4-3 18:02 static/image/common/back.gif
板子上面有设置地址的,那个一系列的焊盘

不错,是有地址,可是我找了I2C扫描的程序去检测了一下,没有扫出来。= =

908495557 发表于 2016-4-16 10:50:34

你好,最近我也刚开始要用pca9685.Arduino上的4,5为什么要接scl和sda??关于这个板子有什么资料或者实例可以参考吗???

DEU 发表于 2016-5-5 13:13:47

908495557 发表于 2016-4-16 10:50 static/image/common/back.gif
你好,最近我也刚开始要用pca9685.Arduino上的4,5为什么要接scl和sda??关于这个板子有什么资料或者实例可 ...

我发的那个压缩包就是PCA9685的控制源程序

hrf150806 发表于 2016-6-28 16:05:15

同问?谢谢大神解答

Hackerpro 发表于 2016-10-9 09:55:28

默认的iic地址就没错,我用逻辑分析仪看了,有应答,但是就是没有pwm输出,搞不懂这是要哪样

超级无敌掌门狗 发表于 2016-10-9 10:32:40

http://www.geek-workshop.com/thread-25046-1-1.html 楼主看看这个

tianjitingyu 发表于 2016-11-7 21:10:08

楼主问题解决了吗 我也遇到同样问题无pwm输出

dyl2016 发表于 2016-12-8 21:01:31

我们也刚买了个 pca9685的板子,但是没有办法跟Arduino   连接到一块? 你知道怎么利用程序进行编辑吗

2234575324 发表于 2017-1-17 08:56:50

/***************************************************
  这是对我们的一个例子Adafruit 16通道PWM和伺服驱动
  伺服测试——这将推动16伺服系统,一个接一个
  
  接一个adafruit商店今天!
  这些显示使用I2C通信2针需要
  接口。对于Arduino凯泽本人,这是sci - >模拟5,SDA - >模拟4
  
  Adafruit投入时间和资源提供这个开源的代码,
  请支持Adafruit和开源硬件通过购买
  产品从Adafruit !
****************************************************/

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

// 这种方式,它使用默认地址0 x40
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
// 你也可以叫它你想要使用不同的地址
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x41);

//根据伺服,脉冲宽度最小和最大可能不同,你
//想要这些尽可能小/大打的很难停止
//为马克斯。你将不得不调整需要匹配的伺服系统
// !
#define SERVOMIN150 // 这是最小的脉冲长度数(4096)
#define SERVOMAX600 // 这是最大的脉冲长度数(4096)

// 我们的伺服#计数器
//uint8_t servonum = 0;

void setup() {
Serial.begin(9600);
Serial.println("16 channel Servo test!");

pwm.begin();

pwm.setPWMFreq(60);// 模拟伺服系统运行~ 60赫兹更新
}

//这个函数可以使用如果你想设置脉冲长度在几秒钟内
//例如setServoPulse(0,- 0.001)~ 1毫秒脉冲宽度。它不准确!
void setServoPulse(uint8_t n, double pulse) {
double pulselength;

pulselength = 1000000;   // 1,000,000 us per second
pulselength /= 60;   // 60 Hz
Serial.print(pulselength); Serial.println(" us per period");
pulselength /= 4096;// 12 bits of resolution
Serial.print(pulselength); Serial.println(" us per bit");
pulse *= 1000;
pulse /= pulselength;
Serial.println(pulse);
pwm.setPWM(n, 0, pulse);
}

void loop() {
// 驱动每个伺服一次
//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);
}
delay(500);
for (uint16_t pulselen = SERVOMAX; pulselen > SERVOMIN; pulselen--) {
    pwm.setPWM(0, 0, 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);
}
delay(500);

}

狍狍狍 发表于 2017-10-10 16:05:32

楼主,我把你的程序复制到Arduino IDE,为什么显示编译错误啊?

jinshan 发表于 2019-8-15 14:26:50

楼主 你那个图片是什么软件写出来的
页: [1]
查看完整版本: 求各路大神支招:Arduino UNO驱动PCA9685的程序