世纪电源网社区logo
社区
Datasheet
标题
返回顶部
原创

【世健ADI技术分享】宽压超低功耗电池电量计

[复制链接]
查看: 1365 |回复: 2
1
haoli
  • haoli
  • 离线
  • LV2
  • 本网技师
  • 积分:196
  • |
  • 主题:1
  • |
  • 帖子:4
积分:196
LV2
本网技师
  • 2023-8-24 16:45:46
分享人:haoli
所在行业:智能家居,服务机器人,配送机器人
应用领域:电池电量计
应用案例名称:超低功耗电池电量计
ADI电源产品类型(请选择):电池管理
ADI电源产品型号: LTC2959
LTC2959是一款超低功耗电池电量计,可精确测量电荷、电压、电流和温度。LTC2959具有宽输入电压范围和低工作电流,使其适合许多应用,包括长时间工作的占空比系统。

精密库伦计数器通过在电池电流路径中任何点上连接的外部检测电阻检测电流。16位ADC可配置为在单次、占空比(1S/52s)或连续模式(2.5kS/s)下测量电压、电流、温度和/或辅助输入。测量结果存储在可通过板载I2C/SMBus接口访问的内部寄存器中。

LTC2959具有可编程的高低阈值和最小值/最大值跟踪寄存器。如果超过阈值,该器件会在内部状态寄存器中设置标志并使用SMBus警报协议通知警报(如这样配置)。

应用场景主要有:
远程传感器
能量采集系统
低功耗手持式产品
电源工具

优势和特点:
工作电源电流 <1.0μA
1.8V 至 60V 的电源电压
用于低端或高端检测的 0V 至 60V 检测电压
快速 16 位 ADC 测量电压、电流和温度
1% 电压、电流和充电精度
无需石英或其他时间参考
可编程死区可防止电荷漂移
包括电池电压看门狗
包括精密温度传感器
可编程警报和最小/最大跟踪寄存器
用于传感器读数检测的辅助 ADC 输入
I2C/SMBus 接口
采用小型 10 引脚 3mm × 2mm DFN 封装


LTC2959是一款超低功耗电池电量计,有着很宽的工作电压,从1.8V 至 60V的输入电源电压范围,让它足以满足从单节锂电池到多节锂电池甚至多个铅酸电池串联的应用场景,也使用它可以应用于12V 和24V的电池供电电压的场景。

应用电路简单

封装小巧,采用小型 10 引脚 3mm × 2mm DFN 封装,占用面积小

uA级功耗,超低功耗,非常适合电池常供电应用



库仑检测受电池电压和温度影响的偏差如下图所示

工作电流受 电流检测分压电压值及电池电压,工作温度的影响如下

检测误差受温度影响如下

从上面的图表可以得知,芯片在不同电池电压及工作温度变化的情况下,都能保持较低的工作电流和较低的检测误差

电路板布局简单清晰


LTC2959R 库仑计数器的32 位累积电荷寄存器(ACR) 的固定 LSB(最小计数值) 为 533nAh,这使它可容纳各种各样的电池;最大2289Ah电池容量计数足够容纳大多数大型电池,而且即使是10mAh的满量程充电也可以达到远低于0.01%的计数精度。






收藏收藏
haoli
  • haoli
  • 离线
  • LV2
  • 本网技师
  • 积分:196
  • |
  • 主题:1
  • |
  • 帖子:4
积分:196
LV2
本网技师
  • 2023-8-31 11:02:00
  • 倒数2
 
