关闭

arduino使用 iic协议控制16路pmw板的扩展

标签: arduino扩展pwm 机器人 舵机
389人阅读 评论(0) 收藏 举报
分类:

arduino使用 iic协议控制16路pmw板的扩展

上位机串口与arduino 通讯

串口数据协议

数据协议

11aa aaAA 10AA dddd 01dd dddd

控制协议未定义

//00xxxx11 00xxxx10 00xxxx01 00xxxx00


源码

#include <Wire.h>

#include "EZ_PWMServoDriver.h" //#include <Adafruit_PWMServoDriver.h> //Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); EZ_PWMServoDriver pwm = EZ_PWMServoDriver(); //数据协议 //11aa aaAA 10AA dddd 01dd dddd //控制协议未定义 //00xxxx11 00xxxx10 00xxxx01 00xxxx00 byte buf[3]; byte aaa; byte AAA; unsigned int ddd; byte comchar; byte p=0; void setupPWMSD(){ //遍历总线设置频率 for(byte i=0;i<0x10;i++){ //Serial.println(i) ; pwm.setAddr(0x40+i); pwm.begin(); pwm.setPWMFreq(50); } } void sendToIIC(byte _AAA,byte _aaa,unsigned int _ddd){ //50hz 相当于20ms(20000us)的 周期, 4096分辨率,分辨率每单位占用时间t 为20000us/4096=4.8828125us //舵机控制所需脉宽Th范围0.5~2.5ms(500~2500us)因此高电平分辨率范围就是Th/t =(102.4~512)个单位。 //取整 最小103 最大512 范围是512-103=409; pwm.setAddr(0x40+_AAA); float per=(float)_ddd/1024.0;//参数ddd为10位正整数最大1024 uint16_t offNum=103+int(409*per); //pwm.setPWM(num,on,off);num pmw的id代号,on 上升沿(在0-4096之间)开始位置,off 下降沿在(在0-4096之间)的开始位置 pwm.setPWM(_aaa, 0, offNum); /* Serial.print("per = :"); Serial.println(per) ; Serial.print("num = :"); Serial.println(offNum) ; */ } void setup() { Serial.begin(115200); while(Serial.read()>= 0){}//clear serialbuffer setupPWMSD(); yield(); Serial.println("hello,setup success"); } void parseBuf(){ //00111100 aaa=(buf[0]&0x3C)>>2; //00000011 //00110000 AAA=(buf[0]&0x03)<<2; AAA+=(buf[1]&0x30)>>4; //00001111 //00111111 ddd=(buf[1]&0x0f); ddd<<=6; ddd+=(buf[2]&0x3f); } void loop() { // read data from serial port while(Serial.available()>0){ comchar = Serial.read();//读串口第一个字节 Serial.println(comchar, HEX) ; if((comchar&0xC0)==0xC0){ buf[0]=comchar&0x3f; p=1; continue; } if((comchar&0x80)==0x80){ if(p==1){ buf[1]=comchar&0x3f; p=2; }else{ p=0; //抛弃 } continue; } if((comchar&0x40)==0x40){ if(p==2){ buf[2]=comchar&0x3f; //完成一个包的接收 parseBuf(); /* Serial.println("=========================:"); Serial.print("Serial.aaa = :"); Serial.println(aaa, BIN) ;//得到 "1001110" Serial.print("Serial.AAA = :"); Serial.println(AAA, BIN) ;//得到 "1001110" Serial.print("Serial.ddd = :"); Serial.println(ddd, BIN) ;//得到 "1001110" */ //解包 转iic协议发送 sendToIIC( AAA, aaa, ddd); } p=0; continue; } if((comchar&0xC0)==0x00){ p=0; //控制协议 continue; } } //delay(100); //Serial.println("loop"); }

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 EZ_PWMServoDriver {
 public:
  EZ_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);
  void setAddr(uint8_t addr1);//zzz add
 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
 ****************************************************/

#include "EZ_PWMServoDriver.h"
#include <Wire.h>
#if defined(ARDUINO_SAM_DUE)
 #define WIRE Wire1
