MAX17205(油量表)问题与COPY NV BLOCK[E904h]。

问题描述 投票:1回答:1

从过去的2个星期,我试图整合的一个 IC MAX17205 (燃油表) 在arduino mega 2560上。我可以读写寄存器,但每当我尝试复制内容的 影子RAM非易失性存储器CommStat.NVError 变得很高,如果没有,我不能修改 PackCfg 注册&获得 电压 对于 3S细胞 配置。请帮助我在这。我已经提供了下面的数据表和代码的链接。

MAX17205 数据表

max17205.inio


/**
   This is an example demonstrating the use of the max1720x library
   Print out the information to serial monitor at 115200 baud
*/

#include <Wire.h>
#include <max1720x.h>

max1720x gauge;

void setup()
{
  Serial.begin(9600); // Initializes serial port
  // Waits for serial port to connect. Needed for Leonardo only
  while ( !Serial ) ;
  gauge.reset();  // Resets MAX1720x
  delay(200);  // Waits for the initial measurements to be made
}

void loop()
{
  //   gauge.reset();
  if (gauge.getAvgCurrent() != 0) {
    Serial.println(gauge.getAvgCurrent());
    Wire.beginTransmission(MAX1720X_ADDR);
    Wire.write(MAX1720X_COMMAND_ADDR);
    Wire.write(0x04);
    Wire.write(0xE9);
    // delay(500);
    Wire.endTransmission();
    delay(400);
  }
  else{
  Serial.print("Capacity: ");
  Serial.print(gauge.getCapacity());  // Gets the battery's state of charge
  Serial.print(" mAh, TTE: ");
  Serial.print(gauge.getTTE());  // Gets the battery's state of charge
  Serial.print(" s, TTF: ");
  Serial.print(gauge.getTTF());  // Gets the battery's state of charge
  Serial.print(" s, Current: ");
  Serial.print(gauge.getCurrent());  // Gets the battery's state of charge
  Serial.print(" mA, Temperature: ");
  Serial.print(gauge.getAvgCurrent());  // Gets the battery's state of charge
  Serial.print(" mA, Temperature: ");
  Serial.print(gauge.getTemperature());  // Gets the battery's state of charge
  Serial.print(" degC, SOC: ");
  Serial.print(gauge.getSOC());  // Gets the battery's state of charge
  Serial.print("%, VCELL: ");
  Serial.print(gauge.getVoltage());  // Gets the battery voltage
  Serial.println('mV');

  delay(2000);
  }
}

MAX17205.c

/**
 * Name: max1720x
 * Author: Luka Mustafa - Institute IRNAS Race { [email protected] }
 * Version: 1.0
 * Description: A library for interfacing the MAXIM MAX17201/MAX17205
 *              Li+ fuel gauges.
 * Source: https://github.com/pAIgn10/max1720x
 * License: Copyright (c) 2017 Nick Lamprianidis 
 *          This library is licensed under the GPL license
 *          http://www.opensource.org/licenses/mit-license.php
 * Inspiration: The library is inspired by: https://github.com/pAIgn10/max1720x
 * Filename: max1720x.cpp
 * File description: Definitions and methods for the max1720x library
 */

#include "max1720x.h"

// Initializes variables and the Wire library
max1720x::max1720x() { 
    Wire.begin(); 
}

// Returns a measurement of the voltage of the connected LiIon Polymer battery
double max1720x::getVoltage()
{
    Wire.beginTransmission(MAX1720X_ADDR);
    Wire.write(MAX1720X_VBAT_ADDR);
    Wire.endTransmission(false);
    Wire.requestFrom(MAX1720X_ADDR, (int)2,HIGH); //send stop
    uint16_t combined = Wire.read()|(Wire.read()<<8); // LSB or-ed with MSB
    double voltage = combined; //combine registers
    return voltage*0.078125; // //calculate actual value and return in mV
}

