LTC2944库仑计(电量计)芯片应用笔记(Arduino,ESP32) 您所在的位置:网站首页 电池库仑计设置代码怎么设置 LTC2944库仑计(电量计)芯片应用笔记(Arduino,ESP32)

LTC2944库仑计(电量计)芯片应用笔记(Arduino,ESP32)

2024-07-17 02:26| 来源: 网络整理| 查看: 265

但是这个程序是Linduino平台的,这个东东咱也没用过,但是源码还是可以参考下的。

下面我们把链接上的LTC2944.h和LTC2944.cpp下载下来进行改造。

详细的改造过程省略了,对改造过程感兴趣的可以对比下下面代码和原来的代码之间的差异。

主要改造4个函数:

int8_t LTC2944_write(uint8_t i2c_address, uint8_t adc_command, uint8_t code);     int8_t  LTC2944_write_16_bits(uint8_t i2c_address, uint8_t adc_command, uint16_t code);     int8_t  LTC2944_read(uint8_t i2c_address, uint8_t adc_command, uint8_t *adc_code);     int8_t  LTC2944_read_16_bits(uint8_t i2c_address, uint8_t adc_command, uint16_t *adc_code)

这4个函数是对总线的操作,改造内容是把I2C的操作方法改成Wire方法,其他函数基本都是内部计算函数,不用改造。其他的改造内容都是为了方便使用而改造的,包括增加一些操作函数。

直接给出改造后的源码如下。

LTC2944.h

#ifndef LTC2944_h #define LTC2944_h #include "Arduino.h" #include "Wire.h" #define I2C_ADDRESS_LTC2944 0x64 //#define I2C_ADDR_LTC2944 144 //Registers #define LTC2944_STATUS_REG 0x00 #define LTC2944_CONTROL_REG 0x01 #define LTC2944_ACCUM_CHARGE_MSB_REG 0x02 #define LTC2944_ACCUM_CHARGE_LSB_REG 0x03 #define LTC2944_CHARGE_THRESH_HIGH_MSB_REG 0x04 #define LTC2944_CHARGE_THRESH_HIGH_LSB_REG 0x05 #define LTC2944_CHARGE_THRESH_LOW_MSB_REG 0x06 #define LTC2944_CHARGE_THRESH_LOW_LSB_REG 0x07 #define LTC2944_VOLTAGE_MSB_REG 0x08 #define LTC2944_VOLTAGE_LSB_REG 0x09 #define LTC2944_VOLTAGE_THRESH_HIGH_MSB_REG 0x0A #define LTC2944_VOLTAGE_THRESH_HIGH_LSB_REG 0x0B #define LTC2944_VOLTAGE_THRESH_LOW_MSB_REG 0x0C #define LTC2944_VOLTAGE_THRESH_LOW_LSB_REG 0x0D #define LTC2944_CURRENT_MSB_REG 0x0E #define LTC2944_CURRENT_LSB_REG 0x0F #define LTC2944_CURRENT_THRESH_HIGH_MSB_REG 0x10 #define LTC2944_CURRENT_THRESH_HIGH_LSB_REG 0x11 #define LTC2944_CURRENT_THRESH_LOW_MSB_REG 0x12 #define LTC2944_CURRENT_THRESH_LOW_LSB_REG 0x13 #define LTC2944_TEMPERATURE_MSB_REG 0x14 #define LTC2944_TEMPERATURE_LSB_REG 0x15 #define LTC2944_TEMPERATURE_THRESH_HIGH_REG 0x16 #define LTC2944_TEMPERATURE_THRESH_LOW_REG 0x17 // Command Codes #define LTC2944_AUTOMATIC_MODE 0xC0 #define LTC2944_SCAN_MODE 0x80 #define LTC2944_MANUAL_MODE 0x40 #define LTC2944_SLEEP_MODE 0x00 #define LTC2944_PRESCALAR_M_1 0x00 #define LTC2944_PRESCALAR_M_4 0x08 #define LTC2944_PRESCALAR_M_16 0x10 #define LTC2944_PRESCALAR_M_64 0x18 #define LTC2944_PRESCALAR_M_256 0x20 #define LTC2944_PRESCALAR_M_1024 0x28 #define LTC2944_PRESCALAR_M_4096 0x30 #define LTC2944_PRESCALAR_M_4096_2 0x31 #define LTC2944_ALERT_MODE 0x04 #define LTC2944_CHARGE_COMPLETE_MODE 0x02 #define LTC2944_DISABLE_ALCC_PIN 0x00 #define LTC2944_SHUTDOWN_MODE 0x01 #define LTC2944_SHUTDOWN_MODE_UNDO 0x00 class I2CLTC2944 { public: I2CLTC2944(TwoWire * ptrI2CBus) { _ptrI2CBus=ptrI2CBus; } int8_t LTC2944_write(uint8_t i2c_address, uint8_t adc_command, uint8_t code); int8_t LTC2944_write_16_bits(uint8_t i2c_address, uint8_t adc_command, uint16_t code); int8_t LTC2944_read(uint8_t i2c_address, uint8_t adc_command, uint8_t *adc_code); int8_t LTC2944_read_16_bits(uint8_t i2c_address, uint8_t adc_command, uint16_t *adc_code); float LTC2944_code_to_coulombs(uint16_t adc_code, float resistor, uint16_t prescalar); float LTC2944_code_to_mAh(uint16_t adc_code, float resistor, uint16_t prescalar ); float LTC2944_code_to_voltage(uint16_t adc_code); float LTC2944_code_to_current(uint16_t adc_code, float resistor); float LTC2944_code_to_kelvin_temperature(uint16_t adc_code); float LTC2944_code_to_celcius_temperature(uint16_t adc_code); int8_t LTC2944_register_set_clear_bits(uint8_t i2c_address, uint8_t register_address, uint8_t bits_to_set, uint8_t bits_to_clear); int8_t LTC2944_set_mode(uint8_t i2c_address,uint8_t mode); int8_t LTC2944_set_prescalar(uint8_t i2c_address,uint16_t prescalarVal); int8_t LTC2944_set_ALCC(uint8_t i2c_address,uint8_t ALCCMode); int8_t LTC2944_set_shutdown(uint8_t i2c_address,uint8_t shutdown); int8_t LTC2944_set_ACR_full(uint8_t i2c_address); private: TwoWire * _ptrI2CBus; }; #endif

