drivers/ina220: Add driver for INA220 current and power sensor.
This commit is contained in:
parent
bfe2c9a47f
commit
5ea9eaf386
@ -40,3 +40,6 @@ endif
|
||||
ifneq (,$(filter mpu9150,$(USEMODULE)))
|
||||
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/mpu9150/include
|
||||
endif
|
||||
ifneq (,$(filter ina220,$(USEMODULE)))
|
||||
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/ina220/include
|
||||
endif
|
||||
|
||||
3
drivers/ina220/Makefile
Normal file
3
drivers/ina220/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE = ina220
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
||||
109
drivers/ina220/ina220.c
Normal file
109
drivers/ina220/ina220.c
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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 driver_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 Gebart <joakim.gebart@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(ina220_t *dev, uint8_t reg, uint16_t *out)
|
||||
{
|
||||
union {
|
||||
char c[2];
|
||||
uint16_t u16;
|
||||
} tmp = { .u16 = 0 };
|
||||
int status = 0;
|
||||
|
||||
status = i2c_read_regs(dev->i2c, dev->addr, reg, &tmp.c[0], 2);
|
||||
|
||||
if (status != 2) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*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(ina220_t *dev, uint8_t reg, uint16_t in)
|
||||
{
|
||||
union {
|
||||
char 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);
|
||||
|
||||
if (status != 2) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
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(ina220_t *dev, uint16_t calibration)
|
||||
{
|
||||
return ina220_write_reg(dev, INA220_REG_CALIBRATION, calibration);
|
||||
}
|
||||
|
||||
int ina220_set_config(ina220_t *dev, uint16_t config)
|
||||
{
|
||||
return ina220_write_reg(dev, INA220_REG_CONFIGURATION, config);
|
||||
}
|
||||
|
||||
int ina220_read_shunt(ina220_t *dev, int16_t *voltage)
|
||||
{
|
||||
return ina220_read_reg(dev, INA220_REG_SHUNT_VOLTAGE, (uint16_t *)voltage);
|
||||
}
|
||||
|
||||
int ina220_read_bus(ina220_t *dev, int16_t *voltage)
|
||||
{
|
||||
return ina220_read_reg(dev, INA220_REG_BUS_VOLTAGE, (uint16_t *)voltage);
|
||||
}
|
||||
|
||||
int ina220_read_current(ina220_t *dev, int16_t *current)
|
||||
{
|
||||
return ina220_read_reg(dev, INA220_REG_CURRENT, (uint16_t *)current);
|
||||
}
|
||||
|
||||
int ina220_read_power(ina220_t *dev, int16_t *power)
|
||||
{
|
||||
return ina220_read_reg(dev, INA220_REG_POWER, (uint16_t *)power);
|
||||
}
|
||||
50
drivers/ina220/include/ina220-regs.h
Normal file
50
drivers/ina220/include/ina220-regs.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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 driver_ina220
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Register definitions for Texas Instruments INA220 High or Low
|
||||
* Side, Bi-Directional CURRENT/POWER MONITOR with Two-Wire
|
||||
* Interface
|
||||
*
|
||||
* @author Joakim Gebart <joakim.gebart@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 /* __L3G4200D_REGS_H */
|
||||
/** @} */
|
||||
227
drivers/include/ina220.h
Normal file
227
drivers/include/ina220.h
Normal file
@ -0,0 +1,227 @@
|
||||
/*
|
||||
* 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 driver_ina220 INA220 current/power monitor
|
||||
* @ingroup drivers
|
||||
* @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 Gebart <joakim.gebart@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 = 0x0200, /**< 32 V bus voltage full scale range, default. */
|
||||
} ina220_brng_t;
|
||||
|
||||
/**
|
||||
* @brief Shunt ADC settings
|
||||
*
|
||||
* @see Table 5 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 5 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(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(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(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(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(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(ina220_t *dev, int16_t *power);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* INA220_H */
|
||||
/** @} */
|
||||
22
tests/driver_ina220/Makefile
Normal file
22
tests/driver_ina220/Makefile
Normal file
@ -0,0 +1,22 @@
|
||||
APPLICATION = driver_ina220
|
||||
include ../Makefile.tests_common
|
||||
|
||||
FEATURES_REQUIRED = periph_i2c
|
||||
|
||||
USEMODULE += ina220
|
||||
USEMODULE += vtimer
|
||||
|
||||
ifneq (,$(TEST_INA220_I2C))
|
||||
CFLAGS += -DTEST_INA220_I2C=$(TEST_INA220_I2C)
|
||||
else
|
||||
# set arbitrary default
|
||||
CFLAGS += -DTEST_INA220_I2C=I2C_0
|
||||
endif
|
||||
ifneq (,$(TEST_INA220_ADDR))
|
||||
CFLAGS += -DTEST_INA220_ADDR=$(TEST_INA220_ADDR)
|
||||
else
|
||||
# set arbitrary default
|
||||
CFLAGS += -DTEST_INA220_ADDR=0x40
|
||||
endif
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
||||
11
tests/driver_ina220/README.md
Normal file
11
tests/driver_ina220/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# 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.
|
||||
106
tests/driver_ina220/main.c
Normal file
106
tests/driver_ina220/main.c
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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 Gebart <joakim.gebart@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 "vtimer.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 (100 * 1000U)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
ina220_t dev;
|
||||
int16_t val;
|
||||
|
||||
puts("INA220 sensor driver test application\n");
|
||||
printf("Initializing I2C_%i... ", TEST_INA220_I2C);
|
||||
if (i2c_init_master(TEST_INA220_I2C, I2C_SPEED_FAST) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
vtimer_usleep(SLEEP);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user