#else
 #define WIRE Wire
#endif


// Set to true to print some debug messages, or false to disable them.
#define ENABLE_DEBUG_OUTPUT false

EZ_PWMServoDriver::EZ_PWMServoDriver(uint8_t addr) {
  _i2caddr = addr;
}

void EZ_PWMServoDriver::begin(void) {
 WIRE.begin();
 reset();
}


void EZ_PWMServoDriver::reset(void) {
 write8(PCA9685_MODE1, 0x0);
}

void EZ_PWMServoDriver::setPWMFreq(float freq) {
  //Serial.print("Attempting to set freq ");
  //Serial.println(freq);
  freq *= 0.9;  // Correct for overshoot in the frequency setting (see issue #11).
  float prescaleval = 25000000;
  prescaleval /= 4096;
  prescaleval /= freq;
  prescaleval -= 1;
  if (ENABLE_DEBUG_OUTPUT) {
    //Serial.print("Estimated pre-scale: "); Serial.println(prescaleval);
  }
  uint8_t prescale = floor(prescaleval + 0.5);
  if (ENABLE_DEBUG_OUTPUT) {
    //Serial.print("Final pre-scale: "); Serial.println(prescale);
  }
  
  uint8_t oldmode = read8(PCA9685_MODE1);
  uint8_t newmode = (oldmode&0x7F) | 0x10; // sleep
  write8(PCA9685_MODE1, newmode); // go to sleep
  write8(PCA9685_PRESCALE, prescale); // set the prescaler
  write8(PCA9685_MODE1, oldmode);
  delay(5);
  write8(PCA9685_MODE1, oldmode | 0xa1);  //  This sets the MODE1 register to turn on auto increment.
                                          // This is why the beginTransmission below was not working.
  //  Serial.print("Mode now 0x"); Serial.println(read8(PCA9685_MODE1), HEX);
}

void EZ_PWMServoDriver::setPWM(uint8_t num, uint16_t on, uint16_t off) {
  //Serial.print("Setting PWM "); Serial.print(num); Serial.print(": "); Serial.print(on); Serial.print("->"); Serial.println(off);

  WIRE.beginTransmission(_i2caddr);
  WIRE.write(LED0_ON_L+4*num);
  WIRE.write(on);
  WIRE.write(on>>8);
  WIRE.write(off);
  WIRE.write(off>>8);
  WIRE.endTransmission();
}

// Sets pin without having to deal with on/off tick placement and properly handles
// a zero value as completely off.  Optional invert parameter supports inverting
// the pulse for sinking to ground.  Val should be a value from 0 to 4095 inclusive.
void EZ_PWMServoDriver::setPin(uint8_t num, uint16_t val, bool invert)
{
  // Clamp value between 0 and 4095 inclusive.
  val = min(val, 4095);
  if (invert) {
    if (val == 0) {
      // Special value for signal fully on.
      setPWM(num, 4096, 0);
    }
    else if (val == 4095) {
      // Special value for signal fully off.
      setPWM(num, 0, 4096);
    }
    else {
      setPWM(num, 0, 4095-val);
    }
  }
  else {
    if (val == 4095) {
      // Special value for signal fully on.
      setPWM(num, 4096, 0);
    }
    else if (val == 0) {
      // Special value for signal fully off.
      setPWM(num, 0, 4096);
    }
    else {
      setPWM(num, 0, val);
    }
  }
}
void EZ_PWMServoDriver::setAddr(uint8_t addr1){//zzz add
  _i2caddr = addr1;
}
uint8_t EZ_PWMServoDriver::read8(uint8_t addr) {
  WIRE.beginTransmission(_i2caddr);
  WIRE.write(addr);
  WIRE.endTransmission();

  WIRE.requestFrom((uint8_t)_i2caddr, (uint8_t)1);
  return WIRE.read();
}

void EZ_PWMServoDriver::write8(uint8_t addr, uint8_t d) {
  WIRE.beginTransmission(_i2caddr);
  WIRE.write(addr);
  WIRE.write(d);
  WIRE.endTransmission();
}