接上      因为LTC2959是需要进行通信的,在网上找了一圈该芯片的配置程序和读写程序,没找到。然后因为LTC2944在功能上跟LTC2959是相近的,但LTC2959是LTC2944的升级版本,AD检测从14位升级为16位AD, 库仑计数位数也从16位升级至32位计数,及功耗上都有明显的升级改善。遂找到了一个LTC2944的arduino程序,对比LTC2959的寄存器表,做些修改会容易上手一些。     这里上传一下LTC2944与LTC2959的芯片datasheet方便大家下载对比
    LTC2944.pdf (269.33 KB, 下载次数: 1)
    LTC2959.pdf (835.79 KB, 下载次数: 0)
     从下方的寄存表可以看出两个芯片的寄存器区别
     
        上图为LTC2944的寄存器表
       LTC2944的寄存器数量明显比LTC2959少了几个
      
     
          上图为LTC2959的寄存器表
      这里上传 LTC2944的arduino程序,希望对大家有一定帮助
       LTC2944-Arduino-Library-master.zip (6.49 KB, 下载次数: 2)
      下面是LTC2944 的头文件
  1. /*
  2.         Arduino Library for LTC2944
  3. */

  4. #ifndef LTC2944_H
  5. #define LTC2944_H

  6. #include "Arduino.h"
  7. #include "Wire.h"

  8. #define LTC2944_ADDRESS                        0x64

  9. /* Register Map */

  10. #define REG_A_STATUS                        0x00 // Status (R)
  11. #define REG_B_CONTROL                        0x01 // Control (R/W)
  12. #define REG_C_ACC_CHG_MSB                0x02 // Accumulated Charge MSB (R/W)
  13. #define REG_D_ACC_CHG_LSB                0x03 // Accumulated Charge LSB (R/W)
  14. #define REG_E_CHG_THR_H_MSB                0x04 // Charge Threshold High MSB (R/W)
  15. #define REG_F_CHG_THR_H_LSB                0x05 // Charge Threshold High LSB (R/W)
  16. #define REG_G_CHG_THR_L_MSB                0x06 // Charge Threshold Low MSB (R/W)
  17. #define REG_H_CHG_THR_L_LSB                0x07 // Charge Threshold Low LSB (R/W)
  18. #define REG_I_VOLTAGE_MSB                0x08 // Voltage MSB (R)
  19. #define REG_J_VOLTAGE_LSB                0x09 // Voltage LSB (R)
  20. #define REG_K_VOLTAGE_THR_H_MSB        0x0A // Voltage Threshold High MSB (R/W)
  21. #define REG_L_VOLTAGE_THR_H_LSB        0x0B // Voltage Threshold High LSB (R/W)
  22. #define REG_M_VOLTAGE_THR_L_MSB        0x0C // Voltage Threshold Low MSB (R/W)
  23. #define REG_N_VOLTAGE_THR_L_LSB        0x0D // Voltage Threshold Low LSB (R/W)
  24. #define REG_O_CURRENT_MSB                0x0E // Current MSB (R)
  25. #define REG_P_CURRENT_LSB                0x0F // Current LSB (R)
  26. #define REG_Q_CURRENT_THR_H_MSB        0x10 // Current Threshold High MSB (R/W)
  27. #define REG_R_CURRENT_THR_H_LSB        0x11 // Current Threshold High LSB (R/W)
  28. #define REG_S_CURRENT_THR_L_MSB        0x12 // Current Threshold Low MSB (R/W)
  29. #define REG_T_CURRENT_THR_L_LSB        0x13 // Current Threshold Low LSB (R/W)
  30. #define REG_U_TEMP_MSB                        0x14 // Temperature MSB (R)
  31. #define REG_V_TEMP_LSB                        0x15 // Temperature LSB (R)
  32. #define REG_W_TEMP_THR_H                0x16 // Temperature Threshold High (R/W)
  33. #define REG_X_TEMP_THR_L                0x17 // Temperature Threshold Low (R/W)

  34. /* Status Register (A) */

  35. #define A_CHIP_ID_OFFSET                7 // Default 0
  36. #define CHIP_ID_LTC2944                        0
  37. #define CHIP_ID_LTC2943                        1
  38. // Bits below are cleared after register is read
  39. #define A_CURRENT_ALERT_OFFSET        6 // Default 0
  40. #define A_ACC_CHG_OF_UF_OFFSET        5 // Default 0
  41. #define A_TEMP_ALERT_OFFSET                4 // Default 0
  42. #define A_CHG_ALERT_H_OFFSET        3 // Default 0
  43. #define A_CHG_ALERT_L_OFFSET        2 // Default 0
  44. #define A_VOLTAGE_ALERT_OFFSET        1 // Default 0
  45. #define A_UV_LOCK_ALERT_OFFSET        0

  46. /* Control Register (B) */

  47. #define B_ADC_MODE_OFFSET                6 // Default [00]
  48. #define ADC_MODE_MASK                        0b00111111
  49. #define ADC_MODE_AUTO                        0b11
  50. #define ADC_MODE_SCAN                        0b10
  51. #define ADC_MODE_MANUAL                        0b01
  52. #define ADC_MODE_SLEEP                        0b00

  53. #define B_PRESCALER_M_OFFSET        3 // Default [111], M = 2^(4 * B[5] + 2 * B[4] + B[3])
  54. #define PRESCALER_M_MASK                0b11000111

  55. #define B_ALCC_CONFIG_OFFSET        1 // Default [10]
  56. #define ALCC_CONFIG_MASK                0b11111001
  57. #define ALCC_MODE_ALERT                        0b10
  58. #define ALCC_MODE_CHG_COMPLETE        0b01
  59. #define ALCC_MODE_DISABLED                0b00
  60. #define ALCC_MODE_NOT_ALLOWED        0b11

  61. #define SHUTDOWN_MASK                        0b11111110

  62. class LTC2944 {
  63.         public:
  64.                 LTC2944(uint8_t rSense = 50);
  65.                 bool begin(TwoWire &wirePort = Wire);
  66.                 void startMeasurement();
  67.                 void stopMeasurement();
  68.                 uint8_t getStatus();
  69.                 uint8_t findExponentOfPowerOfTwo(uint16_t value);
  70.                 uint16_t roundUpToPowerOfTwo(uint16_t value);
  71.                 void setPrescalerM(uint16_t m);
  72.                 void getPrescalerM();
  73.                 void setADCMode(uint8_t mode);
  74.                 void configureALCC(uint8_t mode);
  75.                 uint16_t getRawAccumulatedCharge();
  76.                 float getRemainingCapacity();
  77.                 float getVoltage(bool oneShot = true);
  78.                 float getTemperature(bool oneShot = true);
  79.                 float getCurrent(bool oneShot = true);
  80.                 void setBatteryCapacity(uint16_t mAh);
  81.                 void setBatteryToFull();
  82.                 void setRawAccumulatedCharge(uint16_t charge);
  83.                 void setChargeThresholds(uint16_t high, uint16_t low);
  84.                 void setVoltageThresholds(float high, float low);
  85.                 void setTemperatureThresholds(float high, float low);
  86.                 void setCurrentThresholds(float high, float low);
  87.                 //---
  88.                 uint16_t readWordFromRegisters(uint8_t msbAddress);
  89.                 bool writeWordToRegisters(uint8_t msbAddress, uint16_t value);
  90.                 uint8_t readByteFromRegister(uint8_t address);
  91.                 bool writeByteToRegister(uint8_t address, uint8_t value);
  92.         private:
  93.                 uint8_t _rSense;
  94.                 uint16_t _prescalerM;
  95.                 uint16_t _batteryCapacity;
  96.                 TwoWire *_i2cPort;
  97. };

  98. #endif
