Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/libraries/AP_ADC/AP_ADC_ADS1115.cpp
Views: 1798
#include <AP_HAL/AP_HAL.h>1#include <AP_HAL/utility/sparse-endian.h>23#include "AP_ADC_ADS1115.h"45#define ADS1115_ADDRESS_ADDR_GND 0x48 // address pin low (GND)6#define ADS1115_ADDRESS_ADDR_VDD 0x49 // address pin high (VCC)7#define ADS1115_ADDRESS_ADDR_SDA 0x4A // address pin tied to SDA pin8#define ADS1115_ADDRESS_ADDR_SCL 0x4B // address pin tied to SCL pin910#define ADS1115_I2C_ADDR ADS1115_ADDRESS_ADDR_GND11#define ADS1115_I2C_BUS 11213#define ADS1115_RA_CONVERSION 0x0014#define ADS1115_RA_CONFIG 0x0115#define ADS1115_RA_LO_THRESH 0x0216#define ADS1115_RA_HI_THRESH 0x031718#define ADS1115_OS_SHIFT 1519#define ADS1115_OS_INACTIVE 0x00 << ADS1115_OS_SHIFT20#define ADS1115_OS_ACTIVE 0x01 << ADS1115_OS_SHIFT2122#define ADS1115_MUX_SHIFT 1223#define ADS1115_MUX_P0_N1 0x00 << ADS1115_MUX_SHIFT /* default */24#define ADS1115_MUX_P0_N3 0x01 << ADS1115_MUX_SHIFT25#define ADS1115_MUX_P1_N3 0x02 << ADS1115_MUX_SHIFT26#define ADS1115_MUX_P2_N3 0x03 << ADS1115_MUX_SHIFT27#define ADS1115_MUX_P0_NG 0x04 << ADS1115_MUX_SHIFT28#define ADS1115_MUX_P1_NG 0x05 << ADS1115_MUX_SHIFT29#define ADS1115_MUX_P2_NG 0x06 << ADS1115_MUX_SHIFT30#define ADS1115_MUX_P3_NG 0x07 << ADS1115_MUX_SHIFT3132#define ADS1115_PGA_SHIFT 933#define ADS1115_PGA_6P144 0x00 << ADS1115_PGA_SHIFT34#define ADS1115_PGA_4P096 0x01 << ADS1115_PGA_SHIFT35#define ADS1115_PGA_2P048 0x02 << ADS1115_PGA_SHIFT // default36#define ADS1115_PGA_1P024 0x03 << ADS1115_PGA_SHIFT37#define ADS1115_PGA_0P512 0x04 << ADS1115_PGA_SHIFT38#define ADS1115_PGA_0P256 0x05 << ADS1115_PGA_SHIFT39#define ADS1115_PGA_0P256B 0x06 << ADS1115_PGA_SHIFT40#define ADS1115_PGA_0P256C 0x07 << ADS1115_PGA_SHIFT4142#define ADS1115_MV_6P144 0.187500f43#define ADS1115_MV_4P096 0.125000f44#define ADS1115_MV_2P048 0.062500f // default45#define ADS1115_MV_1P024 0.031250f46#define ADS1115_MV_0P512 0.015625f47#define ADS1115_MV_0P256 0.007813f48#define ADS1115_MV_0P256B 0.007813f49#define ADS1115_MV_0P256C 0.007813f5051#define ADS1115_MODE_SHIFT 852#define ADS1115_MODE_CONTINUOUS 0x00 << ADS1115_MODE_SHIFT53#define ADS1115_MODE_SINGLESHOT 0x01 << ADS1115_MODE_SHIFT // default5455#define ADS1115_RATE_SHIFT 556#define ADS1115_RATE_8 0x00 << ADS1115_RATE_SHIFT57#define ADS1115_RATE_16 0x01 << ADS1115_RATE_SHIFT58#define ADS1115_RATE_32 0x02 << ADS1115_RATE_SHIFT59#define ADS1115_RATE_64 0x03 << ADS1115_RATE_SHIFT60#define ADS1115_RATE_128 0x04 << ADS1115_RATE_SHIFT // default61#define ADS1115_RATE_250 0x05 << ADS1115_RATE_SHIFT62#define ADS1115_RATE_475 0x06 << ADS1115_RATE_SHIFT63#define ADS1115_RATE_860 0x07 << ADS1115_RATE_SHIFT6465#define ADS1115_COMP_MODE_SHIFT 466#define ADS1115_COMP_MODE_HYSTERESIS 0x00 << ADS1115_COMP_MODE_SHIFT // default67#define ADS1115_COMP_MODE_WINDOW 0x01 << ADS1115_COMP_MODE_SHIFT6869#define ADS1115_COMP_POL_SHIFT 370#define ADS1115_COMP_POL_ACTIVE_LOW 0x00 << ADS1115_COMP_POL_SHIFT // default71#define ADS1115_COMP_POL_ACTIVE_HIGH 0x01 << ADS1115_COMP_POL_SHIFT7273#define ADS1115_COMP_LAT_SHIFT 274#define ADS1115_COMP_LAT_NON_LATCHING 0x00 << ADS1115_COMP_LAT_SHIFT // default75#define ADS1115_COMP_LAT_LATCHING 0x01 << ADS1115_COMP_LAT_SHIFT7677#define ADS1115_COMP_QUE_SHIFT 078#define ADS1115_COMP_QUE_ASSERT1 0x00 << ADS1115_COMP_SHIFT79#define ADS1115_COMP_QUE_ASSERT2 0x01 << ADS1115_COMP_SHIFT80#define ADS1115_COMP_QUE_ASSERT4 0x02 << ADS1115_COMP_SHIFT81#define ADS1115_COMP_QUE_DISABLE 0x03 // default8283#define ADS1115_DEBUG 084#if ADS1115_DEBUG85#include <cstdio>86#define debug(fmt, args ...) do {hal.console->printf("%s:%d: " fmt "\n", __FUNCTION__, __LINE__, ## args); } while(0)87#define error(fmt, args ...) do {fprintf(stderr,"%s:%d: " fmt "\n", __FUNCTION__, __LINE__, ## args); } while(0)88#else89#define debug(fmt, args ...)90#define error(fmt, args ...)91#endif9293extern const AP_HAL::HAL &hal;9495#define ADS1115_CHANNELS_COUNT 69697const uint8_t AP_ADC_ADS1115::_channels_number = ADS1115_CHANNELS_COUNT;9899/* Only two differential channels used */100static const uint16_t mux_table[ADS1115_CHANNELS_COUNT] = {101ADS1115_MUX_P1_N3,102ADS1115_MUX_P2_N3,103ADS1115_MUX_P0_NG,104ADS1115_MUX_P1_NG,105ADS1115_MUX_P2_NG,106ADS1115_MUX_P3_NG107};108109110AP_ADC_ADS1115::AP_ADC_ADS1115()111: _dev{}112, _gain(ADS1115_PGA_4P096)113, _channel_to_read(0)114{115_samples = NEW_NOTHROW adc_report_s[_channels_number];116}117118AP_ADC_ADS1115::~AP_ADC_ADS1115()119{120delete[] _samples;121}122123bool AP_ADC_ADS1115::init()124{125_dev = hal.i2c_mgr->get_device(ADS1115_I2C_BUS, ADS1115_I2C_ADDR);126if (!_dev) {127return false;128}129130_gain = ADS1115_PGA_4P096;131132_dev->register_periodic_callback(100000, FUNCTOR_BIND_MEMBER(&AP_ADC_ADS1115::_update, void));133134return true;135}136137bool AP_ADC_ADS1115::_start_conversion(uint8_t channel)138{139struct PACKED {140uint8_t reg;141be16_t val;142} config;143144config.reg = ADS1115_RA_CONFIG;145config.val = htobe16(ADS1115_OS_ACTIVE | _gain | mux_table[channel] |146ADS1115_MODE_SINGLESHOT | ADS1115_COMP_QUE_DISABLE |147ADS1115_RATE_250);148149return _dev->transfer((uint8_t *)&config, sizeof(config), nullptr, 0);150}151152size_t AP_ADC_ADS1115::read(adc_report_s *report, size_t length) const153{154for (size_t i = 0; i < length; i++) {155report[i].data = _samples[i].data;156report[i].id = _samples[i].id;157}158159return length;160}161162float AP_ADC_ADS1115::_convert_register_data_to_mv(int16_t word) const163{164165float pga;166167switch (_gain) {168case ADS1115_PGA_6P144:169pga = ADS1115_MV_6P144;170break;171case ADS1115_PGA_4P096:172pga = ADS1115_MV_4P096;173break;174case ADS1115_PGA_2P048:175pga = ADS1115_MV_2P048;176break;177case ADS1115_PGA_1P024:178pga = ADS1115_MV_1P024;179break;180case ADS1115_PGA_0P512:181pga = ADS1115_MV_0P512;182break;183case ADS1115_PGA_0P256:184pga = ADS1115_MV_0P256;185break;186case ADS1115_PGA_0P256B:187pga = ADS1115_MV_0P256B;188break;189case ADS1115_PGA_0P256C:190pga = ADS1115_MV_0P256C;191break;192default:193pga = 0.0f;194DEV_PRINTF("Wrong gain");195AP_HAL::panic("ADS1115: wrong gain selected");196break;197}198199return (float) word * pga;200}201202void AP_ADC_ADS1115::_update()203{204uint8_t config[2];205be16_t val;206207if (!_dev->read_registers(ADS1115_RA_CONFIG, config, sizeof(config))) {208error("_dev->read_registers failed in ADS1115");209return;210}211212/* check rdy bit */213if ((config[1] & 0x80) != 0x80 ) {214return;215}216217if (!_dev->read_registers(ADS1115_RA_CONVERSION, (uint8_t *)&val, sizeof(val))) {218return;219}220221float sample = _convert_register_data_to_mv(be16toh(val));222223_samples[_channel_to_read].data = sample;224_samples[_channel_to_read].id = _channel_to_read;225226/* select next channel */227_channel_to_read = (_channel_to_read + 1) % _channels_number;228_start_conversion(_channel_to_read);229}230231232