LTC2944.cpp

#include "Arduino.h" #include "LTC2944.h" //Conversion Constants const float LTC2944_CHARGE_lsb = 0.34E-3; const float LTC2944_VOLTAGE_lsb = 1.068E-3; const float LTC2944_CURRENT_lsb = 29.3E-6; const float LTC2944_TEMPERATURE_lsb = 0.25; const float LTC2944_FULLSCALE_VOLTAGE = 70; const float LTC2944_FULLSCALE_CURRENT = 60E-3; const float LTC2944_FULLSCALE_TEMPERATURE = 510; const float resistor = .020; //!< resistor value int8_t I2CLTC2944::LTC2944_write(uint8_t i2c_address, uint8_t adc_command, uint8_t code) { // Write an 8-bit code to the LTC2944. // The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge. int32_t ack; //ack = i2c_write_byte_data(i2c_address, adc_command, code); _ptrI2CBus->beginTransmission(i2c_address); _ptrI2CBus->write(adc_command); _ptrI2CBus->write(code); ack=_ptrI2CBus->endTransmission(true); return(ack); } int8_t I2CLTC2944::LTC2944_write_16_bits(uint8_t i2c_address, uint8_t adc_command, uint16_t code) { // Write a 16-bit code to the LTC2944. // The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge. int8_t ack; //ack = i2c_write_word_data(i2c_address, adc_command, code); _ptrI2CBus->beginTransmission(i2c_address); _ptrI2CBus->write(adc_command); _ptrI2CBus->write(code); ack=_ptrI2CBus->endTransmission(true); return(ack); } int8_t I2CLTC2944::LTC2944_read(uint8_t i2c_address, uint8_t adc_command, uint8_t *adc_code) { // Reads an 8-bit adc_code from LTC2944 // The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge. int32_t ack; //ack = i2c_read_byte_data(i2c_address, adc_command, adc_code); _ptrI2CBus->flush(); _ptrI2CBus->beginTransmission(i2c_address); _ptrI2CBus->write(adc_command); ack=_ptrI2CBus->endTransmission(false); uint8_t bytesReceived=0; bytesReceived=_ptrI2CBus->requestFrom(i2c_address,1); if(bytesReceived==1) { *adc_code=_ptrI2CBus->read(); } else { //Serial.println("LTC2944_read reply error!"); } return(ack); } int8_t I2CLTC2944::LTC2944_read_16_bits(uint8_t i2c_address, uint8_t adc_command, uint16_t *adc_code) { // Reads a 16-bit adc_code from LTC2944 // The function returns the state of the acknowledge bit after the I2C address write. 0=acknowledge, 1=no acknowledge. int32_t ack; //ack = i2c_read_word_data(i2c_address, adc_command, adc_code); _ptrI2CBus->flush(); _ptrI2CBus->beginTransmission(i2c_address); _ptrI2CBus->write(adc_command); ack=_ptrI2CBus->endTransmission(false); uint8_t bytesReceived=0; uint8_t temp[2]; bytesReceived=_ptrI2CBus->requestFrom(i2c_address,2); if(bytesReceived==2) { temp[0]=_ptrI2CBus->read(); //Serial.print("MSB=");Serial.println(temp[0]); temp[1]=_ptrI2CBus->read(); //Serial.print("LSB=");Serial.println(temp[1]); //_ptrI2CBus->readBytes(temp, bytesReceived); *adc_code=temp[0]*256+temp[1]; } else { //Serial.print("read NOT 2 bytes! recv bytes=");Serial.println(bytesReceived); } return(ack); } float I2CLTC2944::LTC2944_code_to_coulombs(uint16_t adc_code, float resistor, uint16_t prescalar) { // The function converts the 16-bit RAW adc_code to Coulombs float coulomb_charge; coulomb_charge = 1000*(float)(adc_code*LTC2944_CHARGE_lsb*prescalar*50E-3)/(resistor*4096); coulomb_charge = coulomb_charge*3.6f; return(coulomb_charge); } float I2CLTC2944::LTC2944_code_to_mAh(uint16_t adc_code, float resistor, uint16_t prescalar ) { // The function converts the 16-bit RAW adc_code to mAh float mAh_charge; mAh_charge = 1000*(float)(adc_code*LTC2944_CHARGE_lsb*prescalar*50E-3)/(resistor*4096); return(mAh_charge); } float I2CLTC2944::LTC2944_code_to_voltage(uint16_t adc_code) { // The function converts the 16-bit RAW adc_code to Volts float voltage; voltage = ((float)adc_code/(65535))*LTC2944_FULLSCALE_VOLTAGE; return(voltage); } float I2CLTC2944::LTC2944_code_to_current(uint16_t adc_code, float resistor) { // The function converts the 16-bit RAW adc_code to Amperes float current; current = (((float)adc_code-32767)/(32767))*((float)(LTC2944_FULLSCALE_CURRENT)/resistor); return(current); } float I2CLTC2944::LTC2944_code_to_kelvin_temperature(uint16_t adc_code) { // The function converts the 16-bit RAW adc_code to Kelvin float temperature; temperature = adc_code*((float)(LTC2944_FULLSCALE_TEMPERATURE)/65535); return(temperature); } float I2CLTC2944::LTC2944_code_to_celcius_temperature(uint16_t adc_code) { // The function converts the 16-bit RAW adc_code to Celcius float temperature; temperature = adc_code*((float)(LTC2944_FULLSCALE_TEMPERATURE)/65535) - 273.15; return(temperature); } int8_t I2CLTC2944::LTC2944_register_set_clear_bits(uint8_t i2c_address, uint8_t register_address, uint8_t bits_to_set, uint8_t bits_to_clear) { // Used to set and clear bits in a control register. bits_to_set will be bitwise OR'd with the register. // bits_to_clear will be inverted and bitwise AND'd with the register so that every location with a 1 will result in a 0 in the register. uint8_t register_data; int8_t ack = 0; ack |= LTC2944_read(i2c_address, register_address, ®ister_data); register_data = register_data & (~bits_to_clear); register_data = register_data | bits_to_set; ack |= LTC2944_write(i2c_address, register_address, register_data); return(ack); } int8_t I2CLTC2944::LTC2944_set_mode(uint8_t i2c_address,uint8_t mode) { //"mode" must be one of the defined symbols: // LTC2944_AUTOMATIC_MODE,LTC2944_SCAN_MODE,LTC2944_MANUAL_MODE,LTC2944_SLEEP_MODE uint8_t curCode; uint8_t setCode; int8_t ack = 0; ack |= LTC2944_read(i2c_address, LTC2944_CONTROL_REG, &curCode); setCode = mode | (curCode & B00111111);//B[7:6] ack |= LTC2944_write(i2c_address, LTC2944_CONTROL_REG, setCode); return(ack); } int8_t I2CLTC2944::LTC2944_set_prescalar(uint8_t i2c_address,uint16_t prescalarVal) { //"prescalarVal" must be one of the defined symbols: // LTC2944_PRESCALAR_M_1,LTC2944_PRESCALAR_M_4,LTC2944_PRESCALAR_M_16 // LTC2944_PRESCALAR_M_64,LTC2944_PRESCALAR_M_256,LTC2944_PRESCALAR_M_1024 // LTC2944_PRESCALAR_M_4096 uint8_t curCode; uint8_t setCode; int8_t ack = 0; LTC2944_read(i2c_address,LTC2944_CONTROL_REG,&curCode); setCode = prescalarVal | (curCode & B11000111);//B[5:3] ack |= LTC2944_write(i2c_address, LTC2944_CONTROL_REG, setCode); return(ack); } int8_t I2CLTC2944::LTC2944_set_ALCC(uint8_t i2c_address,uint8_t ALCCMode) { //"ALCCMode" must be one of the defined symbols: // LTC2944_ALERT_MODE,LTC2944_CHARGE_COMPLETE_MODE,LTC2944_DISABLE_ALCC_PIN,LTC2944_SHUTDOWN_MODE uint8_t curCode; uint8_t setCode; int8_t ack = 0; ack |= LTC2944_read(i2c_address, LTC2944_CONTROL_REG, &curCode); setCode = ALCCMode | (curCode & B11111001);//B[2:1] ack |= LTC2944_write(i2c_address, LTC2944_CONTROL_REG, setCode); return(ack); } int8_t I2CLTC2944::LTC2944_set_shutdown(uint8_t i2c_address,uint8_t shutdown) { //"ALCCMode" must be one of the defined symbols: // LTC2944_SHUTDOWN_MODE,LTC2944_SHUTDOWN_MODE_UNDO uint8_t curCode; uint8_t setCode; int8_t ack = 0; ack |= LTC2944_read(i2c_address, LTC2944_CONTROL_REG, &curCode); setCode = shutdown | (curCode & B11111110);//B[0] ack |= LTC2944_write(i2c_address, LTC2944_CONTROL_REG, setCode); return(ack); } int8_t I2CLTC2944::LTC2944_set_ACR_full(uint8_t i2c_address) { //set ACR to 0xFFFF uint8_t curCode; uint8_t setCode; int8_t ack = 0; ack |= LTC2944_write(i2c_address, LTC2944_ACCUM_CHARGE_MSB_REG, 0xff); ack |= LTC2944_write(i2c_address, LTC2944_ACCUM_CHARGE_LSB_REG, 0xff); return(ack); } 2.调用方法及测试代码

