From 093054dfe04ec35148ae76974db00160040b2258 Mon Sep 17 00:00:00 2001 From: Englebert Date: Sat, 9 Mar 2024 19:44:55 +0800 Subject: [PATCH] initial --- README.md | 6 +- lib/ADS1X15/.arduino-ci.yml | 28 + lib/ADS1X15/.github/FUNDING.yml | 4 + .../.github/workflows/arduino-lint.yml | 13 + .../.github/workflows/arduino_test_runner.yml | 17 + lib/ADS1X15/.github/workflows/jsoncheck.yml | 18 + lib/ADS1X15/.piopm | 1 + lib/ADS1X15/ADS1X15.cpp | 750 ++++++++++++++++++ lib/ADS1X15/ADS1X15.h | 251 ++++++ lib/ADS1X15/CHANGELOG.md | 138 ++++ lib/ADS1X15/LICENSE | 21 + lib/ADS1X15/README.md | 504 ++++++++++++ .../ADS1113_getMaxVoltage.ino | 49 ++ .../examples/ADS_1114_four/ADS_1114_four.ino | 115 +++ .../ADS_1114_two_continuous.ino | 120 +++ .../examples/ADS_RP2040_WIRE1/.arduino-ci.yml | 27 + .../ADS_RP2040_WIRE1/ADS_RP2040_WIRE1.ino | 55 ++ .../ADS_async_16_channel.ino | 124 +++ .../ADS_async_8_channel.ino | 142 ++++ .../ADS_async_differential.ino | 99 +++ .../ADS_continuous/ADS_continuous.ino | 74 ++ .../ADS_continuous_3_channel.ino | 124 +++ .../ADS_continuous_4_channel.ino | 106 +++ .../ADS_continuous_8_channel.ino | 144 ++++ .../ADS_continuous_differential.ino | 129 +++ .../ADS_differential/ADS_differential.ino | 70 ++ .../ADS_high_speed_differential.ino | 129 +++ .../examples/ADS_minimum/ADS_minimum.ino | 54 ++ .../ADS_performance/ADS_performance.ino | 111 +++ .../ADS_performance/performance_0.3.9.md | 49 ++ .../ADS_pointerToFunction/.arduino-ci.yml | 28 + .../ADS_pointerToFunction.ino | 50 ++ lib/ADS1X15/examples/ADS_read/ADS_read.ino | 55 ++ .../examples/ADS_read_RDY/ADS_read_RDY.ino | 68 ++ .../ADS_read_async/ADS_read_async.ino | 57 ++ .../ADS_read_async_rdy/ADS_read_async_rdy.ino | 71 ++ .../ADS_read_comparator_1.ino | 86 ++ .../ADS_setWireClock/ADS_setWireClock.ino | 66 ++ lib/ADS1X15/keywords.txt | 73 ++ lib/ADS1X15/library.json | 23 + lib/ADS1X15/library.properties | 11 + platformio.ini | 11 +- src/main.cpp | 82 +- src/main.h | 51 ++ 44 files changed, 4197 insertions(+), 7 deletions(-) create mode 100644 lib/ADS1X15/.arduino-ci.yml create mode 100644 lib/ADS1X15/.github/FUNDING.yml create mode 100644 lib/ADS1X15/.github/workflows/arduino-lint.yml create mode 100644 lib/ADS1X15/.github/workflows/arduino_test_runner.yml create mode 100644 lib/ADS1X15/.github/workflows/jsoncheck.yml create mode 100644 lib/ADS1X15/.piopm create mode 100644 lib/ADS1X15/ADS1X15.cpp create mode 100644 lib/ADS1X15/ADS1X15.h create mode 100644 lib/ADS1X15/CHANGELOG.md create mode 100644 lib/ADS1X15/LICENSE create mode 100644 lib/ADS1X15/README.md create mode 100644 lib/ADS1X15/examples/ADS1113_getMaxVoltage/ADS1113_getMaxVoltage.ino create mode 100644 lib/ADS1X15/examples/ADS_1114_four/ADS_1114_four.ino create mode 100644 lib/ADS1X15/examples/ADS_1114_two_continuous/ADS_1114_two_continuous.ino create mode 100644 lib/ADS1X15/examples/ADS_RP2040_WIRE1/.arduino-ci.yml create mode 100644 lib/ADS1X15/examples/ADS_RP2040_WIRE1/ADS_RP2040_WIRE1.ino create mode 100644 lib/ADS1X15/examples/ADS_async_16_channel/ADS_async_16_channel.ino create mode 100644 lib/ADS1X15/examples/ADS_async_8_channel/ADS_async_8_channel.ino create mode 100644 lib/ADS1X15/examples/ADS_async_differential/ADS_async_differential.ino create mode 100644 lib/ADS1X15/examples/ADS_continuous/ADS_continuous.ino create mode 100644 lib/ADS1X15/examples/ADS_continuous_3_channel/ADS_continuous_3_channel.ino create mode 100644 lib/ADS1X15/examples/ADS_continuous_4_channel/ADS_continuous_4_channel.ino create mode 100644 lib/ADS1X15/examples/ADS_continuous_8_channel/ADS_continuous_8_channel.ino create mode 100644 lib/ADS1X15/examples/ADS_continuous_differential/ADS_continuous_differential.ino create mode 100644 lib/ADS1X15/examples/ADS_differential/ADS_differential.ino create mode 100644 lib/ADS1X15/examples/ADS_high_speed_differential/ADS_high_speed_differential.ino create mode 100644 lib/ADS1X15/examples/ADS_minimum/ADS_minimum.ino create mode 100644 lib/ADS1X15/examples/ADS_performance/ADS_performance.ino create mode 100644 lib/ADS1X15/examples/ADS_performance/performance_0.3.9.md create mode 100644 lib/ADS1X15/examples/ADS_pointerToFunction/.arduino-ci.yml create mode 100644 lib/ADS1X15/examples/ADS_pointerToFunction/ADS_pointerToFunction.ino create mode 100644 lib/ADS1X15/examples/ADS_read/ADS_read.ino create mode 100644 lib/ADS1X15/examples/ADS_read_RDY/ADS_read_RDY.ino create mode 100644 lib/ADS1X15/examples/ADS_read_async/ADS_read_async.ino create mode 100644 lib/ADS1X15/examples/ADS_read_async_rdy/ADS_read_async_rdy.ino create mode 100644 lib/ADS1X15/examples/ADS_read_comparator_1/ADS_read_comparator_1.ino create mode 100644 lib/ADS1X15/examples/ADS_setWireClock/ADS_setWireClock.ino create mode 100644 lib/ADS1X15/keywords.txt create mode 100644 lib/ADS1X15/library.json create mode 100644 lib/ADS1X15/library.properties diff --git a/README.md b/README.md index 6854dbf..8aebac5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ ### TODO - +1. To have a total flight time used record +2. To have a current flight time (Each armed will be reset) +3. To have a current total flight time +4. To have a total runtime +5. To have a total runtime after charged. Meaning each charging will reset this counter. Also when is charging time, this counter will be remains zero. ### I2C MODULES 1. Touch Sensors diff --git a/lib/ADS1X15/.arduino-ci.yml b/lib/ADS1X15/.arduino-ci.yml new file mode 100644 index 0000000..f57dc77 --- /dev/null +++ b/lib/ADS1X15/.arduino-ci.yml @@ -0,0 +1,28 @@ +platforms: + rpipico: + board: rp2040:rp2040:rpipico + package: rp2040:rp2040 + gcc: + features: + defines: + - ARDUINO_ARCH_RP2040 + warnings: + flags: + +packages: + rp2040:rp2040: + url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json + + +compile: + # Choosing to run compilation tests on 2 different Arduino platforms + platforms: + - uno + # - due + # - zero + # - leonardo + - m4 + - esp32 + # - esp8266 + # - mega2560 + - rpipico diff --git a/lib/ADS1X15/.github/FUNDING.yml b/lib/ADS1X15/.github/FUNDING.yml new file mode 100644 index 0000000..eff841a --- /dev/null +++ b/lib/ADS1X15/.github/FUNDING.yml @@ -0,0 +1,4 @@ +# These are supported funding model platforms + +github: RobTillaart + diff --git a/lib/ADS1X15/.github/workflows/arduino-lint.yml b/lib/ADS1X15/.github/workflows/arduino-lint.yml new file mode 100644 index 0000000..6f3b2e6 --- /dev/null +++ b/lib/ADS1X15/.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@v4 + - uses: arduino/arduino-lint-action@v1 + with: + library-manager: update + compliance: strict diff --git a/lib/ADS1X15/.github/workflows/arduino_test_runner.yml b/lib/ADS1X15/.github/workflows/arduino_test_runner.yml new file mode 100644 index 0000000..8dde2fc --- /dev/null +++ b/lib/ADS1X15/.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@v4 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.6 + - run: | + gem install arduino_ci + arduino_ci.rb diff --git a/lib/ADS1X15/.github/workflows/jsoncheck.yml b/lib/ADS1X15/.github/workflows/jsoncheck.yml new file mode 100644 index 0000000..6ab6d18 --- /dev/null +++ b/lib/ADS1X15/.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@v4 + - name: json-syntax-check + uses: limitusus/json-syntax-check@v1 + with: + pattern: "\\.json$" + diff --git a/lib/ADS1X15/.piopm b/lib/ADS1X15/.piopm new file mode 100644 index 0000000..807d765 --- /dev/null +++ b/lib/ADS1X15/.piopm @@ -0,0 +1 @@ +{"type": "library", "name": "ADS1X15", "version": "0.4.2", "spec": {"owner": "robtillaart", "id": 10968, "name": "ADS1X15", "requirements": null, "uri": null}} \ No newline at end of file diff --git a/lib/ADS1X15/ADS1X15.cpp b/lib/ADS1X15/ADS1X15.cpp new file mode 100644 index 0000000..9685755 --- /dev/null +++ b/lib/ADS1X15/ADS1X15.cpp @@ -0,0 +1,750 @@ +// +// FILE: ADS1X15.cpp +// AUTHOR: Rob Tillaart +// VERSION: 0.4.2 +// DATE: 2013-03-24 +// PURPOSE: Arduino library for ADS1015 and ADS1115 +// URL: https://github.com/RobTillaart/ADS1X15 + + +#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 | ADS111x | 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 // disable 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; + _lastRequest = 0xFFFF; // no request yet +} + + +bool ADS1X15::begin(int sda, int scl) +{ + // _wire = &Wire1; + _wire->begin(sda, scl); + if ((_address < 0x48) || (_address > 0x4B)) return false; + if (! isConnected()) return false; + return true; +} + + +bool ADS1X15::begin() +{ + if ((_address < 0x48) || (_address > 0x4B)) return false; + if (! isConnected()) return false; + return true; +} + + +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 value) +{ + if (value == 0) return 0; + + float volts = getMaxVoltage(); + if (volts < 0) return volts; // propagate error + + volts *= value; + if (_config & ADS_CONF_RES_16) + { + volts /= 32767; // value = 16 bits - sign bit = 15 bits mantissa + } + else + { + volts /= 2047; // value = 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); +} + + +int16_t ADS1X15::readADC_Differential_0_1() +{ + return _readADC(ADS1X15_MUX_DIFF_0_1); +} + + +int16_t ADS1X15::getValue() +{ + int16_t raw = _readRegister(_address, ADS1X15_REG_CONVERT); + if (_bitShift) raw >>= _bitShift; // Shift 12-bit results + return raw; +} + + +void ADS1X15::requestADC(uint8_t pin) +{ + if (pin >= _maxPorts) return; + uint16_t mode = ((4 + pin) << 12); // pin to mask + _requestADC(mode); +} + + +void ADS1X15::requestADC_Differential_0_1() +{ + _requestADC(ADS1X15_MUX_DIFF_0_1); +} + + +bool ADS1X15::isBusy() +{ + return isReady() == false; +} + + +bool ADS1X15::isReady() +{ + uint16_t val = _readRegister(_address, ADS1X15_REG_CONFIG); + return ((val & ADS1X15_OS_NOT_BUSY) > 0); +} + + +uint8_t ADS1X15::lastRequest() +{ + switch (_lastRequest) + { + case ADS1X15_READ_0: return 0x00; + case ADS1X15_READ_1: return 0x01; + case ADS1X15_READ_2: return 0x02; + case ADS1X15_READ_3: return 0x03; + // technically 0x01 -- but would collide with READ_1 + case ADS1X15_MUX_DIFF_0_1: return 0x10; + case ADS1X15_MUX_DIFF_0_3: return 0x30; + case ADS1X15_MUX_DIFF_1_3: return 0x31; + case ADS1X15_MUX_DIFF_2_3: return 0x32; + } + return 0xFF; +} + + +void ADS1X15::setComparatorMode(uint8_t mode) +{ + _compMode = mode == 0 ? 0 : 1; +} + + +uint8_t ADS1X15::getComparatorMode() +{ + return _compMode; +} + + +void ADS1X15::setComparatorPolarity(uint8_t pol) +{ + _compPol = pol ? 0 : 1; +} + + +uint8_t ADS1X15::getComparatorPolarity() +{ + return _compPol; +} + + +void ADS1X15::setComparatorLatch(uint8_t latch) +{ + _compLatch = latch ? 0 : 1; +} + + +uint8_t ADS1X15::getComparatorLatch() +{ + return _compLatch; +} + + +void ADS1X15::setComparatorQueConvert(uint8_t mode) +{ + _compQueConvert = (mode < 3) ? mode : 3; +} + + +uint8_t ADS1X15::getComparatorQueConvert() +{ + return _compQueConvert; +} + + +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; +} + + +////////////////////////////////////////////////////// +// +// EXPERIMENTAL +// +void ADS1X15::setWireClock(uint32_t clockSpeed) +{ + _clockSpeed = clockSpeed; + _wire->setClock(_clockSpeed); +} + +// see https://github.com/RobTillaart/ADS1X15/issues/22 +// https://github.com/arduino/Arduino/issues/11457 +// TODO: get the real clock speed from the I2C interface if possible. +uint32_t ADS1X15::getWireClock() +{ +// UNO 328 and +#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) + 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 is remembering it + 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 + { + // needed in continuous mode too, otherwise one get old value. + delay(_conversionDelay); + } + 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); + + // remember last request type. + _lastRequest = readmode; +} + + +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((int) address, (int) 2); + if (rv == 2) + { + uint16_t value = _wire->read() << 8; + value += _wire->read(); + return value; + } + return 0x0000; +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// DERIVED CLASSES +// + + +/////////////////////////////////////////////////////////////////////////// +// +// 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; + _gain = ADS1X15_PGA_2_048V; // fixed value +} + + +// ADS1x13 has no gain so set default. +// Table 8. Config Register Field Descriptions +void ADS1013::setGain(uint8_t gain) +{ + _gain = gain; // keep compiler happy. + _gain = ADS1X15_PGA_2_048V; // fixed value +} + + +uint8_t ADS1013::getGain() +{ + return 2; // fixed value +} + + +/////////////////////////////////////////////////////////////////////////// +// +// 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; + _gain = ADS1X15_PGA_2_048V; // fixed value +} + + +// ADS1x13 has no gain so set default. +// Table 8. Config Register Field Descriptions +void ADS1113::setGain(uint8_t gain) +{ + _gain = gain; // keep compiler happy. + _gain = ADS1X15_PGA_2_048V; // fixed value +} + + +uint8_t ADS1113::getGain() +{ + return 2; // fixed value +} + + +/////////////////////////////////////////////////////////////////////////// +// +// 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/lib/ADS1X15/ADS1X15.h b/lib/ADS1X15/ADS1X15.h new file mode 100644 index 0000000..4b1b96b --- /dev/null +++ b/lib/ADS1X15/ADS1X15.h @@ -0,0 +1,251 @@ +#pragma once +// +// FILE: ADS1X15.h +// AUTHOR: Rob Tillaart +// VERSION: 0.4.2 +// DATE: 2013-03-24 +// PURPOSE: Arduino library for ADS1015 and ADS1115 +// URL: https://github.com/RobTillaart/ADS1X15 +// + + +#include "Arduino.h" +#include "Wire.h" + +#define ADS1X15_LIB_VERSION (F("0.4.2")) + +// 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(); + + bool begin(int sda, int scl); + 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 value = 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 = 0); + int16_t readADC_Differential_0_1(); + + // used by continuous mode and async mode. + // [[deprecated("Use getValue() instead")]] + // 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 = 0); + void requestADC_Differential_0_1(); + bool isBusy(); + bool isReady(); + + + // returns a pin 0x0[0..3] or + // a differential "mode" 0x[pin second][pin first] or + // 0xFF (no request / invalid request) + uint8_t lastRequest(); + + + // COMPARATOR + // 0 = TRADITIONAL > high => on < low => off + // else = WINDOW > high or < low => on between => off + void setComparatorMode(uint8_t mode); + uint8_t getComparatorMode(); + + // 0 = LOW (default) + // else = HIGH + void setComparatorPolarity(uint8_t pol); + uint8_t getComparatorPolarity(); + + // 0 = NON LATCH + // else = LATCH + void setComparatorLatch(uint8_t latch); + uint8_t getComparatorLatch(); + + // 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); + uint8_t getComparatorQueConvert(); + + void setComparatorThresholdLow(int16_t lo); + int16_t getComparatorThresholdLow(); + void setComparatorThresholdHigh(int16_t hi); + int16_t getComparatorThresholdHigh(); + + + int8_t getError(); + + // EXPERIMENTAL + // see https://github.com/RobTillaart/ADS1X15/issues/22 + void setWireClock(uint32_t clockSpeed = 100000); + // prototype + // - 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; + + // variable to track the last pin requested, + // to allow for round robin query of + // pins based on this state == if no last request then == 0xFFFF. + uint16_t _lastRequest; + + 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); + void setGain(uint8_t gain); + uint8_t getGain(); +}; + + +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(); +}; + + +class ADS1113 : public ADS1X15 +{ +public: + ADS1113(uint8_t address = ADS1115_ADDRESS, TwoWire *wire = &Wire); + void setGain(uint8_t gain); + uint8_t getGain(); +}; + + +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/lib/ADS1X15/CHANGELOG.md b/lib/ADS1X15/CHANGELOG.md new file mode 100644 index 0000000..bb825a1 --- /dev/null +++ b/lib/ADS1X15/CHANGELOG.md @@ -0,0 +1,138 @@ +# Change Log +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + + +## [0.4.2] - 2024-03-04 +- fix #68, gain bugs ADS1x13 +- add unit test for ADS1x13 +- update GitHub/actions to v4 +- removed depreciated **getLastValue()** +- add multiplexer section to readme.md + + +## [0.4.1] - 2024-01-02 +- fix some typos +- minor edits + +## [0.4.0] - 2023-12-06 +- refactor API, begin() +- update readme.md +- update examples + +---- + +## [0.3.13] - 2023-09-20 +- fix #61 ESP32 begin() + +## [0.3.12] - 2023-09-11 +- update and add examples +- add **getLastRequest()** to track last type of measurement. +- update readme.md +- minor edits. + +## [0.3.11] - 2023-08-31 +- update readme.md +- move code from .h to .cpp +- reordered code in .cpp to follow .h +- minor edits + +## [0.3.10] - 2023-06-07 +- fix NANO RP2040 +- update and add examples +- minor edits + +## [0.3.9] - 2023-01-21 +- update GitHub actions +- update license 2023 +- update readme.md +- minor edits + +## [0.3.8] - 2022-10-17 +- add RP2040 support (kudos to intubun) +- simplified changelog.md + +## [0.3.7] - 2022-06-21 +- fix ESP32 Wire.begin data type + +## [0.3.6] - 2022-03-10 + +- add CHANGELOG.md: moved history in ADS1x15.cpp to this file. +- add default parameters for single channel devices. + - **readADC(uint8_t pin = 0);** + - **requestADC(uint8_t pin = 0);** +- add two examples for the **ADS1114** (single channel devices) +- update readme.md. + +## [0.3.5] - 2022-01-21 +- fix #36 support for Nano Every + +## [0.3.4] - 2021-12-11 +- add unit test constants. +- update library.json, license, +- minor edits including layout + +## [0.3.3] - 2021-10-17 +- update build-CI (esp32), readme.md, keywords.txt + +## [0.3.2] - 2021-10-07 +- added examples +- update readme +- fix build-CI; + +## [0.3.1] - 2021-04-25 +- add get/setClock() for Wire speed +- add reset() +- fix issue #22 + +## [0.3.0] - 2021-03-29 +- add Wire parameter to constructors. + +---- + +### 0.2.7 - 2020-09-27 +- redo readRegister() +- getValue() +- getError() + +### [0.2.6] - 2020-09-01 +- fix #12 +- fix getMaxVoltage +- refactor + +### [0.2.5] - 2020-08-26 +- add missing readADC_Differential_X_X() + +### [0.2.4] - 2020-08-26 +- check readme.md and minor fixes + +### [0.2.3] - 2020-08-20 +- add comparator code +- add async mode + +### [0.2.2] - 2020-08-18 +- add begin(sda, scl) for ESP32 + +### [0.2.1] - 2020-08-15 +- fix issue #2 gain + +### [0.2.0] - 2020-04-08 +- initial release; +- refactor ad fundum; + +---- + +### [0.1.0] - 2017-07-31 +- removed pre 1.0 support; +- added getVoltage + +### [0.0.1] - 2013-03-24 +- first working version + +### [0.0.0] - 2013-03-24 +- initial version + + + diff --git a/lib/ADS1X15/LICENSE b/lib/ADS1X15/LICENSE new file mode 100644 index 0000000..b76adfd --- /dev/null +++ b/lib/ADS1X15/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2013-2024 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/lib/ADS1X15/README.md b/lib/ADS1X15/README.md new file mode 100644 index 0000000..3b4438d --- /dev/null +++ b/lib/ADS1X15/README.md @@ -0,0 +1,504 @@ + +[![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) +[![GitHub issues](https://img.shields.io/github/issues/RobTillaart/ADS1X15.svg)](https://github.com/RobTillaart/ADS1X15/issues) + +[![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) +[![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/ADS1X15.svg)](https://registry.platformio.org/libraries/robtillaart/ADS1X15) + + +# ADS1X15 + +Arduino library for I2C ADC ADS1015, ADS1115, and similar. + +For using I2C ADC with Raspberry pi or other SBC with Linux OS, +you can check similar library [here](https://github.com/chandrawi/ADS1x15-ADC). + + +## 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 ADS1015 and the ADS1115 are both 4 channels these are the most +interesting from functionality point of view as these can also do +differential measurements. + + +#### 0.4.0 Breaking change + +Version 0.4.0 introduced a breaking change. +You cannot set the pins in **begin()** any more. +This reduces the dependency of processor dependent Wire implementations. +The user has to call **Wire.begin()** and can optionally set the Wire pins +before calling **begin()**. + + +#### Related + +- https://github.com/RobTillaart/MCP_ADC (10 & 12 bit ADC, SPI, fast) +- https://github.com/RobTillaart/PCF8591 (8 bit ADC + 1 bit DAC) + + +## I2C Address + +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 | | + + +#### I2C multiplexing + +Sometimes you need to control more devices than possible with the default +address range the device provides. +This is possible with an I2C multiplexer e.g. TCA9548 which creates up +to eight channels (think of it as I2C subnets) which can use the complete +address range of the device. + +Drawback of using a multiplexer is that it takes more administration in +your code e.g. which device is on which channel. +This will slow down the access, which must be taken into account when +deciding which devices are on which channel. +Also note that switching between channels will slow down other devices +too if they are behind the multiplexer. + +- https://github.com/RobTillaart/TCA9548 + + +## Interface + +```cpp +#include "ADS1X15.h" +``` + +#### Initializing + +To initialize the library you must call a constructor as described below. + +- **ADS1x15()** base constructor, should not be used. +- **ADS1013(uint8_t address, TwoWire \*wire = &Wire)** Constructor with device address, +and optional the Wire interface as parameter. +- **ADS1014(uint8_t address, TwoWire \*wire = &Wire)** Constructor with device address, +and optional the Wire interface as parameter. +- **ADS1015(uint8_t address, TwoWire \*wire = &Wire)** Constructor with device address, +and optional the Wire interface as parameter. +- **ADS1113(uint8_t address, TwoWire \*wire = &Wire)** Constructor with device address, +and optional the Wire interface as parameter. +- **ADS1114(uint8_t address, TwoWire \*wire = &Wire)** Constructor with device address, +and optional the Wire interface as parameter. +- **ADS1115(uint8_t address, TwoWire \*wire = &Wire)** Constructor with device address, +and optional the Wire interface as parameter. + + +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. + +For example. + +```cpp +#include "ADS1X15.h" + +// initialize ADS1115 on I2C bus 1 with default address 0x48 +ADS1115 ADS(0x48); + +void begin() { + if (!ADS.isConnected()) { + // error ADS1115 not connected + } +} +``` + + +#### I2C clock speed + +The function **void setWireClock(uint32_t speed = 100000)** is used to set the clock speed +in Hz of the used I2C interface. typical value is 100 KHz. + +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). + +See - https://github.com/arduino/Arduino/issues/11457 + +Question: Should this functionality be in this library? + + +#### Programmable Gain + +- **void setGain(uint8_t gain)** set the gain value, indicating the maxVoltage that can be measured +Adjusting the gain allowing 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](https://github.com/RobTillaart/ADS1X15/blob/master/examples/ADS_read_comparator_1/ADS_read_comparator_1.ino). + +```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 conversions needed you 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 is described on table below. + +| data rate | ADS101x | ADS111x | 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 = 0)** normal ADC functionality, pin = 0..3. +If the pin number is out of range, this function will return 0. +Default pin = 0 as this is convenient for 1 channel devices. + +```cpp +// read ADC in pin 2 +ADS.readADC(2); + +// read ADC in pin 0 - two ways +ADS.readADC(); +ADS.readADC(0); +``` + +See [examples](https://github.com/RobTillaart/ADS1X15/blob/master/examples/ADS_minimum/ADS_minimum.ino). + +To read the ADC in an asynchronous way (e.g. to minimize blocking) you need call three functions: +- **void requestADC(uint8_t pin = 0)** Start the conversion. pin = 0..3. +Default pin = 0 as this is convenient for 1 channel devices. +- **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()) + { + value = ADS.getValue(); + ADS.requestADC(pin); // request new conversion + } + // do other things here + } +``` +See [examples](https://github.com/RobTillaart/ADS1X15/blob/master/examples/ADS_read_async/ADS_read_async.ino). + + +#### 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) + +```cpp +// read differential ADC between pin 0 and 1 +ADS.readADC_Differential_0_1(0); +``` + +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 you need to call +- **int16_t getValue()** Read the result of the last conversion. + +See [examples](https://github.com/RobTillaart/ADS1X15/blob/master/examples/ADS_differential/ADS_differential.ino). + + +#### lastRequestMode + +Since 0.3.12 the library tracks the last request mode, single pin or differential. +This variable is set at the moment of request, and keeps its value until a new +request is made. This implies that the value / request can be quite old. + +Values >= 0x10 are differential, values < 0x10 are single pin. + +- **uint8_t lastRequest()** returns one of the values below. + +| Value | Description | Notes | +|:-------:|:-----------------------------|:--------| +| 0xFF | no (invalid) request made | after call constructor. +| 0x00 | single pin 0 | +| 0x01 | single pin 1 | +| 0x02 | single pin 2 | +| 0x03 | single pin 3 | +| 0x10 | differential pin 1 0 | +| 0x30 | differential pin 3 0 | +| 0x31 | differential pin 3 1 | +| 0x32 | differential pin 3 2 | + + +Please note that (for now) the function does not support a descriptive return value +for the following two requests: +- **readADC_Differential_0_2()** ADS1x15 only - in software (no async equivalent) +- **readADC_Differential_1_2()** ADS1x15 only - in software (no async equivalent) + +As these are emulated in software by two single pin calls, the state would be +one of the two single pin values. + + +#### ReadADC continuous mode + +To use the continuous mode you need call three functions: +- **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. + +```cpp +void setup() { + // configuration things here + ADS.setMode(ADS.MODE_CONTINUOUS); + ADS.requestADC(0); // request on pin 0 +} + +void loop() { + value = ADS.getValue() + sleep(1) +} +``` + +See [examples](https://github.com/RobTillaart/ADS1X15/blob/master/examples/ADS_continuous/ADS_continuous.ino) +. +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, you can't use **isBusy()** or **isReady()** functions to wait until new data available. +Instead you can configure the threshold registers to allow the **ALERT/RDY** +pin to trigger an interrupt signal when conversion data ready. + + +#### Switching mode or channel during continuous mode + +When switching the operating mode or the ADC channel in continuous mode, be aware that +the device will always finish the running conversion. +This implies that after switching the mode or channel the first sample you get is probably +the last sample with the previous settings, e.g. channel. +This might be a problem for your project as this value can be in an "unexpected" range (outlier). + +The robust way to change mode or channel therefore seems to be: + +1. stop continuous mode, +1. wait for running conversion to be ready, +1. reject the last conversion or process it "under old settings", +1. change the settings, +1. restart (continuous mode) with the new settings. + +This explicit stop takes extra time, however it should prevent "incorrect" readings. + +(need to be verified with different models) + + +#### Threshold registers + +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](https://github.com/RobTillaart/ADS1X15/blob/master/examples/ADS_read_RDY/ADS_read_RDY.ino). + + +#### 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 calling +**readADC()** or **requestADC()** functions. + + +#### 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. +To enable the conversion-ready function of the ALERT/RDY pin, it is necessary to set the MSB of the Hi_thresh register to 1 and the MSB of the Lo_thresh register to 0. + +See [examples](https://github.com/RobTillaart/ADS1X15/blob/master/examples/ADS_continuous_differential/ADS_continuous_differential.ino). + +- **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 + +#### Must + +- Improve documentation (always) + +#### Should + + +#### Could + +- More examples +- SMB alert command (00011001) on I2C bus? +- sync order .h / .cpp + + +#### Wont (unless requested) + +- type flag? +- constructor for ADS1X15? No as all types are supported. + + +## Support + +If you appreciate my libraries, you can support the development and maintenance. +Improve the quality of the libraries by providing issues and Pull Requests, or +donate through PayPal or GitHub sponsors. + +Thank you, + diff --git a/lib/ADS1X15/examples/ADS1113_getMaxVoltage/ADS1113_getMaxVoltage.ino b/lib/ADS1X15/examples/ADS1113_getMaxVoltage/ADS1113_getMaxVoltage.ino new file mode 100644 index 0000000..a12f26d --- /dev/null +++ b/lib/ADS1X15/examples/ADS1113_getMaxVoltage/ADS1113_getMaxVoltage.ino @@ -0,0 +1,49 @@ +// +// FILE: ADS1113_getMaxVoltage.ino +// AUTHOR: Rob.Tillaart +// PURPOSE: read analog inputs - straightforward. +// URL: https://github.com/RobTillaart/ADS1X15 + +// test for issue #68 behaviour ADS1113 / ADS1013 +// +// connect 1 potmeter per port. +// +// GND ---[ x ]------ 5V +// | +// +// measure at x (connect to AIN0). + + +#include "ADS1X15.h" + +ADS1113 ADS(0x48); + + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("ADS1X15_LIB_VERSION: "); + Serial.println(ADS1X15_LIB_VERSION); + + Wire.begin(); + ADS.begin(); + + for (int g = 0; g < 8; g++) + { + ADS.setGain(g); + Serial.print(g); + Serial.print('\t'); + Serial.print(ADS.getGain()); // should all print 2 + Serial.print('\t'); + Serial.println(ADS.getMaxVoltage(), 3); // should all print 2.048 + } +} + + +void loop() +{ +} + + +// -- END OF FILE -- diff --git a/lib/ADS1X15/examples/ADS_1114_four/ADS_1114_four.ino b/lib/ADS1X15/examples/ADS_1114_four/ADS_1114_four.ino new file mode 100644 index 0000000..5f2ec38 --- /dev/null +++ b/lib/ADS1X15/examples/ADS_1114_four/ADS_1114_four.ino @@ -0,0 +1,115 @@ +// +// FILE: ADS_1114_four.ino +// AUTHOR: Rob.Tillaart +// PURPOSE: demo reading four ADS1114 modules in parallel +// 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" + + +ADS1114 ADS[4]; +uint16_t val[4]; + +uint32_t last = 0, now = 0; + + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("ADS1X15_LIB_VERSION: "); + Serial.println(ADS1X15_LIB_VERSION); + + Wire.begin(); + + for (uint8_t i = 0; i < 4; i++) + { + uint8_t address = 0x48 + i; + ADS[i] = ADS1114(address); + + Serial.print(address, HEX); + Serial.print(" "); + Serial.println(ADS[i].begin() ? "connected" : "not connected"); + + // 0 = slow 4 = medium 7 = fast, but more noise + ADS[i].setDataRate(4); + } + ADS_request_all(); +} + + +void loop() +{ + // Serial.println(__FUNCTION__); + // wait until all is read... + while(ADS_read_all()); + + // we have all values, so process (print) them + ADS_print_all(); + + // wait a second, comment this line for more samples. + delay(1000); + ADS_request_all(); +} + + +void ADS_request_all() +{ + // Serial.println(__FUNCTION__); + for (int i = 0; i < 4; i++) + { + if (ADS[i].isConnected()) ADS[i].requestADC(0); + // get them evenly spaced in time ... + delayMicroseconds(200); + } +} + + +bool ADS_read_all() +{ + // Serial.println(__FUNCTION__); + 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] = ADS[i].getValue(); + } + } + ADS_request_all(); + return false; +} + + +void ADS_print_all() +{ + // Serial.println(__FUNCTION__); + // print duration since last print. + now = millis(); + Serial.print(now - last); + last = now; + Serial.println(); + + // PRINT ALL VALUES + for (int i = 0; i < 4; i++) + { + Serial.print(val[i]); + Serial.print("\t"); + } + Serial.println(); +} + + +// -- END OF FILE -- diff --git a/lib/ADS1X15/examples/ADS_1114_two_continuous/ADS_1114_two_continuous.ino b/lib/ADS1X15/examples/ADS_1114_two_continuous/ADS_1114_two_continuous.ino new file mode 100644 index 0000000..e8a7ad1 --- /dev/null +++ b/lib/ADS1X15/examples/ADS_1114_two_continuous/ADS_1114_two_continuous.ino @@ -0,0 +1,120 @@ +// +// FILE: ADS_1114_two_continuous.ino +// AUTHOR: Rob.Tillaart +// PURPOSE: demo reading four ADS1114 modules in parallel +// URL: https://github.com/RobTillaart/ADS1X15 + + +#include "ADS1X15.h" + + +ADS1114 ADS_1(0x49); +ADS1114 ADS_2(0x48); + + +// two interrupt flags +volatile bool RDY_1 = false; +volatile bool RDY_2 = false; + +int16_t val_1 = 0; +int16_t val_2 = 0; + + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("ADS1X15_LIB_VERSION: "); + Serial.println(ADS1X15_LIB_VERSION); + + Wire.begin(); + + // SETUP FIRST ADS1114 + ADS_1.begin(); + ADS_1.setGain(0); // 0 == 6.144 volt, default + ADS_1.setDataRate(7); // 0 = slow 4 = medium 7 = fast + + // 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); // 0 == continuous mode + ADS_1.readADC(); // 0 == default channel, trigger first read + + + // SETUP SECOND ADS1114 + ADS_2.begin(); + ADS_2.setGain(0); // 0 == 6.144 volt, default + ADS_2.setDataRate(7); // 7 == highest + + // 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); // 0 == continuous mode + ADS_2.readADC(); // 0 == default channel, trigger first read +} + + +void loop() +{ + if (handleConversion() == true) + { + Serial.print('\t'); + Serial.print(val_1); + Serial.print('\t'); + Serial.print(val_2); + Serial.println(); + } +} + + +// catch interrupt and set flag device 1 +void adsReady_1() +{ + RDY_1 = true; +} + +// catch interrupt and set flag device 1 +void adsReady_2() +{ + RDY_2 = true; +} + + +// handle conversions that are ready +bool handleConversion() +{ + bool rv = false; + if (RDY_1) + { + // save the last value + val_1 = ADS_1.getValue(); + ADS_1.readADC(0); + RDY_1 = false; + rv = true; + } + if (RDY_2) + { + // save the last value + val_2 = ADS_2.getValue(); + ADS_2.readADC(0); + RDY_2 = false; + rv = true; + } + return rv; +} + + +// -- END OF FILE -- + diff --git a/lib/ADS1X15/examples/ADS_RP2040_WIRE1/.arduino-ci.yml b/lib/ADS1X15/examples/ADS_RP2040_WIRE1/.arduino-ci.yml new file mode 100644 index 0000000..b267198 --- /dev/null +++ b/lib/ADS1X15/examples/ADS_RP2040_WIRE1/.arduino-ci.yml @@ -0,0 +1,27 @@ +platforms: + rpipico: + board: rp2040:rp2040:rpipico + package: rp2040:rp2040 + gcc: + features: + defines: + - ARDUINO_ARCH_RP2040 + warnings: + flags: + +packages: + rp2040:rp2040: + url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json + +compile: + # Choosing to run compilation tests on 2 different Arduino platforms + platforms: + # - uno + # - due + # - zero + # - leonardo + # - m4 + # - esp32 + # - esp8266 + # - mega2560 + - rpipico \ No newline at end of file diff --git a/lib/ADS1X15/examples/ADS_RP2040_WIRE1/ADS_RP2040_WIRE1.ino b/lib/ADS1X15/examples/ADS_RP2040_WIRE1/ADS_RP2040_WIRE1.ino new file mode 100644 index 0000000..f24bc70 --- /dev/null +++ b/lib/ADS1X15/examples/ADS_RP2040_WIRE1/ADS_RP2040_WIRE1.ino @@ -0,0 +1,55 @@ +// +// FILE: ADS_RP2040_WIRE1.ino +// AUTHOR: Rob.Tillaart / Intubun +// PURPOSE: read analog input +// URL: https://github.com/RobTillaart/ADS1X15 + +// test +// connect 1 potentiometer +// +// GND ---[ x ]------ 5V +// | +// +// measure at x (connect to AIN0). + + +#include "ADS1X15.h" + + +// choose your sensor +// ADS1013 ADS(0x48); +// ADS1014 ADS(0x48); +// ADS1015 ADS(0x48); +// ADS1113 ADS(0x48); +// ADS1114 ADS(0x48); +ADS1115 ADS(0x48, &Wire1); + + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("ADS1X15_LIB_VERSION: "); + Serial.println(ADS1X15_LIB_VERSION); + + // SDA (Pin 26), SCL(Pin 27) + Wire1.begin(); + Wire1.setSDA(26); + Wire1.setSCL(27); + + ADS.begin(); + ADS.setGain(0); // 6.144 volt + ADS.setDataRate(7); // 0 = slow 4 = medium 7 = fast + ADS.setMode(0); // continuous mode + ADS.readADC(0); // first read to trigger +} + + +void loop() +{ + Serial.println(ADS.getValue()); + // optional other code here +} + + +// -- END OF FILE -- diff --git a/lib/ADS1X15/examples/ADS_async_16_channel/ADS_async_16_channel.ino b/lib/ADS1X15/examples/ADS_async_16_channel/ADS_async_16_channel.ino new file mode 100644 index 0000000..2c9dd54 --- /dev/null +++ b/lib/ADS1X15/examples/ADS_async_16_channel/ADS_async_16_channel.ino @@ -0,0 +1,124 @@ +// +// FILE: ADS_async_16_channel.ino +// AUTHOR: Rob Tillaart +// PURPOSE: demo reading four ADS1115 modules in parallel +// 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); + + Wire.begin(); + + 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"); + + // 0 = slow 4 = medium 7 = fast, but more noise + ADS[i].setDataRate(4); + } + ADS_request_all(); +} + + +void loop() +{ + // Serial.println(__FUNCTION__); + // wait until all is read... + while (ADS_read_all()); + + // we have all values + ADS_print_all(); + + // wait a second. + delay(1000); + 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/lib/ADS1X15/examples/ADS_async_8_channel/ADS_async_8_channel.ino b/lib/ADS1X15/examples/ADS_async_8_channel/ADS_async_8_channel.ino new file mode 100644 index 0000000..f147164 --- /dev/null +++ b/lib/ADS1X15/examples/ADS_async_8_channel/ADS_async_8_channel.ino @@ -0,0 +1,142 @@ +// +// FILE: ADS_async_8_channel.ino +// AUTHOR: Rob Tillaart +// PURPOSE: demo reading two ADS1115 modules in parallel +// 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); + + Wire.begin(); + + ADS0.begin(); + ADS1.begin(); + // ADS2.begin(); + // ADS3.begin(); + + Serial.println(ADS0.isConnected()); + Serial.println(ADS1.isConnected()); + // Serial.println(ADS2.isConnected()); + // Serial.println(ADS3.isConnected()); + + // 0 = slow 4 = medium 7 = fast but more noise + ADS0.setDataRate(4); + 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(); + + // wait a second. + delay(1000); + 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/lib/ADS1X15/examples/ADS_async_differential/ADS_async_differential.ino b/lib/ADS1X15/examples/ADS_async_differential/ADS_async_differential.ino new file mode 100644 index 0000000..a77e863 --- /dev/null +++ b/lib/ADS1X15/examples/ADS_async_differential/ADS_async_differential.ino @@ -0,0 +1,99 @@ +// +// FILE: ADS_async_differential.ino +// AUTHOR: Rob.Tillaart +// PURPOSE: read multiple differential continuously +// URL: https://github.com/RobTillaart/ADS1X15 + +// test +// connect 4 potmeters +// +// GND ---[ x ]------ 5V +// | +// +// measure at x - connect to AIN0..4. +// + + +#include "ADS1X15.h" + + +// choose your 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); + + Wire.begin(); + + ADS.begin(); + ADS.setGain(0); // 6.144 volt + ADS.setDataRate(4); // 0 = slow 4 = medium 7 = fast + + // 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/lib/ADS1X15/examples/ADS_continuous/ADS_continuous.ino b/lib/ADS1X15/examples/ADS_continuous/ADS_continuous.ino new file mode 100644 index 0000000..212981f --- /dev/null +++ b/lib/ADS1X15/examples/ADS_continuous/ADS_continuous.ino @@ -0,0 +1,74 @@ +// +// FILE: ADS_continuous.ino +// AUTHOR: Rob.Tillaart +// PURPOSE: read analog input +// URL: https://github.com/RobTillaart/ADS1X15 + +// test +// connect 1 potmeter +// +// GND ---[ x ]------ 5V +// | +// +// measure at x (connect to AIN0). +// +// See https://github.com/RobTillaart/ADS1X15/issues/49 +// + +#include "ADS1X15.h" + + +// choose your sensor +// ADS1013 ADS(0x48); +// ADS1014 ADS(0x48); +// ADS1015 ADS(0x48); +// ADS1113 ADS(0x48); +// ADS1114 ADS(0x48); +ADS1115 ADS(0x48); + +uint16_t count = 0; +uint16_t value = 0; +uint16_t prev = 0; +uint32_t lastTime = 0; +uint32_t lastSample = 0; + + +void setup() +{ + Serial.begin(500000); + Serial.println(__FILE__); + Serial.print("ADS1X15_LIB_VERSION: "); + Serial.println(ADS1X15_LIB_VERSION); + + Wire.begin(); + + ADS.begin(); + ADS.setGain(0); // 6.144 volt + ADS.setDataRate(7); // 0 = slow 4 = medium 7 = fast + ADS.setMode(0); // continuous mode + ADS.readADC(0); // first read to trigger +} + + +void loop() +{ + uint32_t now = micros(); + if (now - lastSample >= 1160) // almost exact 860 SPS + { + lastSample = now; + value = ADS.getValue(); + count++; + Serial.print(count); + Serial.print("\t"); + Serial.println(value); + } + if (now - 1000000 >= lastTime) + { + lastTime = now; + count = 0; + } +} + + +// -- END OF FILE -- + diff --git a/lib/ADS1X15/examples/ADS_continuous_3_channel/ADS_continuous_3_channel.ino b/lib/ADS1X15/examples/ADS_continuous_3_channel/ADS_continuous_3_channel.ino new file mode 100644 index 0000000..60ef2ff --- /dev/null +++ b/lib/ADS1X15/examples/ADS_continuous_3_channel/ADS_continuous_3_channel.ino @@ -0,0 +1,124 @@ +// +// FILE: ADS_continuous_3_channel.ino +// AUTHOR: Rob.Tillaart +// PURPOSE: read multiple analog inputs continuously +// interrupt driven to catch all conversions. +// URL: https://github.com/RobTillaart/ADS1X15 +// https://github.com/RobTillaart/ADS1X15/issues/49 +// +// experimental, not tested extensively + +// test +// connect multiple potmeters +// +// RDY ----------------- pin 2 (for IRQ) +// +// GND ---[ x ]------ 5V +// | +// | +// ADS(n) +// +// measure at x - connect to AIN0..3. +// +// for the test it is an option to have AIN3 connected to 5V and AIN4 to GND +// so one can see these as references in the output. +// +// has an issue with the index of the channels. not not investigated yet. + + +#include "ADS1X15.h" + + +// choose your 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 }; + +int SPS = 0; +uint32_t lastTime = 0; + + +void setup() +{ + Serial.begin(230400); // <<<<<<<<< fast! + Serial.println(__FILE__); + Serial.print("ADS1X15_LIB_VERSION: "); + Serial.println(ADS1X15_LIB_VERSION); + + Wire.begin(); + Wire.setClock(400000); + + ADS.begin(); + ADS.setGain(0); // 6.144 volt + ADS.setDataRate(7); // 0 = slow 4 = medium 7 = fast + + // 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 + channel = 0; + ADS.requestADC(channel); // start at 0 +} + + +void loop() +{ + // if conversion ready + // request a new one and print the last one. + if (RDY) + { + SPS++; + val[channel] = ADS.getValue(); + // request next channel asap + channel++; + if (channel >= 3) channel = 0; + ADS.requestADC(channel); + RDY = false; + + // to see it works + if (SPS % 200 == 0) + { + for (int i = 0; i < 4; i++) + { + Serial.print('\t'); + Serial.print(val[i]); + } + Serial.println(); + } + } + + + // print the SPS + if (millis() - lastTime >= 1000) + { + lastTime = millis(); + Serial.print("SPS: "); + Serial.println(SPS); + SPS = 0; + } +} + + +// interrupt service routine +// kept as minimal as possible +void adsReady() +{ + RDY = true; +} + + +// -- END OF FILE -- + diff --git a/lib/ADS1X15/examples/ADS_continuous_4_channel/ADS_continuous_4_channel.ino b/lib/ADS1X15/examples/ADS_continuous_4_channel/ADS_continuous_4_channel.ino new file mode 100644 index 0000000..fca4cf0 --- /dev/null +++ b/lib/ADS1X15/examples/ADS_continuous_4_channel/ADS_continuous_4_channel.ino @@ -0,0 +1,106 @@ +// +// FILE: ADS_continuous_4_channel.ino +// AUTHOR: Rob.Tillaart +// PURPOSE: read multiple analog inputs continuously +// interrupt driven to catch all conversions. +// URL: https://github.com/RobTillaart/ADS1X15 + +// 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 your 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); + + Wire.begin(); + + pinMode(2, INPUT_PULLUP); + attachInterrupt(digitalPinToInterrupt(2), adsReady, RISING); + + ADS.begin(); + ADS.setGain(0); // 6.144 volt + ADS.setDataRate(7); // 0 = slow 4 = medium 7 = fast + + // 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); +} + + +// interrupt service routine +// kept as minimal as possible +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/lib/ADS1X15/examples/ADS_continuous_8_channel/ADS_continuous_8_channel.ino b/lib/ADS1X15/examples/ADS_continuous_8_channel/ADS_continuous_8_channel.ino new file mode 100644 index 0000000..adf3cd8 --- /dev/null +++ b/lib/ADS1X15/examples/ADS_continuous_8_channel/ADS_continuous_8_channel.ino @@ -0,0 +1,144 @@ +// +// FILE: ADS_continuous_8_channel.ino +// AUTHOR: Rob.Tillaart +// PURPOSE: read multiple analog inputs continuously +// interrupt driven to catch all conversions. +// URL: https://github.com/RobTillaart/ADS1X15 + +// 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); + +// two interrupt flags +volatile bool RDY_1 = false; +volatile bool RDY_2 = false; + +uint8_t channel_1 = 0; // channel from device 1 +uint8_t channel_2 = 0; // channel from device 2 + +// array to hold the data. +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); + + Wire.begin(); + + // SETUP FIRST ADS1115 + ADS_1.begin(); + ADS_1.setGain(0); // 6.144 volt + ADS_1.setDataRate(7); // 0 = slow 4 = medium 7 = fast + + // 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 device 1 +void adsReady_1() +{ + RDY_1 = true; +} + +// catch interrupt and set flag device 1 +void adsReady_2() +{ + RDY_2 = true; +} + + +// handle conversions that are ready +bool handleConversion() +{ + bool rv = false; + 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; + rv = true; + } + 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; + rv = true; + } + return rv; +} + + +// -- END OF FILE -- + diff --git a/lib/ADS1X15/examples/ADS_continuous_differential/ADS_continuous_differential.ino b/lib/ADS1X15/examples/ADS_continuous_differential/ADS_continuous_differential.ino new file mode 100644 index 0000000..e91ad81 --- /dev/null +++ b/lib/ADS1X15/examples/ADS_continuous_differential/ADS_continuous_differential.ino @@ -0,0 +1,129 @@ +// +// FILE: ADS_continuous_differential.ino +// AUTHOR: Rob.Tillaart +// PURPOSE: read multiple differential continuously +// URL: https://github.com/RobTillaart/ADS1X15 + +// test +// connect 4 potmeters +// +// GND ---[ x ]------ 5V +// | +// +// measure at x - connect to AIN0..4. +// + + +#include "ADS1X15.h" + + +// choose your 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); + + Wire.begin(); + + // 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 (QueConvert mode) + // set the MSB of the Hi_thresh register to 1 + ADS.setComparatorThresholdHigh(0x8000); + // set the MSB of the Lo_thresh register to 0 + 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, 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/lib/ADS1X15/examples/ADS_differential/ADS_differential.ino b/lib/ADS1X15/examples/ADS_differential/ADS_differential.ino new file mode 100644 index 0000000..ad182da --- /dev/null +++ b/lib/ADS1X15/examples/ADS_differential/ADS_differential.ino @@ -0,0 +1,70 @@ +// +// FILE: ADS_differential.ino +// AUTHOR: Rob.Tillaart +// PURPOSE: read differential +// URL: https://github.com/RobTillaart/ADS1X15 + +// 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); + + Wire.begin(); + + 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/lib/ADS1X15/examples/ADS_high_speed_differential/ADS_high_speed_differential.ino b/lib/ADS1X15/examples/ADS_high_speed_differential/ADS_high_speed_differential.ino new file mode 100644 index 0000000..2b181ab --- /dev/null +++ b/lib/ADS1X15/examples/ADS_high_speed_differential/ADS_high_speed_differential.ino @@ -0,0 +1,129 @@ +// +// FILE: ADS_high_speed_differential.ino.ino +// AUTHOR: Rob.Tillaart +// PURPOSE: read from 2 IC's for high speed differential +// interrupt driven to catch all conversions. +// URL: https://github.com/RobTillaart/ADS1X15 + +// 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); + + Wire.begin(); + + // SETUP FIRST ADS1115 + ADS_1.begin(); + ADS_1.setGain(0); // 6.144 volt + ADS_1.setDataRate(7); // 0 = slow 4 = medium 7 = fast + + // SET ALERT RDY PIN (QueConvert mode) + // set the MSB of the Hi_thresh register to 1 + ADS_1.setComparatorThresholdHigh(0x8000); + // set the MSB of the Lo_thresh register to 0 + 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 + // set the MSB of the Hi_thresh register to 1 + ADS_2.setComparatorThresholdHigh(0x8000); + // set the MSB of the Lo_thresh register to 0 + 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/lib/ADS1X15/examples/ADS_minimum/ADS_minimum.ino b/lib/ADS1X15/examples/ADS_minimum/ADS_minimum.ino new file mode 100644 index 0000000..6f3e984 --- /dev/null +++ b/lib/ADS1X15/examples/ADS_minimum/ADS_minimum.ino @@ -0,0 +1,54 @@ +// +// FILE: ADS_minimum.ino +// AUTHOR: Rob.Tillaart +// PURPOSE: read analog input +// URL: https://github.com/RobTillaart/ADS1X15 + +// test +// connect 1 potmeter +// +// GND ---[ x ]------ 5V +// | +// +// measure at x (connect to AIN0). +// +// view with Serial Plotter + + +#include "ADS1X15.h" + + +// choose your 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); + + Wire.begin(); + + 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/lib/ADS1X15/examples/ADS_performance/ADS_performance.ino b/lib/ADS1X15/examples/ADS_performance/ADS_performance.ino new file mode 100644 index 0000000..e23a87c --- /dev/null +++ b/lib/ADS1X15/examples/ADS_performance/ADS_performance.ino @@ -0,0 +1,111 @@ +// +// FILE: ADS_performance.ino +// AUTHOR: Rob.Tillaart +// PURPOSE: read analog input +// URL: https://github.com/RobTillaart/ADS1X15 + +// test +// connect 1 potmeter +// +// GND ---[ x ]------ 5V +// | +// +// measure at x (connect to AIN0). +// +// https://github.com/RobTillaart/ADS1X15/issues/53 + + +#include "ADS1X15.h" + + +// choose your 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); + + Wire.begin(); + Wire.setClock(100000); + + ADS.begin(); + ADS.setGain(0); // 6.144 volt + + for (int dr = 0; dr < 8; dr++) + { + // 0 = slow 4 = medium 7 = fast + 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.print(d1); // TIME (us) + Serial.print("\t\t"); + Serial.println(100000000.0 / d1); // SPS + delay(100); +} + + +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.print(d2); // TIME (us) + Serial.print("\t\t"); + Serial.println(100000000.0 / d2); // SPS + delay(100); +} + + +// -- END OF FILE -- + diff --git a/lib/ADS1X15/examples/ADS_performance/performance_0.3.9.md b/lib/ADS1X15/examples/ADS_performance/performance_0.3.9.md new file mode 100644 index 0000000..fd80add --- /dev/null +++ b/lib/ADS1X15/examples/ADS_performance/performance_0.3.9.md @@ -0,0 +1,49 @@ +Based upon output of **ADS_performance.ino** +UNO 16 MHz. +IDE 1.8.19 + + +Synchronous calls I2C **100 KHz** + +| DataRate | Time 100 calls | SPS | +|:----------:|:----------------:|:------:| +| 0 | 12861340 | 7.78 | +| 1 | 6481396 | 15.4 | +| 2 | 3347512 | 29.9 | +| 3 | 1724380 | 58.0 | +| 4 | 941032 | 106 | +| 5 | 549204 | 182 | +| 6 | 381340 | 262 | +| 7 | 269448 | 371 | + + +Synchronous calls I2C **400 KHz** + +| DataRate | Time 100 calls | SPS | +|:----------:|:----------------:|:------:| +| 0 | 12872804 | 7.77 | +| 1 | 6402848 | 15.6 | +| 2 | 3234156 | 30.9 | +| 3 | 1649272 | 60.6 | +| 4 | 862188 | 116 | +| 5 | 468652 | 213 | +| 6 | 271552 | 368 | +| 7 | 173412 | 577 | + + +Synchronous calls I2C **600 KHz** + +| DataRate | Time 100 calls | SPS | +|:----------:|:----------------:|:------:| +| 0 | 12736788 | 7.85 | +| 1 | 6390104 | 15.7 | +| 2 | 3223568 | 31.0 | +| 3 | 1645768 | 60.8 | +| 4 | 852300 | 117 | +| 5 | 448520 | 223 | +| 6 | 261216 | 383 | +| 7 | 167660 | 596 | + +These are maxima of the SPS feasible, they do not include further processing. +At least this test shows the effect of the I2C bus speed. + diff --git a/lib/ADS1X15/examples/ADS_pointerToFunction/.arduino-ci.yml b/lib/ADS1X15/examples/ADS_pointerToFunction/.arduino-ci.yml new file mode 100644 index 0000000..f8835f0 --- /dev/null +++ b/lib/ADS1X15/examples/ADS_pointerToFunction/.arduino-ci.yml @@ -0,0 +1,28 @@ +platforms: + rpipico: + board: rp2040:rp2040:rpipico + package: rp2040:rp2040 + gcc: + features: + defines: + - ARDUINO_ARCH_RP2040 + warnings: + flags: + +packages: + rp2040:rp2040: + url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json + + +compile: + # Choosing to run compilation tests on 2 different Arduino platforms + platforms: + - uno + # - due + # - zero + # - leonardo + # - m4 + # - esp32 + # - esp8266 + # - mega2560 + - rpipico diff --git a/lib/ADS1X15/examples/ADS_pointerToFunction/ADS_pointerToFunction.ino b/lib/ADS1X15/examples/ADS_pointerToFunction/ADS_pointerToFunction.ino new file mode 100644 index 0000000..32f3e1c --- /dev/null +++ b/lib/ADS1X15/examples/ADS_pointerToFunction/ADS_pointerToFunction.ino @@ -0,0 +1,50 @@ +// FILE: ADS_pointerToFunction.ino +// AUTHOR: Rob Tillaart +// PURPOSE: replace internal ADC with external ADC by using pointer to function +// URL: https://github.com/RobTillaart/ADS1X15 +// +// WARNING ONLY TESTED ON AVR + + +#include "Arduino.h" +#include "ADS1X15.h" + +// adjust address if needed +ADS1115 ADS(0x48); + +// pointer to ADC function +int (*readADC)(uint8_t); + + +void setup() +{ + Serial.begin(115200); + while(!Serial); + Serial.println(__FILE__); + + Wire.begin(); + Wire.setClock(100000); + + ADS.begin(); // use defaults + + readADC = analogRead; // start with internal +} + + +void loop() +{ + delay(500); + int x = readADC(1); + Serial.println(x); + if (millis() > 5000) readADC = wrapper; +} + +// wrapper takes care +int wrapper(uint8_t x) +{ + return ADS.readADC(x); +} + + + +// -- END OF FILE -- diff --git a/lib/ADS1X15/examples/ADS_read/ADS_read.ino b/lib/ADS1X15/examples/ADS_read/ADS_read.ino new file mode 100644 index 0000000..ef0b7f7 --- /dev/null +++ b/lib/ADS1X15/examples/ADS_read/ADS_read.ino @@ -0,0 +1,55 @@ +// +// FILE: ADS_read.ino +// AUTHOR: Rob.Tillaart +// PURPOSE: read analog inputs - straightforward. +// URL: https://github.com/RobTillaart/ADS1X15 + +// 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); + + Wire.begin(); + 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/lib/ADS1X15/examples/ADS_read_RDY/ADS_read_RDY.ino b/lib/ADS1X15/examples/ADS_read_RDY/ADS_read_RDY.ino new file mode 100644 index 0000000..ddee6c9 --- /dev/null +++ b/lib/ADS1X15/examples/ADS_read_RDY/ADS_read_RDY.ino @@ -0,0 +1,68 @@ +// +// FILE: ADS_read_RDY.ino +// AUTHOR: Rob.Tillaart +// PURPOSE: read analog inputs - straightforward. +// URL: https://github.com/RobTillaart/ADS1X15 + +// test +// connect 1 potentiometer 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); + + Wire.begin(); + + ADS.begin(); + ADS.setGain(0); // 6.144 volt + ADS.setDataRate(7); // 0 = slow 4 = medium 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/lib/ADS1X15/examples/ADS_read_async/ADS_read_async.ino b/lib/ADS1X15/examples/ADS_read_async/ADS_read_async.ino new file mode 100644 index 0000000..e7b8e53 --- /dev/null +++ b/lib/ADS1X15/examples/ADS_read_async/ADS_read_async.ino @@ -0,0 +1,57 @@ +// +// FILE: ADS_read_async.ino +// AUTHOR: Rob.Tillaart +// PURPOSE: read analog inputs - asynchronous +// URL: https://github.com/RobTillaart/ADS1X15 + +// 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); + + Wire.begin(); + + 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(); + // request a new one + ADS.requestADC(0); + 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/lib/ADS1X15/examples/ADS_read_async_rdy/ADS_read_async_rdy.ino b/lib/ADS1X15/examples/ADS_read_async_rdy/ADS_read_async_rdy.ino new file mode 100644 index 0000000..edf1e49 --- /dev/null +++ b/lib/ADS1X15/examples/ADS_read_async_rdy/ADS_read_async_rdy.ino @@ -0,0 +1,71 @@ +// +// FILE: ADS_read_async_rdy.ino +// AUTHOR: Rob.Tillaart +// PURPOSE: read analog inputs - straightforward. +// URL: https://github.com/RobTillaart/ADS1X15 + +// 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); + + Wire.begin(); + + ADS.begin(); + ADS.setGain(0); // 6.144 volt + + // select slow so the led blinks visible for the eye. + ADS.setDataRate(0); // 0 = slow 4 = medium 7 = fast + 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(); + // request a new one + ADS.requestADC(0); + 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/lib/ADS1X15/examples/ADS_read_comparator_1/ADS_read_comparator_1.ino b/lib/ADS1X15/examples/ADS_read_comparator_1/ADS_read_comparator_1.ino new file mode 100644 index 0000000..a7d51f1 --- /dev/null +++ b/lib/ADS1X15/examples/ADS_read_comparator_1/ADS_read_comparator_1.ino @@ -0,0 +1,86 @@ +// +// FILE: ADS_read_comparator_1.ino +// AUTHOR: Rob.Tillaart +// PURPOSE: read analog inputs - straightforward. +// URL: https://github.com/RobTillaart/ADS1X15 + +// 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); + + Wire.begin(); + + 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/lib/ADS1X15/examples/ADS_setWireClock/ADS_setWireClock.ino b/lib/ADS1X15/examples/ADS_setWireClock/ADS_setWireClock.ino new file mode 100644 index 0000000..31086f2 --- /dev/null +++ b/lib/ADS1X15/examples/ADS_setWireClock/ADS_setWireClock.ino @@ -0,0 +1,66 @@ +// +// FILE: ADS_setWireClock.ino +// AUTHOR: Rob.Tillaart +// PURPOSE: read analog inputs - straightforward. +// URL: https://github.com/RobTillaart/ADS1X15 + +// test +// connect 1 potentiometer 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/lib/ADS1X15/keywords.txt b/lib/ADS1X15/keywords.txt new file mode 100644 index 0000000..fa5df2b --- /dev/null +++ b/lib/ADS1X15/keywords.txt @@ -0,0 +1,73 @@ +# Syntax Colouring Map For ADS1X15 + +# Data types (KEYWORD1) +ADS1X15 KEYWORD1 +ADS1013 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 + +getLastRequest 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/lib/ADS1X15/library.json b/lib/ADS1X15/library.json new file mode 100644 index 0000000..ba64b32 --- /dev/null +++ b/lib/ADS1X15/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.4.2", + "license": "MIT", + "frameworks": "*", + "platforms": "*", + "headers": "ADS1X15.h" +} diff --git a/lib/ADS1X15/library.properties b/lib/ADS1X15/library.properties new file mode 100644 index 0000000..2ab647f --- /dev/null +++ b/lib/ADS1X15/library.properties @@ -0,0 +1,11 @@ +name=ADS1X15 +version=0.4.2 +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/platformio.ini b/platformio.ini index 73701df..ddb4235 100644 --- a/platformio.ini +++ b/platformio.ini @@ -13,7 +13,7 @@ default_envs = default boards_dir = ./boards [env] -platform = espressif32 +platform = espressif32@3.0.0 board = lilygo-t-displays3 framework = arduino build_flags = @@ -24,14 +24,17 @@ build_flags = [env:default] lib_deps = h2zero/NimBLE-Arduino@^1.4.1 - robtillaart/ADS1X15@^0.4.1 +; robtillaart/ADS1X15@^0.4.1 lemmingdev/ESP32-BLE-Gamepad@^0.5.2 +; lorol/LittleFS_esp32@^1.0.6 [env:lilygo-t-display-s3] -platform = espressif32 +platform = espressif32@3.0.0 board = lilygo-t-display-s3 +; board_build.partitions = S3R8TX.csv framework = arduino lib_deps = h2zero/NimBLE-Arduino@^1.4.1 - robtillaart/ADS1X15@^0.4.1 +; robtillaart/ADS1X15@^0.4.1 lemmingdev/ESP32-BLE-Gamepad@^0.5.2 +; lorol/LittleFS_esp32@^1.0.6 diff --git a/src/main.cpp b/src/main.cpp index dabb93a..e85215b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -165,7 +165,12 @@ TinyGPSCustom snr[MAX_SATELLITES]; // #### Variables #### uint32_t uptime = 0; +uint32_t uptime_grandtotal = 0; uint32_t charge_time = 0; +uint32_t discharged_time = 0; +uint32_t discharged_time_grandtotal = 0; +uint32_t flight_time = 0; +uint32_t flight_time_total = 0; void setup() { @@ -176,7 +181,7 @@ void setup() { // if(!SWSerialPort) { // Serial.println("Software Serial ERROR"); // } - delay(280); + delay(1000); Serial.print("S3R8TX - "); Serial.println(VERSION); @@ -184,6 +189,12 @@ void setup() { // Set it Max setCpuFrequencyMhz(240); + // Setting up Storage for Configurations + Serial.println("Before init_storage()"); + init_storage(); + Serial.println("After init_storage()"); + // storage.begin(); + // Turn on display, it will be off when is LOW when using battery but not for USB cable attached pinMode(PIN_POWER_ON, OUTPUT); digitalWrite(PIN_POWER_ON, HIGH); @@ -275,6 +286,16 @@ void setup() { CPU_0 ); + xTaskCreatePinnedToCore( + taskESPNow, + "TaskESPNow", // Name of the process + 16384, // This stack size can be checked & adjusted by reading the Stack Highwater + NULL, + 5, // Priority + NULL, + CPU_0 + ); + xTaskCreatePinnedToCore( taskBLE, "TaskBLE", // Name of the process @@ -290,6 +311,22 @@ void setup() { } +void init_storage(void) { + /*** + if(!FFat.begin()){ + Serial.println("FFat Mount Failed"); + // Format it..... + FFat.format(); + // ESP.restart(); + return; + // REF: https://gitcode.net/as350144/arduino-esp32/-/blob/feature/idf_component_ci_and_ver_check/libraries/FFat/examples/FFat_Test/FFat_Test.ino + } + ***/ + // Serial.printf("Total space: %10u\n", FFat.totalBytes()); + // Serial.printf("Free space: %10u\n", FFat.freeBytes()); +} + + void screen_intro(void) { char strbuf[255]; @@ -313,7 +350,7 @@ void screen_intro(void) { - delay(5000); + delay(2000); current_screen++; } @@ -605,6 +642,7 @@ void load_mainscreen(void) { else sprite.pushImage(240, 0, 80, 80, (uint16_t *)button_off); + // Based on the voltage to display the icon if(charge_state) { sprite.pushImage(320-BATTERY_CHARGING_WIDTH, 90, BATTERY_CHARGING_WIDTH, BATTERY_CHARGING_HEIGHT, (uint16_t *)battery_charging); @@ -648,6 +686,14 @@ void load_mainscreen(void) { sprintf(strbuf, "B: %dmV R: %d", batt_volt, profile_gimbal_rate); sprite.drawString(strbuf, 0, 134); + // Top Left Physical Switch + if(toggles[0]) { + sprintf(strbuf, "ARMED"); + } else { + sprintf(strbuf, "DISARMED"); + } + sprite.drawString(strbuf, 0, 118); + sprite.pushSprite(0, 0); // Reading input from the touch screen @@ -1325,6 +1371,26 @@ void taskDisplay(void *pvParameters) { } +void taskESPNow(void *pvParameters) { + (void) pvParameters; + + for(;;) { + vTaskDelay(10); + } +} + + +/*** Template for task functions +void taskESPNow(void *pvParameters) { + (void) pvParameters; + + for(;;) { + vTaskDelay(10); + } +} + ***/ + + void taskBLE(void *pvParameters) { (void) pvParameters; bool ble_begin = false; @@ -1332,6 +1398,8 @@ void taskBLE(void *pvParameters) { bool ble_start = false; uint32_t last_updated = 0; + uint8_t toggle_count = 0; + for(;;) { vTaskDelay(10); @@ -1355,6 +1423,16 @@ void taskBLE(void *pvParameters) { bleGamepad.setAxes(yaw_bt, throttle_bt, roll_bt, pitch_bt, 0, 0, DPAD_CENTERED); + if(toggles[0]) + bleGamepad.press(BUTTON_1); + else + bleGamepad.release(BUTTON_1); + + if(toggles[1]) + bleGamepad.press(BUTTON_2); + else + bleGamepad.release(BUTTON_2); + /**** uint32_t m = millis(); if(button1) { diff --git a/src/main.h b/src/main.h index 730c6b0..7e140da 100644 --- a/src/main.h +++ b/src/main.h @@ -3,6 +3,8 @@ #define VERSION "1.0.0" +#include + /* The product now has two screens, and the initialization code needs a small change in the new version. The LCD_MODULE_CMD_1 is used to define the switch macro. */ #define LCD_MODULE_CMD_1 @@ -63,6 +65,10 @@ #define SW_ARM 1 #define SW_AUX 2 +// ESPNow Defaule channel +#define ESPNOW_DEFAULT_CHANNEL 1 +#define EEPROM_SIZE 7 + #include #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5,0,0) #error "The current version is not supported for the time being, please use a version below Arduino ESP32 3.0" @@ -74,6 +80,8 @@ // #include #include +#include +#include #include "TouchLib.h" #include "Wire.h" #include "ADS1X15.h" @@ -89,6 +97,10 @@ #include "battery_2.h" #include "battery_1.h" +// #include "FS.h" +// #include "FFat.h" + + enum screen_names { SCREEN_INTRO, @@ -116,14 +128,51 @@ enum transmission_names { }; +// ESPNOW Status +enum MessageType { + PAIRING, + DATA +}; + +// ESPNOW Paring status +enum PairingStatus { + NOT_PAIRED, + PAIR_REQUEST, + PAIR_REQUESTED, + PAIR_PAIRED +}; + +// ESPNOW paring structure +typedef struct struct_pairing { + uint8_t message_type; + uint8_t channel; +} struct_pairing; + +// ESPNOW gimbal and button data (NOT SURE!!!) +typedef struct struct_data { + uint8_t message_type; + uint16_t throttle; + uint16_t yaw; + uint16_t roll; + uint16_t pitch; + uint16_t aux; + // bool aux[9]; + uint16_t rubybutton; + // bool rubybutton[9]; +} struct_data; + + + uint8_t current_screen = SCREEN_INTRO; void taskSystem(void *pvParameters); void taskDisplay(void *pvParameters); void taskGimbal(void *pvParameters); void taskBLE(void *pvParameters); +void taskESPNow(void *pvParameters); // void taskGPS(void *pvParameters); + void screen_intro(void); void screen_watchface_0(void); void screen_watchface_1(void); @@ -131,6 +180,8 @@ void screen_tools_1(void); void screen_tools_2(void); void screen_tools_3(void); +void init_storage(void); + // void screen_gps(void); void screen_system(void); // void display_info(void);