PCA9685在nodeMCU开发板的驱动移植

背景

最近尝试做六足机器人,遇到了需要用pwm控制板控制舵机的问题。淘了快PCA9685的16路舵机控制板,卖家给的参考程序是在Arduino uno的驱动,想着移植到nodeMCU上,用lua能省不少开发时间。

clipboard.png

c版驱动

/*************************************************** 
  This is a library for our Adafruit 16-channel PWM & Servo driver

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

#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
/*************************************************** 
  This is a library for our Adafruit 16-channel PWM & Servo driver

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

#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

c版测试

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

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

// 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);

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!

  pwm.begin();
  pwm.setPWMFreq(1600);  // This is the maximum PWM frequency
    
  // save I2C bitrate
  uint8_t twbrbackup = TWBR;
  // must be changed after calling Wire.begin() (inside pwm.begin())
  TWBR = 12; // upgrade to 400KHz!
    
}

void loop() {
  // Drive each PWM in a 'wave'
  for (uint16_t i=0; i<4096; i += 8) {
    for (uint8_t pwmnum=0; pwmnum < 16; pwmnum++) {
      pwm.setPWM(pwmnum, 0, (i + (4096/16)*pwmnum) % 4096 );
    }
  }
}

lua版驱动

PwmSvr={
    id=0,            PCA9685_SUBADR1=0x2,    LED0_ON_L=0x6,    ALLLED_ON_L=0xFA,
    pinSCL=1,        PCA9685_SUBADR2=0x3,    LED0_ON_H=0x7,    ALLLED_ON_H=0xFB,
    pinSDA=2,        PCA9685_SUBADR3=0x4,    LED0_OFF_L=0x8,    ALLLED_OFF_L=0xFC,
    _i2caddr=0x40,    PCA9685_MODE1=0x0,        LED0_OFF_H=0x9,    ALLLED_OFF_H=0xFD,
    addr=nil,        PCA9685_PRESCALE=0xFE
}
function PwmSvr.read8(addr)
    i2c.start(PwmSvr.id)
    i2c.address(PwmSvr.id, PwmSvr._i2caddr,i2c.TRANSMITTER)
    i2c.write(PwmSvr.id,addr)
    i2c.stop(PwmSvr.id)
    i2c.start(PwmSvr.id)
    i2c.address(PwmSvr.id, PwmSvr._i2caddr,i2c.RECEIVER)
    local c=i2c.read(PwmSvr.id,1)
    i2c.stop(PwmSvr.id)
    return string.byte(c)
end
function PwmSvr.write8(addr,d)
    i2c.start(PwmSvr.id)
    i2c.address(PwmSvr.id, PwmSvr._i2caddr ,i2c.TRANSMITTER)
    i2c.write(PwmSvr.id,addr,d)
    i2c.stop(PwmSvr.id)
end
function PwmSvr.reset()
    PwmSvr.write8(PwmSvr.PCA9685_MODE1,0x0)
end
function PwmSvr.begin()
    i2c.setup(PwmSvr.id, PwmSvr.pinSDA, PwmSvr.pinSCL, i2c.SLOW)
    PwmSvr.reset()
end
function PwmSvr.setPWMFreq(freq)
    local prescale=math.ceil((25000000/4096)/(freq*0.9)+0.5)
    local oldmode = PwmSvr.read8(PwmSvr.PCA9685_MODE1)
    local newmode =bit.bor(bit.band(oldmode,0x7F),0x10)
    PwmSvr.write8(PwmSvr.PCA9685_MODE1,newmode)
    PwmSvr.write8(PwmSvr.PCA9685_PRESCALE,prescale)
    PwmSvr.write8(PwmSvr.PCA9685_MODE1,oldmode)
    for i=0,6000 do tmr.wdclr() end
    PwmSvr.write8(PwmSvr.PCA9685_MODE1, bit.bor(oldmode,0xa1))
end
function PwmSvr.setPWM(num,on,off)
    i2c.start(PwmSvr.id)
    i2c.address(PwmSvr.id, PwmSvr._i2caddr ,i2c.TRANSMITTER)
    i2c.write(PwmSvr.id
        ,PwmSvr.LED0_ON_L+4*num
        ,bit.band(on,0xff)
        ,bit.rshift(on,8)
        ,bit.band(off,0xff)
        ,bit.rshift(off,8)
    )
    i2c.stop(PwmSvr.id)
end
function PwmSvr.setPin(num,val,invert)
    if(val>4095) then val=4095 end
    if(invert) then
        if(val==0) then
            PwmSvr.setPWM(num, 4096, 0)
        elseif(val==4095) then
            PwmSvr.setPWM(num, 0, 4096)
        else
            PwmSvr.setPWM(num, 0, 4095-val)
        end
    else
        if(val==4095) then
            PwmSvr.setPWM(num, 4096, 0)
        elseif(val==0) then
            PwmSvr.setPWM(num, 0, 4096)
        else
            PwmSvr.setPWM(num, 0, val)
        end
    end
    
end

lua版测试

dofile("PwmSvr_PCA9685.lua")
PwmSvr.begin()
PwmSvr.setPWMFreq(60)
for pin=0,15 do
    for r=150,400 do
        PwmSvr.setPWM(pin, 0, r)
        tmr.wdclr()
    end
end

源码地址

https://github.com/Seasonley/...

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1.1python软件的安装 先安装python软件优先,因为其他步骤如果用到sudo apt-get update 会导致python程序不是py2而是py3,就用不了我们的程序了 树莓派鼓励用户使用python和C++作为其开发语言,所以原则上可以不用安装python的编译器,但是树莓派自带的python(IDLE)和Thonny python IDE都过于简陋,不太适合python使用者进行复杂的OpenCV开发。在这里推荐Spyder作为树莓派的python IDE。这种编译器相对上述两种编译器略显笨重,但是对内核和运算值的控制更加灵活。   树莓派安装Spyder非常的方便,在命令行输入: sudo apt-get install spyder 下载时间可能比较长,因为在安装spyder3的同时很多python开发开发必要的依赖也一并被安装到树莓派里了,这也说明牺牲一定的空间下载spyder3是值得的。此时,我们已经可以在树莓派的开始菜单-programming中看到编译器了。注意: 1、 在下载spyder之前请不要输入 “sudo apt-get update/upgrade”, 否则会下载适用于python3.6的spyder,无法正常使用,比如图1-0中的spyder的python版本就是3.6,说明下载出现错误。 2、 如果看不到编译器说明安装过程出错,尝试重新执行:sudo apt-get update和 sudo apt-get install spyder3两条命令。   图 1-0下载完成后,在“start”中已经能看到Spyder编译器了     图 1-00 Spyder3的Python3.6版本 我们可以在preference/syntax coloring scheme中更换自己喜欢的主题,怎么样?是不是已经觉得树莓派和普通PC一样方便了呢?现在我们已经可以用在树莓派上舒适的开发python了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值