编写测试代码如下。注意我的Rsense=20mΩ,M的值保持为默认值4096我没有修改它。

#include "Wire.h" #include "LTC2944.h" I2CLTC2944 objI2CLTC2944(&Wire1); const float resistor = .020; //我的Rsense是20毫欧的 void setup() { Serial.begin(115200); pinMode(14,OUTPUT); digitalWrite(14,HIGH);//打开外围设备供电,用不到就删掉 uint8_t data; uint16_t data16; float voltage; int8_t reply; Wire1.begin(41,42);//改成你自己的I2C总线引脚 delay(1000); objI2CLTC2944.LTC2944_set_shutdown(I2C_ADDRESS_LTC2944,LTC2944_SHUTDOWN_MODE_UNDO);//undoshutdown,使芯片工作 objI2CLTC2944.LTC2944_set_mode(I2C_ADDRESS_LTC2944,LTC2944_AUTOMATIC_MODE);//设置为自动模式 reply=objI2CLTC2944.LTC2944_read(I2C_ADDRESS_LTC2944,LTC2944_CONTROL_REG,&data); Serial.printf("LTC2944 read data= 0x%02X\n", data); delay(1000); objI2CLTC2944.LTC2944_set_mode(I2C_ADDRESS_LTC2944,LTC2944_SCAN_MODE); reply=objI2CLTC2944.LTC2944_read(I2C_ADDRESS_LTC2944,LTC2944_CONTROL_REG,&data); Serial.printf("LTC2944 read data= 0x%02X\n", data); delay(1000); objI2CLTC2944.LTC2944_set_mode(I2C_ADDRESS_LTC2944,LTC2944_MANUAL_MODE); reply=objI2CLTC2944.LTC2944_read(I2C_ADDRESS_LTC2944,LTC2944_CONTROL_REG,&data); Serial.printf("LTC2944 read data= 0x%02X\n", data); delay(1000); objI2CLTC2944.LTC2944_set_mode(I2C_ADDRESS_LTC2944,LTC2944_SLEEP_MODE); reply=objI2CLTC2944.LTC2944_read(I2C_ADDRESS_LTC2944,LTC2944_CONTROL_REG,&data); Serial.printf("LTC2944 read data= 0x%02X\n", data); delay(1000); objI2CLTC2944.LTC2944_set_mode(I2C_ADDRESS_LTC2944,LTC2944_AUTOMATIC_MODE); reply=objI2CLTC2944.LTC2944_read(I2C_ADDRESS_LTC2944,LTC2944_CONTROL_REG,&data); Serial.printf("LTC2944 read data= 0x%02X\n", data); delay(1000); objI2CLTC2944.LTC2944_set_mode(I2C_ADDRESS_LTC2944,LTC2944_AUTOMATIC_MODE); reply=objI2CLTC2944.LTC2944_read(I2C_ADDRESS_LTC2944,LTC2944_CONTROL_REG,&data); Serial.printf("LTC2944 read data= 0x%02X\n", data); delay(1000); //objI2CLTC2944.LTC2944_set_ACR_full(I2C_ADDRESS_LTC2944);电池充满状态下认为设置ACR为0xFFFF,便于实际计算电池电量 } void loop() { byte error, address; int nDevices = 0; uint8_t data; uint16_t data16; float voltage; float current; int8_t reply; objI2CLTC2944.LTC2944_read_16_bits(I2C_ADDRESS_LTC2944,LTC2944_VOLTAGE_MSB_REG,&data16); Serial.printf("LTC2944 read data= 0x%04X\n", data16); voltage=objI2CLTC2944.LTC2944_code_to_voltage(data16); Serial.print("read voltage=");Serial.println(voltage); delay(1000); objI2CLTC2944.LTC2944_read_16_bits(I2C_ADDRESS_LTC2944,LTC2944_CURRENT_MSB_REG,&data16); Serial.printf("LTC2944 read data= 0x%04X\n", data16); current=objI2CLTC2944.LTC2944_code_to_current(data16,resistor)*1000; Serial.print("read current=");Serial.print(current);Serial.println("mA"); delay(1000); /* //扫描I2C总线看芯片在总线上不 Serial.println("Scanning for I2C devices ..."); for(address = 0x01; address < 0x7f; address++){ Wire1.beginTransmission(address); error = Wire1.endTransmission(); if (error == 0){ Serial.printf("I2C device found at address 0x%02X\n", address); nDevices++; } else if(error != 2){ Serial.printf("Error %d at address 0x%02X\n", error, address); } } if (nDevices == 0){ Serial.println("No I2C devices found"); } */ }

下载后CPU从串口持续输出电流和电压测量值。

3.电路部分

LTC2944的电路比较简单,把充电部分的电路也一并贴上。左边是充电模块,右边是LTC2944

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数嵌入式工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!

img

img

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以+V:Vip1104z获取!!! (备注:嵌入式)

img 最后

资料整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~

你的支持,我的动力;祝各位前程似锦,offer不断,步步高升!!!

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!*

[外链图片转存中…(img-S4GgOAPu-1712297639734)]

[外链图片转存中…(img-2h3u1bTN-1712297639735)]

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以+V:Vip1104z获取!!! (备注:嵌入式)

img 最后

资料整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~

你的支持,我的动力;祝各位前程似锦,offer不断,步步高升!!!

更多资料点击此处获qu!!



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有