Merge pull request #11350 from maribu/ina2xx
drivers/ina220: Changed to comply with RIOT's driver design goals & SAUL adaption
This commit is contained in:
commit
16ee7aed32
@ -219,7 +219,11 @@ ifneq (,$(filter hts221,$(USEMODULE)))
|
||||
FEATURES_REQUIRED += periph_i2c
|
||||
endif
|
||||
|
||||
ifneq (,$(filter ina220,$(USEMODULE)))
|
||||
ifneq (,$(filter ina2%,$(USEMODULE)))
|
||||
USEMODULE += ina2xx
|
||||
endif
|
||||
|
||||
ifneq (,$(filter ina2xx,$(USEMODULE)))
|
||||
FEATURES_REQUIRED += periph_i2c
|
||||
endif
|
||||
|
||||
|
||||
@ -114,8 +114,8 @@ ifneq (,$(filter hts221,$(USEMODULE)))
|
||||
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/hts221/include
|
||||
endif
|
||||
|
||||
ifneq (,$(filter ina220,$(USEMODULE)))
|
||||
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/ina220/include
|
||||
ifneq (,$(filter ina2xx,$(USEMODULE)))
|
||||
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/ina2xx/include
|
||||
endif
|
||||
|
||||
ifneq (,$(filter ina3221,$(USEMODULE)))
|
||||
|
||||
@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Eistec AB
|
||||
*
|
||||
* 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_ina220
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Device driver implementation for Texas Instruments INA220 High
|
||||
* or Low Side, Bi-Directional CURRENT/POWER MONITOR with Two-Wire
|
||||
* Interface
|
||||
*
|
||||
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ina220.h"
|
||||
#include "ina220-regs.h"
|
||||
#include "periph/i2c.h"
|
||||
#include "byteorder.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
/** @brief Read one 16 bit register from a INA220 device and swap byte order, if necessary. */
|
||||
static int ina220_read_reg(const ina220_t *dev, uint8_t reg, uint16_t *out)
|
||||
{
|
||||
union {
|
||||
uint8_t c[2];
|
||||
uint16_t u16;
|
||||
} tmp = { .u16 = 0 };
|
||||
int status = 0;
|
||||
|
||||
status = i2c_read_regs(dev->i2c, dev->addr, reg, &tmp.c[0], 2, 0);
|
||||
|
||||
if (status < 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
*out = ntohs(tmp.u16);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Write one 16 bit register to a INA220 device and swap byte order, if necessary. */
|
||||
static int ina220_write_reg(const ina220_t *dev, uint8_t reg, uint16_t in)
|
||||
{
|
||||
union {
|
||||
uint8_t c[2];
|
||||
uint16_t u16;
|
||||
} tmp = { .u16 = 0 };
|
||||
int status = 0;
|
||||
|
||||
tmp.u16 = htons(in);
|
||||
|
||||
status = i2c_write_regs(dev->i2c, dev->addr, reg, &tmp.c[0], 2, 0);
|
||||
|
||||
if (status < 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int ina220_init(ina220_t *dev, i2c_t i2c, uint8_t address)
|
||||
{
|
||||
/* write device descriptor */
|
||||
dev->i2c = i2c;
|
||||
dev->addr = address;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ina220_set_calibration(const ina220_t *dev, uint16_t calibration)
|
||||
{
|
||||
return ina220_write_reg(dev, INA220_REG_CALIBRATION, calibration);
|
||||
}
|
||||
|
||||
int ina220_set_config(const ina220_t *dev, uint16_t config)
|
||||
{
|
||||
return ina220_write_reg(dev, INA220_REG_CONFIGURATION, config);
|
||||
}
|
||||
|
||||
int ina220_read_shunt(const ina220_t *dev, int16_t *voltage)
|
||||
{
|
||||
return ina220_read_reg(dev, INA220_REG_SHUNT_VOLTAGE, (uint16_t *)voltage);
|
||||
}
|
||||
|
||||
int ina220_read_bus(const ina220_t *dev, int16_t *voltage)
|
||||
{
|
||||
return ina220_read_reg(dev, INA220_REG_BUS_VOLTAGE, (uint16_t *)voltage);
|
||||
}
|
||||
|
||||
int ina220_read_current(const ina220_t *dev, int16_t *current)
|
||||
{
|
||||
return ina220_read_reg(dev, INA220_REG_CURRENT, (uint16_t *)current);
|
||||
}
|
||||
|
||||
int ina220_read_power(const ina220_t *dev, int16_t *power)
|
||||
{
|
||||
return ina220_read_reg(dev, INA220_REG_POWER, (uint16_t *)power);
|
||||
}
|
||||
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Eistec AB
|
||||
*
|
||||
* 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_ina220
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Register definitions for Texas Instruments INA220 High or Low
|
||||
* Side, Bi-Directional CURRENT/POWER MONITOR with Two-Wire
|
||||
* Interface
|
||||
*
|
||||
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
|
||||
*/
|
||||
|
||||
#ifndef INA220_REGS_H
|
||||
#define INA220_REGS_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief INA220 register addresses
|
||||
*
|
||||
* All registers in the INA220 are 16 bit wide and transmitted MSB first.
|
||||
*/
|
||||
typedef enum ina220_reg {
|
||||
INA220_REG_CONFIGURATION = 0x00, /**< Configuration register (read/write) */
|
||||
INA220_REG_SHUNT_VOLTAGE = 0x01, /**< Shunt voltage register (read only) */
|
||||
INA220_REG_BUS_VOLTAGE = 0x02, /**< Bus voltage register (read only) */
|
||||
INA220_REG_POWER = 0x03, /**< Power register (read only) */
|
||||
INA220_REG_CURRENT = 0x04, /**< Current register (read only) */
|
||||
INA220_REG_CALIBRATION = 0x05, /**< Calibration register (read/write) */
|
||||
} ina220_reg_t;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* INA220_REGS_H */
|
||||
/** @} */
|
||||
@ -1,3 +1,3 @@
|
||||
MODULE = ina220
|
||||
MODULE = ina2xx
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
||||
206
drivers/ina2xx/ina2xx.c
Normal file
206
drivers/ina2xx/ina2xx.c
Normal file
@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Eistec AB
|
||||
* 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_ina2xx
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Device driver implementation for Texas Instruments INA2XX High
|
||||
* or Low Side, Bi-Directional CURRENT/POWER MONITOR with Two-Wire
|
||||
* Interface
|
||||
*
|
||||
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
|
||||
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ina2xx.h"
|
||||
#include "ina2xx_defines.h"
|
||||
#include "periph/i2c.h"
|
||||
#include "byteorder.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
/*
|
||||
* The value in the current register is obtained by:
|
||||
*
|
||||
* I = (V_shunt * C) / 4096
|
||||
*
|
||||
* Where V_shunt is the value in the shunt voltage register and C is the
|
||||
* value programmed (upon driver initialization) into the calibration register
|
||||
*/
|
||||
#define CURRENT_QUOTIENT (4096LU)
|
||||
|
||||
/** @brief Read one 16 bit register from a INA2XX device and swap byte order, if necessary. */
|
||||
static int ina2xx_read_reg(const ina2xx_t *dev, uint8_t reg, uint16_t *out)
|
||||
{
|
||||
union {
|
||||
uint8_t c[2];
|
||||
uint16_t u16;
|
||||
} tmp;
|
||||
int status = 0;
|
||||
|
||||
status = i2c_read_regs(dev->params.i2c, dev->params.addr, reg, &tmp.c[0],
|
||||
2, 0);
|
||||
|
||||
if (status < 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
*out = ntohs(tmp.u16);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @brief Write one 16 bit register to a INA2XX device and swap byte order, if necessary. */
|
||||
static int ina2xx_write_reg(const ina2xx_t *dev, uint8_t reg, uint16_t in)
|
||||
{
|
||||
union {
|
||||
uint8_t c[2];
|
||||
uint16_t u16;
|
||||
} tmp;
|
||||
int status = 0;
|
||||
|
||||
tmp.u16 = htons(in);
|
||||
|
||||
status = i2c_write_regs(dev->params.i2c, dev->params.addr, reg, &tmp.c[0],
|
||||
2, 0);
|
||||
|
||||
if (status < 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int ina2xx_init(ina2xx_t *dev, const ina2xx_params_t *params)
|
||||
{
|
||||
uint16_t config;
|
||||
int status;
|
||||
if (!dev || !params) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev->params = *params;
|
||||
/* Reset device */
|
||||
status = ina2xx_write_reg(dev, INA2XX_REG_CONFIGURATION, INA2XX_RESET);
|
||||
if (status < 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Check if default config is preset after reset */
|
||||
status = ina2xx_read_reg(dev, INA2XX_REG_CONFIGURATION, &config);
|
||||
if (status < 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (config != INA2XX_DEFCONFIG) {
|
||||
DEBUG("[ina2xx]: Reset did't restore default config. Wrong device?\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
status = ina2xx_write_reg(dev, INA2XX_REG_CONFIGURATION, params->config);
|
||||
if (status < 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Set calibration register based on the shunt resistor.
|
||||
* ==> Current will be in mA
|
||||
* Multiply by 100
|
||||
* ==> Current will be in mA
|
||||
*/
|
||||
uint32_t calib = (100 * CURRENT_QUOTIENT) / params->rshunt_mohm;
|
||||
/* Divide by 2^i_range to reduce the resolution by factor 2^i_range */
|
||||
calib >>= params->i_range;
|
||||
|
||||
if (calib > UINT16_MAX) {
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
return ina2xx_write_reg(dev, INA2XX_REG_CALIBRATION, (uint16_t)calib);
|
||||
}
|
||||
|
||||
int ina2xx_read_shunt(const ina2xx_t *dev, int16_t *voltage)
|
||||
{
|
||||
return ina2xx_read_reg(dev, INA2XX_REG_SHUNT_VOLTAGE, (uint16_t *)voltage);
|
||||
}
|
||||
|
||||
int ina2xx_read_bus(const ina2xx_t *dev, uint16_t *voltage)
|
||||
{
|
||||
uint16_t tmp;
|
||||
int status = ina2xx_read_reg(dev, INA2XX_REG_BUS_VOLTAGE, &tmp);
|
||||
if (status < 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
/* The voltage given by bits 15-3 in steps of 4 mV
|
||||
* ==> Take bits 15-3, shift 3 bits right, multiply by 4
|
||||
* ==> Same as: Take bits 15-3, shift 3 bits right, shift 2 bits left
|
||||
* ==> Same as: Take bits 15-3, shift 1 bit right
|
||||
*/
|
||||
*voltage = (tmp & ~0x7) >> 1;
|
||||
|
||||
if (tmp & INA2XX_VBUS_OVF) {
|
||||
return -EDOM;
|
||||
}
|
||||
|
||||
return (tmp & INA2XX_VBUS_CNVR) ? 1 : 0;
|
||||
}
|
||||
|
||||
int ina2xx_read_current(const ina2xx_t *dev, int32_t *current)
|
||||
{
|
||||
int16_t tmp;
|
||||
int status = ina2xx_read_reg(dev, INA2XX_REG_CURRENT, (uint16_t *)&tmp);
|
||||
if (status < 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* The calibration is chosen according to the selected value in
|
||||
* dev->params.i_range, so that tmp * 2^i_range gives us the
|
||||
* current in E-05 A. We can thus simple use a left shift to convert
|
||||
* the current into E-05 A.
|
||||
*/
|
||||
*current = ((int32_t)tmp) << dev->params.i_range;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ina2xx_read_power(const ina2xx_t *dev, uint32_t *power)
|
||||
{
|
||||
int status;
|
||||
uint16_t tmp;
|
||||
status = ina2xx_read_reg(dev, INA2XX_REG_POWER, &tmp);
|
||||
if (status < 0) {
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* The resolution of the raw power value depends only on the resolution
|
||||
* of the raw current value, as the bus voltage has a resolution of 4 mV
|
||||
* regardless of configuration and calibration values. The product of
|
||||
* bus voltage and raw current value is divided by 5000, this results in
|
||||
* the following resolutions:
|
||||
*
|
||||
* Res current | res power
|
||||
* 0.01 mA | 0.2 mW
|
||||
* 0.02 mA | 0.4 mW
|
||||
* 0.04 mA | 0.8 mW
|
||||
* ...
|
||||
*
|
||||
* ==> multiply by 2^(1 + i_range) to get power in E-04W
|
||||
*/
|
||||
*power = ((uint32_t)tmp) << (1 + dev->params.i_range);
|
||||
return 0;
|
||||
}
|
||||
86
drivers/ina2xx/ina2xx_saul.c
Normal file
86
drivers/ina2xx/ina2xx_saul.c
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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_ina2xx
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief SAUL adaption of the INA2XX driver
|
||||
*
|
||||
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "phydat.h"
|
||||
#include "saul.h"
|
||||
#include "ina2xx.h"
|
||||
|
||||
static int read_current(const void *_dev, phydat_t *res)
|
||||
{
|
||||
ina2xx_t *dev = (ina2xx_t *)_dev;
|
||||
int32_t current;
|
||||
|
||||
if (ina2xx_read_current(dev, ¤t) == 0) {
|
||||
res->scale = -5;
|
||||
res->unit = UNIT_A;
|
||||
phydat_fit(res, ¤t, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return -ECANCELED;
|
||||
}
|
||||
|
||||
static int read_power(const void *_dev, phydat_t *res)
|
||||
{
|
||||
ina2xx_t *dev = (ina2xx_t *)_dev;
|
||||
uint32_t power;
|
||||
if (ina2xx_read_power(dev, &power) == 0) {
|
||||
res->unit = UNIT_W;
|
||||
res->scale = -4;
|
||||
phydat_fit(res, (int32_t *)&power, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return -ECANCELED;
|
||||
}
|
||||
|
||||
static int read_voltage(const void *_dev, phydat_t *res)
|
||||
{
|
||||
ina2xx_t *dev = (ina2xx_t *)_dev;
|
||||
if (ina2xx_read_bus(dev, (uint16_t *)&res->val[0]) >= 0) {
|
||||
res->unit = UNIT_V;
|
||||
res->scale = -3;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return -ECANCELED;
|
||||
}
|
||||
|
||||
const saul_driver_t ina2xx_saul_current_driver = {
|
||||
.read = read_current,
|
||||
.write = saul_notsup,
|
||||
.type = SAUL_SENSE_CURRENT
|
||||
};
|
||||
|
||||
const saul_driver_t ina2xx_saul_power_driver = {
|
||||
.read = read_power,
|
||||
.write = saul_notsup,
|
||||
.type = SAUL_SENSE_POWER
|
||||
};
|
||||
|
||||
const saul_driver_t ina2xx_saul_voltage_driver = {
|
||||
.read = read_voltage,
|
||||
.write = saul_notsup,
|
||||
.type = SAUL_SENSE_VOLTAGE
|
||||
};
|
||||
66
drivers/ina2xx/include/ina2xx_defines.h
Normal file
66
drivers/ina2xx/include/ina2xx_defines.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Eistec AB
|
||||
* 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_ina2xx
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Various definitions for Texas Instruments INA219/INA220
|
||||
* Bi-Directional CURRENT/POWER MONITOR with Two-Wire Interface
|
||||
*
|
||||
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
|
||||
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
|
||||
*/
|
||||
|
||||
#ifndef INA2XX_DEFINES_H
|
||||
#define INA2XX_DEFINES_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief INA2XX register addresses
|
||||
*
|
||||
* All registers in the INA2XX are 16 bit wide and transmitted MSB first.
|
||||
*/
|
||||
typedef enum ina2xx_reg {
|
||||
INA2XX_REG_CONFIGURATION = 0x00, /**< Configuration register (read/write) */
|
||||
INA2XX_REG_SHUNT_VOLTAGE = 0x01, /**< Shunt voltage register (read only) */
|
||||
INA2XX_REG_BUS_VOLTAGE = 0x02, /**< Bus voltage register (read only) */
|
||||
INA2XX_REG_POWER = 0x03, /**< Power register (read only) */
|
||||
INA2XX_REG_CURRENT = 0x04, /**< Current register (read only) */
|
||||
INA2XX_REG_CALIBRATION = 0x05, /**< Calibration register (read/write) */
|
||||
} ina2xx_reg_t;
|
||||
|
||||
/**
|
||||
* @name Flags in the INA2XX Bus Voltage Register
|
||||
* @{
|
||||
*/
|
||||
#define INA2XX_VBUS_CNVR (0x2) /**< Unread value in power register ready */
|
||||
#define INA2XX_VBUS_OVF (0x1) /**< Math overflow during conversion */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Special configuration register values
|
||||
* @{
|
||||
*/
|
||||
#define INA2XX_RESET (0x8000)/**< Write to config reg to reset device */
|
||||
#define INA2XX_DEFCONFIG (0x399f)/**< Default config after reset */
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* INA2XX_DEFINES_H */
|
||||
/** @} */
|
||||
128
drivers/ina2xx/include/ina2xx_params.h
Normal file
128
drivers/ina2xx/include/ina2xx_params.h
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (C) 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_ina2xx
|
||||
*
|
||||
* @{
|
||||
* @file
|
||||
* @brief Default configuration for INA2xx power/current monitors
|
||||
*
|
||||
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
|
||||
*/
|
||||
|
||||
#ifndef INA2XX_PARAMS_H
|
||||
#define INA2XX_PARAMS_H
|
||||
|
||||
#include "board.h"
|
||||
#include "ina2xx.h"
|
||||
#include "saul_reg.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name Set default configuration parameters for the INA2XX
|
||||
* @{
|
||||
*/
|
||||
#ifndef INA2XX_PARAM_I2C
|
||||
/**
|
||||
* @brief Default to first I2C device
|
||||
*/
|
||||
#define INA2XX_PARAM_I2C (I2C_DEV(0))
|
||||
#endif
|
||||
#ifndef INA2XX_PARAM_ADDR
|
||||
/**
|
||||
* @brief Default to address 0x40, which is active if A0 and A1 are connected
|
||||
* to GND
|
||||
*
|
||||
* On the popular INA219 breakout board this is the default address if solder
|
||||
* jumpers remain open.
|
||||
*/
|
||||
#define INA2XX_PARAM_ADDR (0x40)
|
||||
#endif
|
||||
#ifndef INA2XX_PARAM_CONFIG
|
||||
/**
|
||||
* @brief Default to an optimal configuration for current/power measurements
|
||||
* of USB high-power devices using the popular INA219 break out board
|
||||
* with 128 samples averaged
|
||||
*
|
||||
* | Setting | Value |
|
||||
* |:------------------- |:--------------------------------------------- |
|
||||
* | Mode | Continuous shunt and bus voltage measurements |
|
||||
* | Shunt ADC Setting | 128 Samples, 68.10 ms per conversion |
|
||||
* | Bus ADC Setting | 128 Samples, 68.10 ms per conversion |
|
||||
* | Shunt Voltage Range | ±80mV |
|
||||
* | Bus Voltage Range | 16V |
|
||||
*/
|
||||
#define INA2XX_PARAM_CONFIG (INA2XX_MODE_CONTINUOUS_SHUNT_BUS | \
|
||||
INA2XX_SADC_AVG_128_SAMPLES | \
|
||||
INA2XX_BADC_AVG_128_SAMPLES | \
|
||||
INA2XX_SHUNT_RANGE_80MV | \
|
||||
INA2XX_BUS_RANGE_16V)
|
||||
#endif
|
||||
#ifndef INA2XX_PARAM_RSHUNT_MOHM
|
||||
/**
|
||||
* @brief Default to 100 mΩ as shunt resistor
|
||||
*
|
||||
* This is the value used in the popular INA219 breakout board.
|
||||
*/
|
||||
#define INA2XX_PARAM_RSHUNT_MOHM (100)
|
||||
#endif
|
||||
#ifndef INA2XX_PARAM_I_RANGE
|
||||
/**
|
||||
* @brief Default to a current range of ±655.36mA
|
||||
*
|
||||
* This is the highest resolution suitable to measure USB high-power devices
|
||||
* (up to 500 mA).
|
||||
*/
|
||||
#define INA2XX_PARAM_I_RANGE (INA2XX_CURRENT_RANGE_655_MA)
|
||||
#endif
|
||||
#ifndef INA2XX_PARAMS
|
||||
#define INA2XX_PARAMS { .i2c = INA2XX_PARAM_I2C, \
|
||||
.addr = INA2XX_PARAM_ADDR, \
|
||||
.config = INA2XX_PARAM_CONFIG, \
|
||||
.rshunt_mohm = INA2XX_PARAM_RSHUNT_MOHM, \
|
||||
.i_range = INA2XX_PARAM_I_RANGE }
|
||||
#endif
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
* @name Set default SAUL info for the INA2XX
|
||||
* @{
|
||||
*/
|
||||
#ifndef INA2XX_SAULINFO
|
||||
#define INA2XX_SAULINFO { .name = "INA2XX current" }, \
|
||||
{ .name = "INA2XX power" }, \
|
||||
{ .name = "INA2XX voltage" }
|
||||
#endif
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
* @brief Configure INA2XX devices
|
||||
*/
|
||||
static const ina2xx_params_t ina2xx_params[] =
|
||||
{
|
||||
INA2XX_PARAMS
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Allocate and configure entries to the SAUL registry
|
||||
*/
|
||||
static const saul_reg_info_t ina2xx_saul_info[] =
|
||||
{
|
||||
INA2XX_SAULINFO
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* INA2XX_PARAMS_H */
|
||||
/** @} */
|
||||
@ -1,233 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Eistec AB
|
||||
*
|
||||
* 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_ina220 INA220 current/power monitor
|
||||
* @ingroup drivers_sensors
|
||||
* @brief Device driver for Texas Instruments INA220 High or Low Side,
|
||||
* Bi-Directional CURRENT/POWER MONITOR with Two-Wire Interface
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Device driver interface for Texas Instruments INA220 High or Low
|
||||
* Side, Bi-Directional CURRENT/POWER MONITOR with Two-Wire
|
||||
* Interface
|
||||
*
|
||||
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
|
||||
*/
|
||||
|
||||
#ifndef INA220_H
|
||||
#define INA220_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "periph/i2c.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Device descriptor for INA220 sensors
|
||||
*/
|
||||
typedef struct {
|
||||
i2c_t i2c; /**< I2C device the sensor is connected to */
|
||||
uint8_t addr; /**< the slave address of the sensor on the I2C bus */
|
||||
} ina220_t;
|
||||
|
||||
/**
|
||||
* @brief INA220 possible mode settings
|
||||
*/
|
||||
typedef enum ina220_mode {
|
||||
INA220_MODE_POWERDOWN = 0x0000, /**< Power down */
|
||||
INA220_MODE_TRIGGER_SHUNT_ONLY = 0x0001, /**< Shunt Voltage, Triggered */
|
||||
INA220_MODE_TRIGGER_BUS_ONLY = 0x0002, /**< Bus Voltage, Triggered */
|
||||
INA220_MODE_TRIGGER_SHUNT_BUS = 0x0003, /**< Shunt and Bus, Triggered */
|
||||
INA220_MODE_ADC_DISABLE = 0x0004, /**< ADC Off (disabled) */
|
||||
INA220_MODE_CONTINUOUS_SHUNT_ONLY = 0x0005, /**< Shunt Voltage, Continuous */
|
||||
INA220_MODE_CONTINUOUS_BUS_ONLY = 0x0006, /**< Bus Voltage, Continuous */
|
||||
INA220_MODE_CONTINUOUS_SHUNT_BUS = 0x0007, /**< Shunt and Bus, Continuous, default */
|
||||
} ina220_mode_t;
|
||||
|
||||
/**
|
||||
* @brief Shunt voltage measurement range (PGA settings)
|
||||
*/
|
||||
typedef enum ina220_range {
|
||||
INA220_RANGE_40MV = 0x0000, /**< +/- 40 mV range */
|
||||
INA220_RANGE_80MV = 0x0800, /**< +/- 80 mV range */
|
||||
INA220_RANGE_160MV = 0x1000, /**< +/- 160 mV range */
|
||||
INA220_RANGE_320MV = 0x1800, /**< +/- 320 mV range, default */
|
||||
} ina220_range_t;
|
||||
|
||||
/**
|
||||
* @brief Bus voltage measurement range
|
||||
*/
|
||||
typedef enum ina220_brng {
|
||||
INA220_BRNG_16V_FSR = 0x0000, /**< 16 V bus voltage full scale range */
|
||||
INA220_BRNG_32V_FSR = 0x2000, /**< 32 V bus voltage full scale range, default. */
|
||||
} ina220_brng_t;
|
||||
|
||||
/**
|
||||
* @brief Shunt ADC settings
|
||||
*
|
||||
* @see Table 4 in INA220 data sheet
|
||||
*/
|
||||
typedef enum ina220_sadc {
|
||||
/** 9 bit resolution, 84 us conversion time */
|
||||
INA220_SADC_9BIT = 0x0000,
|
||||
/** 10 bit resolution, 148 us conversion time */
|
||||
INA220_SADC_10BIT = 0x0008,
|
||||
/** 11 bit resolution, 276 us conversion time */
|
||||
INA220_SADC_11BIT = 0x0010,
|
||||
/** 12 bit resolution, 532 us conversion time, default */
|
||||
INA220_SADC_12BIT = 0x0018,
|
||||
/** 12 bit resolution, 532 us conversion time, same as INA220_SADC_12BIT */
|
||||
INA220_SADC_AVG_1_SAMPLE = 0x0040,
|
||||
/** 2 sample average, 1.06 ms conversion time */
|
||||
INA220_SADC_AVG_2_SAMPLES = 0x0048,
|
||||
/** 4 sample average, 2.13 ms conversion time */
|
||||
INA220_SADC_AVG_4_SAMPLES = 0x0050,
|
||||
/** 8 sample average, 4.26 ms conversion time */
|
||||
INA220_SADC_AVG_8_SAMPLES = 0x0058,
|
||||
/** 16 sample average, 8.51 ms conversion time */
|
||||
INA220_SADC_AVG_16_SAMPLES = 0x0060,
|
||||
/** 32 sample average, 17.02 ms conversion time */
|
||||
INA220_SADC_AVG_32_SAMPLES = 0x0068,
|
||||
/** 64 sample average, 34.05 ms conversion time */
|
||||
INA220_SADC_AVG_64_SAMPLES = 0x0070,
|
||||
/** 128 sample average, 68.10 ms conversion time */
|
||||
INA220_SADC_AVG_128_SAMPLES = 0x0078,
|
||||
} ina220_sadc_t;
|
||||
|
||||
/**
|
||||
* @brief Bus ADC settings
|
||||
*
|
||||
* @see Table 4 in INA220 data sheet
|
||||
*/
|
||||
typedef enum ina220_badc {
|
||||
/** 9 bit resolution, 84 us conversion time */
|
||||
INA220_BADC_9BIT = 0x0000,
|
||||
/** 10 bit resolution, 148 us conversion time */
|
||||
INA220_BADC_10BIT = 0x0080,
|
||||
/** 11 bit resolution, 276 us conversion time */
|
||||
INA220_BADC_11BIT = 0x0100,
|
||||
/** 12 bit resolution, 532 us conversion time, default */
|
||||
INA220_BADC_12BIT = 0x0180,
|
||||
/** 12 bit resolution, 532 us conversion time, same as INA220_BADC_12BIT */
|
||||
INA220_BADC_AVG_1_SAMPLE = 0x0400,
|
||||
/** 2 sample average, 1.06 ms conversion time */
|
||||
INA220_BADC_AVG_2_SAMPLES = 0x0480,
|
||||
/** 4 sample average, 2.13 ms conversion time */
|
||||
INA220_BADC_AVG_4_SAMPLES = 0x0500,
|
||||
/** 8 sample average, 4.26 ms conversion time */
|
||||
INA220_BADC_AVG_8_SAMPLES = 0x0580,
|
||||
/** 16 sample average, 8.51 ms conversion time */
|
||||
INA220_BADC_AVG_16_SAMPLES = 0x0600,
|
||||
/** 32 sample average, 17.02 ms conversion time */
|
||||
INA220_BADC_AVG_32_SAMPLES = 0x0680,
|
||||
/** 64 sample average, 34.05 ms conversion time */
|
||||
INA220_BADC_AVG_64_SAMPLES = 0x0700,
|
||||
/** 128 sample average, 68.10 ms conversion time */
|
||||
INA220_BADC_AVG_128_SAMPLES = 0x0780,
|
||||
} ina220_badc_t;
|
||||
|
||||
/** INA220 reset command bit (in configuration register) */
|
||||
#define INA220_RESET_BIT (0x8000)
|
||||
|
||||
/** Location of the bus voltage in the INA220 bus voltage register */
|
||||
#define INA220_BUS_VOLTAGE_SHIFT (3)
|
||||
|
||||
/**
|
||||
* @brief Initialize a current sensor
|
||||
*
|
||||
* @param[out] dev device descriptor of sensor to initialize
|
||||
* @param[in] i2c I2C bus the sensor is connected to
|
||||
* @param[in] address I2C slave address of the sensor
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return <0 on error
|
||||
*/
|
||||
int ina220_init(ina220_t *dev, i2c_t i2c, uint8_t address);
|
||||
|
||||
/**
|
||||
* @brief Write to calibration register
|
||||
*
|
||||
* @param[in] dev device descriptor of sensor to configure
|
||||
* @param[in] calibration calibration register settings, see data sheet
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return <0 on error
|
||||
*/
|
||||
int ina220_set_calibration(const ina220_t *dev, uint16_t calibration);
|
||||
|
||||
/**
|
||||
* @brief Write to configuration register
|
||||
*
|
||||
* @param[in] dev device descriptor of sensor to configure
|
||||
* @param[in] config configuration register settings, see data sheet
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return <0 on error
|
||||
*/
|
||||
int ina220_set_config(const ina220_t *dev, uint16_t config);
|
||||
|
||||
/**
|
||||
* @brief Read shunt voltage
|
||||
*
|
||||
* @param[in] dev device descriptor of sensor
|
||||
* @param[out] voltage measured voltage across shunt resistor
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return <0 on error
|
||||
*/
|
||||
int ina220_read_shunt(const ina220_t *dev, int16_t *voltage);
|
||||
|
||||
/**
|
||||
* @brief Read bus voltage register
|
||||
*
|
||||
* The bus voltage can be found in the most significant bits of the bus voltage
|
||||
* register, the lower three bits are flags/reserved.
|
||||
*
|
||||
* See the device data sheet for details.
|
||||
*
|
||||
* @param[in] dev device descriptor of sensor
|
||||
* @param[out] voltage measured bus voltage
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return <0 on error
|
||||
*/
|
||||
int ina220_read_bus(const ina220_t *dev, int16_t *voltage);
|
||||
|
||||
/**
|
||||
* @brief Read shunt current
|
||||
*
|
||||
* @param[in] dev device descriptor of sensor
|
||||
* @param[out] current measured current through shunt resistor
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return <0 on error
|
||||
*/
|
||||
int ina220_read_current(const ina220_t *dev, int16_t *current);
|
||||
|
||||
/**
|
||||
* @brief Read power consumption
|
||||
*
|
||||
* @param[in] dev device descriptor of sensor
|
||||
* @param[out] power measured power consumption
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return <0 on error
|
||||
*/
|
||||
int ina220_read_power(const ina220_t *dev, int16_t *power);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* INA220_H */
|
||||
/** @} */
|
||||
260
drivers/include/ina2xx.h
Normal file
260
drivers/include/ina2xx.h
Normal file
@ -0,0 +1,260 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Eistec AB
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup drivers_ina2xx INA2XX current/power monitor
|
||||
* @ingroup drivers_sensors
|
||||
* @brief Device driver for Texas Instruments INA219/INA2XX
|
||||
* Bi-Directional CURRENT/POWER MONITOR with Two-Wire Interface
|
||||
*
|
||||
* # Supported Hardware
|
||||
* This driver currently supports the INA219 and the INA2XX - and possibly
|
||||
* other devices of the INA2xx family. The popular INA219 breakout boards are
|
||||
* supported out of the box.
|
||||
*
|
||||
* # Choosing the Right Shunt Resistor
|
||||
* The shunt resistor should generate a voltage drop of at least 40 mV and of
|
||||
* at most 320 mV at maximum current (add some safety margin to the maximum
|
||||
* current). E.g. when the expected maximum current is 500 mA and we add a
|
||||
* safety margin of 33 mA, a 75 mΩ shunt resistor would cause a drop of 40 mV
|
||||
* at about 533 mA, and a 600 mΩ shunt resistor would cause a drop of 320 mV.
|
||||
* So every shunt resistor between 75 mΩ and 600 mΩ would result in a decent
|
||||
* resolution, but shunt resistors that almost max out one of the selectable
|
||||
* shunt voltage ranges (40 mV, 80 mV, 160 mV and 320 mV) would be ideal.
|
||||
* Often the voltage drop should be as low as possible, therefore the lowest
|
||||
* reasonable shunt resistor has to be chosen in that case.
|
||||
*
|
||||
* The popular INA219 breakout boards have a shunt resistor of 100 mΩ, which
|
||||
* allows to measure a current of up to 400 mA at PGA = /1, and of up two 3.2 A
|
||||
* at PGA = /8.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Device driver interface for Texas Instruments INA219/INA2XX
|
||||
* Bi-Directional CURRENT/POWER MONITOR with Two-Wire Interface
|
||||
*
|
||||
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
|
||||
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
|
||||
*/
|
||||
|
||||
#ifndef INA2XX_H
|
||||
#define INA2XX_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "periph/i2c.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief INA2XX possible mode settings
|
||||
*/
|
||||
typedef enum ina2xx_mode {
|
||||
INA2XX_MODE_POWERDOWN = 0x0000, /**< Power down */
|
||||
INA2XX_MODE_TRIGGER_SHUNT_ONLY = 0x0001, /**< Shunt Voltage, Triggered */
|
||||
INA2XX_MODE_TRIGGER_BUS_ONLY = 0x0002, /**< Bus Voltage, Triggered */
|
||||
INA2XX_MODE_TRIGGER_SHUNT_BUS = 0x0003, /**< Shunt and Bus, Triggered */
|
||||
INA2XX_MODE_ADC_DISABLE = 0x0004, /**< ADC Off (disabled) */
|
||||
INA2XX_MODE_CONTINUOUS_SHUNT_ONLY = 0x0005, /**< Shunt Voltage, Continuous */
|
||||
INA2XX_MODE_CONTINUOUS_BUS_ONLY = 0x0006, /**< Bus Voltage, Continuous */
|
||||
INA2XX_MODE_CONTINUOUS_SHUNT_BUS = 0x0007, /**< Shunt and Bus, Continuous, default */
|
||||
} ina2xx_mode_t;
|
||||
|
||||
/**
|
||||
* @brief Shunt ADC settings
|
||||
*
|
||||
* @see Table 4 in INA2XX data sheet
|
||||
*/
|
||||
typedef enum ina2xx_sadc {
|
||||
/** 9 bit resolution, 84 us conversion time */
|
||||
INA2XX_SADC_9BIT = 0x0000,
|
||||
/** 10 bit resolution, 148 us conversion time */
|
||||
INA2XX_SADC_10BIT = 0x0008,
|
||||
/** 11 bit resolution, 276 us conversion time */
|
||||
INA2XX_SADC_11BIT = 0x0010,
|
||||
/** 12 bit resolution, 532 us conversion time, default */
|
||||
INA2XX_SADC_12BIT = 0x0018,
|
||||
/** 12 bit resolution, 532 us conversion time, same as INA2XX_SADC_12BIT */
|
||||
INA2XX_SADC_AVG_1_SAMPLE = 0x0040,
|
||||
/** 2 sample average, 1.06 ms conversion time */
|
||||
INA2XX_SADC_AVG_2_SAMPLES = 0x0048,
|
||||
/** 4 sample average, 2.13 ms conversion time */
|
||||
INA2XX_SADC_AVG_4_SAMPLES = 0x0050,
|
||||
/** 8 sample average, 4.26 ms conversion time */
|
||||
INA2XX_SADC_AVG_8_SAMPLES = 0x0058,
|
||||
/** 16 sample average, 8.51 ms conversion time */
|
||||
INA2XX_SADC_AVG_16_SAMPLES = 0x0060,
|
||||
/** 32 sample average, 17.02 ms conversion time */
|
||||
INA2XX_SADC_AVG_32_SAMPLES = 0x0068,
|
||||
/** 64 sample average, 34.05 ms conversion time */
|
||||
INA2XX_SADC_AVG_64_SAMPLES = 0x0070,
|
||||
/** 128 sample average, 68.10 ms conversion time */
|
||||
INA2XX_SADC_AVG_128_SAMPLES = 0x0078,
|
||||
} ina2xx_sadc_t;
|
||||
|
||||
/**
|
||||
* @brief Bus ADC settings
|
||||
*
|
||||
* @see Table 4 in INA2XX data sheet
|
||||
*/
|
||||
typedef enum ina2xx_badc {
|
||||
/** 9 bit resolution, 84 us conversion time */
|
||||
INA2XX_BADC_9BIT = 0x0000,
|
||||
/** 10 bit resolution, 148 us conversion time */
|
||||
INA2XX_BADC_10BIT = 0x0080,
|
||||
/** 11 bit resolution, 276 us conversion time */
|
||||
INA2XX_BADC_11BIT = 0x0100,
|
||||
/** 12 bit resolution, 532 us conversion time, default */
|
||||
INA2XX_BADC_12BIT = 0x0180,
|
||||
/** 12 bit resolution, 532 us conversion time, same as INA2XX_BADC_12BIT */
|
||||
INA2XX_BADC_AVG_1_SAMPLE = 0x0400,
|
||||
/** 2 sample average, 1.06 ms conversion time */
|
||||
INA2XX_BADC_AVG_2_SAMPLES = 0x0480,
|
||||
/** 4 sample average, 2.13 ms conversion time */
|
||||
INA2XX_BADC_AVG_4_SAMPLES = 0x0500,
|
||||
/** 8 sample average, 4.26 ms conversion time */
|
||||
INA2XX_BADC_AVG_8_SAMPLES = 0x0580,
|
||||
/** 16 sample average, 8.51 ms conversion time */
|
||||
INA2XX_BADC_AVG_16_SAMPLES = 0x0600,
|
||||
/** 32 sample average, 17.02 ms conversion time */
|
||||
INA2XX_BADC_AVG_32_SAMPLES = 0x0680,
|
||||
/** 64 sample average, 34.05 ms conversion time */
|
||||
INA2XX_BADC_AVG_64_SAMPLES = 0x0700,
|
||||
/** 128 sample average, 68.10 ms conversion time */
|
||||
INA2XX_BADC_AVG_128_SAMPLES = 0x0780,
|
||||
} ina2xx_badc_t;
|
||||
|
||||
/**
|
||||
* @brief Shunt voltage measurement range (PGA settings)
|
||||
*/
|
||||
typedef enum ina2xx_pga {
|
||||
INA2XX_SHUNT_RANGE_40MV = 0x0000, /**< +/- 40 mV range */
|
||||
INA2XX_SHUNT_RANGE_80MV = 0x0800, /**< +/- 80 mV range */
|
||||
INA2XX_SHUNT_RANGE_160MV = 0x1000, /**< +/- 160 mV range */
|
||||
INA2XX_SHUNT_RANGE_320MV = 0x1800, /**< +/- 320 mV range, default */
|
||||
} ina2xx_pga_t;
|
||||
|
||||
/**
|
||||
* @brief Bus voltage measurement range
|
||||
*/
|
||||
typedef enum ina2xx_brng {
|
||||
INA2XX_BUS_RANGE_16V = 0x0000, /**< 16 V bus voltage full scale range */
|
||||
INA2XX_BUS_RANGE_32V = 0x2000, /**< 32 V bus voltage full scale range, default. */
|
||||
} ina2xx_brng_t;
|
||||
|
||||
/**
|
||||
* @brief Current measurement range
|
||||
* @warning Choosing a low range and a small shunt resistor can cause
|
||||
* @ref ina2xx_init to fail. But for high resolution measurements of
|
||||
* low currents a "big" shunt resistor (e.g. 100 mΩ) should be chosen
|
||||
* anyway.
|
||||
*
|
||||
* Choosing the lowest sufficient range for your use case will result in the
|
||||
* optimal resolution
|
||||
*/
|
||||
typedef enum ina2xx_i_range {
|
||||
INA2XX_CURRENT_RANGE_327_MA, /**< ±327.68 mA, 0.01mA resolution */
|
||||
INA2XX_CURRENT_RANGE_655_MA, /**< ±655.36 mA, 0.02mA resolution */
|
||||
INA2XX_CURRENT_RANGE_1310_MA, /**< ±1310.72 mA, 0.04mA resolution */
|
||||
INA2XX_CURRENT_RANGE_2621_MA, /**< ±2621.44 mA, 0.08mA resolution */
|
||||
INA2XX_CURRENT_RANGE_5242_MA, /**< ±5242.88 mA, 0.16mA resolution */
|
||||
INA2XX_CURRENT_RANGE_10485_MA, /**< ±10485.76 mA, 0.32mA resolution */
|
||||
} ina2xx_i_range_t;
|
||||
|
||||
/**
|
||||
* @brief Configuration parameters of the INA2xx driver
|
||||
*/
|
||||
typedef struct {
|
||||
i2c_t i2c; /**< I2C device the sensor is connected to */
|
||||
uint8_t addr; /**< I2C address of the sensr */
|
||||
uint16_t config; /**< Configuration to apply */
|
||||
uint16_t rshunt_mohm; /**< Size of the shunt resistor in mΩ */
|
||||
ina2xx_i_range_t i_range; /**< Range of the measured current */
|
||||
} ina2xx_params_t;
|
||||
|
||||
/**
|
||||
* @brief Device descriptor for INA2XX sensors
|
||||
*/
|
||||
typedef struct {
|
||||
ina2xx_params_t params; /**< Configuration parameters of the driver */
|
||||
} ina2xx_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize a current sensor
|
||||
*
|
||||
* @param[out] dev device descriptor of sensor to initialize
|
||||
* @param[in] params Configuration parameters to use
|
||||
*
|
||||
* @return `0` on success, `<0` on error.
|
||||
* @retval 0 Success
|
||||
* @retval -ENODEV Device seems not to be an INA2XX device
|
||||
* @retval -EINVAL @p dev or @p params is NULL
|
||||
* @retval -ERANGE @p params contained invalid setting: Increase
|
||||
* current range
|
||||
* @retval <0 Failure, error of @ref i2c_read_regs or
|
||||
* @ref i2c_write_regs passed through
|
||||
*/
|
||||
int ina2xx_init(ina2xx_t *dev, const ina2xx_params_t *params);
|
||||
|
||||
/**
|
||||
* @brief Read shunt voltage in E-05 V
|
||||
*
|
||||
* @param[in] dev device descriptor of sensor
|
||||
* @param[out] voltage measured voltage across shunt resistor in E-05 V
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return <0 on error
|
||||
*/
|
||||
int ina2xx_read_shunt(const ina2xx_t *dev, int16_t *voltage);
|
||||
|
||||
/**
|
||||
* @brief Read bus voltage in mV
|
||||
*
|
||||
* @param[in] dev device descriptor of sensor
|
||||
* @param[out] voltage The measured bus voltage in mV
|
||||
*
|
||||
* @return `<0` on error, `>= 0` on success
|
||||
* @retval 0 Success, no new power value available
|
||||
* @retval 1 Success, new value for @ref ina2xx_read_power ready
|
||||
* @retval -EDOM Overflow during power/current calculations.
|
||||
* @retval <0 Error code of @ref i2c_read_regs passed through
|
||||
*/
|
||||
int ina2xx_read_bus(const ina2xx_t *dev, uint16_t *voltage);
|
||||
|
||||
/**
|
||||
* @brief Read shunt current in E-05 A
|
||||
*
|
||||
* @param[in] dev device descriptor of sensor
|
||||
* @param[out] current measured current through shunt resistor in E-05 A
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return <0 on error
|
||||
*/
|
||||
int ina2xx_read_current(const ina2xx_t *dev, int32_t *current);
|
||||
|
||||
/**
|
||||
* @brief Read power consumption in E-04 W
|
||||
*
|
||||
* @param[in] dev device descriptor of sensor
|
||||
* @param[out] power measured power consumption in E-04 W
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return <0 on error
|
||||
*/
|
||||
int ina2xx_read_power(const ina2xx_t *dev, uint32_t *power);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* INA2XX_H */
|
||||
/** @} */
|
||||
@ -105,7 +105,7 @@ enum {
|
||||
SAUL_SENSE_CAPACITANCE = 0x97, /**< sensor: capacitance */
|
||||
SAUL_SENSE_VOLTAGE = 0x98, /**< sensor: voltage */
|
||||
SAUL_SENSE_PH = 0x99, /**< sensor: pH */
|
||||
SAUL_SENSE_POWER = 0x9A, /**< sensor: (electrical) power */
|
||||
SAUL_SENSE_POWER = 0x9a, /**< sensor: power */
|
||||
SAUL_CLASS_ANY = 0xff /**< any device - wildcard */
|
||||
/* extend this list as needed... */
|
||||
};
|
||||
|
||||
@ -124,6 +124,10 @@ PSEUDOMODULES += cc1101
|
||||
PSEUDOMODULES += mpu9150
|
||||
PSEUDOMODULES += mpu9250
|
||||
|
||||
# include variants of INA2xx drivers as pseudo modules
|
||||
PSEUDOMODULES += ina219
|
||||
PSEUDOMODULES += ina220
|
||||
|
||||
# include variants of mrf24j40 drivers as pseudo modules
|
||||
PSEUDOMODULES += mrf24j40m%
|
||||
|
||||
|
||||
@ -422,6 +422,10 @@ void auto_init(void)
|
||||
extern void auto_init_hts221(void);
|
||||
auto_init_hts221();
|
||||
#endif
|
||||
#ifdef MODULE_INA2XX
|
||||
extern void auto_init_ina2xx(void);
|
||||
auto_init_ina2xx();
|
||||
#endif
|
||||
#ifdef MODULE_INA3221
|
||||
extern void auto_init_ina3221(void);
|
||||
auto_init_ina3221();
|
||||
|
||||
82
sys/auto_init/saul/auto_init_ina2xx.c
Normal file
82
sys/auto_init/saul/auto_init_ina2xx.c
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 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 sys_auto_init_saul
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Auto initialization for INA2XX power/current monitors
|
||||
*
|
||||
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef MODULE_INA2XX
|
||||
|
||||
#include "assert.h"
|
||||
#include "log.h"
|
||||
#include "saul_reg.h"
|
||||
#include "ina2xx_params.h"
|
||||
#include "ina2xx.h"
|
||||
|
||||
/**
|
||||
* @brief Define the number of configured sensors
|
||||
*/
|
||||
#define INA2XX_NUM ARRAY_SIZE(ina2xx_params)
|
||||
|
||||
/**
|
||||
* @brief Allocate memory for the device descriptors
|
||||
*/
|
||||
static ina2xx_t ina2xx_devs[INA2XX_NUM];
|
||||
|
||||
/**
|
||||
* @brief Memory for the SAUL registry entries
|
||||
*/
|
||||
static saul_reg_t saul_entries[INA2XX_NUM * 3];
|
||||
|
||||
/**
|
||||
* @brief Define the number of saul info
|
||||
*/
|
||||
#define INA2XX_INFO_NUM ARRAY_SIZE(ina2xx_saul_info)
|
||||
|
||||
/**
|
||||
* @name Import SAUL endpoints
|
||||
* @{
|
||||
*/
|
||||
extern const saul_driver_t ina2xx_saul_current_driver;
|
||||
extern const saul_driver_t ina2xx_saul_power_driver;
|
||||
extern const saul_driver_t ina2xx_saul_voltage_driver;
|
||||
/** @} */
|
||||
|
||||
void auto_init_ina2xx(void)
|
||||
{
|
||||
assert(INA2XX_INFO_NUM == 3 * INA2XX_NUM);
|
||||
|
||||
for (unsigned int i = 0; i < INA2XX_NUM; i++) {
|
||||
LOG_DEBUG("[auto_init_saul] initializing ina2xx #%u\n", i);
|
||||
|
||||
if (ina2xx_init(&ina2xx_devs[i], &ina2xx_params[i])) {
|
||||
LOG_ERROR("[auto_init_saul] error initializing ina2xx #%u\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (unsigned int j = 0; j < 3; j++) {
|
||||
saul_entries[i * 3 + j].dev = &(ina2xx_devs[i]);
|
||||
saul_entries[i * 3 + j].name = ina2xx_saul_info[3 * i + j].name;
|
||||
saul_entries[i * 3 + j].driver = &ina2xx_saul_power_driver;
|
||||
saul_reg_add(&(saul_entries[i * 3 + j]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
typedef int dont_be_pedantic;
|
||||
#endif /* MODULE_INA2XX */
|
||||
@ -1,14 +0,0 @@
|
||||
include ../Makefile.tests_common
|
||||
|
||||
USEMODULE += ina220
|
||||
USEMODULE += xtimer
|
||||
|
||||
# set default device parameters in case they are undefined
|
||||
TEST_INA220_I2C ?= I2C_DEV\(0\)
|
||||
TEST_INA220_ADDR ?= 0x40
|
||||
|
||||
# export parameters
|
||||
CFLAGS += -DTEST_INA220_I2C=$(TEST_INA220_I2C)
|
||||
CFLAGS += -DTEST_INA220_ADDR=$(TEST_INA220_ADDR)
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
||||
@ -1,11 +0,0 @@
|
||||
# About
|
||||
This is a manual test application for the INA220 current and power monitor driver.
|
||||
|
||||
# Usage
|
||||
This test application will initialize the sensor with the following parameters:
|
||||
- ADC resolution: 12 bit
|
||||
- Sampling time: 532 us
|
||||
- Calibration register: 4096
|
||||
|
||||
After initialization, the sensor reads the measurement values every 100ms
|
||||
and prints them to the STDOUT.
|
||||
@ -1,102 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Eistec AB
|
||||
*
|
||||
* 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 application for the INA220 sensor driver
|
||||
*
|
||||
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifndef TEST_INA220_I2C
|
||||
#error "TEST_INA220_I2C not defined"
|
||||
#endif
|
||||
#ifndef TEST_INA220_ADDR
|
||||
#error "TEST_INA220_ADDR not defined"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "xtimer.h"
|
||||
#include "ina220.h"
|
||||
|
||||
/* Use the following configuration:
|
||||
*
|
||||
* - Continuous measurements, both shunt and bus voltage
|
||||
* - +/- 320 mV Vshunt range
|
||||
* - 32 V maximum bus voltage
|
||||
* - 12 bit ADC resolution, no hardware averaging
|
||||
*/
|
||||
#define CONFIG (INA220_MODE_CONTINUOUS_SHUNT_BUS | INA220_RANGE_320MV | \
|
||||
INA220_BRNG_32V_FSR | INA220_SADC_12BIT | INA220_BADC_12BIT)
|
||||
#define CALIBRATION (4096)
|
||||
#define SLEEP_USEC (100 * 1000U)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
ina220_t dev;
|
||||
int16_t val;
|
||||
|
||||
puts("INA220 sensor driver test application\n");
|
||||
|
||||
printf("Initializing INA220 sensor at I2C_%i, address 0x%02x... ",
|
||||
TEST_INA220_I2C, TEST_INA220_ADDR);
|
||||
if (ina220_init(&dev, TEST_INA220_I2C, TEST_INA220_ADDR) == 0) {
|
||||
puts("[OK]\n");
|
||||
} else {
|
||||
puts("[Failed]");
|
||||
return 1;
|
||||
}
|
||||
puts("Set configuration register");
|
||||
if (ina220_set_config(&dev, CONFIG) == 0) {
|
||||
puts("[OK]\n");
|
||||
} else {
|
||||
puts("[Failed]");
|
||||
return 1;
|
||||
}
|
||||
|
||||
puts("Set calibration register");
|
||||
if (ina220_set_calibration(&dev, CALIBRATION) == 0) {
|
||||
puts("[OK]\n");
|
||||
} else {
|
||||
puts("[Failed]");
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
/* Read shunt resistor voltage, in millivolts */
|
||||
ina220_read_shunt(&dev, &val);
|
||||
printf("shunt: %6d", val);
|
||||
|
||||
/* Read VBUS voltage, in millivolts */
|
||||
ina220_read_bus(&dev, &val);
|
||||
/* The bus voltage is found in the topmost 13 bits of the bus voltage
|
||||
* register */
|
||||
val = (val >> INA220_BUS_VOLTAGE_SHIFT);
|
||||
printf("\tbus: %6d", val);
|
||||
|
||||
/* Read current register, the scale depends on the value of the
|
||||
* calibration register */
|
||||
ina220_read_current(&dev, &val);
|
||||
printf("\tcurrent: %6d", val);
|
||||
|
||||
/* Read power register, the scale depends on the value of the
|
||||
* calibration register */
|
||||
ina220_read_power(&dev, &val);
|
||||
printf("\tpower: %6d\n", val);
|
||||
|
||||
xtimer_usleep(SLEEP_USEC);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
6
tests/driver_ina2xx/Makefile
Normal file
6
tests/driver_ina2xx/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
include ../Makefile.tests_common
|
||||
|
||||
USEMODULE += fmt_table
|
||||
USEMODULE += ina219
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
||||
15
tests/driver_ina2xx/README.md
Normal file
15
tests/driver_ina2xx/README.md
Normal file
@ -0,0 +1,15 @@
|
||||
# About
|
||||
This is a manual test application for the INA219/INA220 current and power
|
||||
monitor driver.
|
||||
|
||||
# Usage
|
||||
This test application will initialize the sensor with the default parameters
|
||||
in @ref ina2xx_params.h
|
||||
|
||||
After initialization, the application will print a table of the devices
|
||||
measurement data. If the I2C interface is fast enough, one row corresponds to
|
||||
one measurement of the device. (The sensor indicates when a new measurement is
|
||||
available via flags, this flags are read until the measurement is done. The
|
||||
duration of one measurement depends on the sensor settings and is between
|
||||
84µs and 68.1ms. Please note that blocking stdio might very well be the
|
||||
bottleneck causing the test to miss measurements.)
|
||||
104
tests/driver_ina2xx/main.c
Normal file
104
tests/driver_ina2xx/main.c
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Eistec AB
|
||||
*
|
||||
* 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 application for the INA2XX sensor driver
|
||||
*
|
||||
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
|
||||
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "fmt.h"
|
||||
#include "fmt_table.h"
|
||||
#include "ina2xx.h"
|
||||
#include "ina2xx_params.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
ina2xx_t dev;
|
||||
|
||||
print_str("INA2XX sensor driver test application\n\n");
|
||||
|
||||
print_str("Initializing INA2XX sensor at I2C_");
|
||||
print_s32_dec(ina2xx_params[0].i2c);
|
||||
print_str(", address 0x");
|
||||
print_u32_hex(ina2xx_params[0].addr);
|
||||
print_str("\n");
|
||||
if (ina2xx_init(&dev, &ina2xx_params[0]) == 0) {
|
||||
print_str("[OK]\n");
|
||||
} else {
|
||||
print_str("[Failed]\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const char *line = "+------------+--------------+----------+--------+\n";
|
||||
print_str(line);
|
||||
print_str("| U_Bus [mV] | U_Shunt [µV] | I [µA] | P [µW] |\n");
|
||||
print_str(line);
|
||||
|
||||
while (1) {
|
||||
uint16_t u_bus;
|
||||
int16_t u_shunt;
|
||||
int32_t i_shunt;
|
||||
uint32_t p;
|
||||
|
||||
/* Read bus voltage until flag indicates new value is present */
|
||||
switch (ina2xx_read_bus(&dev, &u_bus)){
|
||||
case 0:
|
||||
/* No measurement available yet */
|
||||
continue;
|
||||
case 1:
|
||||
/* New measurement available, continue */
|
||||
break;
|
||||
case -EDOM:
|
||||
print_str("[WARNING]: INA2xx detected math overflow ==> data "
|
||||
"will be incorrect\n");
|
||||
break;
|
||||
default:
|
||||
/* Error */
|
||||
print_str("Error while reading bus voltage\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (ina2xx_read_shunt(&dev, &u_shunt) < 0) {
|
||||
print_str("Error while reading shunt voltage\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (ina2xx_read_current(&dev, &i_shunt) < 0) {
|
||||
print_str("Error while reading current\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (ina2xx_read_power(&dev, &p) < 0) {
|
||||
print_str("Error while reading power\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
print_str("| ");
|
||||
print_col_u32_dec(u_bus, 10);
|
||||
print_str(" | ");
|
||||
print_col_s32_dec(10 * (int32_t)u_shunt, 12);
|
||||
print_str(" | ");
|
||||
print_col_s32_dec(10 * i_shunt, 8);
|
||||
print_str(" | ");
|
||||
print_col_u32_dec(100 * p, 6);
|
||||
print_str(" |\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user