ESP8266与PCA9685通信I2C

ESP8266与PCA9685通信I2CESP8266与PCA9685通信I2CTalkischeap,showyoucode!/***ESP8266与PCA9685通过I2C协议通信*功能:控制PCA9685上的16个舵机旋转0-180°,串口打印舵机id和角度*说明:本代码没有使用ESP8266自带的I2C,而是pin模拟输出*接线:*SDA->GPIO4(D2)*SCL->GPIO5(D1)*作者:锋2022/

ESP8266与PCA9685通信I2C"

ESP8266与PCA9685通信I2C

Talk is cheap, show you code!

/** * ESP8266与PCA9685通过I2C协议通信 * 功能:控制PCA9685上的16个舵机旋转0-180°,串口打印舵机id和角度 * 说明:本代码没有使用ESP8266自带的I2C,而是pin模拟输出 * 接线: * SDA -> GPIO4(D2) * SCL -> GPIO5(D1) * 作者:锋 2022/1/22/18:43 */

typedef  unsigned char  u8;        
typedef  unsigned short   u16;        

#define sda_pin 4//GPIO4->D2
#define scl_pin 5//GPIO5->D1

#define SDA_H digitalWrite(sda_pin,HIGH)
#define SDA_L digitalWrite(sda_pin,LOW)
#define SCL_H digitalWrite(scl_pin,HIGH)
#define SCL_L digitalWrite(scl_pin,LOW)

#define PCA9685_adrr 0x80// 1+A5+A4+A3+A2+A1+A0+w/r 
#define PCA9685_SUBADR1 0x2
#define PCA9685_SUBADR2 0x3
#define PCA9685_SUBADR3 0x4

#define PCA9685_MODE1 0x00
#define PCA9685_PRESCALE 0xFE

#define LED0_ON_L 0x06
#define LED0_ON_H 0x07
#define LED0_OFF_L 0x08
#define LED0_OFF_H 0x09

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


void setup() { 
   
  // put your setup code here, to run once:
  Serial.begin(115200);

  pinMode(sda_pin,OUTPUT);
  pinMode(scl_pin,OUTPUT);

  PCA9685_Init();
}

void loop() { 
   
  // put your main code here, to run repeatedly:
  
  for(int angle=0;angle<=180;angle+=30)
  { 
   
    //void servo_control(servo_id,angle)
    servo_control(0,angle);
    Serial.printf("servo id=0 angle=%d\n",angle);
    delay(1000);
  }
}

void IIC_init()
{ 
   
    SDA_H;               
    delayMicroseconds(5);
    SCL_H;
    delayMicroseconds(5);
}

void IIC_start()
{ 
   
    SDA_H;
    delayMicroseconds(5);
    SCL_H;                
    delayMicroseconds(5);
    SDA_L;
    delayMicroseconds(5);
    SCL_L;
    delayMicroseconds(5);
}

void IIC_stop()
{ 
   
    SDA_L;
    delayMicroseconds(5);
    SCL_H;    
    delayMicroseconds(5);
    SDA_H;                   
    delayMicroseconds(5);
}

bool ACK()
{ 
   
    u16 i;
    SCL_H;
    //pinMode(sda_pin,INPUT); //change pin mode to INPUT
    delayMicroseconds(5);
    if(digitalRead(sda_pin)==LOW)     //
    { 
   
      SCL_L;
      //pinMode(sda_pin,OUTPUT); //change pin mode to OUTPUT
      delayMicroseconds(5);
      return true;            
    }                                        
    else
    { 
   
      SCL_L;
      //pinMode(sda_pin,OUTPUT); //change pin mode to OUTPUT
      delayMicroseconds(5);
      return false;                                 
    }    
}

void write_byte(u8 byte_)
{ 
   
    u8 i;
    for(i=0;i<8;i++)
    { 
      
      if(byte_&0x80) 
      { 
    
        SDA_H;
      }
      else 
      { 
   
        SDA_L;
      }
      delayMicroseconds(5);
      SCL_H;
      byte_<<=1;
      delayMicroseconds(5);
      SCL_L;
    }
}

u8 read_byte()
{ 
   
    u8 i,j,k;
    SCL_L;
    delayMicroseconds(5);
    SDA_H;
    delayMicroseconds(5);
    //pinMode(sda_pin,INPUT); //change pin mode to INPUT
    for(i=0;i<8;i++)        
    { 
   
      delayMicroseconds(5);
      SCL_H;
      delayMicroseconds(5);
      if(digitalRead(sda_pin)==HIGH)      //
      { 
   
        j=1;
      }
      else j=0;
      k=(k<< 1)|j;  
      SCL_L;            
    }
    //pinMode(sda_pin,OUTPUT); //change pin mode to OUTPUT
    delayMicroseconds(5);
    return k;
}

void PCA9685_write(u8 address,u8 date)
{ 
   
    IIC_start();
    write_byte(PCA9685_adrr); 
    ACK();                          
    write_byte(address); 
    ACK();
    write_byte(date); 
    ACK();
    IIC_stop();
}

u8 PCA9685_read(u8 address)
{ 
   
    u8 data;
    IIC_start();
    write_byte(PCA9685_adrr); 
    ACK();
    write_byte(address);
    ACK();
    IIC_start();
    write_byte(PCA9685_adrr|0x01); 
    ACK();
    data=read_byte();
    IIC_stop();
    return data;
}

void PCA9685_reset(void) 
{ 
   
  PCA9685_write(PCA9685_MODE1,0x0);
}

void setPWMFreq(float freq) 
{ 
   
    u16 prescale,oldmode,newmode;
    float prescaleval;
    freq *= 0.92;  // Correct for overshoot in the frequency setting 
    prescaleval = 25000000;
    prescaleval /= 4096;
    prescaleval /= freq;
    prescaleval -= 1;
    prescale = floor(prescaleval + 0.5);
    
    oldmode = PCA9685_read(PCA9685_MODE1);
    newmode = (oldmode&0x7F) | 0x10; // sleep
    PCA9685_write(PCA9685_MODE1, newmode); // go to sleep
    PCA9685_write(PCA9685_PRESCALE, prescale); // set the prescaler
    PCA9685_write(PCA9685_MODE1, oldmode);
    delay(2);
    PCA9685_write(PCA9685_MODE1, oldmode | 0xa1); 
}

void servo_control(u8 servo_id, u16 angle) 
{ 
   
    u16 off = 102.4+2.275555556*angle;
    PCA9685_write(LED0_ON_L+4*servo_id,0);
    PCA9685_write(LED0_ON_H+4*servo_id,0);
    PCA9685_write(LED0_OFF_L+4*servo_id,off);
    PCA9685_write(LED0_OFF_H+4*servo_id,off>>8);
}

void PCA9685_Init()
{ 
   
  IIC_init();
  PCA9685_reset();
  setPWMFreq(50);
}

今天的文章ESP8266与PCA9685通信I2C分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/28103.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注