double max1720x::getCurrent()
{
    Wire.beginTransmission(MAX1720X_ADDR);
    Wire.write(MAX1720X_CURENT_ADDR);
    Wire.endTransmission(false);
    Wire.requestFrom(MAX1720X_ADDR, (int)2,HIGH); //send stop
    int16_t combined = Wire.read()|(Wire.read()<<8); // LSB or-ed with MSB
    double current = (double)combined*0.0015625/0.01;
    return current;//calculate actual value as 0.0015625 mV/Ohm
}

double max1720x::getAvgCurrent()
{
    Wire.beginTransmission(MAX1720X_ADDR);
    Wire.write(0x61);
    Wire.endTransmission(false);
    Wire.requestFrom(MAX1720X_ADDR, (int)2,HIGH); //send stop
    int16_t combined = Wire.read()|(Wire.read()<<8); // LSB or-ed with MSB
    double current = (double)combined*0.0015625/0.01;
    return combined;//calculate actual value as 0.0015625 mV/Ohm
}

double max1720x::getTemperature()
{
    Wire.beginTransmission(MAX1720X_ADDR);
    Wire.write(MAX1720X_TEMP_ADDR);
    Wire.endTransmission(false);
    Wire.requestFrom(MAX1720X_ADDR, (int)2,HIGH); //send stop
    int16_t combined = Wire.read()|(Wire.read()<<8); // LSB or-ed with MSB
    double temperature = (double)combined/256;
    return temperature;
}

// Returns the relative state of charge of the connected LiIon Polymer battery
// as a percentage of the full capacity w/ resolution 1/256%
double max1720x::getSOC()
{
    Wire.beginTransmission(MAX1720X_ADDR);
    Wire.write(MAX1720X_REPSOC_ADDR);
    Wire.endTransmission(false);
    Wire.requestFrom(MAX1720X_ADDR, (int)2);
    uint16_t combined = Wire.read()|(Wire.read()<<8); // LSB or-ed with MSB
    double soc = combined; //combine registers
    return soc/256; //calculate actual value and return in %
}

// RepCap or reported capacity is a filtered version of the AvCap register that prevents large jumps in the reported value caused by changes in the application such as abrupt changes in temperature or load current. 
double max1720x::getCapacity()
{
    Wire.beginTransmission(MAX1720X_ADDR);
    Wire.write(MAX1720X_REPCAP_ADDR);
    Wire.endTransmission(false);
    Wire.requestFrom(MAX1720X_ADDR, (int)2);
    uint16_t combined = Wire.read()|(Wire.read()<<8); // LSB or-ed with MSB
    double capacity = (double)combined*0.005/0.01;
    return capacity;//calculate actual value as 0.005 mVh/Ohm
}

// The TTE register holds the estimated time to empty for the application under present temperature and load conditions 
double max1720x::getTTE()
{
    Wire.beginTransmission(MAX1720X_ADDR);
    Wire.write(MAX1720X_TTE_ADDR);
    Wire.endTransmission(false);
    Wire.requestFrom(MAX1720X_ADDR, (int)2);
    uint16_t combined = Wire.read()|(Wire.read()<<8); // LSB or-ed with MSB
    double capacity = (double)combined*5.625;
    return capacity;//calculate actual value as value*5.625s
}

// The TTF register holds the estimated time to full for the application under present conditions. 
double max1720x::getTTF()
{
    Wire.beginTransmission(MAX1720X_ADDR);
    Wire.write(MAX1720X_TTF_ADDR);
    Wire.endTransmission(false);
    Wire.requestFrom(MAX1720X_ADDR, (int)2);
    uint16_t combined = Wire.read()|(Wire.read()<<8); // LSB or-ed with MSB
    double capacity = (double)combined*5.625;
    return capacity;//calculate actual value as value*5.625s
}

