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?

drivers/iio/adc/ad7280a.c

Yes

Files

Function

File

driver

drivers/iio/adc/ad7280a.c

Hardware configuration

https://wiki.analog.com/_media/resources/tools-software/linux-drivers/iio-adc/ad7280_eval_lr.jpg

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>

More Information