0
0
查看评论

Arduino IICI2C

  • 2015-07-28 09:04
  • 1.15MB
  • 下载

arduino的i2c接口

Arduino各型号使用I2C通信的引脚说明 Arduino中使用I2C通信可直接调用Wire.h库。这个库允许Arduino链接其他I2C设备。 链接线有两条,分别是SDA(数据行)和SCI(时钟线)。 下面是各型号Arduino的I2C对应引脚: Arduino Board:I2C / T...
  • MENGHUANBEIKE
  • MENGHUANBEIKE
  • 2017-07-13 18:04
  • 603

Arduino Wire.h 库函数基本操作 IIC

想测Arduino的I2C性能,又不知道如何使用库函数,又不想自己写函数。。顺手把Arduino官网的Wire.h库函数借鉴下。 首先,arduino中的Wire库主要包含以下函数:  Wire.begin()  Wire.requestFrom()  Wire.b...
  • zhao_120
  • zhao_120
  • 2015-07-23 21:00
  • 17606

Arduino的IIC运行库

  • 2017-08-09 10:42
  • 15KB
  • 下载

STM32控制16路舵机控制板PCA9685

介绍PCA9685 是最新的快速模式 Plus(Fm+)系列中的一员。 Fm+器件可以提供更高的频率 (高达 1MHz)和更频繁(densely populated) 的总线操作(高达 4000pF)。 OE引脚一定要至低使能,或者直接接地 网上Arduino的教程很多,商家给的也是Arduino的...
  • superce
  • superce
  • 2017-12-23 13:25
  • 236

Arduino通过L298N红板控制板控制直流电机

在Arduino论坛上看到很多人都做过智能小车,有两轮的,有四轮的,功能也是多种多样,有寻迹、壁障、无线遥控、红外遥控的,其实小车就是个底盘或者载体,然后可以根据需要向小车上加功能模块。于是我在淘宝上买了一个四轮小车的架子。里面包括四个轮子、四个直流电机还有支架。小车组装之后是下面这个样子。接下来的...
  • gc_2299
  • gc_2299
  • 2017-11-12 19:59
  • 321

Arduino 驱动OLED屏幕IIC接线方式简单入门

OLED一款小巧的显示屏,感觉可以做出很可爱的东西。 这次实验的这款是128X64的OLED屏幕   实验效果 BOM表 针脚说明 接线图 程序开源代码
  • ling3ye
  • ling3ye
  • 2016-11-04 18:38
  • 23209

Arduino - IIC SCANNER

#include <Wire.h>#define SERIAL_BAUD 57600 void setup() { Wire.begin(); Serial.begin(SERIAL_BAUD); Serial.println("I2C Scanner started...
  • sdlgq
  • sdlgq
  • 2015-12-19 16:14
  • 656

Arduino 舵机驱动板编程

需要下载Adafruit的arduino库,这个网上搜索一下很多 我的驱动板是16路基于I2C接口通信,这个arduino库底层都做好了,精度是12位(4096) 设置非常简单,设置一下频率50,那么周期是20ms 如果你想要0.5ms脉宽,那么设置的值是(0.5/20.0)*4096 se...
  • zmy12007
  • zmy12007
  • 2017-05-14 00:09
  • 739

arduino mega 2560结合 ethernet shield拓展板使用心得

最近开始学习arduino的网络应用,刚好要用到数据网络上传的功能,几番尝试后,有些心得体会。 手中有一个arduino mega 2560的开发板和Ethernet shiled的拓展板,还有dht11温湿度传感器 使用目的是为了将传感器获得的温湿度数据上传到yeelink(yeelink.net...
  • beiyan55
  • beiyan55
  • 2015-02-07 16:40
  • 1363
    个人资料
    • 访问:9265次
    • 积分:474
    • 等级:
    • 排名:千里之外
    • 原创:36篇
    • 转载:3篇
    • 译文:2篇
    • 评论:6条
    文章分类
    最新评论