// Status Register (000h) The Status register maintains all flags related to alert thresholds and battery insertion or removal.
uint16_t max1720x::getStatus()
{
    Wire.beginTransmission(MAX1720X_ADDR);
    Wire.write(MAX1720X_STATUS_ADDR);
    Wire.endTransmission(false);
    Wire.requestFrom(MAX1720X_ADDR, (int)2);
    uint16_t combined = Wire.read()|(Wire.read()<<8); // LSB or-ed with MSB
    return combined;
}

// Reset procedure
uint8_t max1720x::reset()
{
    Wire.beginTransmission(MAX1720X_ADDR);
    Wire.write(MAX1720X_COMMAND_ADDR);
    Wire.write(0x0f);
    Wire.write(0x00);
    Wire.endTransmission();
    delay(50);
    Wire.beginTransmission(MAX1720X_ADDR);
    Wire.write(MAX1720X_CONFIG2_ADDR);
    Wire.write(0x01);
    Wire.write(0x00);
    delay(50);
    Wire.beginTransmission(MAX1720X_ADDR);
    Wire.write(MAX1720X_nPackcfg);
    Wire.write(0x03);                   
    Wire.write(0x0A);
    Wire.endTransmission();
    delay(50);
    Wire.beginTransmission(MAX1720X_ADDR);
    Wire.write(0x61);
    Wire.write(0x00);                   
    Wire.write(0x00);
    Wire.endTransmission();
    delay(50);
    Wire.beginTransmission(MAX1720X_ADDR);
    Wire.write(MAX1720X_COMMAND_ADDR);
    Wire.write(0xE0);
    Wire.write(0x01);       
    Wire.endTransmission();
    delay(400);
    return;
}

MAX17205.h

/**
 * Name: max1720x
 * Author: Luka Mustafa - Institute IRNAS Race { [email protected] }
 * Version: 1.0
 * Description: A library for interfacing the MAXIM MAX17201/MAX17205
 *              Li+ fuel gauges.
 * Source: https://github.com/pAIgn10/LiFuelGauge
 * License: Copyright (c) 2017 Nick Lamprianidis 
 *          This library is licensed under the GPL license
 *          http://www.opensource.org/licenses/mit-license.php
 * Inspiration: The library is inspired by: https://github.com/pAIgn10/LiFuelGauge
 * Filename: max1720x.h
 * File description: Definitions and methods for the max1720x library
 */

#ifndef max1720x
#define max1720x_h

#include <Arduino.h>
#include <Wire.h>

// MAX1720X register addresses
const int MAX1720X_ADDR = 0x36;
const int MAX1720X_STATUS_ADDR = 0x00; // Contains alert status and chip status
const int MAX1720X_VCELL_ADDR = 0x09; // Lowest cell voltage of a pack, or the cell voltage for a single cell
const int MAX1720X_REPSOC_ADDR = 0x06; // Reported state of charge
const int MAX1720X_REPCAP_ADDR = 0x05; // Reported remaining capacity
const int MAX1720X_TEMP_ADDR = 0x08; // Temperature
const int MAX1720X_CURENT_ADDR = 0x0A; // Battery current
const int MAX1720X_AVG_CURENT_ADDR = 0x29; // Battery current
const int MAX1720X_TTE_ADDR = 0x11; // Time to empty
const int MAX1720X_TTF_ADDR = 0x20; // Time to full
const int MAX1720X_CAPACITY_ADDR = 0x10; // Full capacity estimation
const int MAX1720X_VBAT_ADDR = 0xDA; // Battery pack voltage
const int MAX1720X_AVCELL_ADDR = 0x17; // Battery cycles
const int MAX1720X_COMMAND_ADDR = 0x60; // Command register
const int MAX1720X_CONFIG2_ADDR = 0xbb; // Command register
const int MAX1720X_nPackcfg = 0xBD;
const int MAX1720X_WriteSlave = 0x6C;