复制代码


      以下是读写程序
  1. /*
  2.         Arduino Library for LTC2944
  3. */

  4. #include "LTC2944.h"

  5. LTC2944::LTC2944(uint8_t rSense) {
  6.         _rSense = rSense;
  7.         _prescalerM = 0xFFFF;
  8.         _batteryCapacity = 22000; // Default value when M = 4096
  9. }

  10. bool LTC2944::begin(TwoWire &wirePort) {
  11.         // Wire.begin() should be called in the application code in advance
  12.         _i2cPort = &wirePort;

  13.         // Checks device ID
  14.         uint8_t chipID = getStatus() >> A_CHIP_ID_OFFSET;
  15.         if (chipID != CHIP_ID_LTC2944) {
  16.                 return false;
  17.         }

  18.         return true;
  19. }

  20. void LTC2944::startMeasurement() {
  21.         uint8_t value = readByteFromRegister(REG_B_CONTROL);
  22.         value &= SHUTDOWN_MASK;
  23.         writeByteToRegister(REG_B_CONTROL, value);
  24. }

  25. void LTC2944::stopMeasurement() {
  26.         uint8_t value = readByteFromRegister(REG_B_CONTROL);
  27.         value |= 1;
  28.         writeByteToRegister(REG_B_CONTROL, value);
  29. }

  30. uint8_t LTC2944::getStatus() {
  31.         return readByteFromRegister(REG_A_STATUS);
  32. }

  33. uint8_t LTC2944::findExponentOfPowerOfTwo(uint16_t value) { //返回对应B[5:3]的值
  34.         if (value > 1024) {
  35.                 return 6;
  36.         }

  37.         for (uint8_t i = 0; i < 6; i++) {
  38.                 if ((value >> (i * 2)) & 1) {
  39.                         return i;
  40.                 }
  41.         }
  42. }

  43. uint16_t LTC2944::roundUpToPowerOfTwo(uint16_t value) { //获取大于等于value的最小的2的幂
  44.         // Reference: https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
  45.         value--;
  46.         value |= value >> 1;
  47.         value |= value >> 2;
  48.         value |= value >> 4;
  49.         value |= value >> 8;
  50.         value++;
  51.         return value;
  52. }

  53. void LTC2944::setPrescalerM(uint16_t m) {
  54.         if (m < 1 || m > 4096) {
  55.                 return;
  56.         }

  57.         // Updates instance variable to avoid unnecessary access to register
  58.         _prescalerM = m;
  59.         m = findExponentOfPowerOfTwo(m);

  60.         uint8_t value = readByteFromRegister(REG_B_CONTROL);
  61.         value &= PRESCALER_M_MASK;
  62.         value |= (m << B_PRESCALER_M_OFFSET);
  63.         writeByteToRegister(REG_B_CONTROL, value);
  64. }

  65. void LTC2944::getPrescalerM() {
  66.         if (_prescalerM == 0xFFFF) {
  67.                 // Needs to obtain M from register B
  68.                 uint8_t value = readByteFromRegister(REG_B_CONTROL);
  69.                 value &= ~PRESCALER_M_MASK;
  70.                 _prescalerM = value >> B_PRESCALER_M_OFFSET;
  71.                 if (_prescalerM > 6) {
  72.                         _prescalerM = 6;
  73.                 }
  74.                 _prescalerM = 1 << (_prescalerM << 1);
  75.         }
  76. }

  77. void LTC2944::setADCMode(uint8_t mode) {
  78.         if (mode > 0b11) {
  79.                 return;
  80.         }

  81.         uint8_t value = readByteFromRegister(REG_B_CONTROL);
  82.         value &= ADC_MODE_MASK;
  83.         value |= (mode << B_ADC_MODE_OFFSET);
  84.         writeByteToRegister(REG_B_CONTROL, value);
  85. }

  86. void LTC2944::configureALCC(uint8_t mode) {
  87.         if (mode >= ALCC_MODE_NOT_ALLOWED) {
  88.                 return;
  89.         }

  90.         uint8_t value = readByteFromRegister(REG_B_CONTROL);
  91.         value &= ALCC_CONFIG_MASK;
  92.         value |= (mode << B_ALCC_CONFIG_OFFSET);
  93.         writeByteToRegister(REG_B_CONTROL, value);
  94. }

  95. uint16_t LTC2944::getRawAccumulatedCharge() {
  96.         return readWordFromRegisters(REG_C_ACC_CHG_MSB);
  97. }

  98. float LTC2944::getRemainingCapacity() { //?
  99.         getPrescalerM();
  100.         uint16_t acr = getRawAccumulatedCharge();
  101.         float unitRange = 0.34 * ((float) 50 / _rSense) * ((float) _prescalerM / 4096);
  102.         float chargeMAH = unitRange * (0xFFFF - acr);
  103.         return _batteryCapacity - chargeMAH; // mAh
  104. }

  105. float LTC2944::getVoltage(bool oneShot) {
  106.         if (oneShot) {
  107.                 setADCMode(ADC_MODE_MANUAL);
  108.                 delay(10);
  109.         }
  110.         uint16_t value = readWordFromRegisters(REG_I_VOLTAGE_MSB);
  111.         return 70.8 * ((float) value / 0xFFFF); // V
  112. }

  113. float LTC2944::getTemperature(bool oneShot) {
  114.         if (oneShot) {
  115.                 setADCMode(ADC_MODE_MANUAL);
  116.                 delay(10);
  117.         }
  118.         uint16_t value = readWordFromRegisters(REG_U_TEMP_MSB);
  119.         return 510 * ((float) value / 0xFFFF) - 273.15; // Celsius
  120. }

  121. float LTC2944::getCurrent(bool oneShot) {
  122.         if (oneShot) {
  123.                 setADCMode(ADC_MODE_MANUAL);
  124.                 delay(10);
  125.         }
  126.         uint16_t value = readWordFromRegisters(REG_O_CURRENT_MSB);
  127.         return ((float) value / 0x7FFF - 1) * 64 / _rSense; // A
  128. }

  129. void LTC2944::setBatteryCapacity(uint16_t mAh) {
  130.         _batteryCapacity = mAh;
  131.         uint32_t m = 4096 * ((float) mAh / (0x10000 * 0.34)) * ((float) _rSense / 50);
  132.         if (m > 4096) {
  133.                 m = 4096;
  134.         }
  135.         m = roundUpToPowerOfTwo((uint16_t) m);
  136.         setPrescalerM(m);
  137. }

  138. void LTC2944::setBatteryToFull() {
  139.         writeWordToRegisters(REG_C_ACC_CHG_MSB, 0xFFFF);
  140. }

  141. void LTC2944::setRawAccumulatedCharge(uint16_t charge) {
  142.         writeWordToRegisters(REG_C_ACC_CHG_MSB, charge);
  143. }

  144. void LTC2944::setChargeThresholds(uint16_t high, uint16_t low) {
  145.         writeWordToRegisters(REG_E_CHG_THR_H_MSB, high);
  146.         writeWordToRegisters(REG_G_CHG_THR_L_MSB, low);
  147. }

  148. void LTC2944::setVoltageThresholds(float high, float low) {
  149.         uint32_t _high = high * 0xFFFF / 70.8;
  150.         uint32_t _low = low * 0xFFFF / 70.8;
  151.         if(_high > 0xFFFF){
  152.                 _high = 0xFFFF;
  153.         }else if(_high < 0){
  154.                 _high = 0;
  155.         }
  156.         if(_low > 0xFFFF){
  157.                 _low = 0xFFFF;
  158.         }else if(_low < 0){
  159.                 _low = 0;
  160.         }
  161.         writeWordToRegisters(REG_K_VOLTAGE_THR_H_MSB, (uint16_t) _high);
  162.         writeWordToRegisters(REG_M_VOLTAGE_THR_L_MSB, (uint16_t) _low);
  163. }

  164. void LTC2944::setTemperatureThresholds(float high, float low) {
  165.         uint32_t _high = (high + 273.15) * 0xFFFF / 510;
  166.         uint32_t _low = (low + 273.15) * 0xFFFF / 510;
  167.         _high >>= 8;
  168.         _low >>= 8;
  169.         if(_high >= 0xFF){
  170.                 _high = 0xFE;
  171.         }else if(_high < 0){
  172.                 _high = 0;
  173.         }
  174.         if(_low > 0xFF){
  175.                 _low = 0xFF;
  176.         }else if(_low <= 0){
  177.                 _low = 1;
  178.         }
  179.         writeByteToRegister(REG_W_TEMP_THR_H, (uint8_t) _high);
  180.         writeByteToRegister(REG_X_TEMP_THR_L, (uint8_t) _low);
  181. }

  182. void LTC2944::setCurrentThresholds(float high, float low) {
  183.         uint32_t _high = (high * _rSense / 64 + 1 ) * 0x7FFF;
  184.         uint32_t _low = (low * _rSense / 64 + 1 ) * 0x7FFF;
  185.         if(_high > 0xFFFF){
  186.                 _high = 0xFFFF;
  187.         }else if(_high < 0){
  188.                 _high = 0;
  189.         }
  190.         if(_low > 0xFFFF){
  191.                 _low = 0xFFFF;
  192.         }else if(_low < 0){
  193.                 _low = 0;
  194.         }
  195.         writeWordToRegisters(REG_Q_CURRENT_THR_H_MSB, (uint16_t) _high);
  196.         writeWordToRegisters(REG_S_CURRENT_THR_L_MSB, (uint16_t) _low);
  197. }

  198. //---

  199. uint16_t LTC2944::readWordFromRegisters(uint8_t msbAddress) {
  200.         uint16_t value = 0;
  201.         uint8_t msb = 0;
  202.         uint8_t lsb = 0;

  203.         _i2cPort->beginTransmission(LTC2944_ADDRESS);
  204.         _i2cPort->write(msbAddress);
  205.         _i2cPort->endTransmission(false);

  206.         _i2cPort->requestFrom(LTC2944_ADDRESS, 2);
  207.         msb = _i2cPort->read();
  208.         lsb = _i2cPort->read();
  209.         _i2cPort->endTransmission();
  210.         value = (msb << 8) | lsb;

  211.         return value;
  212. }

  213. bool LTC2944::writeWordToRegisters(uint8_t msbAddress, uint16_t value) {
  214.         _i2cPort->beginTransmission(LTC2944_ADDRESS);
  215.         _i2cPort->write(msbAddress);
  216.         _i2cPort->write((uint8_t) (value >> 8));
  217.         _i2cPort->write((uint8_t) value);
  218.         return (_i2cPort->endTransmission() == 0);
  219. }

  220. uint8_t LTC2944::readByteFromRegister(uint8_t address) {
  221.         uint8_t value = 0;

  222.         _i2cPort->beginTransmission(LTC2944_ADDRESS);
  223.         _i2cPort->write(address);
  224.         _i2cPort->endTransmission(false);

  225.         _i2cPort->requestFrom(LTC2944_ADDRESS, 1);
  226.         value = _i2cPort->read();
  227.         _i2cPort->endTransmission();

  228.         return value;
  229. }

  230. bool LTC2944::writeByteToRegister(uint8_t address, uint8_t value) {
  231.         _i2cPort->beginTransmission(LTC2944_ADDRESS);
  232.         _i2cPort->write(address);
  233.         _i2cPort->write(value);
  234.         return (_i2cPort->endTransmission() == 0);
  235. }
