极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 24417|回复: 13

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

[复制链接]
发表于 2016-4-2 21:47:00 | 显示全部楼层 |阅读模式
最近在搞一个  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 SERVOMIN  150 // this is the 'minimum' pulse length count (out of 4096)       //定义舵机的最大最小脉冲宽度
#define SERVOMAX  600 // 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


adafruit_products_Servo_bb-1024.jpg

Adafruit-PWM-Servo-Driver-Library-master.zip

8.49 KB, 下载次数: 301

程序

回复

使用道具 举报

发表于 2016-4-2 22:07:23 | 显示全部楼层
你找个i2c 地址扫描的程序确定一下这个设备的 I2c地址吧
回复 支持 反对

使用道具 举报

发表于 2016-4-3 18:02:11 | 显示全部楼层
板子上面有设置地址的,那个一系列的焊盘
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-4-3 21:17:20 | 显示全部楼层
code-AR 发表于 2016-4-3 18:02
板子上面有设置地址的,那个一系列的焊盘

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

使用道具 举报

发表于 2016-4-16 10:50:34 | 显示全部楼层
你好,最近我也刚开始要用pca9685.Arduino上的4,5为什么要接scl和sda??关于这个板子有什么资料或者实例可以参考吗???
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-5-5 13:13:47 | 显示全部楼层
908495557 发表于 2016-4-16 10:50
你好,最近我也刚开始要用pca9685.Arduino上的4,5为什么要接scl和sda??关于这个板子有什么资料或者实例可 ...

我发的那个压缩包就是PCA9685的控制源程序
回复 支持 反对

使用道具 举报

发表于 2016-6-28 16:05:15 | 显示全部楼层
同问?谢谢大神解答
回复 支持 反对

使用道具 举报

发表于 2016-10-9 09:55:28 | 显示全部楼层
默认的iic地址就没错,我用逻辑分析仪看了,有应答,但是就是没有pwm输出,搞不懂这是要哪样
回复 支持 反对

使用道具 举报

发表于 2016-10-9 10:32:40 | 显示全部楼层
回复 支持 反对

使用道具 举报

发表于 2016-11-7 21:10:08 | 显示全部楼层
楼主问题解决了吗 我也遇到同样问题  无pwm输出
回复 支持 反对

使用道具 举报

发表于 2016-12-8 21:01:31 | 显示全部楼层
我们也刚买了个 pca9685的板子,但是没有办法跟Arduino   连接到一块? 你知道怎么利用程序进行编辑吗
回复 支持 反对

使用道具 举报

发表于 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 SERVOMIN  150 // 这是最小的脉冲长度数(4096)
#define SERVOMAX  600 // 这是最大的脉冲长度数(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,为什么显示编译错误啊?
回复 支持 反对

使用道具 举报

发表于 2019-8-15 14:26:50 | 显示全部楼层
楼主 你那个图片是什么软件写出来的
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|联系我们|极客工坊 ( 浙ICP备09023225号 )

GMT+8, 2020-7-9 11:08 , Processed in 0.062615 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表