AD7280A
AD7280A IIO Lithium Ion Battery Monitoring System.
Supported Devices
Evaluation Boards
Reference Circuits
Description
This is a Linux industrial I/O (Linux Industrial I/O Subsystem) subsystem driver, targeting multi channel serial interface ADCs. The industrial I/O subsystem provides a unified framework for drivers for many different types of converters and sensors using a number of different physical interfaces (i2c, spi, etc). See Linux Industrial I/O Subsystem for more information.
The AD7280A contains all the functions required for general-purpose monitoring of stacked lithium ion batteries as used in hybrid electric vehicles, battery backup applications, and power tools. The part has multiplexed cell voltage and auxiliary ADC measurement channels for up to six cells of battery management. This driver supports the daisy-chain interface allowing up to eight parts to be stacked without the need for individual device isolation.
The driver automatically detects then number of devices present and creates the iio device files accordingly.
Source Code
Status
Source |
Mainlined? |
||
|---|---|---|---|
Yes |
Files
Function |
File |
|---|---|
driver |
Hardware configuration
Adding Linux driver support
Kernel configuration
Configure kernel with make menuconfig (alternatively use make xconfig or
make qconfig)
Note
The AD7280A Driver depends on CONFIG_SPI
Linux Kernel Configuration
Device Drivers --->
[*] Staging drivers --->
<*> Industrial I/O support --->
--- Industrial I/O support
-*- Enable buffer support within IIO
-*- Enable triggered sampling support
*** Analog to digital converters ***
[--snip--]
<*> Analog Devices AD7280A Lithium Ion Battery Monitoring System
[--snip--]
Platform-data configuration
Example platform device initialization
For compile time configuration, it’s common Linux practice to keep board- and application-specific configuration out of the main driver file, instead putting it into the board support file.
For devices on custom boards, as typical of embedded and SoC-(system-on-chip)
based hardware, Linux uses platform_data to point to board-specific structures
describing devices and how they are connected to the SoC. This can include
available ports, chip variants, preferred modes, default initialization,
additional pin roles, and so on. This shrinks the board-support packages (BSPs)
and minimizes board and application specific #ifdefs in drivers.
The driver reads firmware properties instead of ad7280_platform_data:
adi,acquisition-time-ns (400, 800, 1200 or 1600; default 400),
adi,thermistor-termination (boolean, defaults to off when absent), and
adi,voltage-alert-last-chan. The ad7280_platform_data structure and
defaults below describe the board-file API only. Oversampling starts disabled
and is configurable through the oversampling_ratio attribute.
#define AD7280A_ACQ_TIME_400ns 0
#define AD7280A_ACQ_TIME_800ns 1
#define AD7280A_ACQ_TIME_1200ns 2
#define AD7280A_ACQ_TIME_1600ns 3
#define AD7280A_CONV_AVG_DIS 0
#define AD7280A_CONV_AVG_2 1
#define AD7280A_CONV_AVG_4 2
#define AD7280A_CONV_AVG_8 3
#define AD7280A_ALERT_REMOVE_VIN5 (1 << 2)
#define AD7280A_ALERT_REMOVE_VIN4_VIN5 (2 << 2)
#define AD7280A_ALERT_REMOVE_AUX5 (1 << 0)
#define AD7280A_ALERT_REMOVE_AUX4_AUX5 (2 << 0)
struct ad7280_platform_data {
unsigned acquisition_time;
unsigned conversion_averaging;
unsigned chain_last_alert_ignore;
bool thermistor_term_en;
}
Tip
In case platform_data is not present or set to NULL, the driver will use following defaults:
static const struct ad7280_platform_data ad7280_default_pdata = {
.acquisition_time = AD7280A_ACQ_TIME_400ns,
.conversion_averaging = AD7280A_CONV_AVG_DIS,
.thermistor_term_en = true,
};
Unlike PCI or USB devices, SPI devices are not enumerated at the hardware level. Instead, the software must know which devices are connected on each SPI bus segment, and what slave selects these devices are using. For this reason, the kernel code must instantiate SPI devices explicitly. The most common method is to declare the SPI devices by bus number.
This method is appropriate when the SPI bus is a system bus, as in many
embedded systems, wherein each SPI bus has a number which is known in advance.
It is thus possible to pre-declare the SPI devices that inhabit this bus. This
is done with an array of struct spi_board_info, which is registered by
calling spi_register_board_info().
For more information see: Overview of Linux kernel SPI support
Depending on the converter IC used, you may need to set the modalias accordingly, matching your part name. It may also required to adjust max_speed_hz. Please consult the datasheet, for maximum spi clock supported by the device in question.
static struct spi_board_info board_spi_board_info[] __initdata = {
#if defined(CONFIG_AD7280A) || \
defined(CONFIG_AD7280A_MODULE)
{
.modalias = "ad7280a",
.max_speed_hz = 1000000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0,
.chip_select = GPIO_PF10 + MAX_CTRL_CS, /* CS, change it for your board */
.mode = SPI_MODE_1,
.irq = IRQ_PF6
},
#endif
};
static int __init board_init(void)
{
[--snip--]
spi_register_board_info(board_spi_board_info, ARRAY_SIZE(board_spi_board_info));
[--snip--]
return 0;
}
arch_initcall(board_init);
Driver testing
Each and every IIO device, typically a hardware chip, has a device folder under
/sys/bus/iio/devices/iio:deviceX. Where X is the IIO index of the device. Under
every of these directory folders reside a set of files, depending on the
characteristics and features of the hardware device in question. These files
are consistently generalized and documented in the IIO ABI documentation. In
order to determine which IIO deviceX corresponds to which hardware device, the
user can read the name file /sys/bus/iio/devices/iio:deviceX/name. In case
the sequence in which the iio device drivers are loaded/registered is constant,
the numbering is constant and may be known in advance.
Each cell is exposed as a differential channel in_voltageX-voltageY_raw
with balance_switch_en and balance_switch_timer attributes; the
auxiliary inputs are in_tempN_raw. The scales in_voltage-voltage_scale
and in_temp_scale are shared, and threshold events are under events/.
Identify the device
root:/sys/devices/platform/bfin-spi.0/spi0.18/device0> cat name
ad7280a
Basic operation
Show cell channel scale
Cell attributes are in_voltageX-voltageY_raw with
in_voltage-voltage_scale; auxiliary attributes are in_tempN_raw with
in_temp_scale. The scales are 4000/4096 (0.9765625) and 5000/4096
(1.220703125) mV/code respectively. The 1000 mV cell offset in the examples
below is part of the cell transfer function; the driver has no offset
attribute.
root:/sys/devices/platform/bfin-spi.0/spi0.18/device0> cat in_voltage-voltage_scale
0.976562500
Enabling cell and auxiliary/temperature channel threshold events
The AD7280A includes a dynamic alert function that can detect whether the cell voltages or auxiliary ADC inputs exceed an upper or lower limit defined by the user.
The thresholds are set in the events/ directory with
in_voltage-voltage_thresh_rising_value and
in_voltage-voltage_thresh_falling_value (in_temp_thresh_*_value for
the auxiliary channels). Voltage thresholds are in millivolts, quantized to
15.68 mV steps above 1000 mV.
root:/sys/bus/iio/devices/iio:device0/events> echo 2300 > in_voltage-voltage_thresh_falling_value
root:/sys/bus/iio/devices/iio:device0/events> cat in_voltage-voltage_thresh_falling_value
2285
root:/sys/bus/iio/devices/iio:device0/events> echo 4000 > in_voltage-voltage_thresh_rising_value
root:/sys/bus/iio/devices/iio:device0/events> cat in_voltage-voltage_thresh_rising_value
3994
Show channel 0-1 measurement
Description: Raw unscaled voltage measurement on cell channel in_voltage0-voltage1_raw
root:/sys/devices/platform/bfin-spi.0/spi0.18/device0> cat in_voltage0-voltage1_raw
2254
U = in_voltage0-voltage1_raw * in_voltage-voltage_scale + offset = 2254 * 0.9765625 + 1000 = 3201.172 mV
Show voltage across all cells measurement
Description: Raw unscaled voltage measurement on all cell channel in_voltage0-voltageX_raw
root:/sys/devices/platform/bfin-spi.0/spi0.18/device0> cat in_voltage0-voltage12_raw
27048
U = in_voltage0-voltage12_raw * in_voltage-voltage_scale + (cell_num * offset) = 27048 * 0.9765625 + (12 * 1000) = 38414.063 mV
Show auxiliary/temperature channel scale
Description: scale to be applied to in_tempX_raw in order to obtain the measured voltage in millivolts.
root:/sys/devices/platform/bfin-spi.0/spi0.18/device0> cat in_temp_scale
1.220703125
Show auxiliary/temperature channel measurement
Description: The auxiliary ADC channels are named in_tempN_raw but
return voltages, scaled as 5000/4096 mV per code; converting an external
thermistor reading into temperature is left to the user.
root:/sys/devices/platform/bfin-spi.0/spi0.18/device0> cat in_temp0_raw
2096
U = in_temp0_raw * in_temp_scale = 2096 * 1.220703125 = 2558.594 mV
Enable cell balance output switch on channel 4-5
The AD7280A has cell balancing interface outputs designed to control external FET transistors to allow discharging of individual cells.
Description: Writing 1 enables the cell balance output switch corresponding
to input Y. Writing 0 disables it. If
in_voltageY-voltageZ_balance_switch_timer is set to a nonzero value, the
corresponding switch will enable for the programmed amount of time before it
automatically disables.
root:/sys/devices/platform/bfin-spi.0/spi0.18/device0> echo 1 > in_voltage4-voltage5_balance_switch_en
root:/sys/devices/platform/bfin-spi.0/spi0.18/device0> cat in_voltage4-voltage5_balance_switch_en
1
root:/sys/devices/platform/bfin-spi.0/spi0.18/device0> echo 0 > in_voltage4-voltage5_balance_switch_en
root:/sys/devices/platform/bfin-spi.0/spi0.18/device0> cat in_voltage4-voltage5_balance_switch_en
0
root:/sys/devices/platform/bfin-spi.0/spi0.18/device0>
Enable cell balance timer on channel 4-5
Description: The in_voltageY-voltageZ_balance_switch_timer file lets
the user program individual times for each cell balance output. The AD7280A
allows a value from 0 to 36.9 minutes, in steps of 71.5 seconds. The value is
in seconds, with a fractional part accepted but rounded down to the nearest
step. Zero disables the timer.
root:/sys/devices/platform/bfin-spi.0/spi0.18/device0> echo 150 > in_voltage4-voltage5_balance_switch_timer
root:/sys/devices/platform/bfin-spi.0/spi0.18/device0> cat in_voltage4-voltage5_balance_switch_timer
143.0
root:/sys/devices/platform/bfin-spi.0/spi0.18/device0>