commit aef37c6fe887cd91d0c22484a1671511a6dd4c46 Author: willem Date: Sun Nov 28 12:03:26 2021 +0100 fork from github diff --git a/.arduino-ci.yml b/.arduino-ci.yml new file mode 100644 index 0000000..e7cb463 --- /dev/null +++ b/.arduino-ci.yml @@ -0,0 +1,11 @@ +compile: + # Choosing to run compilation tests on 2 different Arduino platforms + platforms: + - uno + # - due + # - zero + # - leonardo + - m4 + - esp32 + # - esp8266 + # - mega2560 \ No newline at end of file diff --git a/.github/workflows/arduino-lint.yml b/.github/workflows/arduino-lint.yml new file mode 100644 index 0000000..b2ca058 --- /dev/null +++ b/.github/workflows/arduino-lint.yml @@ -0,0 +1,13 @@ + +name: Arduino-lint + +on: [push, pull_request] +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: arduino/arduino-lint-action@v1 + with: + library-manager: update + compliance: strict diff --git a/.github/workflows/arduino_test_runner.yml b/.github/workflows/arduino_test_runner.yml new file mode 100644 index 0000000..096b975 --- /dev/null +++ b/.github/workflows/arduino_test_runner.yml @@ -0,0 +1,17 @@ +--- +name: Arduino CI + +on: [push, pull_request] + +jobs: + runTest: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.6 + - run: | + gem install arduino_ci + arduino_ci.rb diff --git a/.github/workflows/jsoncheck.yml b/.github/workflows/jsoncheck.yml new file mode 100644 index 0000000..04603d0 --- /dev/null +++ b/.github/workflows/jsoncheck.yml @@ -0,0 +1,18 @@ +name: JSON check + +on: + push: + paths: + - '**.json' + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: json-syntax-check + uses: limitusus/json-syntax-check@v1 + with: + pattern: "\\.json$" + diff --git a/ADS1X15.cpp b/ADS1X15.cpp new file mode 100644 index 0000000..4960cab --- /dev/null +++ b/ADS1X15.cpp @@ -0,0 +1,636 @@ +// +// FILE: ADS1X15.cpp +// AUTHOR: Rob Tillaart +// VERSION: 0.3.3 +// DATE: 2013-03-24 +// PUPROSE: Arduino library for ADS1015 and ADS1115 +// URL: https://github.com/RobTillaart/ADS1X15 +// +// HISTORY: +// 0.0.0 2013-03-24 initial version +// 0.0.1 2013-03-24 first working version +// 0.1.0 2017-07-31 removed pre 1.0 support; added getVoltage +// 0.2.0 2020-04-08 initial release; refactor ad fundum; +// 0.2.1 2020-08-15 fix issue 2 gain; refactor +// 0.2.2 2020-08-18 add begin(sda, scl) for ESP32 +// 0.2.3 2020-08-20 add comparator code + async mode +// 0.2.4 2020-08-26 check readme.md and minor fixes +// 0.2.5 2020-08-26 add missing readADC_Differential_X_X() +// 0.2.6 2020-09-01 fix #12 - fix getMaxVoltage + minor refactor +// 0.2.7 2020-09-27 redo readRegister() + getValue() + getError() +// 0.3.0 2021-03-29 add Wire parameter to constructors. +// 0.3.1 2021-04-25 #22, add get/setClock() for Wire speed + reset() +// 0.3.2 2021-10-07 fix build-CI; update readme + add new examples +// 0.3.3 2021-10-17 update build-CI (esp32), readme.md, keywords.txt + + +#include "ADS1X15.h" + +#define ADS1015_CONVERSION_DELAY 1 +#define ADS1115_CONVERSION_DELAY 8 + + +// Kept #defines a bit in line with Adafruit library. + +// REGISTERS +#define ADS1X15_REG_CONVERT 0x00 +#define ADS1X15_REG_CONFIG 0x01 +#define ADS1X15_REG_LOW_THRESHOLD 0x02 +#define ADS1X15_REG_HIGH_THRESHOLD 0x03 + + +// CONFIG REGISTER + +// BIT 15 Operational Status // 1 << 15 +#define ADS1X15_OS_BUSY 0x0000 +#define ADS1X15_OS_NOT_BUSY 0x8000 +#define ADS1X15_OS_START_SINGLE 0x8000 + +// BIT 12-14 read differential +#define ADS1X15_MUX_DIFF_0_1 0x0000 +#define ADS1X15_MUX_DIFF_0_3 0x1000 +#define ADS1X15_MUX_DIFF_1_3 0x2000 +#define ADS1X15_MUX_DIFF_2_3 0x3000 +// read single +#define ADS1X15_READ_0 0x4000 // pin << 12 +#define ADS1X15_READ_1 0x5000 // pin = 0..3 +#define ADS1X15_READ_2 0x6000 +#define ADS1X15_READ_3 0x7000 + + +// BIT 9-11 gain // (0..5) << 9 +#define ADS1X15_PGA_6_144V 0x0000 // voltage +#define ADS1X15_PGA_4_096V 0x0200 // +#define ADS1X15_PGA_2_048V 0x0400 // default +#define ADS1X15_PGA_1_024V 0x0600 +#define ADS1X15_PGA_0_512V 0x0800 +#define ADS1X15_PGA_0_256V 0x0A00 + +// BIT 8 mode // 1 << 8 +#define ADS1X15_MODE_CONTINUE 0x0000 +#define ADS1X15_MODE_SINGLE 0x0100 + +// BIT 5-7 data rate sample per second // (0..7) << 5 +/* +differs for different devices, check datasheet or readme.md + +| data rate | ADS101x | ADS 111x | Notes | +|:---------:|--------:|---------:|:-------:| +| 0 | 128 | 8 | slowest | +| 1 | 250 | 16 | | +| 2 | 490 | 32 | | +| 3 | 920 | 64 | | +| 4 | 1600 | 128 | default | +| 5 | 2400 | 250 | | +| 6 | 3300 | 475 | | +| 7 | 3300 | 860 | fastest | +*/ + +// BIT 4 comparator modi // 1 << 4 +#define ADS1X15_COMP_MODE_TRADITIONAL 0x0000 +#define ADS1X15_COMP_MODE_WINDOW 0x0010 + +// BIT 3 ALERT active value // 1 << 3 +#define ADS1X15_COMP_POL_ACTIV_LOW 0x0000 +#define ADS1X15_COMP_POL_ACTIV_HIGH 0x0008 + +// BIT 2 ALERT latching // 1 << 2 +#define ADS1X15_COMP_NON_LATCH 0x0000 +#define ADS1X15_COMP_LATCH 0x0004 + +// BIT 0-1 ALERT mode // (0..3) +#define ADS1X15_COMP_QUE_1_CONV 0x0000 // trigger alert after 1 convert +#define ADS1X15_COMP_QUE_2_CONV 0x0001 // trigger alert after 2 converts +#define ADS1X15_COMP_QUE_4_CONV 0x0002 // trigger alert after 4 converts +#define ADS1X15_COMP_QUE_NONE 0x0003 // dosable comparator + + +// _CONFIG masks +// +// | bit | description | +// |:----:|:---------------------| +// | 0 | # channels | +// | 1 | - | +// | 2 | resolution | +// | 3 | - | +// | 4 | GAIN supported | +// | 5 | COMPARATOR supported | +// | 6 | - | +// | 7 | - | +// +#define ADS_CONF_CHAN_1 0x00 +#define ADS_CONF_CHAN_4 0x01 +#define ADS_CONF_RES_12 0x00 +#define ADS_CONF_RES_16 0x04 +#define ADS_CONF_NOGAIN 0x00 +#define ADS_CONF_GAIN 0x10 +#define ADS_CONF_NOCOMP 0x00 +#define ADS_CONF_COMP 0x20 + + +////////////////////////////////////////////////////// +// +// BASE CONSTRUCTOR +// +ADS1X15::ADS1X15() +{ + reset(); +} + + +////////////////////////////////////////////////////// +// +// PUBLIC +// +void ADS1X15::reset() +{ + setGain(0); // _gain = ADS1X15_PGA_6_144V; + setMode(1); // _mode = ADS1X15_MODE_SINGLE; + setDataRate(4); // middle speed, depends on device. + + // COMPARATOR variables # see notes .h + _compMode = 0; + _compPol = 1; + _compLatch = 0; + _compQueConvert = 3; +} + + +#if defined (ESP8266) || defined(ESP32) +bool ADS1X15::begin(uint8_t sda, uint8_t scl) +{ + _wire = &Wire; + _wire->begin(sda, scl); + if ((_address < 0x48) || (_address > 0x4B)) return false; + if (! isConnected()) return false; + return true; +} +#endif + + +bool ADS1X15::begin() +{ + _wire->begin(); + if ((_address < 0x48) || (_address > 0x4B)) return false; + if (! isConnected()) return false; + return true; +} + + +bool ADS1X15::isBusy() +{ + return isReady() == false; +} + + +bool ADS1X15::isReady() +{ + uint16_t val = _readRegister(_address, ADS1X15_REG_CONFIG); + return ((val & ADS1X15_OS_NOT_BUSY) > 0); +} + + +bool ADS1X15::isConnected() +{ + _wire->beginTransmission(_address); + return (_wire->endTransmission() == 0); +} + + +void ADS1X15::setGain(uint8_t gain) +{ + if (!(_config & ADS_CONF_GAIN)) gain = 0; + switch (gain) + { + default: // catch invalid values and go for the safest gain. + case 0: _gain = ADS1X15_PGA_6_144V; break; + case 1: _gain = ADS1X15_PGA_4_096V; break; + case 2: _gain = ADS1X15_PGA_2_048V; break; + case 4: _gain = ADS1X15_PGA_1_024V; break; + case 8: _gain = ADS1X15_PGA_0_512V; break; + case 16: _gain = ADS1X15_PGA_0_256V; break; + } +} + + +uint8_t ADS1X15::getGain() +{ + if (!(_config & ADS_CONF_GAIN)) return 0; + switch (_gain) + { + case ADS1X15_PGA_6_144V: return 0; + case ADS1X15_PGA_4_096V: return 1; + case ADS1X15_PGA_2_048V: return 2; + case ADS1X15_PGA_1_024V: return 4; + case ADS1X15_PGA_0_512V: return 8; + case ADS1X15_PGA_0_256V: return 16; + } + _err = ADS1X15_INVALID_GAIN; + return _err; +} + + +float ADS1X15::toVoltage(int16_t val) +{ + if (val == 0) return 0; + + float volts = getMaxVoltage(); + if (volts < 0) return volts; + + volts *= val; + if (_config & ADS_CONF_RES_16) + { + volts /= 32767; // val = 16 bits - sign bit = 15 bits mantissa + } + else + { + volts /= 2047; // val = 12 bits - sign bit = 11 bit mantissa + } + return volts; +} + + +float ADS1X15::getMaxVoltage() +{ + switch (_gain) + { + case ADS1X15_PGA_6_144V: return 6.144; + case ADS1X15_PGA_4_096V: return 4.096; + case ADS1X15_PGA_2_048V: return 2.048; + case ADS1X15_PGA_1_024V: return 1.024; + case ADS1X15_PGA_0_512V: return 0.512; + case ADS1X15_PGA_0_256V: return 0.256; + } + _err = ADS1X15_INVALID_VOLTAGE; + return _err; +} + + +void ADS1X15::setMode(uint8_t mode) +{ + switch (mode) + { + case 0: _mode = ADS1X15_MODE_CONTINUE; break; + default: + case 1: _mode = ADS1X15_MODE_SINGLE; break; + } +} + + +uint8_t ADS1X15::getMode(void) +{ + switch (_mode) + { + case ADS1X15_MODE_CONTINUE: return 0; + case ADS1X15_MODE_SINGLE: return 1; + } + _err = ADS1X15_INVALID_MODE; + return _err; +} + + +void ADS1X15::setDataRate(uint8_t dataRate) +{ + _datarate = dataRate; + if (_datarate > 7) _datarate = 4; // default + _datarate <<= 5; // convert 0..7 to mask needed. +} + + +uint8_t ADS1X15::getDataRate(void) +{ + return (_datarate >> 5) & 0x07; // convert mask back to 0..7 +} + + +int16_t ADS1X15::readADC(uint8_t pin) +{ + if (pin >= _maxPorts) return 0; + uint16_t mode = ((4 + pin) << 12); // pin to mask + return _readADC(mode); +} + + +void ADS1X15::requestADC_Differential_0_1() +{ + _requestADC(ADS1X15_MUX_DIFF_0_1); +} + + +int16_t ADS1X15::readADC_Differential_0_1() +{ + return _readADC(ADS1X15_MUX_DIFF_0_1); +} + + +void ADS1X15::requestADC(uint8_t pin) +{ + if (pin >= _maxPorts) return; + uint16_t mode = ((4 + pin) << 12); // pin to mask + _requestADC(mode); +} + + +int16_t ADS1X15::getValue() +{ + int16_t raw = _readRegister(_address, ADS1X15_REG_CONVERT); + if (_bitShift) raw >>= _bitShift; // Shift 12-bit results + return raw; +} + + +void ADS1X15::setComparatorThresholdLow(int16_t lo) +{ + _writeRegister(_address, ADS1X15_REG_LOW_THRESHOLD, lo); +}; + + +int16_t ADS1X15::getComparatorThresholdLow() +{ + return _readRegister(_address, ADS1X15_REG_LOW_THRESHOLD); +}; + + +void ADS1X15::setComparatorThresholdHigh(int16_t hi) +{ + _writeRegister(_address, ADS1X15_REG_HIGH_THRESHOLD, hi); +}; + + +int16_t ADS1X15::getComparatorThresholdHigh() +{ + return _readRegister(_address, ADS1X15_REG_HIGH_THRESHOLD); +}; + + +int8_t ADS1X15::getError() +{ + int8_t rv = _err; + _err = ADS1X15_OK; + return rv; +} + + +void ADS1X15::setWireClock(uint32_t clockSpeed) +{ + _clockSpeed = clockSpeed; + _wire->setClock(_clockSpeed); +} + + +// TODO: get the real clock speed from the I2C interface if possible. +// ESP ==> ?? +uint32_t ADS1X15::getWireClock() +{ +#if defined(__AVR__) + uint32_t speed = F_CPU / ((TWBR * 2) + 16); + return speed; + +#elif defined(ESP32) + return (uint32_t) _wire->getClock(); + +// #elif defined(ESP8266) +// core_esp8266_si2c.cpp holds the data see => void Twi::setClock( +// not supported. +// return -1; + +#else // best effort ... + return _clockSpeed; +#endif +} + + +////////////////////////////////////////////////////// +// +// PROTECTED +// +int16_t ADS1X15::_readADC(uint16_t readmode) +{ + _requestADC(readmode); + if (_mode == ADS1X15_MODE_SINGLE) + { + while ( isBusy() ) yield(); // wait for conversion; yield for ESP. + } + else + { + delay(_conversionDelay); // TODO needed in continuous mode? + } + return getValue(); +} + +void ADS1X15::_requestADC(uint16_t readmode) +{ + // write to register is needed in continuous mode as other flags can be changed + uint16_t config = ADS1X15_OS_START_SINGLE; // bit 15 force wake up if needed + config |= readmode; // bit 12-14 + config |= _gain; // bit 9-11 + config |= _mode; // bit 8 + config |= _datarate; // bit 5-7 + if (_compMode) config |= ADS1X15_COMP_MODE_WINDOW; // bit 4 comparator modi + else config |= ADS1X15_COMP_MODE_TRADITIONAL; + if (_compPol) config |= ADS1X15_COMP_POL_ACTIV_HIGH; // bit 3 ALERT active value + else config |= ADS1X15_COMP_POL_ACTIV_LOW; + if (_compLatch) config |= ADS1X15_COMP_LATCH; + else config |= ADS1X15_COMP_NON_LATCH; // bit 2 ALERT latching + config |= _compQueConvert; // bit 0..1 ALERT mode + _writeRegister(_address, ADS1X15_REG_CONFIG, config); +} + +bool ADS1X15::_writeRegister(uint8_t address, uint8_t reg, uint16_t value) +{ + _wire->beginTransmission(address); + _wire->write((uint8_t)reg); + _wire->write((uint8_t)(value >> 8)); + _wire->write((uint8_t)(value & 0xFF)); + return (_wire->endTransmission() == 0); +} + +uint16_t ADS1X15::_readRegister(uint8_t address, uint8_t reg) +{ + _wire->beginTransmission(address); + _wire->write(reg); + _wire->endTransmission(); + + int rv = _wire->requestFrom(address, (uint8_t) 2); + if (rv == 2) + { + uint16_t value = _wire->read() << 8; + value += _wire->read(); + return value; + } + return 0x0000; +} + + +/////////////////////////////////////////////////////////////////////////// +// +// ADS1013 +// +ADS1013::ADS1013(uint8_t address, TwoWire *wire) +{ + _address = address; + _wire = wire; + _config = ADS_CONF_NOCOMP | ADS_CONF_NOGAIN | ADS_CONF_RES_12 | ADS_CONF_CHAN_1; + _conversionDelay = ADS1015_CONVERSION_DELAY; + _bitShift = 4; + _maxPorts = 1; +} + + +/////////////////////////////////////////////////////////////////////////// +// +// ADS1014 +// +ADS1014::ADS1014(uint8_t address, TwoWire *wire) +{ + _address = address; + _wire = wire; + _config = ADS_CONF_COMP | ADS_CONF_GAIN | ADS_CONF_RES_12 | ADS_CONF_CHAN_1; + _conversionDelay = ADS1015_CONVERSION_DELAY; + _bitShift = 4; + _maxPorts = 1; +} + + +/////////////////////////////////////////////////////////////////////////// +// +// ADS1015 +// +ADS1015::ADS1015(uint8_t address, TwoWire *wire) +{ + _address = address; + _wire = wire; + _config = ADS_CONF_COMP | ADS_CONF_GAIN | ADS_CONF_RES_12 | ADS_CONF_CHAN_4; + _conversionDelay = ADS1015_CONVERSION_DELAY; + _bitShift = 4; + _maxPorts = 4; +} + +int16_t ADS1015::readADC_Differential_0_3() +{ + return _readADC(ADS1X15_MUX_DIFF_0_3); +} + +int16_t ADS1015::readADC_Differential_1_3() +{ + return _readADC(ADS1X15_MUX_DIFF_1_3); +} + +int16_t ADS1015::readADC_Differential_2_3() +{ + return _readADC(ADS1X15_MUX_DIFF_2_3); +} + +int16_t ADS1015::readADC_Differential_0_2() +{ + return readADC(2) - readADC(0); +} + +int16_t ADS1015::readADC_Differential_1_2() +{ + return readADC(2) - readADC(1);; +} + + + +void ADS1015::requestADC_Differential_0_3() +{ + _requestADC(ADS1X15_MUX_DIFF_0_3); +} + +void ADS1015::requestADC_Differential_1_3() +{ + _requestADC(ADS1X15_MUX_DIFF_1_3); +} + +void ADS1015::requestADC_Differential_2_3() +{ + _requestADC(ADS1X15_MUX_DIFF_2_3); +} + + +/////////////////////////////////////////////////////////////////////////// +// +// ADS1113 +// +ADS1113::ADS1113(uint8_t address, TwoWire *wire) +{ + _address = address; + _wire = wire; + _config = ADS_CONF_NOCOMP | ADS_CONF_NOGAIN | ADS_CONF_RES_16 | ADS_CONF_CHAN_1; + _conversionDelay = ADS1115_CONVERSION_DELAY; + _bitShift = 0; + _maxPorts = 1; +} + + +/////////////////////////////////////////////////////////////////////////// +// +// ADS1114 +// +ADS1114::ADS1114(uint8_t address, TwoWire *wire) +{ + _address = address; + _wire = wire; + _config = ADS_CONF_COMP | ADS_CONF_GAIN | ADS_CONF_RES_16 | ADS_CONF_CHAN_1; + _conversionDelay = ADS1115_CONVERSION_DELAY; + _bitShift = 0; + _maxPorts = 1; +} + + +/////////////////////////////////////////////////////////////////////////// +// +// ADS1115 +// +ADS1115::ADS1115(uint8_t address, TwoWire *wire) +{ + _address = address; + _wire = wire; + _config = ADS_CONF_COMP | ADS_CONF_GAIN | ADS_CONF_RES_16 | ADS_CONF_CHAN_4; + _conversionDelay = ADS1115_CONVERSION_DELAY; + _bitShift = 0; + _maxPorts = 4; +} + +int16_t ADS1115::readADC_Differential_0_3() +{ + return _readADC(ADS1X15_MUX_DIFF_0_3); +} + +int16_t ADS1115::readADC_Differential_1_3() +{ + return _readADC(ADS1X15_MUX_DIFF_1_3); +} + +int16_t ADS1115::readADC_Differential_2_3() +{ + return _readADC(ADS1X15_MUX_DIFF_2_3); +} + +int16_t ADS1115::readADC_Differential_0_2() +{ + return readADC(2) - readADC(0); +} + +int16_t ADS1115::readADC_Differential_1_2() +{ + return readADC(2) - readADC(1);; +} + +void ADS1115::requestADC_Differential_0_3() +{ + _requestADC(ADS1X15_MUX_DIFF_0_3); +} + +void ADS1115::requestADC_Differential_1_3() +{ + _requestADC(ADS1X15_MUX_DIFF_1_3); +} + +void ADS1115::requestADC_Differential_2_3() +{ + _requestADC(ADS1X15_MUX_DIFF_2_3); +} + +// --- END OF FILE diff --git a/ADS1X15.h b/ADS1X15.h new file mode 100644 index 0000000..2ec9dd7 --- /dev/null +++ b/ADS1X15.h @@ -0,0 +1,224 @@ +#pragma once +// +// FILE: ADS1X15.H +// AUTHOR: Rob Tillaart +// VERSION: 0.3.3 +// DATE: 2013-03-24 +// PUPROSE: Arduino library for ADS1015 and ADS1115 +// URL: https://github.com/RobTillaart/ADS1X15 +// + + +#include "Arduino.h" +#include "Wire.h" + +#define ADS1X15_LIB_VERSION (F("0.3.3")) + +// allow compile time default address +// address in { 0x48, 0x49, 0x4A, 0x4B }, no test... +#ifndef ADS1015_ADDRESS +#define ADS1015_ADDRESS 0x48 +#endif + +#ifndef ADS1115_ADDRESS +#define ADS1115_ADDRESS 0x48 +#endif + + +#define ADS1X15_OK 0 +#define ADS1X15_INVALID_VOLTAGE -100 +#define ADS1X15_INVALID_GAIN 0xFF +#define ADS1X15_INVALID_MODE 0xFE + + +class ADS1X15 +{ +public: + void reset(); + +#if defined (ESP8266) || defined(ESP32) + bool begin(uint8_t sda, uint8_t scl); +#endif + bool begin(); + bool isConnected(); + + // GAIN + // 0 = ±6.144V default + // 1 = ±4.096V + // 2 = ±2.048V + // 4 = ±1.024V + // 8 = ±0.512V + // 16 = ±0.256V + void setGain(uint8_t gain = 0); // invalid values are mapped to 0 (default). + uint8_t getGain(); // 0xFF == invalid gain error. + + // both may return ADS1X15_INVALID_VOLTAGE if the gain is invalid. + float toVoltage(int16_t val = 1); // converts raw to voltage + float getMaxVoltage(); // -100 == invalid voltage error + + // 0 = CONTINUOUS + // 1 = SINGLE default + void setMode(uint8_t mode = 1); // invalid values are mapped to 1 (default) + uint8_t getMode(); // 0xFE == invalid mode error. + + // 0 = slowest + // 7 = fastest + // 4 = default + void setDataRate(uint8_t dataRate = 4); // invalid values are mapped on 4 (default) + uint8_t getDataRate(); // actual speed depends on device + + int16_t readADC(uint8_t pin); + int16_t readADC_Differential_0_1(); + + // used by continuous mode and async mode. + int16_t getLastValue() { return getValue(); }; // will be obsolete in the future 0.4.0 + int16_t getValue(); + + + // ASYNC INTERFACE + // requestADC(pin) -> isBusy() or isReady() -> getValue(); + // see examples + void requestADC(uint8_t pin); + void requestADC_Differential_0_1(); + bool isBusy(); + bool isReady(); + + + // COMPARATOR + // 0 = TRADITIONAL > high => on < low => off + // else = WINDOW > high or < low => on between => off + void setComparatorMode(uint8_t mode) { _compMode = mode == 0 ? 0 : 1; }; + uint8_t getComparatorMode() { return _compMode; }; + + // 0 = LOW (default) + // else = HIGH + void setComparatorPolarity(uint8_t pol) { _compPol = pol ? 0 : 1; }; + uint8_t getComparatorPolarity() { return _compPol; }; + + // 0 = NON LATCH + // else = LATCH + void setComparatorLatch(uint8_t latch) { _compLatch = latch ? 0 : 1; }; + uint8_t getComparatorLatch() { return _compLatch; }; + + // 0 = trigger alert after 1 conversion + // 1 = trigger alert after 2 conversions + // 2 = trigger alert after 4 conversions + // 3 = Disable comparator = default, also for all other values. + void setComparatorQueConvert(uint8_t mode) { _compQueConvert = (mode < 3) ? mode : 3; }; + uint8_t getComparatorQueConvert() { return _compQueConvert; }; + + void setComparatorThresholdLow(int16_t lo); + int16_t getComparatorThresholdLow(); + void setComparatorThresholdHigh(int16_t hi); + int16_t getComparatorThresholdHigh(); + + + int8_t getError(); + + void setWireClock(uint32_t clockSpeed); + // proto - getWireClock returns the value set by setWireClock not necessary the actual value + uint32_t getWireClock(); + +protected: + ADS1X15(); + + // CONFIGURATION + // BIT DESCRIPTION + // 0 # channels 0 == 1 1 == 4; + // 1 0 + // 2 # resolution 0 == 12 1 == 16 + // 3 0 + // 4 has gain 0 = NO 1 = YES + // 5 has comparator 0 = NO 1 = YES + // 6 0 + // 7 0 + uint8_t _config; + uint8_t _maxPorts; + uint8_t _address; + uint8_t _conversionDelay; + uint8_t _bitShift; + uint16_t _gain; + uint16_t _mode; + uint16_t _datarate; + + // COMPARATOR variables + // TODO merge these into one COMPARATOR MASK? (low priority) + // would speed up code in _requestADC() and save 3 bytes RAM. + // TODO boolean flags for first three, or make it mask value that + // can be or-ed. (low priority) + uint8_t _compMode; + uint8_t _compPol; + uint8_t _compLatch; + uint8_t _compQueConvert; + + int16_t _readADC(uint16_t readmode); + void _requestADC(uint16_t readmode); + bool _writeRegister(uint8_t address, uint8_t reg, uint16_t value); + uint16_t _readRegister(uint8_t address, uint8_t reg); + int8_t _err = ADS1X15_OK; + + TwoWire* _wire; + uint32_t _clockSpeed = 0; +}; + +/////////////////////////////////////////////////////////////////////////// +// +// Derived classes from ADS1X15 +// +class ADS1013 : public ADS1X15 +{ +public: + ADS1013(uint8_t Address = ADS1015_ADDRESS, TwoWire *wire = &Wire); +}; + +class ADS1014 : public ADS1X15 +{ +public: + ADS1014(uint8_t Address = ADS1015_ADDRESS, TwoWire *wire = &Wire); +}; + +class ADS1015 : public ADS1X15 +{ +public: + ADS1015(uint8_t Address = ADS1015_ADDRESS, TwoWire *wire = &Wire); + int16_t readADC_Differential_0_3(); + int16_t readADC_Differential_1_3(); + int16_t readADC_Differential_2_3(); + int16_t readADC_Differential_0_2(); // not possible in async + int16_t readADC_Differential_1_2(); // not possible in async + void requestADC_Differential_0_3(); + void requestADC_Differential_1_3(); + void requestADC_Differential_2_3(); +}; + +/////////////////////////////////////////////////////////////////////////// +// +// Derived classes from ADS1X15 +// +class ADS1113 : public ADS1X15 +{ +public: + ADS1113(uint8_t address = ADS1115_ADDRESS, TwoWire *wire = &Wire); +}; + +class ADS1114 : public ADS1X15 +{ +public: + ADS1114(uint8_t address = ADS1115_ADDRESS, TwoWire *wire = &Wire); +}; + +class ADS1115 : public ADS1X15 +{ +public: + ADS1115(uint8_t address = ADS1115_ADDRESS, TwoWire *wire = &Wire); + int16_t readADC_Differential_0_3(); + int16_t readADC_Differential_1_3(); + int16_t readADC_Differential_2_3(); + int16_t readADC_Differential_0_2(); // not possible in async + int16_t readADC_Differential_1_2(); // not possible in async + void requestADC_Differential_0_3(); + void requestADC_Differential_1_3(); + void requestADC_Differential_2_3(); +}; + +// --- END OF FILE --- diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..39d07e3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2013-2021 Rob Tillaart + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..441b626 --- /dev/null +++ b/README.md @@ -0,0 +1,322 @@ + +[![Arduino CI](https://github.com/RobTillaart/ADS1X15/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci) +[![Arduino-lint](https://github.com/RobTillaart/ADS1X15/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/ADS1X15/actions/workflows/arduino-lint.yml) +[![JSON check](https://github.com/RobTillaart/ADS1X15/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/ADS1X15/actions/workflows/jsoncheck.yml) +[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/ADS1X15/blob/master/LICENSE) +[![GitHub release](https://img.shields.io/github/release/RobTillaart/ADS1X15.svg?maxAge=3600)](https://github.com/RobTillaart/ADS1X15/releases) + +# ADS1X15 + +Arduino library for I2C ADC ADS1015, ADS1115, + + +## Description + +This library should work for the devices mentioned below, +although not all sensors support all functionality. + +| Device | Channels | Resolution | Max sps | Comparator | ProgGainAMP | Notes | +|:-------:|:--------:|:----------:|:-------:|:----------:|:-----------:|:-------| +| ADS1013 | 1 | 12 | 3300 | N | N | | +| ADS1014 | 1 | 12 | 3300 | Y | Y | | +| ADS1015 | 4 | 12 | 3300 | Y | Y | | +| ADS1113 | 1 | 16 | 860 | N | N | | +| ADS1114 | 1 | 16 | 860 | Y | Y | | +| ADS1115 | 4 | 16 | 860 | Y | Y | Tested | + +As the 1015 and the 1115 are both 4 channels these are the most +interesting from functionality point of view as these can also do +differential measurement. + + +## Interface + +The address of the ADS1113/4/5 is determined by to which pin the ADDR +is connected to: + +| ADDR pin connected to | Address | Notes | +|:---------------------:|:-------:|:-------:| +| GND | 0x48 | default | +| VDD | 0x49 | | +| SDA | 0x4A | | +| SCL | 0x4B | | + + +- **ADS1x15()** constructor, should not be used. +- **ADS1013(address, TwoWire \*wire = &Wire)** Constructor with device address, +and optional the Wire interface as parameter. +- **ADS1014(address, TwoWire \*wire = &Wire)** Constructor with device address, +and optional the Wire interface as parameter. +- **ADS1015(address, TwoWire \*wire = &Wire)** Constructor with device address, +and optional the Wire interface as parameter. +- **ADS1113(address, TwoWire \*wire = &Wire)** Constructor with device address, +and optional the Wire interface as parameter. +- **ADS1114(address, TwoWire \*wire = &Wire)** Constructor with device address, +and optional the Wire interface as parameter. +- **ADS1115(address, TwoWire \*wire = &Wire)** Constructor with device address, +and optional the Wire interface as parameter. + +The function **void setWireClock(uint32_t speed)** is used to set the clock speed +of the used I2C interface. + +The function **uint32_t getWireClock()** is a prototype. +It returns the value set by setWireClock(). +This is not necessary the actual value. +When no value is set **getWireClock()** returns 0. +Need to implement a read / calculate from low level I2C code (e.g. TWBR on AVR), +better the Arduino Wire lib should support this call (ESP32 does). + +After construction the **ADS.begin()** need to be called. This will return false +if an invalid address is used. +The function **bool isConnected()** can be used to verify the reading of the ADS. +The function **void reset()** is sets the parameters to their initial value as +in the constructor. + + +#### Programmable Gain + +- **void setGain(uint8_t gain)** set the gain value, indicating the maxVoltage that can be measured +Adjusting the gain allows one to make more precise measurements. +Note: the gain is not set in the device until an explicit read/request of the ADC (any read call will do). +See table below. +- **uint8_t getGain()** returns the gain value (index). + +| PGA value | Max Voltage | Notes | +|:---------:|:-----------:|:-------:| +| 0 | ±6.144V | default | +| 1 | ±4.096V | | +| 2 | ±2.048V | | +| 4 | ±1.024V | | +| 8 | ±0.512V | | +| 16 | ±0.256V | | + +- **float getMaxVoltage()** returns the max voltage with the current gain. +- **float toVoltage(int16_t raw = 1)** converts a raw measurement to a voltage. +Can be used for normal and differential measurements. +The default value of 1 returns the conversion factor for any raw number. + +The voltage factor can also be used to set HIGH and LOW threshold registers +with a voltage in the comparator mode. +Check the examples. + +```cpp + float f = ADS.toVoltage(); + ADS.setComparatorThresholdLow( 3.0 / f ); + ADS.setComparatorThresholdLow( 4.3 / f ); +``` + + +#### Operational mode + +The ADS sensor can operate in single shot or continuous mode. +Depending on how often one needs a conversion one can tune the mode. +- **void setMode(uint8_t mode)** 0 = CONTINUOUS, 1 = SINGLE (default) +Note: the mode is not set in the device until an explicit read/request of the ADC (any read call will do). +- **uint8_t getMode()** returns current mode 0 or 1, or ADS1X15_INVALID_MODE = 0xFE. + + + +#### Data rate + +- **void setDataRate(uint8_t dataRate)** Data rate depends on type of device. +For all devices the index 0..7 can be used, see table below. +Values above 7 ==> will be set to the default 4. +Note: the data rate is not set in the device until an explicit read/request of the ADC (any read call will do). +- **uint8_t getDataRate()** returns the current data rate (index). + +The library has no means to convert this index to the actual numbers +as that would take 32 bytes. + +Data rate in samples per second, based on datasheet numbers. + +| data rate | ADS101x | ADS 111x | Notes | +|:---------:|--------:|---------:|:-------:| +| 0 | 128 | 8 | slowest | +| 1 | 250 | 16 | | +| 2 | 490 | 32 | | +| 3 | 920 | 64 | | +| 4 | 1600 | 128 | default | +| 5 | 2400 | 250 | | +| 6 | 3300 | 475 | | +| 7 | 3300 | 860 | fastest | + + +#### ReadADC Single mode + +Reading the ADC is very straightforward, the **readADC()** function handles +all in one call. Under the hood it uses the asynchronous calls. +- **int16_t readADC(uint8_t pin)** normal ADC functionality, pin = 0..3. +If the pin number is out of range, this function will return 0. + +To read the ADC in an asynchronous way (e.g. to minimize blocking) one has to use three calls: +- **void requestADC(uint8_t pin)** Start the conversion. pin = 0..3. +- **bool isBusy()** Is the conversion not ready yet? Works only in SINGLE mode! +- **bool isReady()** Is the conversion ready? Works only in SINGLE mode! (= wrapper around **isBusy()** ) +- **int16_t getValue()** Read the result of the conversion. + + +in terms of code +```cpp + + void setup() + { + // other setup things here + ADS.setMode(1); // SINGLE SHOT MODE + ADS.requestADC(pin); + } + + + void loop() + { + if (ADS.isReady()) + { + val = ADS.getValue(); + ADS.requestADC(pin); // request new conversion + } + // do other things here + } + +``` +See examples + + +## ReadADC Differential + +For reading the ADC in a differential way there are 4 calls possible. +- **int16_t readADC_Differential_0_1()** returns the difference between 2 ADC pins. +- **int16_t readADC_Differential_0_3()** ADS1x15 only +- **int16_t readADC_Differential_1_3()** ADS1x15 only +- **int16_t readADC_Differential_2_3()** ADS1x15 only +- **int16_t readADC_Differential_0_2()** ADS1x15 only - in software (no async equivalent) +- **int16_t readADC_Differential_1_2()** ADS1x15 only - in software (no async equivalent) + +The differential reading of the ADC can also be done with asynchronous calls. +- **void requestADC_Differential_0_1()** starts conversion for differential reading +- **void requestADC_Differential_0_3()** ADS1x15 only +- **void requestADC_Differential_1_3()** ADS1x15 only +- **void requestADC_Differential_2_3()** ADS1x15 only + +After one of these calls one need to call +- **int16_t getValue()** Read the result of the last conversion. + +The readiness of a CONTINUOUS conversion can only be detected by the RDY line. +Use interrupt for this, see examples. + + +#### ReadADC continuous mode + +To use the continuous mode one need three calls +- **void setMode(0)** 0 = CONTINUOUS, 1 = SINGLE (default). +Note: the mode is not set in the device until an explicit read/request of the ADC (any read call will do). +- **int16_t readADC(uint8_t pin)** or **void requestADC(uint8_t pin)** to get the continuous mode started. +- **int16_t getValue()** to return the last value read by the device. +Note this can be a different pin, so be warned. +Calling this over and over again can give the same value multiple times. + +By using **bool isBusy()** or **bool isReady()** one can wait until new data is available. +Note this only works in the SINGLE_SHOT modus. + +In continuous mode one should use the **ALERT/RDY** pin to trigger via hardware the readiness of the conversion. +This can be done by using an interrupt. + +See examples. + + +#### Threshold registers ==> mode RDY pin + +If the thresholdHigh is set to 0x0100 and the thresholdLow to 0x0000 +the **ALERT/RDY** pin is triggered when a conversion is ready. +- **void setComparatorThresholdLow(int16_t lo)** writes value to device directly. +- **void setComparatorThresholdHigh(int16_t hi)** writes value to device directly. +- **int16_t getComparatorThresholdLow()** reads value from device. +- **int16_t getComparatorThresholdHigh()** reads value from device. + +See examples. + + +## Comparator + +Please read Page 15 of the datasheet as the behaviour of the +comparator is not trivial. + +NOTE: all comparator settings are copied to the device only after an explicit +**readADC()** or **requestADC()** + + +#### Comparator Mode + +When configured as a **TRADITIONAL** comparator, the **ALERT/RDY** pin asserts +(active low by default) when conversion data exceed the limit set in the +high threshold register. The comparator then de-asserts when the input +signal falls below the low threshold register value. + +- **void setComparatorMode(uint8_t mode)** value 0 = TRADITIONAL 1 = WINDOW, +- **uint8_t getComparatorMode()** returns value set. + + +If the comparator **LATCH** is set, the **ALERT/RDY** pin asserts and it will be +reset after reading the sensor (conversion register) again. +*An SMB alert command (00011001) on the I2C bus will also reset the alert state.* +*Not implemented in the library (yet)* + +In **WINDOW** comparator mode, the **ALERT/RDY** pin asserts if conversion data exceeds +the high threshold register or falls below the low threshold register. +In this mode the alert is held if the **LATCH** is set. This is similar as above. + + +#### Polarity + +Default state of the **ALERT/RDY** pin is **LOW**, can be to set **HIGH**. + +- **void setComparatorPolarity(uint8_t pol)** +Flag is only explicitly set after a **readADC()** or a **requestADC()** +- **uint8_t getComparatorPolarity()** returns value set. + + +#### Latch + +Holds the **ALERT/RDY** to **HIGH** (or **LOW** depending on polarity) after triggered +even if actual value has been 'restored to normal' value. + +- **void setComparatorLatch(uint8_t latch)** 0 = NO LATCH, not 0 = LATCH +- **uint8_t getComparatorLatch()** returns value set. + + +#### QueConvert + +Set the number of conversions before trigger activates. +The **void setComparatorQueConvert(uint8_t mode)** is used to set the number of +conversions that exceed the threshold before the **ALERT/RDY** pin is set **HIGH**. +A value of 3 (or above) effectively disables the comparator. See table below. + +- **void setComparatorQueConvert(uint8_t mode)** See table below. +- **uint8_t getComparatorQueConvert()** returns value set. + +| value | meaning | Notes | +|:-----:|:----------------------------------|:--------| +| 0 | trigger alert after 1 conversion | | +| 1 | trigger alert after 2 conversions | | +| 2 | trigger alert after 4 conversions | | +| 3 | Disable comparator | default | + + +#### Threshold registers comparator mode + +Depending on the comparator mode **TRADITIONAL** or **WINDOW** the thresholds registers +mean something different see - Comparator Mode above or datasheet. +- **void setComparatorThresholdLow(int16_t lo)** set the low threshold; take care the hi >= lo. +- **void setComparatorThresholdHigh(int16_t hi)** set the high threshold; take care the hi >= lo. +- **int16_t getComparatorThresholdLow()** reads value from device. +- **int16_t getComparatorThresholdHigh()** reads value from device. + + +## Future ideas & improvements + +- Improve documentation +- More examples ? +- SMB alert command (00011001) on I2C bus? + + +## Operation + +See examples diff --git a/examples/ADS_async_16_channel/ADS_async_16_channel.ino b/examples/ADS_async_16_channel/ADS_async_16_channel.ino new file mode 100644 index 0000000..4fcc8bb --- /dev/null +++ b/examples/ADS_async_16_channel/ADS_async_16_channel.ino @@ -0,0 +1,119 @@ +// +// FILE: ADS_async_16_channel.ino +// AUTHOR: Rob Tillaart +// VERSION: 0.1.0 +// PURPOSE: demo reading four ADS1115 modules in parallel +// DATE: 2021-07-06 +// URL: https://github.com/RobTillaart/ADS1X15 + + +// Note all IO with the sensors are guarded by an isConnected() +// this is max robust, in non critical application one may either +// cache the value or only verify it in setup (least robust). +// Less robust may cause the application to hang - watchdog reset ? + + +#include "ADS1X15.h" + + +ADS1115 ADS[4]; +uint16_t val[16]; +int idx = 0; + +uint32_t last = 0, now = 0; + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("ADS1X15_LIB_VERSION: "); + Serial.println(ADS1X15_LIB_VERSION); + + for (uint8_t i = 0; i < 4; i++) + { + uint8_t address = 0x48 + i; + ADS[i] = ADS1115(address); + + Serial.print(address, HEX); + Serial.print(" "); + Serial.println(ADS[i].begin() ? "connected" : "not connected"); + + ADS[i].setDataRate(4); // 7 is fastest, but more noise + } + ADS_request_all(); +} + + +void loop() +{ + // Serial.println(__FUNCTION__); + // wait until all is read... + while (ADS_read_all()); + + // we have all values + ADS_print_all(); + + delay(1000); // wait a second. + ADS_request_all(); +} + + +void ADS_request_all() +{ + // Serial.println(__FUNCTION__); + for (int i = 0; i < 4; i++) + { + if (ADS[i].isConnected()) ADS[i].requestADC(idx); + } +} + + +bool ADS_read_all() +{ + for (int i = 0; i < 4; i++) + { + if (ADS[i].isConnected() && ADS[i].isBusy()) return true; + } + // Serial.print("IDX:\t"); + // Serial.println(idx); + for (int i = 0; i < 4; i++) + { + if (ADS[i].isConnected()) + { + val[i * 4 + idx] = ADS[i].getValue(); + } + } + idx++; + if (idx < 4) + { + ADS_request_all(); + return true; + } + idx = 0; + return false; +} + + +void ADS_print_all() +{ + // Serial.println(__FUNCTION__); + // TIMESTAMP + now = millis(); + Serial.print(now - last); + last = now; + Serial.println(); + + // PRINT ALL VALUES + for (int i = 0; i < 4; i++) + { + for (int j = 0; j < 4; j++) + { + Serial.print(val[j * 4 + i]); + Serial.print("\t"); + } + Serial.println(); + } + Serial.println(); +} + +// -- END OF FILE -- diff --git a/examples/ADS_async_8_channel/ADS_async_8_channel.ino b/examples/ADS_async_8_channel/ADS_async_8_channel.ino new file mode 100644 index 0000000..3e0ad54 --- /dev/null +++ b/examples/ADS_async_8_channel/ADS_async_8_channel.ino @@ -0,0 +1,136 @@ +// +// FILE: ADS_async_8_channel.ino +// AUTHOR: Rob Tillaart +// PURPOSE: demo reading two ADS1115 modules in parallel +// DATE: 2021-07-05 +// URL: https://github.com/RobTillaart/ADS1X15 + + +// Note all IO with the sensors are guarded by an isConnected() +// this is max robust, in non critical application one may either +// cache the value or only verify it in setup (least robust). +// Less robust may cause the application to hang - watchdog reset ? + + +#include "ADS1X15.h" + + +ADS1115 ADS0(0x48); +ADS1115 ADS1(0x49); +//ADS1115 ADS2(0x4A); +//ADS1115 ADS3(0x4B); + +int16_t val0[4] = { 0, 0, 0, 0 }; +int16_t val1[4] = { 0, 0, 0, 0 }; +//int16_t val2[4] = { 0, 0, 0, 0 }; +//int16_t val3[4] = { 0, 0, 0, 0 }; +int idx = 0; + +uint32_t lastTime = 0; + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("ADS1X15_LIB_VERSION: "); + Serial.println(ADS1X15_LIB_VERSION); + + ADS0.begin(); + ADS1.begin(); + // ADS2.begin(); + // ADS3.begin(); + + Serial.println(ADS0.isConnected()); + Serial.println(ADS1.isConnected()); + // Serial.println(ADS2.isConnected()); + // Serial.println(ADS3.isConnected()); + + ADS0.setDataRate(4); // 7 is fastest, but more noise + ADS1.setDataRate(4); + // ADS2.setDataRate(4); + // ADS3.setDataRate(4); + + idx = 0; + ADS_request_all(); +} + + +void loop() +{ + // wait until all is read... + while (ADS_read_all()); + + // we have all 8 values + ADS_print_all(); + + delay(1000); // wait a second. + ADS_request_all(); +} + + +void ADS_request_all() +{ + if (ADS0.isConnected()) ADS0.requestADC(idx); + if (ADS1.isConnected()) ADS1.requestADC(idx); + // if (ADS2.isConnected()) ADS2.requestADC(idx); + // if (ADS3.isConnected()) ADS3.requestADC(idx); +} + + +bool ADS_read_all() +{ + if (ADS0.isConnected() && ADS0.isBusy()) return true; + if (ADS1.isConnected() && ADS1.isBusy()) return true; + // if (ADS2.isConnected() && ADS2.isBusy()) return true; + // if (ADS3.isConnected() && ADS3.isBusy()) return true; + + if (ADS0.isConnected()) val0[idx] = ADS0.getValue(); + if (ADS1.isConnected()) val1[idx] = ADS1.getValue(); + // if (ADS2.isConnected()) val2[idx] = ADS2.getValue(); + // if (ADS3.isConnected()) val3[idx] = ADS3.getValue(); + idx++; + if (idx < 4) + { + ADS_request_all(); + return true; + } + idx = 0; + return false; +} + + +void ADS_print_all() +{ + uint32_t now = millis(); + Serial.println(now - lastTime); + lastTime = now; + + // PRINT ALL VALUES OF ADC0 + for (int i = 0; i < 4; i++) + { + Serial.print(val0[i]); + Serial.print("\t"); + } + // PRINT ALL VALUES OF ADC1 + for (int i = 0; i < 4; i++) + { + Serial.print(val1[i]); + Serial.print("\t"); + } + Serial.println(); + // // PRINT ALL VALUES OF ADC2 + // for (int i = 0; i < 4; i++) + // { + // Serial.print(val2[i]); + // Serial.print("\t"); + // } + // // PRINT ALL VALUES OF ADC3 + // for (int i = 0; i < 4; i++) + // { + // Serial.print(val3[i]); + // Serial.print("\t"); + // } + // Serial.println(); +} + +// -- END OF FILE -- diff --git a/examples/ADS_async_differential/ADS_async_differential.ino b/examples/ADS_async_differential/ADS_async_differential.ino new file mode 100644 index 0000000..36103c9 --- /dev/null +++ b/examples/ADS_async_differential/ADS_async_differential.ino @@ -0,0 +1,95 @@ +// +// FILE: ADS_async_differential.ino +// AUTHOR: Rob.Tillaart +// VERSION: 0.1.0 +// PURPOSE: read multiple differential continuously +// + +// test +// connect 4 potmeters +// +// GND ---[ x ]------ 5V +// | +// +// measure at x - connect to AIN0..4. +// +// + + +#include "ADS1X15.h" + +// choose you sensor +// ADS1013 ADS(0x48); +// ADS1014 ADS(0x48); +// ADS1015 ADS(0x48); +// ADS1113 ADS(0x48); +// ADS1114 ADS(0x48); +ADS1115 ADS(0x48); + + +uint8_t pair = 01; +int16_t val_01 = 0; +int16_t val_23 = 0; + + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("ADS1X15_LIB_VERSION: "); + Serial.println(ADS1X15_LIB_VERSION); + + ADS.begin(); + ADS.setGain(0); // 6.144 volt + ADS.setDataRate(4); // medium + + // single shot mode + ADS.setMode(1); + // start with first pair + pair = 01; + // trigger first read + ADS.requestADC_Differential_0_1(); +} + +void loop() +{ + if (handleConversion() == true) + { + Serial.print("COMP:\t"); + Serial.print(val_01); + Serial.print("\t"); + Serial.print(val_23); + Serial.println(); + } + + // do other stuff here + delay(10); +} + + +// can be changed to hold other differentials reads too. +bool handleConversion() +{ + if (ADS.isReady()) + { + if (pair == 01) + { + val_01 = ADS.getValue(); + pair = 23; + ADS.requestADC_Differential_2_3(); + return false; // only one done + } + + // last of series to check + if (pair == 23) + { + val_23 = ADS.getValue(); + pair = 01; + ADS.requestADC_Differential_0_1(); + return true; // both are updated + } + } + return false; // default not all read +} + +// -- END OF FILE -- diff --git a/examples/ADS_continuous/ADS_continuous.ino b/examples/ADS_continuous/ADS_continuous.ino new file mode 100644 index 0000000..2e0c343 --- /dev/null +++ b/examples/ADS_continuous/ADS_continuous.ino @@ -0,0 +1,47 @@ +// +// FILE: ADS_continuous.ino +// AUTHOR: Rob.Tillaart +// VERSION: 0.1.1 +// PURPOSE: read analog input +// + +// test +// connect 1 potmeter +// +// GND ---[ x ]------ 5V +// | +// +// measure at x (connect to AIN0). + + +#include "ADS1X15.h" + +// choose you sensor +// ADS1013 ADS(0x48); +// ADS1014 ADS(0x48); +// ADS1015 ADS(0x48); +// ADS1113 ADS(0x48); +// ADS1114 ADS(0x48); +ADS1115 ADS(0x48); + + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("ADS1X15_LIB_VERSION: "); + Serial.println(ADS1X15_LIB_VERSION); + + ADS.begin(); + ADS.setGain(0); // 6.144 volt + ADS.setDataRate(7); // fast + ADS.setMode(0); // continuous mode + ADS.readADC(0); // first read to trigger +} + +void loop() +{ + Serial.println(ADS.getValue()); +} + +// -- END OF FILE -- \ No newline at end of file diff --git a/examples/ADS_continuous_4_channel/ADS_continuous_4_channel.ino b/examples/ADS_continuous_4_channel/ADS_continuous_4_channel.ino new file mode 100644 index 0000000..22666be --- /dev/null +++ b/examples/ADS_continuous_4_channel/ADS_continuous_4_channel.ino @@ -0,0 +1,94 @@ +// +// FILE: ADS_continuous_4_channel.ino +// AUTHOR: Rob.Tillaart +// VERSION: 0.1.2 +// PURPOSE: read multiple analog inputs continuously +// interrupt driven to catch all conversions. +// + +// test +// connect multiple potmeters +// +// GND ---[ x ]------ 5V +// | +// +// measure at x - connect to AIN0..4. +// +// for the test it is good to have AIN3 connected to 5V and AIN4 to GND +// so one can see these as references in the output. +// + +#include "ADS1X15.h" + +// choose you sensor +// ADS1013 ADS(0x48); +// ADS1014 ADS(0x48); +// ADS1015 ADS(0x48); +// ADS1113 ADS(0x48); +// ADS1114 ADS(0x48); +ADS1115 ADS(0x48); + +volatile bool RDY = false; +uint8_t channel = 0; +int16_t val[4] = { 0, 0, 0, 0 }; + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("ADS1X15_LIB_VERSION: "); + Serial.println(ADS1X15_LIB_VERSION); + + pinMode(2, INPUT_PULLUP); + attachInterrupt(digitalPinToInterrupt(2), adsReady, RISING); + + ADS.begin(); + ADS.setGain(0); // 6.144 volt + ADS.setDataRate(7); // slow + + // SET ALERT RDY PIN + ADS.setComparatorThresholdHigh(0x8000); + ADS.setComparatorThresholdLow(0x0000); + ADS.setComparatorQueConvert(0); + + // SET INTERRUPT HANDLER TO CATCH CONVERSION READY + pinMode(2, INPUT_PULLUP); + attachInterrupt(digitalPinToInterrupt(2), adsReady, RISING); + + ADS.setMode(0); // continuous mode + ADS.readADC(channel); // trigger first read +} + +void loop() +{ + handleConversion(); + + for (int i = 0; i < 4; i++) + { + Serial.print(val[i]); + Serial.print('\t'); + handleConversion(); + } + Serial.println(); + delay(100); +} + +void adsReady() +{ + RDY = true; +} + +void handleConversion() +{ + if (RDY) + { + // save the value + val[channel] = ADS.getValue(); + // request next channel + channel++; + if (channel >= 4) channel = 0; + ADS.readADC(channel); + RDY = false; + } +} +// -- END OF FILE -- diff --git a/examples/ADS_continuous_8_channel/ADS_continuous_8_channel.ino b/examples/ADS_continuous_8_channel/ADS_continuous_8_channel.ino new file mode 100644 index 0000000..cee55b0 --- /dev/null +++ b/examples/ADS_continuous_8_channel/ADS_continuous_8_channel.ino @@ -0,0 +1,126 @@ +// +// FILE: ADS_continuous_8_channel.ino +// AUTHOR: Rob.Tillaart +// VERSION: 0.1.1 +// PURPOSE: read multiple analog inputs continuously +// interrupt driven to catch all conversions. +// + +// test +// connect multiple potmeters to 2 ADS1115 +// +// GND ---[ x ]------ 5V +// | +// +// measure at x - connect to AIN0..4. +// +// for the test it is good to have AIN3 connected to 5V and AIN4 to GND +// so one can see these as references in the output. +// + +#include "ADS1X15.h" + +// adjust addresses if needed +ADS1115 ADS_1(0x49); +ADS1115 ADS_2(0x48); + +volatile bool RDY_1 = false; +volatile bool RDY_2 = false; +uint8_t channel_1 = 0; +uint8_t channel_2 = 0; +int16_t val[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("ADS1X15_LIB_VERSION: "); + Serial.println(ADS1X15_LIB_VERSION); + + // SETUP FIRST ADS1115 + ADS_1.begin(); + ADS_1.setGain(0); // 6.144 volt + ADS_1.setDataRate(7); + + // SET ALERT RDY PIN + ADS_1.setComparatorThresholdHigh(0x8000); + ADS_1.setComparatorThresholdLow(0x0000); + ADS_1.setComparatorQueConvert(0); + + // SET INTERRUPT HANDLER TO CATCH CONVERSION READY + pinMode(2, INPUT_PULLUP); + attachInterrupt(digitalPinToInterrupt(2), adsReady_1, RISING); + + ADS_1.setMode(0); // continuous mode + ADS_1.readADC(channel_1); // trigger first read + + + // SETUP SECOND ADS1115 + ADS_2.begin(); + ADS_2.setGain(0); // 6.144 volt + ADS_2.setDataRate(7); + + // SET ALERT RDY PIN + ADS_2.setComparatorThresholdHigh(0x8000); + ADS_2.setComparatorThresholdLow(0x0000); + ADS_2.setComparatorQueConvert(0); + + // SET INTERRUPT HANDLER TO CATCH CONVERSION READY + pinMode(3, INPUT_PULLUP); + attachInterrupt(digitalPinToInterrupt(3), adsReady_2, RISING); + + ADS_2.setMode(0); // continuous mode + ADS_2.readADC(channel_2); // trigger first read +} + +void loop() +{ + handleConversion(); + + for (int i = 0; i < 8; i++) + { + Serial.print(val[i]); + Serial.print('\t'); + handleConversion(); + } + Serial.println(); + delay(100); +} + +// catch interrupt and set flag +void adsReady_1() +{ + RDY_1 = true; +} + +void adsReady_2() +{ + RDY_2 = true; +} + +// handle conversions that are ready +void handleConversion() +{ + if (RDY_1) + { + // save the last value + val[channel_1] = ADS_1.getValue(); + // request next channel + channel_1++; + if (channel_1 >= 4) channel_1 = 0; + ADS_1.readADC(channel_1); + RDY_1 = false; + } + if (RDY_2) + { + // save the last value + val[4 + channel_2] = ADS_2.getValue(); + // request next channel + channel_2++; + if (channel_2 >= 4) channel_2 = 0; + ADS_2.readADC(channel_2); + RDY_2 = false; + } +} + +// -- END OF FILE -- diff --git a/examples/ADS_continuous_differential/ADS_continuous_differential.ino b/examples/ADS_continuous_differential/ADS_continuous_differential.ino new file mode 100644 index 0000000..7a83336 --- /dev/null +++ b/examples/ADS_continuous_differential/ADS_continuous_differential.ino @@ -0,0 +1,123 @@ +// +// FILE: ADS_continuous_differential.ino +// AUTHOR: Rob.Tillaart +// VERSION: 0.1.0 +// PURPOSE: read multiple differential continuously +// + +// test +// connect 4 potmeters +// +// GND ---[ x ]------ 5V +// | +// +// measure at x - connect to AIN0..4. +// +// + + +#include "ADS1X15.h" + +// choose you sensor +// ADS1013 ADS(0x48); +// ADS1014 ADS(0x48); +// ADS1015 ADS(0x48); +// ADS1113 ADS(0x48); +// ADS1114 ADS(0x48); +ADS1115 ADS(0x48); + + +// interrupt flag +volatile bool RDY = false; +// which pair to use for differential +uint8_t pair = 01; +// two values to hold differential measurements. +int16_t val_01 = 0; +int16_t val_23 = 0; + + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("ADS1X15_LIB_VERSION: "); + Serial.println(ADS1X15_LIB_VERSION); + + // SET INTERRUPT HANDLER TO CATCH CONVERSION READY + pinMode(2, INPUT_PULLUP); + attachInterrupt(digitalPinToInterrupt(2), adsReady, RISING); + + ADS.begin(); + Serial.print("connected: "); + Serial.println(ADS.isConnected()); + ADS.setGain(0); // 6.144 volt + ADS.setDataRate(0); // 0 = slow 4 = medium 7 = fast (7 = fails ) + // every step is about a factor 2 slower. + + // SET ALERT RDY PIN + ADS.setComparatorThresholdHigh(0x8000); + ADS.setComparatorThresholdLow(0x0000); + ADS.setComparatorQueConvert(0); + + // continuous mode + ADS.setMode(0); + // start with first pair + pair = 01; + // trigger first read + ADS.requestADC_Differential_0_1(); +} + + +void loop() +{ + static uint32_t last = 0; + if (handleConversion() == true) + { + uint32_t now = millis(); + Serial.print(now - last); + last = now; + Serial.print("\tCOMP:\t"); + Serial.print(val_01); + Serial.print("\t"); + Serial.print(val_23); + Serial.println(); + } + + // do other stuff here + // delay(10); +} + +// interrupt handler, just sets the RDY flag +void adsReady() +{ + RDY = true; +} + +// can be changed to hold other differentials or normal reads too. +bool handleConversion() +{ + if (RDY) + { + RDY = false; + if (pair == 01) + { + val_01 = ADS.getValue(); + pair = 23; + ADS.requestADC_Differential_2_3(); + return false; // only one done + } + + // last of series to check + if (pair == 23) + { + val_23 = ADS.getValue(); + pair = 01; + ADS.requestADC_Differential_0_1(); + return true; // both are updated + } + } + return false; // default not all read +} + + +// -- END OF FILE -- diff --git a/examples/ADS_differential/ADS_differential.ino b/examples/ADS_differential/ADS_differential.ino new file mode 100644 index 0000000..91711a8 --- /dev/null +++ b/examples/ADS_differential/ADS_differential.ino @@ -0,0 +1,64 @@ +// +// FILE: ADS_differential.ino +// AUTHOR: Rob.Tillaart +// VERSION: 0.1.1 +// PURPOSE: read differential +// + +// test 1 +// connect 2 potmeters in series +// +// GND ---[ x ]------[ y ]---- 5V +// | | +// +// measure at x and y (connect to AIN0 and AIN1). +// x should be lower or equal to y + +// test 2 +// connect 2 potmeters parallel +// +// GND ---[ x ]------ 5V +// | +// +// GND ---[ y ]------ 5V +// | +// +// measure at x and y (connect to AIN0 and AIN1). +// range from -VDD .. +VDD are possible + +#include + +ADS1115 ADS(0x48); + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("ADS1X15_LIB_VERSION: "); + Serial.println(ADS1X15_LIB_VERSION); + + ADS.begin(); + ADS.setGain(0); +} + +void loop() +{ + int16_t val_01 = ADS.readADC_Differential_0_1(); + int16_t val_03 = ADS.readADC_Differential_0_3(); + int16_t val_13 = ADS.readADC_Differential_1_3(); + int16_t val_23 = ADS.readADC_Differential_2_3(); + float volts_01 = ADS.toVoltage(val_01); + float volts_03 = ADS.toVoltage(val_03); + float volts_13 = ADS.toVoltage(val_13); + float volts_23 = ADS.toVoltage(val_23); + + Serial.print("\tval_01: "); Serial.print(val_01); Serial.print("\t"); Serial.println(volts_01, 3); + Serial.print("\tval_03: "); Serial.print(val_03); Serial.print("\t"); Serial.println(volts_03, 3); + Serial.print("\tval_13: "); Serial.print(val_13); Serial.print("\t"); Serial.println(volts_13, 3); + Serial.print("\tval_23: "); Serial.print(val_23); Serial.print("\t"); Serial.println(volts_23, 3); + Serial.println(); + + delay(1000); +} + +// -- END OF FILE -- diff --git a/examples/ADS_high_speed_differential/ADS_high_speed_differential.ino b/examples/ADS_high_speed_differential/ADS_high_speed_differential.ino new file mode 100644 index 0000000..d548029 --- /dev/null +++ b/examples/ADS_high_speed_differential/ADS_high_speed_differential.ino @@ -0,0 +1,124 @@ +// +// FILE: ADS_high_speed_differential.ino.ino +// AUTHOR: Rob.Tillaart +// VERSION: 0.1.0 +// PURPOSE: read from 2 IC's for high speed differential +// interrupt driven to catch all conversions. +// + +// test setup (not tested yet) +// - connect 2 ADS1x15 to I2C bus +// - connect potmeters to all channels +// - code reads both at the same frequency +// and calculates differential per pair. +// as 2 ADC's go in parallel, two ADS1015 should get +// 3000+ differential samples / second. +// + + +#include "ADS1X15.h" + +// adjust addresses if needed +ADS1115 ADS_1(0x49); +ADS1115 ADS_2(0x48); + +volatile bool RDY_1 = false; +volatile bool RDY_2 = false; +uint8_t channel = 0; +int32_t differential[4] = { 0, 0, 0, 0 }; + + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("ADS1X15_LIB_VERSION: "); + Serial.println(ADS1X15_LIB_VERSION); + + // SETUP FIRST ADS1115 + ADS_1.begin(); + ADS_1.setGain(0); // 6.144 volt + ADS_1.setDataRate(7); // fastest conversion rate. + + // SET ALERT RDY PIN + ADS_1.setComparatorThresholdHigh(0x8000); + ADS_1.setComparatorThresholdLow(0x0000); + ADS_1.setComparatorQueConvert(0); + + // SET INTERRUPT HANDLER TO CATCH CONVERSION READY + pinMode(2, INPUT_PULLUP); + attachInterrupt(digitalPinToInterrupt(2), adsReady_1, RISING); + + ADS_1.setMode(0); // continuous mode + ADS_1.readADC(channel); // trigger first read + + + // SETUP SECOND ADS1115 + ADS_2.begin(); + ADS_2.setGain(0); // 6.144 volt + ADS_2.setDataRate(7); + + // SET ALERT RDY PIN + ADS_2.setComparatorThresholdHigh(0x8000); + ADS_2.setComparatorThresholdLow(0x0000); + ADS_2.setComparatorQueConvert(0); + + // SET INTERRUPT HANDLER TO CATCH CONVERSION READY + pinMode(3, INPUT_PULLUP); + attachInterrupt(digitalPinToInterrupt(3), adsReady_2, RISING); + + ADS_2.setMode(0); // continuous mode + ADS_2.readADC(channel); // trigger first read +} + +void loop() +{ + if (handleConversion() == true) + { + for (int i = 0; i < 4; i++) + { + Serial.print(differential[i]); + Serial.print("\t"); + } + Serial.println(); + } + + +} + + +// catch interrupt and set flag +void adsReady_1() +{ + RDY_1 = true; +} + +void adsReady_2() +{ + RDY_2 = true; +} + + +// handle conversions if both are ready +bool handleConversion() +{ + if (RDY_1 == false) return false; + if (RDY_2 == false) return false; + + // read the value of both + int16_t a = ADS_1.getValue(); + int16_t b = ADS_2.getValue(); + differential[channel] = a - b; + // request next channel + channel++; + if (channel >= 4) channel = 0; + ADS_1.readADC(channel); + ADS_2.readADC(channel); + RDY_1 = false; + RDY_2 = false; + + return true; +} + + +// -- END OF FILE -- diff --git a/examples/ADS_minimum/ADS_minimum.ino b/examples/ADS_minimum/ADS_minimum.ino new file mode 100644 index 0000000..d854951 --- /dev/null +++ b/examples/ADS_minimum/ADS_minimum.ino @@ -0,0 +1,46 @@ +// +// FILE: ADS_minimum.ino +// AUTHOR: Rob.Tillaart +// VERSION: 0.1.0 +// PURPOSE: read analog input +// + +// test +// connect 1 potmeter +// +// GND ---[ x ]------ 5V +// | +// +// measure at x (connect to AIN0). + +// view with Serial Plotter + +#include "ADS1X15.h" + +// choose you sensor +// ADS1013 ADS(0x48); +// ADS1014 ADS(0x48); +// ADS1015 ADS(0x48); +// ADS1113 ADS(0x48); +// ADS1114 ADS(0x48); +ADS1115 ADS(0x48); + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("ADS1X15_LIB_VERSION: "); + Serial.println(ADS1X15_LIB_VERSION); + + ADS.begin(); + ADS.setGain(0); // 6.144 volt + Serial.println("Voltage"); +} + +void loop() +{ + int16_t raw = ADS.readADC(0); + Serial.println(ADS.toVoltage(raw), 3); +} + +// -- END OF FILE -- diff --git a/examples/ADS_performance/ADS_performance.ino b/examples/ADS_performance/ADS_performance.ino new file mode 100644 index 0000000..a94d8b8 --- /dev/null +++ b/examples/ADS_performance/ADS_performance.ino @@ -0,0 +1,92 @@ +// +// FILE: ADS_performance.ino +// AUTHOR: Rob.Tillaart +// VERSION: 0.1.1 +// PURPOSE: read analog input +// + +// test +// connect 1 potmeter +// +// GND ---[ x ]------ 5V +// | +// +// measure at x (connect to AIN0). + + +#include "ADS1X15.h" + +// choose you sensor +// ADS1013 ADS(0x48); +// ADS1014 ADS(0x48); +// ADS1015 ADS(0x48); +// ADS1113 ADS(0x48); +// ADS1114 ADS(0x48); +ADS1115 ADS(0x48); + +uint32_t start, d1, d2; +int x; + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("ADS1X15_LIB_VERSION: "); + Serial.println(ADS1X15_LIB_VERSION); + + ADS.begin(); + ADS.setGain(0); // 6.144 volt + + for (int dr = 0; dr < 8; dr++) + { + ADS.setDataRate(dr); + Serial.print("DR:\t"); + Serial.println(dr); + + test_single_shot(); + test_continuous(); + + Serial.print("\t\tFACTOR:\t"); + Serial.println(1.0 * d1 / d2); + } + + Serial.println("\nDone..."); +} + +void loop() +{ +} + +void test_single_shot() +{ + Serial.print(__FUNCTION__); + + ADS.setMode(1); + start = micros(); + x = ADS.readADC(0); + for (int i = 0; i < 100; i++) + { + x = ADS.readADC(0); + } + d1 = micros() - start; + Serial.print("\t"); + Serial.println(d1); +} + +void test_continuous() +{ + Serial.print(__FUNCTION__); + + ADS.setMode(0); + start = micros(); + x = ADS.readADC(0); + for (int i = 0; i < 100; i++) + { + x = ADS.getValue(); + } + d2 = micros() - start; + Serial.print("\t\t"); + Serial.println(d2); +} + +// -- END OF FILE -- \ No newline at end of file diff --git a/examples/ADS_read/ADS_read.ino b/examples/ADS_read/ADS_read.ino new file mode 100644 index 0000000..dba2f67 --- /dev/null +++ b/examples/ADS_read/ADS_read.ino @@ -0,0 +1,51 @@ +// +// FILE: ADS_read.ino +// AUTHOR: Rob.Tillaart +// VERSION: 0.2.1 +// PURPOSE: read analog inputs - straightforward. +// + +// test +// connect 1 potmeter per port. +// +// GND ---[ x ]------ 5V +// | +// +// measure at x (connect to AIN0). +// + +#include "ADS1X15.h" + +ADS1115 ADS(0x48); + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("ADS1X15_LIB_VERSION: "); + Serial.println(ADS1X15_LIB_VERSION); + + ADS.begin(); +} + +void loop() +{ + ADS.setGain(0); + + int16_t val_0 = ADS.readADC(0); + int16_t val_1 = ADS.readADC(1); + int16_t val_2 = ADS.readADC(2); + int16_t val_3 = ADS.readADC(3); + + float f = ADS.toVoltage(1); // voltage factor + + Serial.print("\tAnalog0: "); Serial.print(val_0); Serial.print('\t'); Serial.println(val_0 * f, 3); + Serial.print("\tAnalog1: "); Serial.print(val_1); Serial.print('\t'); Serial.println(val_1 * f, 3); + Serial.print("\tAnalog2: "); Serial.print(val_2); Serial.print('\t'); Serial.println(val_2 * f, 3); + Serial.print("\tAnalog3: "); Serial.print(val_3); Serial.print('\t'); Serial.println(val_3 * f, 3); + Serial.println(); + + delay(1000); +} + +// -- END OF FILE -- diff --git a/examples/ADS_read_RDY/ADS_read_RDY.ino b/examples/ADS_read_RDY/ADS_read_RDY.ino new file mode 100644 index 0000000..fa84eb6 --- /dev/null +++ b/examples/ADS_read_RDY/ADS_read_RDY.ino @@ -0,0 +1,62 @@ +// +// FILE: ADS_read_RDY.ino +// AUTHOR: Rob.Tillaart +// VERSION: 0.1.0 +// PURPOSE: read analog inputs - straightforward. +// + +// test +// connect 1 potmeter per port. +// +// GND ---[ x ]------ 5V +// | +// +// measure at x (connect to AIN0). +// + +// EXPERIMENTAL +// +// The RDY pin (or ALERT Pin) is triggered when conversion is ready +// + +#include "ADS1X15.h" + +ADS1115 ADS(0x48); + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("ADS1X15_LIB_VERSION: "); + Serial.println(ADS1X15_LIB_VERSION); + + ADS.begin(); + ADS.setGain(0); // 6.144 volt + ADS.setDataRate(7); // fast + ADS.setMode(1); // continuous mode + ADS.readADC(0); // first read to trigger + + // set the thresholds to Trigger RDY pin + ADS.setComparatorThresholdLow(0x0000); + ADS.setComparatorThresholdHigh(0x0200); + ADS.setComparatorQueConvert(0); // enable RDY pin !! + ADS.setComparatorLatch(0); +} + +void loop() +{ + ADS.setGain(0); + + int16_t val_0 = ADS.readADC(0); + + float f = ADS.toVoltage(1); // voltage factor + + Serial.print("\tAnalog0: "); + Serial.print(val_0); + Serial.print('\t'); + Serial.println(val_0 * f, 3); + + delay(1000); +} + +// -- END OF FILE -- diff --git a/examples/ADS_read_async/ADS_read_async.ino b/examples/ADS_read_async/ADS_read_async.ino new file mode 100644 index 0000000..174f919 --- /dev/null +++ b/examples/ADS_read_async/ADS_read_async.ino @@ -0,0 +1,50 @@ +// +// FILE: ADS_read_async.ino +// AUTHOR: Rob.Tillaart +// VERSION: 0.1.1 +// PURPOSE: read analog inputs - asynchronous +// + +// test +// connect 1 potmeter per port. +// +// GND ---[ x ]------ 5V +// | +// +// measure at x (connect to AIN0). +// + +#include "ADS1X15.h" + +ADS1115 ADS(0x48); +float f = 0; + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("ADS1X15_LIB_VERSION: "); + Serial.println(ADS1X15_LIB_VERSION); + + ADS.begin(); + ADS.setGain(0); + f = ADS.toVoltage(); // voltage factor + ADS.requestADC(0); +} + +void loop() +{ + if (ADS.isBusy() == false) + { + int16_t val_0 = ADS.getValue(); + ADS.requestADC(0); // request a new one + Serial.print("\tAnalog0: "); + Serial.print(val_0); + Serial.print('\t'); + Serial.println(val_0 * f, 3); + } + // simulate other tasks... + delay(2000); +} + +// -- END OF FILE -- diff --git a/examples/ADS_read_async_rdy/ADS_read_async_rdy.ino b/examples/ADS_read_async_rdy/ADS_read_async_rdy.ino new file mode 100644 index 0000000..9b04081 --- /dev/null +++ b/examples/ADS_read_async_rdy/ADS_read_async_rdy.ino @@ -0,0 +1,62 @@ +// +// FILE: ADS_read_async_rdy.ino +// AUTHOR: Rob.Tillaart +// VERSION: 0.1.1 +// PURPOSE: read analog inputs - straightforward. +// + +// test +// connect 1 potmeter per port. +// +// GND ---[ x ]------ 5V +// | +// +// measure at x (connect to AIN0). +// + +// EXPERIMENTAL +// +// The RDY pin (or ALERT Pin) is triggered when conversion is ready +// + +#include "ADS1X15.h" + +ADS1115 ADS(0x48); +float f = 0; + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("ADS1X15_LIB_VERSION: "); + Serial.println(ADS1X15_LIB_VERSION); + + ADS.begin(); + ADS.setGain(0); // 6.144 volt + ADS.setDataRate(0); // slow so the led blinks visible for the eye. + f = ADS.toVoltage(); // voltage factor + ADS.requestADC(0); + + // set the thresholds to Trigger RDY pin + ADS.setComparatorThresholdLow(0x0000); + ADS.setComparatorThresholdHigh(0x0200); + ADS.setComparatorQueConvert(0); // enable RDY pin !! + ADS.setComparatorLatch(0); +} + +void loop() +{ + if (ADS.isReady()) + { + int16_t val_0 = ADS.getValue(); + ADS.requestADC(0); // request a new one + Serial.print("\tAnalog0: "); + Serial.print(val_0); + Serial.print('\t'); + Serial.println(val_0 * f, 3); + } + // simulate other tasks... + delay(2000); +} + +// -- END OF FILE -- diff --git a/examples/ADS_read_comparator_1/ADS_read_comparator_1.ino b/examples/ADS_read_comparator_1/ADS_read_comparator_1.ino new file mode 100644 index 0000000..e7315c1 --- /dev/null +++ b/examples/ADS_read_comparator_1/ADS_read_comparator_1.ino @@ -0,0 +1,82 @@ +// +// FILE: ADS_read_comparator_1.ino +// AUTHOR: Rob.Tillaart +// VERSION: 0.1.0 +// PURPOSE: read analog inputs - straightforward. +// + +// test +// connect 1 potmeter per port. +// +// GND ---[ x ]------ 5V +// | +// +// measure at x (connect to AIN0). +// +// +// GND ---[LED]---[ALERT_PIN]---[ R ]--- 5V +// +// Connect a LED (+ resistor) to ALERT PIN +// and see it trigger at configured way by the comparator. +// + + +#include "ADS1X15.h" + +ADS1115 ADS(0x48); + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("ADS1X15_LIB_VERSION: "); + Serial.println(ADS1X15_LIB_VERSION); + + ADS.begin(); + + // change if needed. + ADS.setComparatorMode(1); // 0 = TRADITIONAL 1 = WINDOW + + ADS.setComparatorPolarity(0); // 0 = LOW (default) 1 = HIGH + + // note NON-LATCH gives only a short pulse + ADS.setComparatorLatch(1); // 0 = NON LATCH 1 = LATCH + + ADS.setComparatorQueConvert(0); // 0 = trigger alert after 1 conversion + + // set the thresholds as a number... + // ADS.setComparatorThresholdLow(5000); // change if needed + // ADS.setComparatorThresholdHigh(20000); // change if needed + + // set the threshold as a voltage by using the voltage factor. + float f = ADS.toVoltage(1); // voltage factor + ADS.setComparatorThresholdLow(1.234 / f); // convert volts to number needed + ADS.setComparatorThresholdHigh(3.142 / f); // convert volts to number needed + + Serial.println(ADS.getComparatorThresholdLow()); + Serial.println(ADS.getComparatorThresholdHigh()); + +} + +void loop() +{ + ADS.setGain(0); + + int16_t val_0 = ADS.readADC(0); + + float f = ADS.toVoltage(1); // voltage factor + + Serial.print("\tAnalog0: "); + Serial.print(val_0); + Serial.print('\t'); + Serial.print(val_0 * f, 3); + Serial.print('\t'); + Serial.print(ADS.getComparatorThresholdLow() * f, 3); + Serial.print('\t'); + Serial.print(ADS.getComparatorThresholdHigh() * f, 3); + Serial.println(); + + delay(100); +} + +// -- END OF FILE -- diff --git a/examples/ADS_setWireClock/ADS_setWireClock.ino b/examples/ADS_setWireClock/ADS_setWireClock.ino new file mode 100644 index 0000000..d2f0232 --- /dev/null +++ b/examples/ADS_setWireClock/ADS_setWireClock.ino @@ -0,0 +1,62 @@ +// +// FILE: ADS_setWireClock.ino +// AUTHOR: Rob.Tillaart +// VERSION: 0.1.0 +// PURPOSE: read analog inputs - straightforward. +// + +// test +// connect 1 potmeter per port. +// +// GND ---[ x ]------ 5V +// | +// +// measure at x (connect to AIN0). +// + +#include "ADS1X15.h" + +ADS1115 ADS(0x48); + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("ADS1X15_LIB_VERSION: "); + Serial.println(ADS1X15_LIB_VERSION); + + ADS.begin(); + + Serial.println(F("\nSET\tACTUAL\n==================")); + for (uint32_t speed = 50000; speed <= 1000000; speed += 50000) + { + ADS.setWireClock(speed); + Serial.print(speed); + Serial.print("\t"); + Serial.println(ADS.getWireClock()); + } + ADS.setWireClock(100000); + Serial.println(); +} + +void loop() +{ + ADS.setGain(0); + + int16_t val_0 = ADS.readADC(0); + int16_t val_1 = ADS.readADC(1); + int16_t val_2 = ADS.readADC(2); + int16_t val_3 = ADS.readADC(3); + + float f = ADS.toVoltage(1); // voltage factor + + Serial.print("\tAnalog0: "); Serial.print(val_0); Serial.print('\t'); Serial.println(val_0 * f, 3); + Serial.print("\tAnalog1: "); Serial.print(val_1); Serial.print('\t'); Serial.println(val_1 * f, 3); + Serial.print("\tAnalog2: "); Serial.print(val_2); Serial.print('\t'); Serial.println(val_2 * f, 3); + Serial.print("\tAnalog3: "); Serial.print(val_3); Serial.print('\t'); Serial.println(val_3 * f, 3); + Serial.println(); + + delay(1000); +} + +// -- END OF FILE -- diff --git a/keywords.txt b/keywords.txt new file mode 100644 index 0000000..f9f6801 --- /dev/null +++ b/keywords.txt @@ -0,0 +1,69 @@ +# Syntax Coloring Map For ADS1X15 + +# Datatypes (KEYWORD1) +ADS1X13 KEYWORD1 +ADS1014 KEYWORD1 +ADS1015 KEYWORD1 +ADS1015 KEYWORD1 +ADS1113 KEYWORD1 +ADS1114 KEYWORD1 +ADS1115 KEYWORD1 + + +# Methods and Functions (KEYWORD2) +begin KEYWORD2 +reset KEYWORD2 +isBusy KEYWORD2 +isReady() KEYWORD2 +isConnected KEYWORD2 + +setGain KEYWORD2 +getGain KEYWORD2 +toVoltage KEYWORD2 +getMaxVoltage KEYWORD2 +setMode KEYWORD2 +getMode KEYWORD2 +setDataRate KEYWORD2 +getDataRate KEYWORD2 + +readADC KEYWORD2 +readADC_Differential_0_1 KEYWORD2 +readADC_Differential_0_3 KEYWORD2 +readADC_Differential_1_3 KEYWORD2 +readADC_Differential_2_3 KEYWORD2 +getValue KEYWORD2 + +setComparatorMode KEYWORD2 +getComparatorMode KEYWORD2 +setComparatorPolarity KEYWORD2 +getComparatorPolarity KEYWORD2 +setComparatorLatch KEYWORD2 +getComparatorLatch KEYWORD2 +setComparatorQueConvert KEYWORD2 +getComparatorQueConvert KEYWORD2 +setComparatorThresholdLow KEYWORD2 +getComparatorThresholdLow KEYWORD2 +setComparatorThresholdHigh KEYWORD2 +getComparatorThresholdHigh KEYWORD2 + +getError KEYWORD2 +setWireClock KEYWORD2 +getWireClock KEYWORD2 + +# ASYNC INTERFACE + +requestADC KEYWORD2 +requestADC_Differential_0_1 KEYWORD2 +requestADC_Differential_0_3 KEYWORD2 +requestADC_Differential_1_3 KEYWORD2 +requestADC_Differential_2_3 KEYWORD2 + + +# Constants (LITERAL1) +ADS1X15_LIB_VERSION LITERAL1 +ADS1X15_INVALID_VOLTAGE LITERAL1 +ADS1X15_INVALID_GAIN LITERAL1 +ADS1X15_INVALID_MODE LITERAL1 +ADS1015_ADDRESS LITERAL1 +ADS1115_ADDRESS LITERAL1 + diff --git a/library.json b/library.json new file mode 100644 index 0000000..283be3a --- /dev/null +++ b/library.json @@ -0,0 +1,23 @@ +{ + "name": "ADS1X15", + "keywords": "ADS1013, ADS1014, ADS1015, ADS1113, ADS1114, ADS1115, I2C, ADC", + "description": "Arduino library for ADS1015 - I2C 12 bit ADC and ADS1115 I2C 16 bit ADC", + "authors": + [ + { + "name": "Rob Tillaart", + "email": "Rob.Tillaart@gmail.com", + "maintainer": true + } + ], + "repository": + { + "type": "git", + "url": "https://github.com/RobTillaart/ADS1X15" + }, + "version": "0.3.3", + "license": "MIT", + "frameworks": "*", + "platforms": "*", + "headers": "AD1x15.h" +} diff --git a/library.properties b/library.properties new file mode 100644 index 0000000..7d44a46 --- /dev/null +++ b/library.properties @@ -0,0 +1,11 @@ +name=ADS1X15 +version=0.3.3 +author=Rob Tillaart +maintainer=Rob Tillaart +sentence=Arduino library for ADS1015 - I2C 12 bit ADC and ADS1115 I2C 16 bit ADC +paragraph=Should work for ADS1013, ADS1014, ADS1113 and ADS1114 +category=Sensors +url=https://github.com/RobTillaart/ADS1X15 +architectures=* +includes=ADS1X15.h +depends= diff --git a/test/unit_test_001.cpp b/test/unit_test_001.cpp new file mode 100644 index 0000000..0489204 --- /dev/null +++ b/test/unit_test_001.cpp @@ -0,0 +1,81 @@ +// +// FILE: unit_test_001.cpp +// AUTHOR: Rob Tillaart +// VERSION: 0.1.0 +// DATE: 2020-12-03 +// PURPOSE: unit tests for the SHT31 temperature and humidity sensor +// https://github.com/RobTillaart/ADS1X15 +// + +// supported assertions +// ---------------------------- +// assertEqual(expected, actual) +// assertNotEqual(expected, actual) +// assertLess(expected, actual) +// assertMore(expected, actual) +// assertLessOrEqual(expected, actual) +// assertMoreOrEqual(expected, actual) +// assertTrue(actual) +// assertFalse(actual) +// assertNull(actual) + +#include + +#include "Arduino.h" +#include "ADS1X15.h" + + +unittest_setup() +{ +} + +unittest_teardown() +{ +} + +unittest(test_begin) +{ + ADS1115 ADS(0x48); + assertTrue(ADS.begin()); + assertTrue(ADS.isConnected()); + assertTrue(ADS.isBusy()); +} + +unittest(test_gain) +{ + ADS1115 ADS(0x48); + assertTrue(ADS.begin()); + + assertEqual(0, ADS.getGain()); + int gains[6] = { 0,1,2,4,8,16 }; + for (int i = 0; i < 6; i++) + { + ADS.setGain(gains[i]); + assertEqual(gains[i], ADS.getGain()); + } + + ADS.setGain(42); + assertEqual(0, ADS.getGain()); +} + +unittest(test_Voltage) +{ + ADS1115 ADS(0x48); + assertTrue(ADS.begin()); + + // should test all values? + ADS.setGain(0); + float volts = ADS.getMaxVoltage(); + float delta = abs(6.144 - volts); + assertMoreOrEqual(0.001, delta); + + ADS.setGain(16); + volts = ADS.getMaxVoltage(); + delta = abs(0.256 - volts); + assertMoreOrEqual(0.001, delta); +} + + +unittest_main() + +// --------