mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
drivers/ltc4150: Allow tracking last minute charge
Implemented an example `ltc4150_recorder_t` implementation as a proof of concept for the recorder API.
This commit is contained in:
parent
fa0d08a08b
commit
db0c66e07f
@ -185,7 +185,7 @@ typedef struct {
|
||||
* @brief `NULL` or a `NULL`-terminated array of data recorders
|
||||
* @pre If not `NULL`, the last element of the array must be `NULL`
|
||||
*/
|
||||
ltc4150_recorder_t **recorders;
|
||||
const ltc4150_recorder_t **recorders;
|
||||
/**
|
||||
* @brief `NULL` or an array of the user defined data for each recorder
|
||||
* @pre If @see ltc4150_params_t::recorders is not `NULL`, this must point
|
||||
@ -207,6 +207,35 @@ struct ltc4150_dev {
|
||||
uint32_t discharged; /**< # of pulses for discharging (POL=low) */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Data structure used by @ref ltc4150_last_minute
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t last_rotate_sec; /**< Time stamp of the last ring "rotation" */
|
||||
/**
|
||||
* @brief Pulses in charging direction recorded in the last minute
|
||||
*/
|
||||
uint16_t charged;
|
||||
/**
|
||||
* @brief Pulses in discharging direction recorded in the last minute
|
||||
*/
|
||||
uint16_t discharged;
|
||||
/**
|
||||
* @brief Ring-buffer to store charge information in 10 sec resolution
|
||||
*/
|
||||
uint8_t buf_charged[7];
|
||||
/**
|
||||
* @brief As above, but in discharging direction
|
||||
*/
|
||||
uint8_t buf_discharged[7];
|
||||
uint8_t ring_pos; /**< Position in the ring buffer */
|
||||
} ltc4150_last_minute_data_t;
|
||||
|
||||
/**
|
||||
* @brief Records the charge transferred within the last minute using
|
||||
*/
|
||||
extern const ltc4150_recorder_t ltc4150_last_minute;
|
||||
|
||||
/**
|
||||
* @brief Initialize the LTC4150 driver
|
||||
*
|
||||
@ -275,6 +304,42 @@ int ltc4150_charge(ltc4150_dev_t *dev, uint32_t *charged, uint32_t *discharged);
|
||||
*/
|
||||
int ltc4150_avg_current(ltc4150_dev_t *dev, int16_t *dest);
|
||||
|
||||
/**
|
||||
* @brief Get the measured charge in the last minute
|
||||
*
|
||||
* @param dev The LTC4150 device to read data from
|
||||
* @param data The data recorded by @ref ltc4150_last_minute
|
||||
* @param[out] charged The charge transferred in charging direction
|
||||
* @param[out] discharged The charge transferred in discharging direction
|
||||
*
|
||||
* @retval 0 Success
|
||||
* @retval -EINVAL Called with an invalid argument
|
||||
*
|
||||
* @warning The returned data may be outdated up to ten seconds
|
||||
*
|
||||
* Passing `NULL` for `charged` or `discharged` is allowed, if only one
|
||||
* information is of interest.
|
||||
*/
|
||||
int ltc4150_last_minute_charge(ltc4150_dev_t *dev,
|
||||
ltc4150_last_minute_data_t *data,
|
||||
uint32_t *charged, uint32_t *discharged);
|
||||
|
||||
/**
|
||||
* @brief Convert the raw data (# pulses) acquired by the LTC4150 device to
|
||||
* charge information in millicoulomb
|
||||
* @note This function will make writing data recorders (see
|
||||
* @ref ltc4150_recorder_t) easier, but is not intended for end users
|
||||
*
|
||||
* @param dev LTC4150 device the data was received from
|
||||
* @param[out] charged Charge in charging direction is stored here
|
||||
* @param[out] discharged Charge in discharging direction is stored here
|
||||
* @param[in] raw_charged Number of pulses in charging direction
|
||||
* @param[in] raw_discharged Number of pulses in discharging direction
|
||||
*/
|
||||
void ltc4150_pulses2c(const ltc4150_dev_t *dev,
|
||||
uint32_t *charged, uint32_t *discharged,
|
||||
uint32_t raw_charged,
|
||||
uint32_t raw_discharged);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -139,20 +139,10 @@ int ltc4150_shutdown(ltc4150_dev_t *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert the raw data (# pulses) acquired by the LTC4150 device to
|
||||
* charge information in millicoulomb
|
||||
*
|
||||
* @param dev LTC4150 device the data was received from
|
||||
* @param[out] charged Charge in charging direction is stored here
|
||||
* @param[out] discharged Charge in discharging direction is stored here
|
||||
* @param[in] raw_charged Number of pulses in charging direction
|
||||
* @param[in] raw_discharged Number of pulses in discharging direction
|
||||
*/
|
||||
static void get_coulomb(const ltc4150_dev_t *dev,
|
||||
uint32_t *charged, uint32_t *discharged,
|
||||
uint32_t raw_charged,
|
||||
uint32_t raw_discharged)
|
||||
void ltc4150_pulses2c(const ltc4150_dev_t *dev,
|
||||
uint32_t *charged, uint32_t *discharged,
|
||||
uint32_t raw_charged,
|
||||
uint32_t raw_discharged)
|
||||
{
|
||||
uint64_t tmp;
|
||||
|
||||
@ -180,7 +170,7 @@ int ltc4150_charge(ltc4150_dev_t *dev, uint32_t *charged, uint32_t *discharged)
|
||||
}
|
||||
|
||||
gpio_irq_disable(dev->params.interrupt);
|
||||
get_coulomb(dev, charged, discharged, dev->charged, dev->discharged);
|
||||
ltc4150_pulses2c(dev, charged, discharged, dev->charged, dev->discharged);
|
||||
gpio_irq_enable(dev->params.interrupt);
|
||||
return 0;
|
||||
}
|
||||
|
95
drivers/ltc4150/ltc4150_last_minute.c
Normal file
95
drivers/ltc4150/ltc4150_last_minute.c
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2019 Otto-von-Guericke-Universität Magdeburg
|
||||
*
|
||||
* 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_ltc4150
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Track the drawn charged of the last minute
|
||||
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ltc4150.h"
|
||||
#include "xtimer.h"
|
||||
|
||||
static void init_or_reset(ltc4150_dev_t *dev, uint64_t now_usec, void *arg);
|
||||
static void pulse(ltc4150_dev_t *dev, ltc4150_dir_t dir, uint64_t now_usec,
|
||||
void *arg);
|
||||
|
||||
const ltc4150_recorder_t ltc4150_last_minute = {
|
||||
.reset = init_or_reset,
|
||||
.pulse = pulse,
|
||||
};
|
||||
|
||||
static void init_or_reset(ltc4150_dev_t *dev, uint64_t now_usec, void *arg)
|
||||
{
|
||||
(void)dev;
|
||||
ltc4150_last_minute_data_t *data = arg;
|
||||
|
||||
memset(data, 0, sizeof(ltc4150_last_minute_data_t));
|
||||
data->last_rotate_sec = now_usec / US_PER_SEC;
|
||||
}
|
||||
|
||||
static void update_ringbuffer(ltc4150_last_minute_data_t *data,
|
||||
uint64_t now_usec)
|
||||
{
|
||||
uint32_t now_sec = (now_usec / US_PER_SEC);
|
||||
|
||||
/* Note: This expression should be correct even when time overflows */
|
||||
while (now_sec - data->last_rotate_sec > 10) {
|
||||
data->last_rotate_sec += 10;
|
||||
data->charged += data->buf_charged[data->ring_pos];
|
||||
data->discharged += data->buf_discharged[data->ring_pos];
|
||||
if (++data->ring_pos >= sizeof(data->buf_charged)/sizeof(data->buf_charged[0])) {
|
||||
data->ring_pos = 0;
|
||||
}
|
||||
data->charged -= data->buf_charged[data->ring_pos];
|
||||
data->discharged -= data->buf_discharged[data->ring_pos];
|
||||
data->buf_charged[data->ring_pos] = 0;
|
||||
data->buf_discharged[data->ring_pos] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void pulse(ltc4150_dev_t *dev, ltc4150_dir_t dir, uint64_t now_usec,
|
||||
void *arg)
|
||||
{
|
||||
(void)dev;
|
||||
ltc4150_last_minute_data_t *data = arg;
|
||||
update_ringbuffer(data, now_usec);
|
||||
|
||||
switch (dir) {
|
||||
case LTC4150_CHARGE:
|
||||
data->buf_charged[data->ring_pos]++;
|
||||
break;
|
||||
default:
|
||||
case LTC4150_DISCHARGE:
|
||||
data->buf_discharged[data->ring_pos]++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int ltc4150_last_minute_charge(ltc4150_dev_t *dev,
|
||||
ltc4150_last_minute_data_t *d,
|
||||
uint32_t *charged, uint32_t *discharged)
|
||||
{
|
||||
if (!dev || !d) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
gpio_irq_disable(dev->params.interrupt);
|
||||
update_ringbuffer(d, xtimer_now_usec64());
|
||||
ltc4150_pulses2c(dev, charged, discharged, d->charged, d->discharged);
|
||||
gpio_irq_enable(dev->params.interrupt);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user