Browse Source

initial

master
Englebert 9 months ago
parent
commit
093054dfe0
  1. 6
      README.md
  2. 28
      lib/ADS1X15/.arduino-ci.yml
  3. 4
      lib/ADS1X15/.github/FUNDING.yml
  4. 13
      lib/ADS1X15/.github/workflows/arduino-lint.yml
  5. 17
      lib/ADS1X15/.github/workflows/arduino_test_runner.yml
  6. 18
      lib/ADS1X15/.github/workflows/jsoncheck.yml
  7. 1
      lib/ADS1X15/.piopm
  8. 750
      lib/ADS1X15/ADS1X15.cpp
  9. 251
      lib/ADS1X15/ADS1X15.h
  10. 138
      lib/ADS1X15/CHANGELOG.md
  11. 21
      lib/ADS1X15/LICENSE
  12. 504
      lib/ADS1X15/README.md
  13. 49
      lib/ADS1X15/examples/ADS1113_getMaxVoltage/ADS1113_getMaxVoltage.ino
  14. 115
      lib/ADS1X15/examples/ADS_1114_four/ADS_1114_four.ino
  15. 120
      lib/ADS1X15/examples/ADS_1114_two_continuous/ADS_1114_two_continuous.ino
  16. 27
      lib/ADS1X15/examples/ADS_RP2040_WIRE1/.arduino-ci.yml
  17. 55
      lib/ADS1X15/examples/ADS_RP2040_WIRE1/ADS_RP2040_WIRE1.ino
  18. 124
      lib/ADS1X15/examples/ADS_async_16_channel/ADS_async_16_channel.ino
  19. 142
      lib/ADS1X15/examples/ADS_async_8_channel/ADS_async_8_channel.ino
  20. 99
      lib/ADS1X15/examples/ADS_async_differential/ADS_async_differential.ino
  21. 74
      lib/ADS1X15/examples/ADS_continuous/ADS_continuous.ino
  22. 124
      lib/ADS1X15/examples/ADS_continuous_3_channel/ADS_continuous_3_channel.ino
  23. 106
      lib/ADS1X15/examples/ADS_continuous_4_channel/ADS_continuous_4_channel.ino
  24. 144
      lib/ADS1X15/examples/ADS_continuous_8_channel/ADS_continuous_8_channel.ino
  25. 129
      lib/ADS1X15/examples/ADS_continuous_differential/ADS_continuous_differential.ino
  26. 70
      lib/ADS1X15/examples/ADS_differential/ADS_differential.ino
  27. 129
      lib/ADS1X15/examples/ADS_high_speed_differential/ADS_high_speed_differential.ino
  28. 54
      lib/ADS1X15/examples/ADS_minimum/ADS_minimum.ino
  29. 111
      lib/ADS1X15/examples/ADS_performance/ADS_performance.ino
  30. 49
      lib/ADS1X15/examples/ADS_performance/performance_0.3.9.md
  31. 28
      lib/ADS1X15/examples/ADS_pointerToFunction/.arduino-ci.yml
  32. 50
      lib/ADS1X15/examples/ADS_pointerToFunction/ADS_pointerToFunction.ino
  33. 55
      lib/ADS1X15/examples/ADS_read/ADS_read.ino
  34. 68
      lib/ADS1X15/examples/ADS_read_RDY/ADS_read_RDY.ino
  35. 57
      lib/ADS1X15/examples/ADS_read_async/ADS_read_async.ino
  36. 71
      lib/ADS1X15/examples/ADS_read_async_rdy/ADS_read_async_rdy.ino
  37. 86
      lib/ADS1X15/examples/ADS_read_comparator_1/ADS_read_comparator_1.ino
  38. 66
      lib/ADS1X15/examples/ADS_setWireClock/ADS_setWireClock.ino
  39. 73
      lib/ADS1X15/keywords.txt
  40. 23
      lib/ADS1X15/library.json
  41. 11
      lib/ADS1X15/library.properties
  42. 11
      platformio.ini
  43. 82
      src/main.cpp
  44. 51
      src/main.h

6
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

28
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

4
lib/ADS1X15/.github/FUNDING.yml

@ -0,0 +1,4 @@
# These are supported funding model platforms
github: RobTillaart

13
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

17
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

18
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$"

1
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}}

750
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 --

251
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 --

138
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

21
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.

504
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,

49
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 --

115
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 --

120
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 --

27
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

55
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 --

124
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 --

142
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 --

99
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 --

74
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 --

124
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 --

106
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 --

144
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 --

129
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 --

70
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 <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);
}
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 --

129
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 --

54
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 --

111
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 --

49
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.

28
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

50
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 --

55
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 --

68
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 --

57
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 --

71
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 --

86
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 --

66
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 --

73
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

23
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"
}

11
lib/ADS1X15/library.properties

@ -0,0 +1,11 @@
name=ADS1X15
version=0.4.2
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
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=

11
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

82
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) {

51
src/main.h

@ -3,6 +3,8 @@
#define VERSION "1.0.0"
#include <Arduino.h>
/* 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 <esp_adc_cal.h>
#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 <NimBLEDevice.h>
#include <BleGamepad.h>
#include <esp_wifi.h>
#include <esp_now.h>
#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);

Loading…
Cancel
Save