1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

drivers/lc709203f: Added support for the LC709203F Fuel Gauge

This commit is contained in:
steffen 2017-10-25 12:53:40 +02:00 committed by MichelRottleuthner
parent ca38df6960
commit 1d38c7d939
8 changed files with 1017 additions and 0 deletions

View File

@ -148,6 +148,9 @@ endif
ifneq (,$(filter apa102,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/apa102/include
endif
ifneq (,$(filter lc709203f, $(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/lc709203f/include
endif
ifneq (,$(filter hts221,$(USEMODULE)))
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/hts221/include
endif

388
drivers/include/lc709203f.h Normal file
View File

@ -0,0 +1,388 @@
/*
* Copyright (C) 2017 RWTH Aachen
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup drivers_lc709203f LC709203F
* @ingroup drivers_sensors
* @brief Device driver interface for the LC709203F Battery Fuel Gauge
* @{
*
* @file
* @brief Device driver interface for the LC709203F Battery Fuel Gauge
*
* @author Steffen Robertz <steffen.robertz@rwth-aachen.de>
* @author Josua Arndt <jarndt@ias.rwth-aachen.de>
*/
#ifndef LC709203F_H
#define LC709203F_H
#ifdef __cplusplus
extern "C" {
#endif
#include "periph/i2c.h"
#include "periph/gpio.h"
/**
* @brief Current direction modes
* @details For more details please see the datasheet (http://www.onsemi.com/pub/Collateral/LC709203F-D.PDF)
* @{
*/
typedef enum {
AUTO_MODE = 0x0,
CHARGE_MODE = 0x1,
DISCHARGE_MODE = 0xffff
} lc709203f_current_direction_t;
/** @} */
/**
* @brief Battery Profile Options
* @details For more details please see the datasheet (http://www.onsemi.com/pub/Collateral/LC709203F-D.PDF)
* @{
*/
typedef enum {
BAT_PROFILE_1 = 0,
BAT_PROFILE_2 = 1
} lc709203f_battery_profile_t;
/** @} */
/**
* @brief Power mode choices
* @details For more details please see the datasheet (http://www.onsemi.com/pub/Collateral/LC709203F-D.PDF)
* @{
*/
typedef enum {
OPERATIONAL_MODE = 1,
SLEEP_MODE = 2
} lc709203f_power_mode_t;
/** @} */
/**
* @brief Temperature obtaining mode options
* @details For more details please see the datasheet (http://www.onsemi.com/pub/Collateral/LC709203F-D.PDF)
* @{
*/
typedef enum {
I2C_MODE = 0,
THERMISTOR_MODE = 1
} lc709203f_temp_obtaining_mode_t;
/** @} */
/**
* @brief Typedef for the Callback function
* @details A function of this type will be called when an Interrupt is triggered on low RSOC or Voltage
* @param[in] arg Additional Arguments that will be passed to the function
*/
typedef void (*lc709203f_cb_t)(void *arg);
/**
* @brief Parameter struct for driver initialization
* @{
*/
typedef struct {
gpio_t alarm_pin; /**< Pin which is connected to the interrupt pin of the sensor */
i2c_t bus; /**< I2C bus to use */
uint8_t addr; /**< I2C Address of the fuel gauge */
} lc709203f_params_t;
/** @} */
enum {
LC709203F_OK = 0, /**< all went as expected */
LC709203F_NOI2C = -1, /**< error using the I2C bus */
LC709203F_CELL_TEMP_INVALID = -2 /**< Cell temp invalid */
};
/**
* @brief Device descriptor for the fuel gauge
* @details This struct will hold all information and configuration for the sensor
* @{
*/
typedef struct {
i2c_t bus; /**< I2C bus to use */
uint8_t addr; /**< I2C Address of fuel gauge */
uint8_t scale; /**< scale for returned values */
lc709203f_params_t params; /**< param struct with static settings etc*/
lc709203f_cb_t cb; /**< callback method*/
void *arg; /**< additional arguments for the callback method*/
} lc709203f_t;
/** @} */
/**
* @brief Register Addresses
* @details For more information on the registers and its funtions see the datasheet
* @{
*/
#define LC709203F_REG_CELL_VOLTAGE 0x09 /**< Register Cell Voltage */
#define LC709203F_REG_RSOC 0x0d /**< Register RSOC (Relative State of Charge) */
#define LC709203F_REG_ITE 0x0f /**< Register ITE (Indicator To Empty) */
#define LC709203F_REG_ID 0x11 /**< Register IC Version */
#define LC709203F_REG_CELL_TEMP 0x08 /**< Register Cell Temperature */
#define LC709203F_REG_STATUS 0x16 /**< Register Status Bit */
#define LC709203F_REG_POWER_MODE 0x15 /**< Register IC Power Mode */
#define LC709203F_REG_ALARM_VOLTAGE 0x14 /**< Register Alarm Low Cell Voltage */
#define LC709203F_REG_ALARM_RSOC 0x13 /**< Register Alarm Low RSOC */
#define LC709203F_REG_CHANGE_PARAMETER 0x12 /**< Register Change of the parameter */
#define LC709203F_REG_APT 0x0c /**< Register APT (Adjustment Pack Thermistor) */
#define LC709203F_REG_APA 0x0b /**< Register APA (Adjustment Pack Application) */
#define LC709203F_REG_CURRENT_DIRECTION 0x0a /**< Register Current Direction */
#define LC709203F_REG_THERMISTOR 0x06 /**< Register Thermistor B */
#define LC709203F_REG_BEFORE_RSOC 0x04 /**< Register Before RSOC */
#define LC709203F_REG_INITIAL_RSOC 0x07 /**< Register Initial RSOC */
/** @} */
#define LC709203F_CRC_POLYNOMIAL 0x07 /**< CRC Polynomial */
/**
* @brief initializes the sensor and i2c
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
* @param[in] *params pointer to lc709203f_param_t struct containing the interrupt pin and callback
*
* @return LC709203F_OK on a working initialization
* @return LC709203F_NOI2C on undefined i2c device given in periph_conf
*/
int lc709203f_init(lc709203f_t *dev, const lc709203f_params_t *params);
/**
* @brief reads battery voltage from Sensor
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
*
* @return voltage in mV
*/
int16_t lc709203f_get_voltage(const lc709203f_t *dev);
/**
* @brief reads battery state of charge from Sensor
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
*
* @return rsoc in %
*/
int16_t lc709203f_get_rsoc(const lc709203f_t *dev);
/**
* @brief reads battery indicator to empty from Sensor
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
*
* @return ite in 0.1%
*/
int16_t lc709203f_get_ite(const lc709203f_t *dev);
/**
* @brief reads Sensor id
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
*
* @return id value
*/
int16_t lc709203f_get_id(const lc709203f_t *dev);
/**
* @brief reads cell temperature from sensor
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
*
* @return temp in 0.1°C steps
*/
int16_t lc709203f_get_cell_temp(const lc709203f_t *dev);
/**
* @brief reads status bit register (Temperature obtaining mode)
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
*
* @return THERMISTOR_MODE Thermistor mode
* @return I2C_MODE I2C Mode
*/
lc709203f_temp_obtaining_mode_t lc709203f_get_status_bit(const lc709203f_t *dev);
/**
* @brief reads IC Power Mode register
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
*
* @return OPERATIONAL_MODE Operational Mode
* @return SLEEP_MODE Sleep mode
*/
lc709203f_power_mode_t lc709203f_get_power_mode(const lc709203f_t *dev);
/**
* @brief reads Alarm Low Cell Voltage Register
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
*
* @return 0 Disable
* @return Threshold value in 1mV steps
*/
int16_t lc709203f_get_alarm_low_voltage(const lc709203f_t *dev);
/**
* @brief reads Alarm Low RSOC Register
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
*
* @return 0 Disable
* @return Threshold value in %
*/
int16_t lc709203f_get_alarm_low_rsoc(const lc709203f_t *dev);
/**
* @brief reads Change of the Parameter register, Battery Profile selection
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
*
* @return Battery profile number (1 or 0)
*/
int16_t lc709203f_get_change_of_parameter(const lc709203f_t *dev);
/**
* @brief reads APT (Adjustment Pack Thermistor)
* value to adjust temperature measurement delay timing.
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
*
* @return value to adjust temperature measurement delay timing.
*/
int16_t lc709203f_get_apt(const lc709203f_t *dev);
/**
* @brief reads APA (Adjustment Pack Application) in 1mOhm steps
* value to adjust temperature measurement delay timing.
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
*
* @return parasitic impedance
*/
int16_t lc709203f_get_apa(const lc709203f_t *dev);
/**
* @brief reads Current Direction Register
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
*
* @return AUTO_MODE Auto mode
* @return CHARGE_MODE charge mode
* @return DISCHARGE_MODE Discharge mode
*/
lc709203f_current_direction_t lc709203f_get_current_direction(const lc709203f_t *dev);
/**
* @brief reads Thermistor-B register (Thermistor B constant to be measured)
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
*
* @return B Value in 1K steps
*/
int16_t lc709203f_get_thermistor_b(const lc709203f_t *dev);
/**
* @brief Executes RSOC initialization with sampled maximum voltage
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
*/
void lc709203f_set_rsoc_before(const lc709203f_t *dev);
/**
* @brief Sets B constant of the Thermistor
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
* @param[in] value Bconstant of thermistor
*/
void lc709203f_set_thermistor_b(const lc709203f_t *dev, const unsigned int value);
/**
* @brief Executes RSOC initialization
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
*/
void lc709203f_set_rsoc_initial(const lc709203f_t *dev);
/**
* @brief Sets cell temperature in I2C-mode
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
* @param[in] value temp in 0.1K 0xAAC=0°C
*
* @return LC709203F_CELL_TEMP_INVALID Invlid cell temp
*/
int8_t lc709203f_set_cell_temp(const lc709203f_t *dev, const unsigned int value);
/**
* @brief Sets current direction
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
* @param[in] direction current direction, AUTO_MODE, CHARGE_MODE, DISCHARGE_MODE
*/
void lc709203f_set_current_direction(const lc709203f_t *dev, const lc709203f_current_direction_t direction);
/**
* @brief Sets parasitic impedance (adjustment pack application)
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
* @param[in] value impedance in 1mOhm steps
*/
void lc709203f_set_apa(const lc709203f_t *dev, const uint8_t value);
/**
* @brief Sets value to adjust temperature measurement delay timing (adjusmtent pack thermistor)
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
* @param[in] value adjustment value
*/
void lc709203f_set_apt(const lc709203f_t *dev, const unsigned int value);
/**
* @brief Sets battery profile
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
* @param[in] value profile (enum) BAT_PROFILE_1 BAT_PROFILE_2
*/
void lc709203f_set_change_of_parameter(const lc709203f_t *dev, const lc709203f_battery_profile_t value);
/**
* @brief Sets threshold for low rsoc alert
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
* @param[in] value alert threshold (0-100%)
*/
void lc709203f_set_alarm_low_rsoc(const lc709203f_t *dev, const uint8_t value);
/**
* @brief Sets threshold for low cell voltage alert
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
* @param[in] value alert threshold in 1mV steps
*/
void lc709203f_set_alarm_low_cell_voltage(const lc709203f_t *dev, const unsigned int value);
/**
* @brief Sets power mode
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
* @param[in] value Power mode (enum) OPERATIONAL_MODE, SLEEP_MODE
*/
void lc709203f_set_power_mode(const lc709203f_t *dev, const lc709203f_power_mode_t value);
/**
* @brief Sets temperature obtaining method
*
* @param[in] *dev pointer to lc709203f_t struct containing the i2c device and the address
* @param[in] value method to be used (enum) I2C_MODE, THERMISTOR_MODE
*/
void lc709203f_set_status_bit(const lc709203f_t *dev, const lc709203f_temp_obtaining_mode_t value);
#ifdef __cplusplus
}
#endif
#endif /* LC709203F_H */
/** @} */

View File

@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,65 @@
/*
* Copyright 2017, RWTH Aachen. All rights reserved.
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_lc709203f
* @name Default parameters for the SHTC1 Temperature and humidity sensor
* @{
*
* @file
* @brief Default parameters for the SHTC1 Temperature and humidity sensor
*
* @author Steffen Robertz <steffen.robertz@rwth-aachen.de>
* @author Josua Arndt <jarndt@ias.rwth-aachen.de>
*/
#ifndef LC709203F_PARAMS_H
#define LC709203F_PARAMS_H
#ifdef __cplusplus
extern "C" {
#endif
#include "board.h" /* THIS INCLUDE IS MANDATORY */
#include "lc709203f.h"
/**
* @brief Default configuration parameters for LC709203F sensors
* @{
*/
#ifndef LC709203F_PARAMS_I2C
#define LC709203F_PARAMS_I2C (I2C_DEV(0))
#endif
#ifndef LC709203F_PARAMS_ADDR
#define LC709203F_PARAMS_ADDR (0xb)
#endif
#ifndef LC709203F_PARAMS_ALARM_PIN
#define LC709203F_PARAMS_ALARM_PIN GPIO_PIN(4, 6)
#endif
#ifndef LC709203F_PARAMS
#define LC709203F_PARAMS { .alarm_pin = LC709203F_PARAMS_ALARM_PIN, \
.bus = LC709203F_PARAMS_I2C, \
.addr = LC709203F_PARAMS_ADDR }
#endif
/** @} */
/**
* @brief Allocation of LC709203f configuration
*/
static const lc709203f_params_t params_default[] = {
#ifdef LC709203F_PARAMS_BOARD
LC709203F_PARAMS_BOARD
#else
LC709203F_PARAMS
#endif
};
#ifdef __cplusplus
}
#endif
#endif /* LC709203F_PARAMS_H */

View File

@ -0,0 +1,480 @@
/*
* Copyright (C) 2017 RWTH Aachen, Steffen Robertz, Josua Arndt
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_lc709203f
* @{
*
* @file
* @brief lc709203f battery fuel gauge device driver
*
* @author Steffen Robertz <steffen.robertz@rwth-aachen.de>
* @author Josua Arndt <jarndt@ias.rwth-aachen.de>
* @}
*/
#include "lc709203f.h"
#include "assert.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
/*
* does a crc check and returns the checksum
*/
static uint8_t _get_crc(uint8_t *rec_values, uint8_t len)
{
uint8_t crc = 0x00;
uint8_t current_byte;
uint8_t bit;
for (current_byte = 0; current_byte < len; current_byte++) {
crc ^= (rec_values[current_byte]);
for (bit = 8; bit > 0; bit--) {
if (crc & 0x80) {
crc = (crc << 1) ^ LC709203F_CRC_POLYNOMIAL;
}
else {
crc = (crc << 1);
}
}
}
return crc;
}
int lc709203f_init(lc709203f_t *dev, const lc709203f_params_t *params)
{
assert(dev && params);
dev->params = *params;
dev->bus = params->bus;
dev->addr = params->addr;
gpio_init_int(dev->params.alarm_pin, GPIO_IN, GPIO_FALLING, dev->cb, dev->arg);
i2c_acquire(dev->bus);
if (i2c_init_master(dev->bus, I2C_SPEED_FAST)) {
i2c_release(dev->bus);
return LC709203F_NOI2C;
}
i2c_release(dev->bus);
if (!lc709203f_get_id(dev)) {
return LC709203F_NOI2C;
}
return LC709203F_OK;
}
int16_t lc709203f_get_voltage(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_CELL_VOLTAGE, rec_buf, 3);
i2c_release(dev->bus);
if (control != 3) {
DEBUG("get_voltage(): Error reading or writing\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_CELL_VOLTAGE, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
int16_t lc709203f_get_rsoc(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_RSOC, rec_buf, 3);
i2c_release(dev->bus);
if (control != 3) {
DEBUG("get_rsoc(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_RSOC, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
int16_t lc709203f_get_ite(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_ITE, rec_buf, 3);
i2c_release(dev->bus);
if (control != 3) {
DEBUG("get_rsoc(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_ITE, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
int16_t lc709203f_get_id(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_ID, rec_buf, 3);
i2c_release(dev->bus);
if (control != 3) {
DEBUG("get_id(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_ID, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
int16_t lc709203f_get_cell_temp(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_CELL_TEMP, rec_buf, 3);
i2c_release(dev->bus);
if (control != 3) {
DEBUG("get_cell_temp(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_CELL_TEMP, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return ((((unsigned int)rec_buf[1] << 8) | rec_buf[0]) - 2731.5);
}
lc709203f_temp_obtaining_mode_t lc709203f_get_status_bit(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_STATUS, rec_buf, 3);
i2c_release(dev->bus);
if (control != 3) {
DEBUG("get_status_bit(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_STATUS, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
lc709203f_power_mode_t lc709203f_get_power_mode(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_POWER_MODE, rec_buf, 3);
i2c_release(dev->bus);
if (control != 3) {
DEBUG("get_power_mode(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_POWER_MODE, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
int16_t lc709203f_get_alarm_low_voltage(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_ALARM_VOLTAGE, rec_buf, 3);
i2c_release(dev->bus);
if (control != 3) {
DEBUG("get_alarm_low_voltage(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_ALARM_VOLTAGE, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
int16_t lc709203f_get_alarm_low_rsoc(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_ALARM_RSOC, rec_buf, 3);
i2c_release(dev->bus);
if (control != 3) {
DEBUG("get_alarm_low_rsoc(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_ALARM_RSOC, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
int16_t lc709203f_get_change_of_parameter(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_CHANGE_PARAMETER, rec_buf, 3);
i2c_release(dev->bus);
if (control != 3) {
DEBUG("get_change_of_parameter(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_CHANGE_PARAMETER, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
int16_t lc709203f_get_apt(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_APT, rec_buf, 3);
i2c_release(dev->bus);
if (control != 3) {
DEBUG("get_apt(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_APT, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
int16_t lc709203f_get_apa(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_APA, rec_buf, 3);
i2c_release(dev->bus);
if (control != 3) {
DEBUG("get_apa(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_APA, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
lc709203f_current_direction_t lc709203f_get_current_direction(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_CURRENT_DIRECTION, rec_buf, 3);
i2c_release(dev->bus);
if (control != 3) {
DEBUG("get_current_direction(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_CURRENT_DIRECTION, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
int16_t lc709203f_get_thermistor_b(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_THERMISTOR, rec_buf, 3);
i2c_release(dev->bus);
if (control != 3) {
DEBUG("get_thermistor_b(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_THERMISTOR, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
void lc709203f_set_rsoc_before(const lc709203f_t *dev)
{
assert(dev);
uint8_t crc_buf[4] = { dev->addr << 1, LC709203F_REG_BEFORE_RSOC, 0x55, 0xAA };
uint8_t send_buf[3] = { crc_buf[2], crc_buf[3], _get_crc(crc_buf, 4) };
i2c_acquire(dev->bus);
i2c_write_regs(dev->bus, dev->addr, crc_buf[1], send_buf, 3);
i2c_release(dev->bus);
}
void lc709203f_set_thermistor_b(const lc709203f_t *dev, const unsigned int value)
{
uint8_t crc_buf[4] = { dev->addr << 1, LC709203F_REG_THERMISTOR, value, value << 8 };
uint8_t send_buf[3] = { crc_buf[2], crc_buf[3], _get_crc(crc_buf, 4) };
i2c_acquire(dev->bus);
i2c_write_regs(dev->bus, dev->addr, crc_buf[1], send_buf, 3);
i2c_release(dev->bus);
}
void lc709203f_set_rsoc_initial(const lc709203f_t *dev)
{
assert(dev);
uint8_t crc_buf[4] = { dev->addr << 1, LC709203F_REG_INITIAL_RSOC, 0x55, 0xAA };
uint8_t send_buf[3] = { crc_buf[2], crc_buf[3], _get_crc(crc_buf, 4) };
i2c_acquire(dev->bus);
i2c_write_regs(dev->bus, dev->addr, crc_buf[1], send_buf, 3);
i2c_release(dev->bus);
}
int8_t lc709203f_set_cell_temp(const lc709203f_t *dev, const unsigned int value)
{
assert(dev);
if (!(value >= 0x9e4 && value <= 0xD04)) {
DEBUG("gauge_set_cell_temp(): temp outside of range \n");
return LC709203F_CELL_TEMP_INVALID;
}
uint8_t crc_buf[4] = { dev->addr << 1, LC709203F_REG_CELL_TEMP, value, value << 8 };
uint8_t send_buf[3] = { crc_buf[2], crc_buf[3], _get_crc(crc_buf, 4) };
i2c_acquire(dev->bus);
int8_t ret_val = i2c_write_regs(dev->bus, dev->addr, crc_buf[1], send_buf, 3);
i2c_release(dev->bus);
return ret_val;
}
void lc709203f_set_current_direction(const lc709203f_t *dev, const lc709203f_current_direction_t direction)
{
assert(dev);
uint8_t crc_buf[4] = { dev->addr << 1, LC709203F_REG_CURRENT_DIRECTION, (uint8_t)direction, (uint8_t)direction << 8 };
uint8_t send_buf[3] = { crc_buf[2], crc_buf[3], _get_crc(crc_buf, 4) };
i2c_acquire(dev->bus);
i2c_write_regs(dev->bus, dev->addr, crc_buf[1], send_buf, 3);
i2c_release(dev->bus);
}
void lc709203f_set_apa(const lc709203f_t *dev, const uint8_t value)
{
assert(dev);
uint8_t crc_buf[4] = { dev->addr << 1, LC709203F_REG_APA, value, 0 };
uint8_t send_buf[3] = { crc_buf[2], crc_buf[3], _get_crc(crc_buf, 4) };
i2c_acquire(dev->bus);
i2c_write_regs(dev->bus, dev->addr, crc_buf[1], send_buf, 3);
i2c_release(dev->bus);
}
void lc709203f_set_apt(const lc709203f_t *dev, const unsigned int value)
{
assert(dev);
uint8_t crc_buf[4] = { dev->addr << 1, LC709203F_REG_APT, value, value << 8 };
uint8_t send_buf[3] = { crc_buf[2], crc_buf[3], _get_crc(crc_buf, 4) };
i2c_acquire(dev->bus);
i2c_write_regs(dev->bus, dev->addr, crc_buf[1], send_buf, 3);
i2c_release(dev->bus);
}
void lc709203f_set_change_of_parameter(const lc709203f_t *dev, const lc709203f_battery_profile_t value)
{
assert(dev);
uint8_t crc_buf[4] = { dev->addr << 1, LC709203F_REG_CHANGE_PARAMETER, (uint8_t) value, (uint8_t) value << 8 };
uint8_t send_buf[3] = { crc_buf[2], crc_buf[3], _get_crc(crc_buf, 4) };
i2c_acquire(dev->bus);
i2c_write_regs(dev->bus, dev->addr, crc_buf[1], send_buf, 3);
i2c_release(dev->bus);
}
void lc709203f_set_alarm_low_rsoc(const lc709203f_t *dev, const uint8_t value)
{
assert(dev);
uint8_t crc_buf[4] = { dev->addr << 1, LC709203F_REG_ALARM_RSOC, value, 0 };
uint8_t send_buf[3] = { crc_buf[2], crc_buf[3], _get_crc(crc_buf, 4) };
i2c_acquire(dev->bus);
i2c_write_regs(dev->bus, dev->addr, crc_buf[1], send_buf, 3);
i2c_release(dev->bus);
}
void lc709203f_set_alarm_low_cell_voltage(const lc709203f_t *dev, const unsigned int value)
{
assert(dev);
uint8_t crc_buf[4] = { dev->addr << 1, LC709203F_REG_ALARM_VOLTAGE, value, value << 8 };
uint8_t send_buf[3] = { crc_buf[2], crc_buf[3], _get_crc(crc_buf, 4) };
i2c_acquire(dev->bus);
i2c_write_regs(dev->bus, dev->addr, crc_buf[1], send_buf, 3);
i2c_release(dev->bus);
}
void lc709203f_set_power_mode(const lc709203f_t *dev, const lc709203f_power_mode_t value)
{
assert(dev);
uint8_t crc_buf[4] = { dev->addr << 1, LC709203F_REG_POWER_MODE, (uint8_t) value, 0 };
uint8_t send_buf[3] = { crc_buf[2], crc_buf[3], _get_crc(crc_buf, 4) };
i2c_acquire(dev->bus);
i2c_write_regs(dev->bus, dev->addr, crc_buf[1], send_buf, 3);
i2c_release(dev->bus);
}
void lc709203f_set_status_bit(const lc709203f_t *dev, const lc709203f_temp_obtaining_mode_t value)
{
assert(dev);
uint8_t crc_buf[4] = { dev->addr << 1, LC709203F_REG_STATUS, (uint8_t) value, 0 };
uint8_t send_buf[3] = { crc_buf[2], crc_buf[3], _get_crc(crc_buf, 4) };
i2c_acquire(dev->bus);
i2c_write_regs(dev->bus, dev->addr, crc_buf[1], send_buf, 3);
i2c_release(dev->bus);
}

View File

@ -0,0 +1,13 @@
APPLICATION = driver_lc709203f
include ../Makefile.tests_common
FEATURES_REQUIRED += periph_i2c
FEATURES_REQUIRED += periph_gpio
USEMODULE += lc709203f
USEMODULE += xtimer
CFLAGS += -DDEVELHELP
include $(RIOTBASE)/Makefile.include

View File

@ -0,0 +1,7 @@
# About
This is a test application for the ON Semiconductor lc709203F Battery Fuel Gauge
# Usage
Just enter the `make BOARD=??? flash` command in the `tests/driver_lc709203F/` folder.
Make sure the `LC709203F_INT_PIN` is set in your boards periph_conf.h
# Results
The sensor will first test the low RSOC interrupt by setting the threshold limit to 100%. Therefor a low RSOC interrupt should be triggered and the message "ALARM low RSOC" should be printed to the terminal. After that all major measurements will be printed and refreshed every 5s.

View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2017 RWTH Aachen, Josua Arndt, Steffen Robertz
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup tests
* @{
* @file
* @brief test aplication for the LC709203F Battery fuel gauge by on semiconductors
*
* @author Steffen Robertz <steffen.robertz@rwth-aachen.de>
* @author Josua Arndt <jarndt@ias.rwth-aachen.de>
* @}
*/
#include <stdio.h>
#include "board.h"
#include "periph_conf.h"
#include "lc709203f.h"
#include "xtimer.h"
#include "lc709203f_params.h"
static void _gauge_cb(void *arg)
{
(void)arg;
printf("\n ALARM: Low RSOC \n");
}
int main(void)
{
puts("LC709203F Fuel Gauge test application");
lc709203f_t dev;
dev.cb = _gauge_cb;
dev.arg = NULL;
if (lc709203f_init(&dev, params_default) == LC709203F_OK) {
puts("The application will trigger an low_rsoc interrupt in 2s");
xtimer_sleep(2);
lc709203f_set_alarm_low_rsoc(&dev, 0);
lc709203f_set_alarm_low_rsoc(&dev, 100);
puts("Read low rsoc threshold level. Should be 100");
printf("Alarm Low RSOC level: %u \n", lc709203f_get_alarm_low_rsoc(&dev));
puts("Voltage, RSOC, ITE, ID and Cell temperature will be printed every 5s");
while (1) {
xtimer_sleep(5);
printf("Voltage in mV: %u \n", lc709203f_get_voltage(&dev));
printf("RSOC: %u \n", lc709203f_get_rsoc(&dev));
printf("Ite in 0.1: %u \n", lc709203f_get_ite(&dev));
printf("ID: %u \n", lc709203f_get_id(&dev));
printf("Cell Temp in 0.1C: %u \n", lc709203f_get_cell_temp(&dev));
}
}
else {
printf("Could not connect to fuel gauge\n");
}
return 0;
}