复制代码


       虽说不能直接用,但是参考意义还是有的
      在mouser 以及 digikey上搜索了下LTC2959芯片,可能是因为这个芯片还刚出来不久,mouser上无货,digikey上的价格也是高得有些离谱,一片70+的价格,所以还没有买芯片进行实际测试,倒是在某宝上找到有LTC2944的模块,只要40+,想着或许可以先用来测试,等LTC2959大量出货价格降下来后,芯片直接替换,修改程序即可进行测试了。
        从datasheet里面的版本更新说明可以看到文档是22年12月更新的A版,所以还没有大量铺货,静待大批量出货后大家能用上这么好的片子。                        

编辑原因:排版错乱
haoli
  • haoli
  • 离线
  • LV2
  • 本网技师
  • 积分:196
  • |
  • 主题:1
  • |
  • 帖子:4
积分:196
LV2
本网技师
最新回复
  • 2023-8-31 11:32:00
  • 倒数1
 
另外,这里也上传一个LTC2943的程序,希望能帮助到大家
Power-monitor-LTC2943-master.zip (32.82 KB, 下载次数: 0)
热门技术、经典电源设计资源推荐

世纪电源网总部

地 址:天津市南开区黄河道大通大厦8层

电 话:400-022-5587

传 真:(022)27690960

邮 编:300110

E-mail:21dy#21dianyuan.com(#换成@)

世纪电源网分部

广 东:(0755)82437996 /(138 2356 2357)

北 京:(010)69525295 /(15901552591)

上 海:(021)24200688 /(13585599008)

香 港:HK(852)92121212

China(86)15220029145

网站简介 | 网站帮助 | 意见反馈 | 联系我们 | 广告服务 | 法律声明 | 友情链接 | 清除Cookie | 小黑屋 | 不良信息举报 | 网站举报

Copyright 2008-2024 21dianyuan.com All Rights Reserved    备案许可证号为:津ICP备10002348号-2   津公网安备 12010402000296号