// Class for interfacing the MAX1720X Li+ fuel gauges
class max1720x
{
public:
    max1720x();
    double getVoltage();
    double getSOC();
    double getTemperature();
    double getCurrent();
    double getAvgCurrent();
    double getCapacity();
    double getTTE();
    double getTTF();
    uint8_t reset();
private:
    uint16_t getStatus();
};

#endif  // max1720x

arduino avr arduino-uno i2c
1个回答
0
投票

如果它可能会帮助别人(我在这里通过谷歌搜索)。

我也一直在纠结于这个过程,但现在已经成功了。这是我的第一次I2C经验,所以我认为我的代码有很大的改进空间。

const int MAX1720x_nV = 0x0b;           // shifted 0x16
int a = 0;                              // to repeat NVCopy in case of failure

// Full Reset procedure
uint8_t max1720x::reset()
{
Wire.beginTransmission(MAX1720X_ADDR);
Wire.write(MAX1720X_COMMAND_ADDR);      // Hardware reset
Wire.write(0x0f);                       
Wire.write(0x00);
Wire.endTransmission(true);
delay(50);                          
Wire.beginTransmission(MAX1720X_ADDR);
Wire.write(MAX1720X_CONFIG2_ADDR);      // Fuel Gauge reset
Wire.write(0x01);
Wire.write(0x00);
return Wire.endTransmission(true);      // delay(at least 10) after this function
}

// copy the shadow RAM to the nonvolatile Block
void max1720x::copyNV()
{
Wire.beginTransmission(MAX1720x_nV);
Wire.write(0x8e);                                   // nODSCTh
Wire.write(0x00);                                   // 16 bit Value to write there
Wire.write(0x00);                                   // continued
Wire.endTransmission(false);

Wire.beginTransmission(MAX1720x_nV);
Wire.write(0x8f);                                   // nODSCCfg
Wire.write(0x00);                                   // 16 bit Value to write there
Wire.write(0x00);                                   // continued
Wire.endTransmission(false);
.
.                                                   // add more configuarations as desired
.
// start NVCopy procedure
Wire.beginTransmission(MAX1720X_ADDR);
Wire.write(0x61);                                   // clear commstat register
Wire.write(0x00);
Wire.write(0x00);
Wire.endTransmission(true);

Wire.beginTransmission(MAX1720X_ADDR);
Wire.write(0x60);                                   // write E904h to 60h as described in datasheet 
Wire.write(0x04);
Wire.write(0xe9);
Wire.endTransmission(true);
delay(1000);                                        // can probably be shorter
Wire.beginTransmission(MAX1720X_ADDR);              // read the CommStat.NVError
Wire.write(0x61);
Wire.endTransmission(false);
Wire.requestFrom(MAX1720x_nV, (int)2, true);
uint8_t combined = Wire.read()|(Wire.read()<<8); 
Wire.endTransmission(true);

Serial.println(combined);                           // not neccessary, just for me
Serial.println(a);
if ((combined != 0) && (a == 1)) {
    Serial.println(a);
    Serial.println("failed more than once");
    return;
    }
if ((combined != 0) && (a == 0)) {
    Serial.println("failed once");
    a++;
    max1720x::copyNV();
    }
else if (combined == 0) {                            // if NVError is empty, finish the routine
    Serial.println("CopyNV success!");
    delay(500);
    max1720x::reset();                                   // initiate a full reset
    delay(150);
    Wire.beginTransmission(MAX1720X_ADDR);               
    Wire.write(0xba);                                    // probably not neccessary
    Wire.write(0x00);                                    // something with hibernate mode?
    Wire.write(0x00);
    Wire.endTransmission(true);
    Wire.beginTransmission(MAX1720X_ADDR);
    Wire.write(MAX1720X_COMMAND_ADDR);
    Wire.write(0x80);                                    // probably not neccessary
    Wire.write(0x00);                                    // something with hibernate mode?
    Wire.endTransmission(true);
    max1720x::reset();                                   // initiate a full reset, probably not neccessary
    delay(500);
    return;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.