├── .arduino-ci.yml ├── .github ├── FUNDING.yml └── workflows │ ├── arduino-lint.yml │ ├── arduino_test_runner.yml │ └── jsoncheck.yml ├── ADS1X15.cpp ├── ADS1X15.h ├── CHANGELOG.md ├── LICENSE ├── README.md ├── examples ├── ADS1113_getMaxVoltage │ └── ADS1113_getMaxVoltage.ino ├── ADS_1114_four │ └── ADS_1114_four.ino ├── ADS_1114_two_continuous │ └── ADS_1114_two_continuous.ino ├── ADS_COMP_POL │ └── ADS_COMP_POL.ino ├── ADS_RP2040_WIRE1 │ ├── .arduino-ci.yml │ └── ADS_RP2040_WIRE1.ino ├── ADS_async_16_channel │ └── ADS_async_16_channel.ino ├── ADS_async_8_channel │ └── ADS_async_8_channel.ino ├── ADS_async_differential │ └── ADS_async_differential.ino ├── ADS_continuous │ └── ADS_continuous.ino ├── ADS_continuous_3_channel │ └── ADS_continuous_3_channel.ino ├── ADS_continuous_4_channel │ └── ADS_continuous_4_channel.ino ├── ADS_continuous_8_channel │ └── ADS_continuous_8_channel.ino ├── ADS_continuous_differential │ └── ADS_continuous_differential.ino ├── ADS_differential │ └── ADS_differential.ino ├── ADS_high_speed_differential │ └── ADS_high_speed_differential.ino ├── ADS_minimum │ └── ADS_minimum.ino ├── ADS_performance │ ├── ADS_performance.ino │ ├── performance_0.3.9.md │ └── performance_0.4.4.md ├── ADS_pointerToFunction │ ├── .arduino-ci.yml │ └── ADS_pointerToFunction.ino ├── ADS_read │ └── ADS_read.ino ├── ADS_read_RDY │ └── ADS_read_RDY.ino ├── ADS_read_async │ └── ADS_read_async.ino ├── ADS_read_async_rdy │ └── ADS_read_async_rdy.ino ├── ADS_read_comparator_1 │ └── ADS_read_comparator_1.ino ├── ADS_read_getError │ └── ADS_read_getError.ino ├── ADS_setWireClock │ └── ADS_setWireClock.ino └── ADS_test_config │ └── ADS_test_config.ino ├── keywords.txt ├── library.json ├── library.properties └── test └── unit_test_001.cpp /.arduino-ci.yml: -------------------------------------------------------------------------------- 1 | platforms: 2 | rpipico: 3 | board: rp2040:rp2040:rpipico 4 | package: rp2040:rp2040 5 | gcc: 6 | features: 7 | defines: 8 | - ARDUINO_ARCH_RP2040 9 | warnings: 10 | flags: 11 | 12 | packages: 13 | rp2040:rp2040: 14 | url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json 15 | 16 | 17 | compile: 18 | # Choosing to run compilation tests on 2 different Arduino platforms 19 | platforms: 20 | - uno 21 | # - due 22 | # - zero 23 | # - leonardo 24 | - m4 25 | - esp32 26 | # - esp8266 27 | # - mega2560 28 | - rpipico 29 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: RobTillaart 4 | custom: "https://www.paypal.me/robtillaart" 5 | -------------------------------------------------------------------------------- /.github/workflows/arduino-lint.yml: -------------------------------------------------------------------------------- 1 | name: Arduino-lint 2 | 3 | on: [push, pull_request] 4 | jobs: 5 | lint: 6 | runs-on: ubuntu-latest 7 | timeout-minutes: 5 8 | steps: 9 | - uses: actions/checkout@v4 10 | - uses: arduino/arduino-lint-action@v1 11 | with: 12 | library-manager: update 13 | compliance: strict -------------------------------------------------------------------------------- /.github/workflows/arduino_test_runner.yml: -------------------------------------------------------------------------------- 1 | name: Arduino CI 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | runTest: 7 | runs-on: ubuntu-latest 8 | timeout-minutes: 20 9 | 10 | steps: 11 | - uses: actions/checkout@v4 12 | - uses: ruby/setup-ruby@v1 13 | with: 14 | ruby-version: 2.6 15 | - run: | 16 | gem install arduino_ci 17 | arduino_ci.rb 18 | -------------------------------------------------------------------------------- /.github/workflows/jsoncheck.yml: -------------------------------------------------------------------------------- 1 | name: JSON check 2 | 3 | on: 4 | push: 5 | paths: 6 | - '**.json' 7 | pull_request: 8 | 9 | jobs: 10 | test: 11 | runs-on: ubuntu-latest 12 | timeout-minutes: 5 13 | steps: 14 | - uses: actions/checkout@v4 15 | - name: json-syntax-check 16 | uses: limitusus/json-syntax-check@v2 17 | with: 18 | pattern: "\\.json$" -------------------------------------------------------------------------------- /ADS1X15.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS1X15.cpp 3 | // AUTHOR: Rob Tillaart 4 | // VERSION: 0.5.2 5 | // DATE: 2013-03-24 6 | // PURPOSE: Arduino library for ADS1015 and ADS1115 7 | // URL: https://github.com/RobTillaart/ADS1X15 8 | 9 | 10 | #include "ADS1X15.h" 11 | 12 | 13 | #define ADS1015_CONVERSION_DELAY 1 14 | #define ADS1115_CONVERSION_DELAY 8 15 | 16 | 17 | // Kept #defines a bit in line with Adafruit library. 18 | 19 | // REGISTERS 20 | #define ADS1X15_REG_CONVERT 0x00 21 | #define ADS1X15_REG_CONFIG 0x01 22 | #define ADS1X15_REG_LOW_THRESHOLD 0x02 23 | #define ADS1X15_REG_HIGH_THRESHOLD 0x03 24 | 25 | 26 | // CONFIG REGISTER 27 | 28 | // BIT 15 Operational Status // 1 << 15 29 | #define ADS1X15_OS_BUSY 0x0000 30 | #define ADS1X15_OS_NOT_BUSY 0x8000 31 | #define ADS1X15_OS_START_SINGLE 0x8000 32 | 33 | // BIT 12-14 read differential 34 | #define ADS1X15_MUX_DIFF_0_1 0x0000 35 | #define ADS1X15_MUX_DIFF_0_3 0x1000 36 | #define ADS1X15_MUX_DIFF_1_3 0x2000 37 | #define ADS1X15_MUX_DIFF_2_3 0x3000 38 | // read single 39 | #define ADS1X15_READ_0 0x4000 // pin << 12 40 | #define ADS1X15_READ_1 0x5000 // pin = 0..3 41 | #define ADS1X15_READ_2 0x6000 42 | #define ADS1X15_READ_3 0x7000 43 | 44 | 45 | // BIT 9-11 gain // (0..5) << 9 46 | #define ADS1X15_PGA_6_144V 0x0000 // voltage 47 | #define ADS1X15_PGA_4_096V 0x0200 // 48 | #define ADS1X15_PGA_2_048V 0x0400 // default 49 | #define ADS1X15_PGA_1_024V 0x0600 50 | #define ADS1X15_PGA_0_512V 0x0800 51 | #define ADS1X15_PGA_0_256V 0x0A00 52 | 53 | // BIT 8 mode // 1 << 8 54 | #define ADS1X15_MODE_CONTINUE 0x0000 55 | #define ADS1X15_MODE_SINGLE 0x0100 56 | 57 | // BIT 5-7 data rate sample per second // (0..7) << 5 58 | /* 59 | differs for different devices, check datasheet or readme.md 60 | 61 | | data rate | ADS101x | ADS111x | Notes | 62 | |:-----------:|----------:|----------:|:---------:| 63 | | 0 | 128 | 8 | slowest | 64 | | 1 | 250 | 16 | | 65 | | 2 | 490 | 32 | | 66 | | 3 | 920 | 64 | | 67 | | 4 | 1600 | 128 | default | 68 | | 5 | 2400 | 250 | | 69 | | 6 | 3300 | 475 | | 70 | | 7 | 3300 | 860 | fastest | 71 | */ 72 | 73 | // BIT 4 comparator modi // 1 << 4 74 | #define ADS1X15_COMP_MODE_TRADITIONAL 0x0000 75 | #define ADS1X15_COMP_MODE_WINDOW 0x0010 76 | 77 | // BIT 3 ALERT active value // 1 << 3 78 | #define ADS1X15_COMP_POL_ACTIV_LOW 0x0000 79 | #define ADS1X15_COMP_POL_ACTIV_HIGH 0x0008 80 | 81 | // BIT 2 ALERT latching // 1 << 2 82 | #define ADS1X15_COMP_NON_LATCH 0x0000 83 | #define ADS1X15_COMP_LATCH 0x0004 84 | 85 | // BIT 0-1 ALERT mode // (0..3) 86 | #define ADS1X15_COMP_QUE_1_CONV 0x0000 // trigger alert after 1 convert 87 | #define ADS1X15_COMP_QUE_2_CONV 0x0001 // trigger alert after 2 converts 88 | #define ADS1X15_COMP_QUE_4_CONV 0x0002 // trigger alert after 4 converts 89 | #define ADS1X15_COMP_QUE_NONE 0x0003 // disable comparator 90 | 91 | 92 | // _CONFIG masks 93 | // 94 | // | bit | description | 95 | // |:-----:|:-----------------------| 96 | // | 0 | # channels | 97 | // | 1 | - | 98 | // | 2 | resolution | 99 | // | 3 | - | 100 | // | 4 | GAIN supported | 101 | // | 5 | COMPARATOR supported | 102 | // | 6 | - | 103 | // | 7 | - | 104 | // 105 | #define ADS_CONF_CHAN_1 0x00 106 | #define ADS_CONF_CHAN_4 0x01 107 | #define ADS_CONF_RES_12 0x00 108 | #define ADS_CONF_RES_16 0x04 109 | #define ADS_CONF_NOGAIN 0x00 110 | #define ADS_CONF_GAIN 0x10 111 | #define ADS_CONF_NOCOMP 0x00 112 | #define ADS_CONF_COMP 0x20 113 | 114 | 115 | ////////////////////////////////////////////////////// 116 | // 117 | // BASE CONSTRUCTOR 118 | // 119 | ADS1X15::ADS1X15() 120 | { 121 | reset(); 122 | } 123 | 124 | 125 | ////////////////////////////////////////////////////// 126 | // 127 | // PUBLIC 128 | // 129 | void ADS1X15::reset() 130 | { 131 | setGain(0); // _gain = ADS1X15_PGA_6_144V; 132 | setMode(1); // _mode = ADS1X15_MODE_SINGLE; 133 | setDataRate(4); // middle speed, depends on device. 134 | 135 | // COMPARATOR variables # see notes .h 136 | _compMode = 0; 137 | _compPol = 1; 138 | _compLatch = 0; 139 | _compQueConvert = 3; 140 | _lastRequest = 0xFFFF; // no request yet 141 | } 142 | 143 | 144 | bool ADS1X15::begin() 145 | { 146 | if ((_address < 0x48) || (_address > 0x4B)) return false; 147 | if (! isConnected()) return false; 148 | return true; 149 | } 150 | 151 | 152 | bool ADS1X15::isConnected() 153 | { 154 | _wire->beginTransmission(_address); 155 | return (_wire->endTransmission() == 0); 156 | } 157 | 158 | 159 | void ADS1X15::setGain(uint8_t gain) 160 | { 161 | if (!(_config & ADS_CONF_GAIN)) gain = 0; 162 | switch (gain) 163 | { 164 | default: // catch invalid values and go for the safest gain. 165 | case 0: _gain = ADS1X15_PGA_6_144V; break; 166 | case 1: _gain = ADS1X15_PGA_4_096V; break; 167 | case 2: _gain = ADS1X15_PGA_2_048V; break; 168 | case 4: _gain = ADS1X15_PGA_1_024V; break; 169 | case 8: _gain = ADS1X15_PGA_0_512V; break; 170 | case 16: _gain = ADS1X15_PGA_0_256V; break; 171 | } 172 | } 173 | 174 | 175 | uint8_t ADS1X15::getGain() 176 | { 177 | if (!(_config & ADS_CONF_GAIN)) return 0; 178 | switch (_gain) 179 | { 180 | case ADS1X15_PGA_6_144V: return 0; 181 | case ADS1X15_PGA_4_096V: return 1; 182 | case ADS1X15_PGA_2_048V: return 2; 183 | case ADS1X15_PGA_1_024V: return 4; 184 | case ADS1X15_PGA_0_512V: return 8; 185 | case ADS1X15_PGA_0_256V: return 16; 186 | } 187 | _error = ADS1X15_INVALID_GAIN; 188 | return _error; 189 | } 190 | 191 | 192 | float ADS1X15::toVoltage(int16_t value) 193 | { 194 | if (value == 0) return 0; 195 | 196 | float volts = getMaxVoltage(); 197 | if (volts < 0) return volts; // propagate error 198 | 199 | volts *= value; 200 | if (_config & ADS_CONF_RES_16) 201 | { 202 | volts /= 32767; // value = 16 bits - sign bit = 15 bits mantissa 203 | } 204 | else 205 | { 206 | volts /= 2047; // value = 12 bits - sign bit = 11 bit mantissa 207 | } 208 | return volts; 209 | } 210 | 211 | 212 | float ADS1X15::getMaxVoltage() 213 | { 214 | switch (_gain) 215 | { 216 | case ADS1X15_PGA_6_144V: return 6.144; 217 | case ADS1X15_PGA_4_096V: return 4.096; 218 | case ADS1X15_PGA_2_048V: return 2.048; 219 | case ADS1X15_PGA_1_024V: return 1.024; 220 | case ADS1X15_PGA_0_512V: return 0.512; 221 | case ADS1X15_PGA_0_256V: return 0.256; 222 | } 223 | _error = ADS1X15_INVALID_VOLTAGE; 224 | return _error; 225 | } 226 | 227 | 228 | void ADS1X15::setMode(uint8_t mode) 229 | { 230 | switch (mode) 231 | { 232 | case 0: _mode = ADS1X15_MODE_CONTINUE; break; 233 | default: // catch invalid modi 234 | case 1: _mode = ADS1X15_MODE_SINGLE; break; 235 | } 236 | } 237 | 238 | 239 | uint8_t ADS1X15::getMode(void) 240 | { 241 | switch (_mode) 242 | { 243 | case ADS1X15_MODE_CONTINUE: return 0; 244 | case ADS1X15_MODE_SINGLE: return 1; 245 | } 246 | _error = ADS1X15_INVALID_MODE; 247 | return _error; 248 | } 249 | 250 | 251 | void ADS1X15::setDataRate(uint8_t dataRate) 252 | { 253 | _datarate = dataRate; 254 | if (_datarate > 7) _datarate = 4; // default 255 | _datarate <<= 5; // convert 0..7 to mask needed. 256 | } 257 | 258 | 259 | uint8_t ADS1X15::getDataRate(void) 260 | { 261 | return (_datarate >> 5) & 0x07; // convert mask back to 0..7 262 | } 263 | 264 | 265 | int16_t ADS1X15::readADC(uint8_t pin) 266 | { 267 | if (pin >= _maxPorts) return 0; 268 | uint16_t mode = ((4 + pin) << 12); // pin to mask 269 | return _readADC(mode); 270 | } 271 | 272 | 273 | int16_t ADS1X15::readADC_Differential_0_1() 274 | { 275 | return _readADC(ADS1X15_MUX_DIFF_0_1); 276 | } 277 | 278 | 279 | int16_t ADS1X15::getValue() 280 | { 281 | int16_t raw = _readRegister(_address, ADS1X15_REG_CONVERT); 282 | if (_bitShift) raw >>= _bitShift; // Shift 12-bit results 283 | return raw; 284 | } 285 | 286 | 287 | void ADS1X15::requestADC(uint8_t pin) 288 | { 289 | if (pin >= _maxPorts) return; 290 | uint16_t mode = ((4 + pin) << 12); // pin to mask 291 | _requestADC(mode); 292 | } 293 | 294 | 295 | void ADS1X15::requestADC_Differential_0_1() 296 | { 297 | _requestADC(ADS1X15_MUX_DIFF_0_1); 298 | } 299 | 300 | 301 | bool ADS1X15::isBusy() 302 | { 303 | return isReady() == false; 304 | } 305 | 306 | 307 | bool ADS1X15::isReady() 308 | { 309 | uint16_t val = _readRegister(_address, ADS1X15_REG_CONFIG); 310 | return ((val & ADS1X15_OS_NOT_BUSY) > 0); 311 | } 312 | 313 | 314 | uint8_t ADS1X15::lastRequest() 315 | { 316 | switch (_lastRequest) 317 | { 318 | case ADS1X15_READ_0: return 0x00; 319 | case ADS1X15_READ_1: return 0x01; 320 | case ADS1X15_READ_2: return 0x02; 321 | case ADS1X15_READ_3: return 0x03; 322 | // technically 0x01 -- but would collide with READ_1 323 | case ADS1X15_MUX_DIFF_0_1: return 0x10; 324 | case ADS1X15_MUX_DIFF_0_3: return 0x30; 325 | case ADS1X15_MUX_DIFF_1_3: return 0x31; 326 | case ADS1X15_MUX_DIFF_2_3: return 0x32; 327 | } 328 | return 0xFF; 329 | } 330 | 331 | 332 | void ADS1X15::setComparatorMode(uint8_t mode) 333 | { 334 | _compMode = mode == 0 ? 0 : 1; 335 | } 336 | 337 | 338 | uint8_t ADS1X15::getComparatorMode() 339 | { 340 | return _compMode; 341 | } 342 | 343 | 344 | void ADS1X15::setComparatorPolarity(uint8_t pol) 345 | { 346 | _compPol = pol == 0 ? 0 : 1; 347 | } 348 | 349 | 350 | uint8_t ADS1X15::getComparatorPolarity() 351 | { 352 | return _compPol; 353 | } 354 | 355 | 356 | void ADS1X15::setComparatorLatch(uint8_t latch) 357 | { 358 | _compLatch = latch == 0 ? 0 : 1; 359 | } 360 | 361 | 362 | uint8_t ADS1X15::getComparatorLatch() 363 | { 364 | return _compLatch; 365 | } 366 | 367 | 368 | void ADS1X15::setComparatorQueConvert(uint8_t mode) 369 | { 370 | _compQueConvert = (mode < 3) ? mode : 3; 371 | } 372 | 373 | 374 | uint8_t ADS1X15::getComparatorQueConvert() 375 | { 376 | return _compQueConvert; 377 | } 378 | 379 | 380 | void ADS1X15::setComparatorThresholdLow(int16_t lo) 381 | { 382 | _writeRegister(_address, ADS1X15_REG_LOW_THRESHOLD, lo); 383 | } 384 | 385 | 386 | int16_t ADS1X15::getComparatorThresholdLow() 387 | { 388 | return _readRegister(_address, ADS1X15_REG_LOW_THRESHOLD); 389 | }; 390 | 391 | 392 | void ADS1X15::setComparatorThresholdHigh(int16_t hi) 393 | { 394 | _writeRegister(_address, ADS1X15_REG_HIGH_THRESHOLD, hi); 395 | }; 396 | 397 | 398 | int16_t ADS1X15::getComparatorThresholdHigh() 399 | { 400 | return _readRegister(_address, ADS1X15_REG_HIGH_THRESHOLD); 401 | }; 402 | 403 | 404 | int8_t ADS1X15::getError() 405 | { 406 | int8_t rv = _error; 407 | _error = ADS1X15_OK; 408 | return rv; 409 | } 410 | 411 | 412 | ////////////////////////////////////////////////////// 413 | // 414 | // EXPERIMENTAL 415 | // 416 | void ADS1X15::setWireClock(uint32_t clockSpeed) 417 | { 418 | _clockSpeed = clockSpeed; 419 | _wire->setClock(_clockSpeed); 420 | } 421 | 422 | // see https://github.com/RobTillaart/ADS1X15/issues/22 423 | // https://github.com/arduino/Arduino/issues/11457 424 | // TODO: get the real clock speed from the I2C interface if possible. 425 | uint32_t ADS1X15::getWireClock() 426 | { 427 | // UNO 328 and 428 | #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) 429 | uint32_t speed = F_CPU / ((TWBR * 2) + 16); 430 | return speed; 431 | 432 | #elif defined(ESP32) 433 | return (uint32_t) _wire->getClock(); 434 | 435 | // #elif defined(ESP8266) 436 | // core_esp8266_si2c.cpp holds the data see => void Twi::setClock( 437 | // not supported. 438 | // return -1; 439 | 440 | #else // best effort is remembering it 441 | return _clockSpeed; 442 | #endif 443 | } 444 | 445 | 446 | ////////////////////////////////////////////////////// 447 | // 448 | // PROTECTED 449 | // 450 | int16_t ADS1X15::_readADC(uint16_t readmode) 451 | { 452 | // note readmode includes the channel 453 | _requestADC(readmode); 454 | 455 | if (_mode == ADS1X15_MODE_SINGLE) 456 | { 457 | uint32_t start = millis(); 458 | // timeout == { 138, 74, 42, 26, 18, 14, 12, 11 } 459 | // added 10 ms more than maximum conversion time from datasheet. 460 | // to prevent premature timeout in RTOS context. 461 | // See #82 462 | uint8_t timeOut = (128 >> (_datarate >> 5)) + 10; 463 | while (isBusy()) 464 | { 465 | if ( (millis() - start) > timeOut) 466 | { 467 | _error = ADS1X15_ERROR_TIMEOUT; 468 | return ADS1X15_ERROR_TIMEOUT; 469 | } 470 | yield(); // wait for conversion; yield for ESP. 471 | } 472 | } 473 | else 474 | { 475 | // needed in continuous mode too, otherwise one get an old value. 476 | delay(_conversionDelay); 477 | } 478 | return getValue(); 479 | } 480 | 481 | 482 | void ADS1X15::_requestADC(uint16_t readmode) 483 | { 484 | // write to register is needed in continuous mode as other flags can be changed 485 | uint16_t config = ADS1X15_OS_START_SINGLE; // bit 15 force wake up if needed 486 | config |= readmode; // bit 12-14 487 | config |= _gain; // bit 9-11 488 | config |= _mode; // bit 8 489 | config |= _datarate; // bit 5-7 490 | if (_compMode) config |= ADS1X15_COMP_MODE_WINDOW; // bit 4 comparator modi 491 | else config |= ADS1X15_COMP_MODE_TRADITIONAL; 492 | if (_compPol) config |= ADS1X15_COMP_POL_ACTIV_HIGH; // bit 3 ALERT active value 493 | else config |= ADS1X15_COMP_POL_ACTIV_LOW; 494 | if (_compLatch) config |= ADS1X15_COMP_LATCH; 495 | else config |= ADS1X15_COMP_NON_LATCH; // bit 2 ALERT latching 496 | config |= _compQueConvert; // bit 0..1 ALERT mode 497 | _writeRegister(_address, ADS1X15_REG_CONFIG, config); 498 | 499 | // remember last request type. 500 | _lastRequest = readmode; 501 | } 502 | 503 | 504 | bool ADS1X15::_writeRegister(uint8_t address, uint8_t reg, uint16_t value) 505 | { 506 | _wire->beginTransmission(address); 507 | _wire->write((uint8_t)reg); 508 | _wire->write((uint8_t)(value >> 8)); 509 | _wire->write((uint8_t)(value & 0xFF)); 510 | int rv = _wire->endTransmission(); 511 | if (rv != 0) 512 | { 513 | _error = ADS1X15_ERROR_I2C; 514 | return false; 515 | } 516 | return true; 517 | } 518 | 519 | 520 | uint16_t ADS1X15::_readRegister(uint8_t address, uint8_t reg) 521 | { 522 | _wire->beginTransmission(address); 523 | _wire->write(reg); 524 | int rv = _wire->endTransmission(); 525 | if (rv == 0) 526 | { 527 | rv = _wire->requestFrom((int) address, (int) 2); 528 | if (rv == 2) 529 | { 530 | uint16_t value = _wire->read() << 8; 531 | value += _wire->read(); 532 | return value; 533 | } 534 | } 535 | _error = ADS1X15_ERROR_I2C; 536 | return 0x0000; 537 | } 538 | 539 | 540 | 541 | /////////////////////////////////////////////////////////////////////////// 542 | // 543 | // DERIVED CLASSES 544 | // 545 | 546 | 547 | /////////////////////////////////////////////////////////////////////////// 548 | // 549 | // ADS1013 550 | // 551 | ADS1013::ADS1013(uint8_t address, TwoWire *wire) 552 | { 553 | _address = address; 554 | _wire = wire; 555 | _config = ADS_CONF_NOCOMP | ADS_CONF_NOGAIN | ADS_CONF_RES_12 | ADS_CONF_CHAN_1; 556 | _conversionDelay = ADS1015_CONVERSION_DELAY; 557 | _bitShift = 4; 558 | _maxPorts = 1; 559 | _gain = ADS1X15_PGA_2_048V; // fixed value 560 | } 561 | 562 | 563 | // ADS1x13 has no gain so set default. 564 | // Table 8. Config Register Field Descriptions 565 | void ADS1013::setGain(uint8_t gain) 566 | { 567 | _gain = gain; // keep compiler happy. 568 | _gain = ADS1X15_PGA_2_048V; // fixed value 569 | } 570 | 571 | 572 | uint8_t ADS1013::getGain() 573 | { 574 | return 2; // fixed value 575 | } 576 | 577 | 578 | /////////////////////////////////////////////////////////////////////////// 579 | // 580 | // ADS1014 581 | // 582 | ADS1014::ADS1014(uint8_t address, TwoWire *wire) 583 | { 584 | _address = address; 585 | _wire = wire; 586 | _config = ADS_CONF_COMP | ADS_CONF_GAIN | ADS_CONF_RES_12 | ADS_CONF_CHAN_1; 587 | _conversionDelay = ADS1015_CONVERSION_DELAY; 588 | _bitShift = 4; 589 | _maxPorts = 1; 590 | } 591 | 592 | 593 | /////////////////////////////////////////////////////////////////////////// 594 | // 595 | // ADS1015 596 | // 597 | ADS1015::ADS1015(uint8_t address, TwoWire *wire) 598 | { 599 | _address = address; 600 | _wire = wire; 601 | _config = ADS_CONF_COMP | ADS_CONF_GAIN | ADS_CONF_RES_12 | ADS_CONF_CHAN_4; 602 | _conversionDelay = ADS1015_CONVERSION_DELAY; 603 | _bitShift = 4; 604 | _maxPorts = 4; 605 | } 606 | 607 | 608 | int16_t ADS1015::readADC_Differential_0_3() 609 | { 610 | return _readADC(ADS1X15_MUX_DIFF_0_3); 611 | } 612 | 613 | 614 | int16_t ADS1015::readADC_Differential_1_3() 615 | { 616 | return _readADC(ADS1X15_MUX_DIFF_1_3); 617 | } 618 | 619 | 620 | int16_t ADS1015::readADC_Differential_2_3() 621 | { 622 | return _readADC(ADS1X15_MUX_DIFF_2_3); 623 | } 624 | 625 | 626 | int16_t ADS1015::readADC_Differential_0_2() 627 | { 628 | return readADC(2) - readADC(0); 629 | } 630 | 631 | 632 | int16_t ADS1015::readADC_Differential_1_2() 633 | { 634 | return readADC(2) - readADC(1);; 635 | } 636 | 637 | 638 | void ADS1015::requestADC_Differential_0_3() 639 | { 640 | _requestADC(ADS1X15_MUX_DIFF_0_3); 641 | } 642 | 643 | 644 | void ADS1015::requestADC_Differential_1_3() 645 | { 646 | _requestADC(ADS1X15_MUX_DIFF_1_3); 647 | } 648 | 649 | 650 | void ADS1015::requestADC_Differential_2_3() 651 | { 652 | _requestADC(ADS1X15_MUX_DIFF_2_3); 653 | } 654 | 655 | 656 | /////////////////////////////////////////////////////////////////////////// 657 | // 658 | // ADS1113 659 | // 660 | ADS1113::ADS1113(uint8_t address, TwoWire *wire) 661 | { 662 | _address = address; 663 | _wire = wire; 664 | _config = ADS_CONF_NOCOMP | ADS_CONF_NOGAIN | ADS_CONF_RES_16 | ADS_CONF_CHAN_1; 665 | _conversionDelay = ADS1115_CONVERSION_DELAY; 666 | _bitShift = 0; 667 | _maxPorts = 1; 668 | _gain = ADS1X15_PGA_2_048V; // fixed value 669 | } 670 | 671 | 672 | // ADS1x13 has no gain so set default. 673 | // Table 8. Config Register Field Descriptions 674 | void ADS1113::setGain(uint8_t gain) 675 | { 676 | _gain = gain; // keep compiler happy. 677 | _gain = ADS1X15_PGA_2_048V; // fixed value 678 | } 679 | 680 | 681 | uint8_t ADS1113::getGain() 682 | { 683 | return 2; // fixed value 684 | } 685 | 686 | 687 | /////////////////////////////////////////////////////////////////////////// 688 | // 689 | // ADS1114 690 | // 691 | ADS1114::ADS1114(uint8_t address, TwoWire *wire) 692 | { 693 | _address = address; 694 | _wire = wire; 695 | _config = ADS_CONF_COMP | ADS_CONF_GAIN | ADS_CONF_RES_16 | ADS_CONF_CHAN_1; 696 | _conversionDelay = ADS1115_CONVERSION_DELAY; 697 | _bitShift = 0; 698 | _maxPorts = 1; 699 | } 700 | 701 | 702 | /////////////////////////////////////////////////////////////////////////// 703 | // 704 | // ADS1115 705 | // 706 | ADS1115::ADS1115(uint8_t address, TwoWire *wire) 707 | { 708 | _address = address; 709 | _wire = wire; 710 | _config = ADS_CONF_COMP | ADS_CONF_GAIN | ADS_CONF_RES_16 | ADS_CONF_CHAN_4; 711 | _conversionDelay = ADS1115_CONVERSION_DELAY; 712 | _bitShift = 0; 713 | _maxPorts = 4; 714 | } 715 | 716 | 717 | int16_t ADS1115::readADC_Differential_0_3() 718 | { 719 | return _readADC(ADS1X15_MUX_DIFF_0_3); 720 | } 721 | 722 | 723 | int16_t ADS1115::readADC_Differential_1_3() 724 | { 725 | return _readADC(ADS1X15_MUX_DIFF_1_3); 726 | } 727 | 728 | 729 | int16_t ADS1115::readADC_Differential_2_3() 730 | { 731 | return _readADC(ADS1X15_MUX_DIFF_2_3); 732 | } 733 | 734 | 735 | int16_t ADS1115::readADC_Differential_0_2() 736 | { 737 | return readADC(2) - readADC(0); 738 | } 739 | 740 | 741 | int16_t ADS1115::readADC_Differential_1_2() 742 | { 743 | return readADC(2) - readADC(1);; 744 | } 745 | 746 | 747 | void ADS1115::requestADC_Differential_0_3() 748 | { 749 | _requestADC(ADS1X15_MUX_DIFF_0_3); 750 | } 751 | 752 | 753 | void ADS1115::requestADC_Differential_1_3() 754 | { 755 | _requestADC(ADS1X15_MUX_DIFF_1_3); 756 | } 757 | 758 | 759 | void ADS1115::requestADC_Differential_2_3() 760 | { 761 | _requestADC(ADS1X15_MUX_DIFF_2_3); 762 | } 763 | 764 | 765 | // -- END OF FILE -- 766 | 767 | -------------------------------------------------------------------------------- /ADS1X15.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // 3 | // FILE: ADS1X15.h 4 | // AUTHOR: Rob Tillaart 5 | // VERSION: 0.5.2 6 | // DATE: 2013-03-24 7 | // PURPOSE: Arduino library for ADS1015 and ADS1115 8 | // URL: https://github.com/RobTillaart/ADS1X15 9 | // 10 | 11 | 12 | #include "Arduino.h" 13 | #include "Wire.h" 14 | 15 | #define ADS1X15_LIB_VERSION (F("0.5.2")) 16 | 17 | // allow compile time default address 18 | // address in { 0x48, 0x49, 0x4A, 0x4B }, no test... 19 | #ifndef ADS1015_ADDRESS 20 | #define ADS1015_ADDRESS 0x48 21 | #endif 22 | 23 | #ifndef ADS1115_ADDRESS 24 | #define ADS1115_ADDRESS 0x48 25 | #endif 26 | 27 | 28 | #define ADS1X15_OK 0 29 | #define ADS1X15_INVALID_VOLTAGE -100 30 | #define ADS1X15_ERROR_TIMEOUT -101 31 | #define ADS1X15_ERROR_I2C -102 32 | #define ADS1X15_INVALID_GAIN 0xFF 33 | #define ADS1X15_INVALID_MODE 0xFE 34 | 35 | 36 | // PARAMETER CONSTANTS NOT USED IN CODE YET 37 | // enum ? 38 | #define ADS1X15_GAIN_6144MV 0x00 39 | #define ADS1X15_GAIN_4096MV 0x01 40 | #define ADS1X15_GAIN_2048MV 0x02 41 | #define ADS1X15_GAIN_1024MV 0x04 42 | #define ADS1X15_GAIN_0512MV 0x08 43 | #define ADS1X15_GAIN_0256MV 0x10 44 | 45 | #define ADS1x15_COMP_MODE_TRADITIONAL 0x00 46 | #define ADS1x15_COMP_MODE_WINDOW 0x01 47 | 48 | #define ADS1x15_COMP_POL_FALLING_EDGE 0x00 49 | #define ADS1x15_COMP_POL_RISING_EDGE 0x01 50 | 51 | #define ADS1x15_COMP_POL_LATCH 0x00 52 | #define ADS1x15_COMP_POL_NOLATCH 0x01 53 | 54 | 55 | 56 | class ADS1X15 57 | { 58 | public: 59 | void reset(); 60 | 61 | bool begin(); 62 | bool isConnected(); 63 | 64 | // GAIN 65 | // 0 = +- 6.144V default 66 | // 1 = +- 4.096V 67 | // 2 = +- 2.048V 68 | // 4 = +- 1.024V 69 | // 8 = +- 0.512V 70 | // 16 = +- 0.256V 71 | void setGain(uint8_t gain = 0); // invalid values are mapped to 0 (default). 72 | uint8_t getGain(); // 0xFF == invalid gain error. 73 | 74 | 75 | // both may return ADS1X15_INVALID_VOLTAGE if the gain is invalid. 76 | float toVoltage(int16_t value = 1); // converts raw to voltage 77 | float getMaxVoltage(); // -100 == invalid voltage error 78 | 79 | 80 | // 0 = CONTINUOUS 81 | // 1 = SINGLE default 82 | void setMode(uint8_t mode = 1); // invalid values are mapped to 1 (default) 83 | uint8_t getMode(); // 0xFE == invalid mode error. 84 | 85 | 86 | // 0 = slowest 87 | // 7 = fastest 88 | // 4 = default 89 | void setDataRate(uint8_t dataRate = 4); // invalid values are mapped on 4 (default) 90 | uint8_t getDataRate(); // actual speed depends on device 91 | 92 | 93 | int16_t readADC(uint8_t pin = 0); 94 | int16_t readADC_Differential_0_1(); 95 | 96 | // used by continuous mode and async mode. 97 | // [[deprecated("Use getValue() instead")]] 98 | // int16_t getLastValue() { return getValue(); }; // will be obsolete in the future 0.4.0 99 | int16_t getValue(); 100 | 101 | 102 | // ASYNC INTERFACE 103 | // requestADC(pin) -> isBusy() or isReady() -> getValue(); 104 | // see examples 105 | void requestADC(uint8_t pin = 0); 106 | void requestADC_Differential_0_1(); 107 | bool isBusy(); 108 | bool isReady(); 109 | 110 | 111 | // returns a pin 0x0[0..3] or 112 | // a differential "mode" 0x[pin second][pin first] or 113 | // 0xFF (no request / invalid request) 114 | uint8_t lastRequest(); 115 | 116 | 117 | // COMPARATOR 118 | // 0 = TRADITIONAL > high => on < low => off 119 | // else = WINDOW > high or < low => on between => off 120 | void setComparatorMode(uint8_t mode); 121 | uint8_t getComparatorMode(); 122 | 123 | // 0 = LOW (default) 124 | // else = HIGH 125 | void setComparatorPolarity(uint8_t pol); 126 | uint8_t getComparatorPolarity(); 127 | 128 | // 0 = NON LATCH 129 | // else = LATCH 130 | void setComparatorLatch(uint8_t latch); 131 | uint8_t getComparatorLatch(); 132 | 133 | // 0 = trigger alert after 1 conversion 134 | // 1 = trigger alert after 2 conversions 135 | // 2 = trigger alert after 4 conversions 136 | // 3 = Disable comparator = default, also for all other values. 137 | void setComparatorQueConvert(uint8_t mode); 138 | uint8_t getComparatorQueConvert(); 139 | 140 | void setComparatorThresholdLow(int16_t lo); 141 | int16_t getComparatorThresholdLow(); 142 | void setComparatorThresholdHigh(int16_t hi); 143 | int16_t getComparatorThresholdHigh(); 144 | 145 | 146 | int8_t getError(); 147 | 148 | 149 | // EXPERIMENTAL 150 | // see https://github.com/RobTillaart/ADS1X15/issues/22 151 | void setWireClock(uint32_t clockSpeed = 100000); 152 | // prototype 153 | // - getWireClock returns the value set by setWireClock 154 | // not necessary the actual value 155 | uint32_t getWireClock(); 156 | 157 | 158 | protected: 159 | ADS1X15(); 160 | 161 | // CONFIGURATION 162 | // BIT DESCRIPTION 163 | // 0 # channels 0 == 1 1 == 4; 164 | // 1 0 165 | // 2 # resolution 0 == 12 1 == 16 166 | // 3 0 167 | // 4 has gain 0 = NO 1 = YES 168 | // 5 has comparator 0 = NO 1 = YES 169 | // 6 0 170 | // 7 0 171 | uint8_t _config; 172 | uint8_t _maxPorts; 173 | uint8_t _address; 174 | uint8_t _conversionDelay; 175 | uint8_t _bitShift; 176 | uint16_t _gain; 177 | uint16_t _mode; 178 | uint16_t _datarate; 179 | 180 | // COMPARATOR variables 181 | // TODO merge these into one COMPARATOR MASK? (low priority) 182 | // would speed up code in _requestADC() and save 3 bytes RAM. 183 | // TODO boolean flags for first three, or make it mask value that 184 | // can be or-ed. (low priority) 185 | uint8_t _compMode; 186 | uint8_t _compPol; 187 | uint8_t _compLatch; 188 | uint8_t _compQueConvert; 189 | 190 | // variable to track the last pin requested, 191 | // to allow for round robin query of 192 | // pins based on this state == if no last request then == 0xFFFF. 193 | uint16_t _lastRequest; 194 | 195 | int16_t _readADC(uint16_t readmode); 196 | void _requestADC(uint16_t readmode); 197 | bool _writeRegister(uint8_t address, uint8_t reg, uint16_t value); 198 | uint16_t _readRegister(uint8_t address, uint8_t reg); 199 | int8_t _error = ADS1X15_OK; 200 | 201 | TwoWire* _wire; 202 | uint32_t _clockSpeed = 0; 203 | }; 204 | 205 | 206 | /////////////////////////////////////////////////////////////////////////// 207 | // 208 | // DERIVED CLASSES from ADS1X15 209 | // 210 | class ADS1013 : public ADS1X15 211 | { 212 | public: 213 | ADS1013(uint8_t Address = ADS1015_ADDRESS, TwoWire *wire = &Wire); 214 | void setGain(uint8_t gain); 215 | uint8_t getGain(); 216 | }; 217 | 218 | 219 | class ADS1014 : public ADS1X15 220 | { 221 | public: 222 | ADS1014(uint8_t Address = ADS1015_ADDRESS, TwoWire *wire = &Wire); 223 | }; 224 | 225 | 226 | class ADS1015 : public ADS1X15 227 | { 228 | public: 229 | ADS1015(uint8_t Address = ADS1015_ADDRESS, TwoWire *wire = &Wire); 230 | int16_t readADC_Differential_0_3(); 231 | int16_t readADC_Differential_1_3(); 232 | int16_t readADC_Differential_2_3(); 233 | int16_t readADC_Differential_0_2(); // not possible in async 234 | int16_t readADC_Differential_1_2(); // not possible in async 235 | void requestADC_Differential_0_3(); 236 | void requestADC_Differential_1_3(); 237 | void requestADC_Differential_2_3(); 238 | }; 239 | 240 | 241 | class ADS1113 : public ADS1X15 242 | { 243 | public: 244 | ADS1113(uint8_t address = ADS1115_ADDRESS, TwoWire *wire = &Wire); 245 | void setGain(uint8_t gain); 246 | uint8_t getGain(); 247 | }; 248 | 249 | 250 | class ADS1114 : public ADS1X15 251 | { 252 | public: 253 | ADS1114(uint8_t address = ADS1115_ADDRESS, TwoWire *wire = &Wire); 254 | }; 255 | 256 | 257 | class ADS1115 : public ADS1X15 258 | { 259 | public: 260 | ADS1115(uint8_t address = ADS1115_ADDRESS, TwoWire *wire = &Wire); 261 | int16_t readADC_Differential_0_3(); 262 | int16_t readADC_Differential_1_3(); 263 | int16_t readADC_Differential_2_3(); 264 | int16_t readADC_Differential_0_2(); // not possible in async 265 | int16_t readADC_Differential_1_2(); // not possible in async 266 | void requestADC_Differential_0_3(); 267 | void requestADC_Differential_1_3(); 268 | void requestADC_Differential_2_3(); 269 | }; 270 | 271 | 272 | // -- END OF FILE -- 273 | 274 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log ADS1x15 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/) 5 | and this project adheres to [Semantic Versioning](http://semver.org/). 6 | 7 | 8 | ## [0.5.2] - 2025-01-27 9 | - Add note about falling edge when using interrupts, see #87 10 | - update comments in some examples 11 | - minor edits 12 | 13 | ## [0.5.1] - 2024-10-17 14 | - fix #82, minimal timeout 10 ms for RTOS, kudos to deKees687 15 | - set error flag for TIMEOUT 16 | - add error codes to keywords.txt 17 | 18 | ## [0.5.0] - 2024-08-20 19 | - Fix #80, setComparatorPolarity() and setComparatorLatch() inverting. 20 | - add test example to test parameters. 21 | - add unit tests to test parameters. 22 | 23 | ---- 24 | 25 | ## [0.4.5] - 2024-07-03 26 | - Fix #78, prevent infinite loop. (Thanks to devmirek). 27 | - Fix #76 (again), update readme.md Comparator Polarity. 28 | - add ADS1X15_ERROR_I2C, communication error. 29 | - add minimal section in readme.md about error codes. 30 | - minor edits. 31 | 32 | ## [0.4.4] - 2024-06-28 33 | - Fix #76, update readme.md Comparator Polarity 34 | - added defines to replace magic numbers (not used in code yet) 35 | - minor edits 36 | 37 | ## [0.4.3] - 2024-06-25 38 | - Fix #74, ALERT/RDY pin documentation 39 | - update readme.md 40 | - minor edits examples 41 | 42 | ## [0.4.2] - 2024-03-04 43 | - fix #68, gain bugs ADS1x13 44 | - add unit test for ADS1x13 45 | - update GitHub/actions to v4 46 | - removed depreciated **getLastValue()** 47 | - add multiplexer section to readme.md 48 | 49 | ## [0.4.1] - 2024-01-02 50 | - fix some typos 51 | - minor edits 52 | 53 | ## [0.4.0] - 2023-12-06 54 | - refactor API, begin() 55 | - update readme.md 56 | - update examples 57 | 58 | ---- 59 | 60 | ## [0.3.13] - 2023-09-20 61 | - fix #61 ESP32 begin() 62 | 63 | ## [0.3.12] - 2023-09-11 64 | - update and add examples 65 | - add **getLastRequest()** to track last type of measurement. 66 | - update readme.md 67 | - minor edits. 68 | 69 | ## [0.3.11] - 2023-08-31 70 | - update readme.md 71 | - move code from .h to .cpp 72 | - reordered code in .cpp to follow .h 73 | - minor edits 74 | 75 | ## [0.3.10] - 2023-06-07 76 | - fix NANO RP2040 77 | - update and add examples 78 | - minor edits 79 | 80 | ## [0.3.9] - 2023-01-21 81 | - update GitHub actions 82 | - update license 2023 83 | - update readme.md 84 | - minor edits 85 | 86 | ## [0.3.8] - 2022-10-17 87 | - add RP2040 support (kudos to intubun) 88 | - simplified changelog.md 89 | 90 | ## [0.3.7] - 2022-06-21 91 | - fix ESP32 Wire.begin data type 92 | 93 | ## [0.3.6] - 2022-03-10 94 | 95 | - add CHANGELOG.md: moved history in ADS1x15.cpp to this file. 96 | - add default parameters for single channel devices. 97 | - **readADC(uint8_t pin = 0);** 98 | - **requestADC(uint8_t pin = 0);** 99 | - add two examples for the **ADS1114** (single channel devices) 100 | - update readme.md. 101 | 102 | ## [0.3.5] - 2022-01-21 103 | - fix #36 support for Nano Every 104 | 105 | ## [0.3.4] - 2021-12-11 106 | - add unit test constants. 107 | - update library.json, license, 108 | - minor edits including layout 109 | 110 | ## [0.3.3] - 2021-10-17 111 | - update build-CI (esp32), readme.md, keywords.txt 112 | 113 | ## [0.3.2] - 2021-10-07 114 | - added examples 115 | - update readme 116 | - fix build-CI; 117 | 118 | ## [0.3.1] - 2021-04-25 119 | - add get/setClock() for Wire speed 120 | - add reset() 121 | - fix issue #22 122 | 123 | ## [0.3.0] - 2021-03-29 124 | - add Wire parameter to constructors. 125 | 126 | ---- 127 | 128 | ### 0.2.7 - 2020-09-27 129 | - redo readRegister() 130 | - getValue() 131 | - getError() 132 | 133 | ### [0.2.6] - 2020-09-01 134 | - fix #12 135 | - fix getMaxVoltage 136 | - refactor 137 | 138 | ### [0.2.5] - 2020-08-26 139 | - add missing readADC_Differential_X_X() 140 | 141 | ### [0.2.4] - 2020-08-26 142 | - check readme.md and minor fixes 143 | 144 | ### [0.2.3] - 2020-08-20 145 | - add comparator code 146 | - add async mode 147 | 148 | ### [0.2.2] - 2020-08-18 149 | - add begin(sda, scl) for ESP32 150 | 151 | ### [0.2.1] - 2020-08-15 152 | - fix issue #2 gain 153 | 154 | ### [0.2.0] - 2020-04-08 155 | - initial release; 156 | - refactor ad fundum; 157 | 158 | ---- 159 | 160 | ### [0.1.0] - 2017-07-31 161 | - removed pre 1.0 support; 162 | - added getVoltage 163 | 164 | ### [0.0.1] - 2013-03-24 165 | - first working version 166 | 167 | ### [0.0.0] - 2013-03-24 168 | - initial version 169 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2013-2025 Rob Tillaart 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | [![Arduino CI](https://github.com/RobTillaart/ADS1X15/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci) 3 | [![Arduino-lint](https://github.com/RobTillaart/ADS1X15/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/ADS1X15/actions/workflows/arduino-lint.yml) 4 | [![JSON check](https://github.com/RobTillaart/ADS1X15/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/ADS1X15/actions/workflows/jsoncheck.yml) 5 | [![GitHub issues](https://img.shields.io/github/issues/RobTillaart/ADS1X15.svg)](https://github.com/RobTillaart/ADS1X15/issues) 6 | 7 | [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/ADS1X15/blob/master/LICENSE) 8 | [![GitHub release](https://img.shields.io/github/release/RobTillaart/ADS1X15.svg?maxAge=3600)](https://github.com/RobTillaart/ADS1X15/releases) 9 | [![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/ADS1X15.svg)](https://registry.platformio.org/libraries/robtillaart/ADS1X15) 10 | 11 | 12 | # ADS1X15 13 | 14 | Arduino library for I2C ADC ADS1015, ADS1115, and similar. 15 | 16 | For using I2C ADC with Raspberry pi or other SBC with Linux OS, 17 | you can check similar library [here](https://github.com/chandrawi/ADS1x15-ADC). 18 | 19 | 20 | ## Description 21 | 22 | This library should work for the devices mentioned below, 23 | although not all sensors support all functionality. 24 | 25 | | Device | Channels | Resolution | Max sps | Comparator | Interrupts | ProgGainAMP | Notes | 26 | |:---------:|:----------:|:------------:|:---------:|:------------:|:------------:|:-------------:|:---------| 27 | | ADS1013 | 1 | 12 | 3300 | N | N | N | | 28 | | ADS1014 | 1 | 12 | 3300 | Y | Y | Y | | 29 | | ADS1015 | 4 | 12 | 3300 | Y | Y | Y | | 30 | | ADS1113 | 1 | 16 | 860 | N | N | N | | 31 | | ADS1114 | 1 | 16 | 860 | Y | Y | Y | | 32 | | ADS1115 | 4 | 16 | 860 | Y | Y | Y | Tested | 33 | 34 | 35 | As the ADS1015 and the ADS1115 are both 4 channels these are the most 36 | interesting from functionality point of view as these can do 37 | differential measurements. 38 | 39 | 40 | ### Interrupts 41 | 42 | Besides polling the **ADS1x14** and **ADS1x15** support interrupts to maximize throughput 43 | with minimal latency. For this these device has an ALERT/RDY pin. 44 | This pin can be used both for interrupts or polling, see table of examples below. 45 | 46 | | example | Interrupts | notes | 47 | |:---------------------------------:|:------------:|:-------:| 48 | | ADS_1114_two_continuous.ino | Y | 49 | | ADS_continuous_3_channel.ino | Y | 50 | | ADS_continuous_4_channel.ino | Y | 51 | | ADS_continuous_8_channel.ino | Y | 52 | | ADS_continuous_differential.ino | Y | 53 | | ADS_high_speed_differential.ino | Y | 54 | | ADS_read_async_rdy.ino | polling | 55 | | ADS_read_RDY.ino | polling | 56 | 57 | 58 | The examples of this library all use the **RISING** edge for the interrupt detection 59 | of the ALERT / RDY pin. 60 | In https://github.com/RobTillaart/ADS1X15/issues/87 it is observed that the **FALLING** 61 | edge gave far more stable results for the application used (determine True RMS). 62 | This effect can not be explained as the edges are only 8 us apart. 63 | Thus changing the edge to **FALLING** might improve your measurements too. 64 | 65 | Datasheet section 7.3.8 Conversion ready pin, figure 7-8 indicates using 66 | the **FALLING** edge as the moment the conversion is ready. 67 | 68 | If anybody can explain the observed effect, please let me know. 69 | 70 | 71 | ### 0.5.0 Breaking change 72 | 73 | Fixed #80, setComparatorPolarity() and setComparatorLatch() as these inverted 74 | the setting. 75 | 76 | 77 | ### 0.4.0 Breaking change 78 | 79 | Version 0.4.0 introduced a breaking change. 80 | You cannot set the pins in **begin()** any more. 81 | This reduces the dependency of processor dependent Wire / I2C implementations. 82 | The user has to call **Wire.begin()** and can optionally set the I2C pins 83 | before calling **begin()**. 84 | 85 | 86 | ### Related 87 | 88 | - https://github.com/RobTillaart/AD7367 2 channel simultaneous 14 bit ADC. 89 | - https://github.com/RobTillaart/ADC081S 10-12 bit, single channel ADC 90 | - https://github.com/RobTillaart/ADC08XS 10-12 bit, 2 + 4 channel ADC 91 | - https://gammon.com.au/adc tutorial about ADC's (UNO specific) 92 | - https://github.com/RobTillaart/MCP_ADC 10-12 bit, 1,2,4,8 channel ADC 93 | - https://github.com/RobTillaart/ADS1x15 94 | - https://github.com/RobTillaart/PCF8591 8 bit single ADC (+ 1 bit DAC) 95 | - https://github.com/RobTillaart/AD5593R 8 channel ADC / DAC / GPIO device. 96 | 97 | 98 | ## I2C Address 99 | 100 | The I2C address of the ADS1113 /14 /15 is determined by to which pin 101 | the **ADDR** is connected to: 102 | 103 | | ADDR pin connected to | Address | Notes | 104 | |:-----------------------:|:---------:|:---------:| 105 | | GND | 0x48 | default | 106 | | VDD | 0x49 | | 107 | | SDA | 0x4A | | 108 | | SCL | 0x4B | | 109 | 110 | 111 | ### I2C multiplexing 112 | 113 | Sometimes you need to control more devices than possible with the default 114 | address range the device provides. 115 | This is possible with an I2C multiplexer e.g. TCA9548 which creates up 116 | to eight channels (think of it as I2C subnets) which can use the complete 117 | address range of the device. 118 | 119 | Drawback of using a multiplexer is that it takes more administration in 120 | your code e.g. which device is on which channel. 121 | This will slow down the access, which must be taken into account when 122 | deciding which devices are on which channel. 123 | Also note that switching between channels will slow down other devices 124 | too if they are behind the multiplexer. 125 | 126 | - https://github.com/RobTillaart/TCA9548 127 | 128 | 129 | ## Interface 130 | 131 | ```cpp 132 | #include "ADS1X15.h" 133 | ``` 134 | 135 | ### Initializing 136 | 137 | To initialize the library you must call a constructor as described below. 138 | 139 | - **ADS1x15()** base constructor, should not be used. 140 | - **ADS1013(uint8_t address, TwoWire \*wire = &Wire)** Constructor with device address, 141 | and optional the Wire interface as parameter. 142 | - **ADS1014(uint8_t address, TwoWire \*wire = &Wire)** Constructor with device address, 143 | and optional the Wire interface as parameter. 144 | - **ADS1015(uint8_t address, TwoWire \*wire = &Wire)** Constructor with device address, 145 | and optional the Wire interface as parameter. 146 | - **ADS1113(uint8_t address, TwoWire \*wire = &Wire)** Constructor with device address, 147 | and optional the Wire interface as parameter. 148 | - **ADS1114(uint8_t address, TwoWire \*wire = &Wire)** Constructor with device address, 149 | and optional the Wire interface as parameter. 150 | - **ADS1115(uint8_t address, TwoWire \*wire = &Wire)** Constructor with device address, 151 | and optional the Wire interface as parameter. 152 | 153 | 154 | After construction the **ADS.begin()** must be called, typical in **setup()**. 155 | 156 | - **bool begin()** Returns false if an invalid address is used. 157 | - **bool isConnected()** is used to check if the device address is visible on I2C. 158 | - **void reset()** sets the internal parameters to their initial value as 159 | in the constructor. 160 | 161 | For example. 162 | 163 | ```cpp 164 | #include "ADS1X15.h" 165 | 166 | // initialize ADS1115 on I2C bus 1 with default address 0x48 167 | ADS1115 ADS(0x48); 168 | 169 | void setup() 170 | { 171 | if (!ADS.begin()) 172 | { 173 | // invalid address ADS1115 or 0x48 not found 174 | } 175 | if (!ADS.isConnected()) 176 | { 177 | // address 0x48 not found 178 | } 179 | } 180 | ``` 181 | 182 | 183 | ### I2C clock speed 184 | 185 | The function **void setWireClock(uint32_t speed = 100000)** is used to set the clock speed 186 | in Hz of the used I2C interface. Typical value is 100 KHz. 187 | 188 | The function **uint32_t getWireClock()** is a prototype. 189 | It returns the value set by setWireClock(). 190 | This is not necessary the actual value. 191 | When no value is set **getWireClock()** returns 0. 192 | Need to implement a read / calculate from low level I2C code (e.g. TWBR on AVR), 193 | better the Arduino Wire lib should support this call (ESP32 does). 194 | 195 | See - https://github.com/arduino/Arduino/issues/11457 196 | 197 | Question: Should this functionality be in this library? 198 | 199 | 200 | ### Programmable Gain 201 | 202 | - **void setGain(uint8_t gain)** set the gain value, indicating the maxVoltage that can be measured 203 | Adjusting the gain allowing to make more precise measurements. 204 | Note: the gain is not set in the device until an explicit read/request of the ADC (any read call will do). 205 | See table below. 206 | - **uint8_t getGain()** returns the gain value (index). 207 | 208 | | PGA value | Max Voltage | Notes | 209 | |:-----------:|:-------------:|:---------:| 210 | | 0 | ±6.144V | default | 211 | | 1 | ±4.096V | | 212 | | 2 | ±2.048V | | 213 | | 4 | ±1.024V | | 214 | | 8 | ±0.512V | | 215 | | 16 | ±0.256V | | 216 | 217 | 218 | - **float getMaxVoltage()** returns the max voltage with the current gain. 219 | - **float toVoltage(int16_t raw = 1)** converts a raw measurement to a voltage. 220 | Can be used for normal and differential measurements. 221 | The default value of 1 returns the conversion factor for any raw number. 222 | 223 | The voltage factor can also be used to set HIGH and LOW threshold registers 224 | with a voltage in the comparator mode. 225 | Check the [examples](https://github.com/RobTillaart/ADS1X15/blob/master/examples/ADS_read_comparator_1/ADS_read_comparator_1.ino). 226 | 227 | ```cpp 228 | float f = ADS.toVoltage(); 229 | ADS.setComparatorThresholdLow( 3.0 / f ); 230 | ADS.setComparatorThresholdHigh( 4.3 / f ); 231 | ``` 232 | 233 | 234 | ### Operational mode 235 | 236 | The ADS sensor can operate in single shot or continuous mode. 237 | Depending on how often conversions needed you can tune the mode. 238 | 239 | - **void setMode(uint8_t mode)** 0 = CONTINUOUS, 1 = SINGLE (default) 240 | Note: the mode is not set in the device until an explicit read/request of the ADC (any read call will do). 241 | - **uint8_t getMode()** returns current mode 0 or 1, or ADS1X15_INVALID_MODE = 0xFE. 242 | 243 | 244 | ### Data rate 245 | 246 | - **void setDataRate(uint8_t dataRate)** Data rate depends on type of device. 247 | For all devices the index 0..7 can be used, see table below. 248 | Values above 7 ==> will be set to the default 4. 249 | Note: the data rate is not set in the device until an explicit read/request of the ADC (any read call will do). 250 | - **uint8_t getDataRate()** returns the current data rate (index). 251 | 252 | The library has no means to convert this index to the actual numbers 253 | as that would take 32 bytes. 254 | 255 | Data rate in samples per second, based on datasheet is described on table below. 256 | 257 | | data rate | ADS101x | ADS111x | Notes | 258 | |:-----------:|----------:|----------:|:---------:| 259 | | 0 | 128 | 8 | slowest | 260 | | 1 | 250 | 16 | | 261 | | 2 | 490 | 32 | | 262 | | 3 | 920 | 64 | | 263 | | 4 | 1600 | 128 | default | 264 | | 5 | 2400 | 250 | | 265 | | 6 | 3300 | 475 | | 266 | | 7 | 3300 | 860 | fastest | 267 | 268 | 269 | ### ReadADC Single mode 270 | 271 | Reading the ADC is very straightforward, the **readADC()** function handles all in one call. 272 | Under the hood it uses the asynchronous calls. 273 | 274 | - **int16_t readADC(uint8_t pin = 0)** normal ADC functionality, pin = 0..3. 275 | If the pin number is out of range, this function will return 0 (seems safest). 276 | Default pin = 0 as this is convenient for the single channel devices. 277 | 278 | ```cpp 279 | // read ADC in pin 2 280 | ADS.readADC(2); 281 | 282 | // read ADC in pin 0 - two ways 283 | ADS.readADC(); 284 | ADS.readADC(0); 285 | ``` 286 | 287 | 288 | See [examples](https://github.com/RobTillaart/ADS1X15/blob/master/examples/ADS_minimum/ADS_minimum.ino). 289 | 290 | The **readADC()** can return **ADS1X15_ERROR_TIMEOUT (-101)** which is an errorcode. 291 | This may conflict with a possible actual value of -101. 292 | Therefore the user should check with **getError()** if an error has occurred after reading the ADC. 293 | 294 | ```cpp 295 | Value = ADS.readADC() 296 | if (ADS.getError() == ADS1X15_OK) 297 | // Use value 298 | else 299 | // handle error 300 | ``` 301 | 302 | The error handling within the library need to be improved, see also issue #84. 303 | 304 | 305 | ### Read the ADC in asynchronous way 306 | 307 | To read the ADC in an asynchronous way (e.g. to minimize blocking) you need call three functions: 308 | 309 | - **void requestADC(uint8_t pin = 0)** Start the conversion. pin = 0..3. 310 | Default pin = 0 as this is convenient for 1 channel devices. 311 | - **bool isBusy()** Is the conversion not ready yet? Works only in SINGLE mode! 312 | - **bool isReady()** Is the conversion ready? Works only in SINGLE mode! (= wrapper around **isBusy()** ) 313 | - **int16_t getValue()** Read the result of the conversion. 314 | 315 | 316 | in terms of code: 317 | 318 | ```cpp 319 | void setup() 320 | { 321 | // other setup things here 322 | ADS.setMode(1); // SINGLE SHOT MODE 323 | ADS.requestADC(pin); 324 | } 325 | 326 | void loop() 327 | { 328 | if (ADS.isReady()) 329 | { 330 | value = ADS.getValue(); 331 | ADS.requestADC(pin); // request new conversion 332 | } 333 | // do other things here 334 | } 335 | ``` 336 | See [examples](https://github.com/RobTillaart/ADS1X15/blob/master/examples/ADS_read_async/ADS_read_async.ino). 337 | 338 | 339 | ### ReadADC Differential 340 | 341 | For reading the ADC in a differential way there are 4 calls possible. 342 | 343 | - **int16_t readADC_Differential_0_1()** returns the difference between 2 ADC pins. 344 | - **int16_t readADC_Differential_0_3()** ADS1x15 only 345 | - **int16_t readADC_Differential_1_3()** ADS1x15 only 346 | - **int16_t readADC_Differential_2_3()** ADS1x15 only 347 | - **int16_t readADC_Differential_0_2()** ADS1x15 only - in software (no async equivalent) 348 | - **int16_t readADC_Differential_1_2()** ADS1x15 only - in software (no async equivalent) 349 | 350 | ```cpp 351 | // read differential ADC between pin 0 and 1 352 | ADS.readADC_Differential_0_1(0); 353 | ``` 354 | 355 | The differential reading of the ADC can also be done with asynchronous calls. 356 | 357 | - **void requestADC_Differential_0_1()** starts conversion for differential reading 358 | - **void requestADC_Differential_0_3()** ADS1x15 only 359 | - **void requestADC_Differential_1_3()** ADS1x15 only 360 | - **void requestADC_Differential_2_3()** ADS1x15 only 361 | 362 | After one of these calls you need to call 363 | - **int16_t getValue()** Read the result of the last conversion. 364 | 365 | See [examples](https://github.com/RobTillaart/ADS1X15/blob/master/examples/ADS_differential/ADS_differential.ino). 366 | 367 | 368 | ### lastRequestMode 369 | 370 | Since 0.3.12 the library tracks the last request mode, single pin or differential. 371 | This variable is set at the moment of request, and keeps its value until a new 372 | request is made. This implies that the value / request can be quite old. 373 | 374 | Values >= 0x10 are differential, values < 0x10 are single pin. 375 | 376 | - **uint8_t lastRequest()** returns one of the values below. 377 | 378 | | Value | Description | Notes | 379 | |:-------:|:-----------------------------|:--------| 380 | | 0xFF | no (invalid) request made | after call constructor. 381 | | 0x00 | single pin 0 | 382 | | 0x01 | single pin 1 | 383 | | 0x02 | single pin 2 | 384 | | 0x03 | single pin 3 | 385 | | 0x10 | differential pin 1 0 | 386 | | 0x30 | differential pin 3 0 | 387 | | 0x31 | differential pin 3 1 | 388 | | 0x32 | differential pin 3 2 | 389 | 390 | 391 | Please note that (for now) the function does not support a descriptive return value 392 | for the following two requests: 393 | - **readADC_Differential_0_2()** ADS1x15 only - in software (no async equivalent) 394 | - **readADC_Differential_1_2()** ADS1x15 only - in software (no async equivalent) 395 | 396 | As these are emulated in software by two single pin calls, the state would be 397 | one of the two single pin values. 398 | 399 | 400 | ### ReadADC continuous mode 401 | 402 | To use the continuous mode you need call three functions: 403 | 404 | - **void setMode(0)** 0 = CONTINUOUS, 1 = SINGLE (default). 405 | Note: the mode is not set in the device until an explicit read/request of the ADC (any read call will do). 406 | - **int16_t readADC(uint8_t pin)** or **void requestADC(uint8_t pin)** to get the continuous mode started. 407 | - **int16_t getValue()** to return the last value read by the device. 408 | Note this can be a different pin, so be warned. 409 | Calling this over and over again can give the same value multiple times. 410 | 411 | ```cpp 412 | void setup() 413 | { 414 | // configuration things here 415 | ADS.setMode(ADS.MODE_CONTINUOUS); 416 | ADS.requestADC(0); // request on pin 0 417 | } 418 | 419 | void loop() 420 | { 421 | value = ADS.getValue() 422 | sleep(1) 423 | } 424 | ``` 425 | 426 | See [examples](https://github.com/RobTillaart/ADS1X15/blob/master/examples/ADS_continuous/ADS_continuous.ino) 427 | . 428 | By using **bool isBusy()** or **bool isReady()** one can wait until new data is available. 429 | Note this only works in the SINGLE_SHOT modus. 430 | 431 | In continuous mode, you can't use **isBusy()** or **isReady()** functions to wait until new data available. 432 | Instead you can configure the threshold registers to allow the **ALERT/RDY** 433 | pin to trigger an interrupt signal when conversion data ready. 434 | 435 | 436 | ### Switching mode or channel during continuous mode 437 | 438 | When switching the operating mode or the ADC channel in continuous mode, be aware that 439 | the device will always finish the running conversion. 440 | This implies that after switching the mode or channel the first sample you get is probably 441 | the last sample with the previous settings, e.g. channel. 442 | This might be a problem for your project as this value can be in an "unexpected" range (outlier). 443 | 444 | The robust way to change mode or channel therefore seems to be: 445 | 446 | 1. stop continuous mode, 447 | 1. wait for running conversion to be ready, 448 | 1. reject the last conversion or process it "under old settings", 449 | 1. change the settings, 450 | 1. restart (continuous mode) with the new settings. 451 | 452 | This explicit stop takes extra time, however it should prevent "incorrect" readings. 453 | 454 | (need to be verified with different models) 455 | 456 | 457 | ### Threshold registers 458 | 459 | (datasheet 9.3.8) 460 | _Conversion Ready Pin (ADS1114 and ADS1115 Only) 461 | The ALERT/RDY pin can also be configured as a conversion ready pin. Set the most-significant bit of the 462 | Hi_thresh register to 1 and the most-significant bit of Lo_thresh register to 0 to enable the pin as a conversion 463 | ready pin._ 464 | 465 | 466 | If the thresholdHigh is set to 0x8000 and the thresholdLow to 0x0000 467 | the **ALERT/RDY** pin is triggered when a conversion is ready. 468 | 469 | - **void setComparatorThresholdLow(int16_t lo)** writes value to device directly. 470 | - **void setComparatorThresholdHigh(int16_t hi)** writes value to device directly. 471 | - **int16_t getComparatorThresholdLow()** reads value from device. 472 | - **int16_t getComparatorThresholdHigh()** reads value from device. 473 | 474 | See [examples](https://github.com/RobTillaart/ADS1X15/blob/master/examples/ADS_read_RDY/ADS_read_RDY.ino). 475 | 476 | 477 | ### Comparator 478 | 479 | Please read Page 15 of the datasheet as the behaviour of the 480 | comparator is not trivial. 481 | 482 | NOTE: all comparator settings are copied to the device only after calling 483 | **readADC()** or **requestADC()** functions. 484 | 485 | 486 | ### Comparator Mode 487 | 488 | When configured as a **TRADITIONAL** comparator, the **ALERT/RDY** pin asserts 489 | (active low by default) when conversion data exceed the limit set in the 490 | high threshold register. The comparator then de-asserts when the input 491 | signal falls below the low threshold register value. 492 | 493 | - **void setComparatorMode(uint8_t mode)** value 0 = TRADITIONAL 1 = WINDOW, 494 | - **uint8_t getComparatorMode()** returns value set. 495 | 496 | 497 | If the comparator **LATCH** is set, the **ALERT/RDY** pin asserts and it will be 498 | reset after reading the sensor (conversion register) again. 499 | *An SMB alert command (00011001) on the I2C bus will also reset the alert state.* 500 | *Not implemented in the library (yet)* 501 | 502 | In **WINDOW** comparator mode, the **ALERT/RDY** pin asserts if conversion data exceeds 503 | the high threshold register or falls below the low threshold register. 504 | In this mode the alert is held if the **LATCH** is set. This is similar as above. 505 | 506 | 507 | ### Polarity 508 | 509 | Default state of the **ALERT/RDY** pin is **LOW**, which can be to set **HIGH**. 510 | 511 | - **void setComparatorPolarity(uint8_t pol)** 512 | Flag is only explicitly set after a **readADC()** or a **requestADC()** 513 | - **uint8_t getComparatorPolarity()** returns value set. 514 | 515 | 516 | From tests (see #76) it became clear that the behaviour of the **ALERT/RDY** pin 517 | looks ambiguous. Further investigation eventually showed that the behaviour is 518 | logical but one should not think in "pulses", more in levels and edges. 519 | 520 | In the continuous mode it looks like an 8us pulse, however this "pulse" is 521 | actual a short time (8 us) of IDLE followed by a long time pulse of converting. 522 | 523 | In the single shot mode it looks like the converting time is the pulse 524 | as that is the only single change visible. This is IMHO the correct view. 525 | 526 | 527 | #### ALERT RDY table 528 | 529 | | MODE | COMP_POL | CONVERT | COMPLETING | READY | 530 | |:---------------|:-----------|:----------|:-------------|:----------| 531 | | 0 = continuous | 0 = LOW | LOW | RISING | FALLING | 532 | | 0 = continuous | 1 = HIGH | HIGH | FALLING | RISING | 533 | | 1 = single | 0 = LOW | LOW | RISING | FALLING | 534 | | 1 = single | 1 = HIGH | HIGH | FALLING | RISING | 535 | 536 | 537 | See issue #76 and #87 for some screenshots. 538 | 539 | See also [Rev. D data sheet, Page 17 Figure 7-8 Conversion Ready Pulse in Continuous-Conversion Mode](https://www.ti.com/lit/ds/symlink/ads1115.pdf) 540 | 541 | 542 | #### Converting time by Data Rate 543 | 544 | | data rate | convert time | Notes | 545 | |:-----------:|:--------------:|:-------:| 546 | | 0 | 125 ms | 547 | | 1 | 62 ms | 548 | | 2 | 32 ms | 549 | | 3 | 16 ms | 550 | | 4 | 8 ms | default, see in table above. 551 | | 5 | 4.4 ms | 552 | | 6 | 2.4 ms | 553 | | 7 | 1.2 ms | 554 | 555 | Times are estimates from scope. 556 | 557 | 558 | #### Conclusions 559 | 560 | - Conversion generates a conversion pulse with length depending on the data rate. 561 | - In continuous mode it looks like there is a short pulse, but actual the long 562 | period is the conversion pulse. 563 | 564 | In short: 565 | 566 | - if COMP_POL = 0, 567 | - a LOW level indicates converting. 568 | - a RISING edge indicates conversion completing. 569 | - a FALLING edge indicates conversion ready. 570 | 571 | - if COMP_POL = 1, 572 | - a HIGH level indicates converting. 573 | - a FALLING edge indicates conversion completing. 574 | - a RISING edge indicates conversion ready. 575 | 576 | This interpretation is in line with all tests done in #76 and #87. 577 | 578 | See also [Rev. D data sheet, Page 17 Figure 7-8 Conversion Ready Pulse in Continuous-Conversion Mode](https://www.ti.com/lit/ds/symlink/ads1115.pdf) 579 | 580 | 581 | ### Latch 582 | 583 | Holds the **ALERT/RDY** to **HIGH** (or **LOW** depending on polarity) after triggered 584 | even if actual value has been 'restored to normal' value. 585 | 586 | - **void setComparatorLatch(uint8_t latch)** 0 = NO LATCH, not 0 = LATCH 587 | - **uint8_t getComparatorLatch()** returns value set. 588 | 589 | The (no-)latch is not verified in detail yet. 590 | 591 | 592 | ### QueConvert 593 | 594 | Set the number of conversions before trigger activates. 595 | 596 | The **void setComparatorQueConvert(uint8_t mode)** is used to set the number of 597 | conversions that exceed the threshold before the **ALERT/RDY** pin is set **HIGH**. 598 | A value of 3 (or above) effectively disables the comparator. See table below. 599 | 600 | See [examples](https://github.com/RobTillaart/ADS1X15/blob/master/examples/ADS_continuous_differential/ADS_continuous_differential.ino). 601 | 602 | - **void setComparatorQueConvert(uint8_t mode)** See table below. 603 | - **uint8_t getComparatorQueConvert()** returns the value set. 604 | 605 | | value | meaning | Notes | 606 | |:-------:|:------------------------------------|:----------| 607 | | 0 | trigger alert after 1 conversion | | 608 | | 1 | trigger alert after 2 conversions | | 609 | | 2 | trigger alert after 4 conversions | | 610 | | 3 | Disable comparator | default | 611 | | other | Disable comparator | | 612 | 613 | To enable the conversion-ready function of the **ALERT/RDY** pin, 614 | it is necessary to set the MSB of the Hi_threshold register to 1 (value 0x8000) 615 | and the MSB of the Lo_threshold register to 0. 616 | See section **Threshold registers** above. 617 | 618 | 619 | ### Threshold registers comparator mode 620 | 621 | Depending on the comparator mode **TRADITIONAL** or **WINDOW** the thresholds registers 622 | mean something different see - Comparator Mode above or datasheet. 623 | 624 | - **void setComparatorThresholdLow(int16_t lo)** set the low threshold; take care the hi >= lo. 625 | - **void setComparatorThresholdHigh(int16_t hi)** set the high threshold; take care the hi >= lo. 626 | - **int16_t getComparatorThresholdLow()** reads value from device. 627 | - **int16_t getComparatorThresholdHigh()** reads value from device. 628 | 629 | 630 | ## Error codes 631 | 632 | This section has to be elaborated. 633 | 634 | Some functions return or set an error value. 635 | This is read and reset by **getError()** 636 | 637 | | Value | Define | Description | 638 | |:-------:|:-------------------------:|:-------------:| 639 | | 0 | ADS1X15_OK | idem. 640 | | -100 | ADS1X15_INVALID_VOLTAGE | getMaxVoltage() 641 | | -101 | ADS1X15_ERROR_TIMEOUT | readADC() device did not respond in time. 642 | | -102 | ADS1X15_ERROR_I2C | I2C communication failure. 643 | | 0xFF | ADS1X15_INVALID_GAIN | getGain() 644 | | 0xFE | ADS1X15_INVALID_MODE | getMode() 645 | 646 | 647 | ## Future ideas & improvements 648 | 649 | #### Must 650 | 651 | - Improve documentation (always) 652 | - split off separate topics? 653 | 654 | #### Should 655 | 656 | - Remove the experimental **getWireClock()** as this is not really a library function 657 | but a responsibility of the I2C library. 658 | - Investigate ADS1118 library which should be a similar SPI based ADC. 659 | - improve error handling 660 | - refactor values to be more logic. 661 | 662 | #### Could 663 | 664 | - SMB alert command (00011001) on I2C bus? 665 | - Sync code order .h / .cpp 666 | 667 | #### Wont (unless requested) 668 | 669 | - Type flag? 670 | - Constructor for ADS1X15? No as all types are supported. 671 | 672 | ## Support 673 | 674 | If you appreciate my libraries, you can support the development and maintenance. 675 | Improve the quality of the libraries by providing issues and Pull Requests, or 676 | donate through PayPal or GitHub sponsors. 677 | 678 | Thank you, 679 | 680 | -------------------------------------------------------------------------------- /examples/ADS1113_getMaxVoltage/ADS1113_getMaxVoltage.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS1113_getMaxVoltage.ino 3 | // AUTHOR: Rob.Tillaart 4 | // PURPOSE: read analog inputs - straightforward. 5 | // URL: https://github.com/RobTillaart/ADS1X15 6 | 7 | // test for issue #68 behaviour ADS1113 / ADS1013 8 | // 9 | // connect 1 potmeter per port. 10 | // 11 | // GND ---[ x ]------ 5V 12 | // | 13 | // 14 | // measure at x (connect to AIN0). 15 | 16 | 17 | #include "ADS1X15.h" 18 | 19 | ADS1113 ADS(0x48); 20 | 21 | 22 | void setup() 23 | { 24 | Serial.begin(115200); 25 | Serial.println(__FILE__); 26 | Serial.print("ADS1X15_LIB_VERSION: "); 27 | Serial.println(ADS1X15_LIB_VERSION); 28 | 29 | Wire.begin(); 30 | ADS.begin(); 31 | 32 | for (int g = 0; g < 8; g++) 33 | { 34 | ADS.setGain(g); 35 | Serial.print(g); 36 | Serial.print('\t'); 37 | Serial.print(ADS.getGain()); // should all print 2 38 | Serial.print('\t'); 39 | Serial.println(ADS.getMaxVoltage(), 3); // should all print 2.048 40 | } 41 | } 42 | 43 | 44 | void loop() 45 | { 46 | } 47 | 48 | 49 | // -- END OF FILE -- 50 | -------------------------------------------------------------------------------- /examples/ADS_1114_four/ADS_1114_four.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS_1114_four.ino 3 | // AUTHOR: Rob.Tillaart 4 | // PURPOSE: demo reading four ADS1114 modules in parallel 5 | // URL: https://github.com/RobTillaart/ADS1X15 6 | 7 | 8 | // Note all IO with the sensors are guarded by an isConnected() 9 | // this is max robust, in non critical application one may either 10 | // cache the value or only verify it in setup (least robust). 11 | // Less robust may cause the application to hang - watchdog reset ? 12 | 13 | 14 | #include "ADS1X15.h" 15 | 16 | 17 | ADS1114 ADS[4]; 18 | uint16_t val[4]; 19 | 20 | uint32_t last = 0, now = 0; 21 | 22 | 23 | void setup() 24 | { 25 | Serial.begin(115200); 26 | Serial.println(__FILE__); 27 | Serial.print("ADS1X15_LIB_VERSION: "); 28 | Serial.println(ADS1X15_LIB_VERSION); 29 | 30 | Wire.begin(); 31 | 32 | for (uint8_t i = 0; i < 4; i++) 33 | { 34 | uint8_t address = 0x48 + i; 35 | ADS[i] = ADS1114(address); 36 | 37 | Serial.print(address, HEX); 38 | Serial.print(" "); 39 | Serial.println(ADS[i].begin() ? "connected" : "not connected"); 40 | 41 | // 0 = slow 4 = medium 7 = fast, but more noise 42 | ADS[i].setDataRate(4); 43 | } 44 | ADS_request_all(); 45 | } 46 | 47 | 48 | void loop() 49 | { 50 | // Serial.println(__FUNCTION__); 51 | // wait until all is read... 52 | while(ADS_read_all()); 53 | 54 | // we have all values, so process (print) them 55 | ADS_print_all(); 56 | 57 | // wait a second, comment this line for more samples. 58 | delay(1000); 59 | ADS_request_all(); 60 | } 61 | 62 | 63 | void ADS_request_all() 64 | { 65 | // Serial.println(__FUNCTION__); 66 | for (int i = 0; i < 4; i++) 67 | { 68 | if (ADS[i].isConnected()) ADS[i].requestADC(0); 69 | // get them evenly spaced in time ... 70 | delayMicroseconds(200); 71 | } 72 | } 73 | 74 | 75 | bool ADS_read_all() 76 | { 77 | // Serial.println(__FUNCTION__); 78 | for (int i = 0; i < 4; i++) 79 | { 80 | if (ADS[i].isConnected() && ADS[i].isBusy()) return true; 81 | } 82 | // Serial.print("IDX:\t"); 83 | // Serial.println(idx); 84 | for (int i = 0; i < 4; i++) 85 | { 86 | if (ADS[i].isConnected()) 87 | { 88 | val[i] = ADS[i].getValue(); 89 | } 90 | } 91 | ADS_request_all(); 92 | return false; 93 | } 94 | 95 | 96 | void ADS_print_all() 97 | { 98 | // Serial.println(__FUNCTION__); 99 | // print duration since last print. 100 | now = millis(); 101 | Serial.print(now - last); 102 | last = now; 103 | Serial.println(); 104 | 105 | // PRINT ALL VALUES 106 | for (int i = 0; i < 4; i++) 107 | { 108 | Serial.print(val[i]); 109 | Serial.print("\t"); 110 | } 111 | Serial.println(); 112 | } 113 | 114 | 115 | // -- END OF FILE -- 116 | -------------------------------------------------------------------------------- /examples/ADS_1114_two_continuous/ADS_1114_two_continuous.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS_1114_two_continuous.ino 3 | // AUTHOR: Rob.Tillaart 4 | // PURPOSE: demo reading four ADS1114 modules in parallel 5 | // interrupt driven to catch all conversions. 6 | // URL: https://github.com/RobTillaart/ADS1X15 7 | 8 | // test 9 | // connect multiple potmeters to 2 ADS1114 10 | // 11 | // 12 | // RDY1 ----------------- pin 2 (for IRQ, adjust if needed) 13 | // 14 | // RDY2 ----------------- pin 3 (for IRQ, adjust if needed) 15 | // 16 | // 17 | // GND ---[ x ]------ 5V 18 | // | 19 | // 20 | // measure at x - connect to AIN0..1. 21 | // 22 | // for the test it is good to have AIN2 connected to 5V and AIN3 to GND 23 | // so one can see these as references in the output. 24 | // 25 | 26 | 27 | #include "ADS1X15.h" 28 | 29 | 30 | ADS1114 ADS_1(0x49); 31 | ADS1114 ADS_2(0x48); 32 | 33 | 34 | // two interrupt flags 35 | volatile bool RDY_1 = false; 36 | volatile bool RDY_2 = false; 37 | 38 | int16_t val_1 = 0; 39 | int16_t val_2 = 0; 40 | 41 | 42 | void setup() 43 | { 44 | Serial.begin(115200); 45 | Serial.println(__FILE__); 46 | Serial.print("ADS1X15_LIB_VERSION: "); 47 | Serial.println(ADS1X15_LIB_VERSION); 48 | 49 | Wire.begin(); 50 | 51 | // SETUP FIRST ADS1114 52 | ADS_1.begin(); 53 | ADS_1.setGain(0); // 0 == 6.144 volt, default 54 | ADS_1.setDataRate(7); // 0 = slow 4 = medium 7 = fast 55 | 56 | // SET ALERT RDY PIN 57 | ADS_1.setComparatorThresholdHigh(0x8000); 58 | ADS_1.setComparatorThresholdLow(0x0000); 59 | ADS_1.setComparatorQueConvert(0); 60 | 61 | // SET INTERRUPT HANDLER TO CATCH CONVERSION READY 62 | pinMode(2, INPUT_PULLUP); 63 | attachInterrupt(digitalPinToInterrupt(2), adsReady_1, RISING); 64 | 65 | ADS_1.setMode(0); // 0 == continuous mode 66 | ADS_1.readADC(); // 0 == default channel, trigger first read 67 | 68 | 69 | // SETUP SECOND ADS1114 70 | ADS_2.begin(); 71 | ADS_2.setGain(0); // 0 == 6.144 volt, default 72 | ADS_2.setDataRate(7); // 7 == highest 73 | 74 | // SET ALERT RDY PIN 75 | ADS_2.setComparatorThresholdHigh(0x8000); 76 | ADS_2.setComparatorThresholdLow(0x0000); 77 | ADS_2.setComparatorQueConvert(0); 78 | 79 | // SET INTERRUPT HANDLER TO CATCH CONVERSION READY 80 | pinMode(3, INPUT_PULLUP); 81 | attachInterrupt(digitalPinToInterrupt(3), adsReady_2, RISING); 82 | 83 | ADS_2.setMode(0); // 0 == continuous mode 84 | ADS_2.readADC(); // 0 == default channel, trigger first read 85 | } 86 | 87 | 88 | void loop() 89 | { 90 | if (handleConversion() == true) 91 | { 92 | Serial.print('\t'); 93 | Serial.print(val_1); 94 | Serial.print('\t'); 95 | Serial.print(val_2); 96 | Serial.println(); 97 | } 98 | } 99 | 100 | 101 | // catch interrupt and set flag device 1 102 | void adsReady_1() 103 | { 104 | RDY_1 = true; 105 | } 106 | 107 | // catch interrupt and set flag device 1 108 | void adsReady_2() 109 | { 110 | RDY_2 = true; 111 | } 112 | 113 | 114 | // handle conversions that are ready 115 | bool handleConversion() 116 | { 117 | bool rv = false; 118 | if (RDY_1) 119 | { 120 | // save the last value 121 | val_1 = ADS_1.getValue(); 122 | ADS_1.readADC(0); 123 | RDY_1 = false; 124 | rv = true; 125 | } 126 | if (RDY_2) 127 | { 128 | // save the last value 129 | val_2 = ADS_2.getValue(); 130 | ADS_2.readADC(0); 131 | RDY_2 = false; 132 | rv = true; 133 | } 134 | return rv; 135 | } 136 | 137 | 138 | // -- END OF FILE -- 139 | 140 | -------------------------------------------------------------------------------- /examples/ADS_COMP_POL/ADS_COMP_POL.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS_COMP_POL.ino 3 | // AUTHOR: Rob.Tillaart 4 | // PURPOSE: read analog input 5 | // URL: https://github.com/RobTillaart/ADS1X15/issues/76 6 | 7 | #include "ADS1X15.h" 8 | 9 | // choose your sensor 10 | // ADS1013 ADS(0x48); 11 | // ADS1014 ADS(0x48); 12 | // ADS1015 ADS(0x48); 13 | // ADS1113 ADS(0x48); 14 | // ADS1114 ADS(0x48); 15 | 16 | ADS1115 ADS(0x48); 17 | 18 | void setup() 19 | { 20 | Serial.begin(115200); 21 | Serial.println(__FILE__); 22 | Serial.print("ADS1X15_LIB_VERSION: "); 23 | Serial.println(ADS1X15_LIB_VERSION); 24 | 25 | Wire.begin(); 26 | 27 | ADS.begin(); 28 | ADS.setGain(0); // 6.144 volt 29 | ADS.setDataRate(4); // 0..7 30 | 31 | // test polarity 32 | // data rate 4 (default) 33 | // MODE COMP_POL ALERT/RDY PIN 34 | // 0 = continuous 0 = LOW LOW with 8 us HIGH PULSE 35 | // 0 = continuous 1 = HIGH HIGH with 8 us LOW pulse 36 | // 1 = single 0 = LOW HIGH with 8 ms LOW pulse 37 | // 1 = single 1 = HIGH LOW with 8 ms HIGH pulse 38 | ADS.setMode(1); 39 | ADS.setComparatorPolarity(1); 40 | // enable ALERT/RDY pin 41 | ADS.setComparatorThresholdHigh(0x8000); 42 | ADS.setComparatorThresholdLow(0x0000); 43 | ADS.setComparatorQueConvert(0); 44 | // activate settings 45 | ADS.requestADC(0); 46 | 47 | Serial.println("Voltage"); 48 | delay(1000); 49 | } 50 | 51 | void loop() 52 | { 53 | // comment all in loop() to get a single pulse 54 | int16_t raw = ADS.readADC(0); 55 | delay(1000); 56 | 57 | Serial.println(ADS.toVoltage(raw), 3); 58 | delay(1000); 59 | } 60 | 61 | // -- END OF FILE -- 62 | -------------------------------------------------------------------------------- /examples/ADS_RP2040_WIRE1/.arduino-ci.yml: -------------------------------------------------------------------------------- 1 | platforms: 2 | rpipico: 3 | board: rp2040:rp2040:rpipico 4 | package: rp2040:rp2040 5 | gcc: 6 | features: 7 | defines: 8 | - ARDUINO_ARCH_RP2040 9 | warnings: 10 | flags: 11 | 12 | packages: 13 | rp2040:rp2040: 14 | url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json 15 | 16 | compile: 17 | # Choosing to run compilation tests on 2 different Arduino platforms 18 | platforms: 19 | # - uno 20 | # - due 21 | # - zero 22 | # - leonardo 23 | # - m4 24 | # - esp32 25 | # - esp8266 26 | # - mega2560 27 | - rpipico -------------------------------------------------------------------------------- /examples/ADS_RP2040_WIRE1/ADS_RP2040_WIRE1.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS_RP2040_WIRE1.ino 3 | // AUTHOR: Rob.Tillaart / Intubun 4 | // PURPOSE: read analog input 5 | // URL: https://github.com/RobTillaart/ADS1X15 6 | 7 | // test 8 | // connect 1 potentiometer 9 | // 10 | // GND ---[ x ]------ 5V 11 | // | 12 | // 13 | // measure at x (connect to AIN0). 14 | 15 | 16 | #include "ADS1X15.h" 17 | 18 | 19 | // choose your sensor 20 | // ADS1013 ADS(0x48); 21 | // ADS1014 ADS(0x48); 22 | // ADS1015 ADS(0x48); 23 | // ADS1113 ADS(0x48); 24 | // ADS1114 ADS(0x48); 25 | ADS1115 ADS(0x48, &Wire1); 26 | 27 | 28 | void setup() 29 | { 30 | Serial.begin(115200); 31 | Serial.println(__FILE__); 32 | Serial.print("ADS1X15_LIB_VERSION: "); 33 | Serial.println(ADS1X15_LIB_VERSION); 34 | 35 | // SDA (Pin 26), SCL(Pin 27) 36 | Wire1.begin(); 37 | Wire1.setSDA(26); 38 | Wire1.setSCL(27); 39 | 40 | ADS.begin(); 41 | ADS.setGain(0); // 6.144 volt 42 | ADS.setDataRate(7); // 0 = slow 4 = medium 7 = fast 43 | ADS.setMode(0); // continuous mode 44 | ADS.readADC(0); // first read to trigger 45 | } 46 | 47 | 48 | void loop() 49 | { 50 | Serial.println(ADS.getValue()); 51 | // optional other code here 52 | } 53 | 54 | 55 | // -- END OF FILE -- 56 | -------------------------------------------------------------------------------- /examples/ADS_async_16_channel/ADS_async_16_channel.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS_async_16_channel.ino 3 | // AUTHOR: Rob Tillaart 4 | // PURPOSE: demo reading four ADS1115 modules in parallel 5 | // URL: https://github.com/RobTillaart/ADS1X15 6 | 7 | 8 | // Note all IO with the sensors are guarded by an isConnected() 9 | // this is max robust, in non critical application one may either 10 | // cache the value or only verify it in setup (least robust). 11 | // Less robust may cause the application to hang - watchdog reset ? 12 | 13 | 14 | #include "ADS1X15.h" 15 | 16 | 17 | ADS1115 ADS[4]; 18 | uint16_t val[16]; 19 | int idx = 0; 20 | 21 | uint32_t last = 0, now = 0; 22 | 23 | 24 | void setup() 25 | { 26 | Serial.begin(115200); 27 | Serial.println(__FILE__); 28 | Serial.print("ADS1X15_LIB_VERSION: "); 29 | Serial.println(ADS1X15_LIB_VERSION); 30 | 31 | Wire.begin(); 32 | 33 | for (uint8_t i = 0; i < 4; i++) 34 | { 35 | uint8_t address = 0x48 + i; 36 | ADS[i] = ADS1115(address); 37 | 38 | Serial.print(address, HEX); 39 | Serial.print(" "); 40 | Serial.println(ADS[i].begin() ? "connected" : "not connected"); 41 | 42 | // 0 = slow 4 = medium 7 = fast, but more noise 43 | ADS[i].setDataRate(4); 44 | } 45 | ADS_request_all(); 46 | } 47 | 48 | 49 | void loop() 50 | { 51 | // Serial.println(__FUNCTION__); 52 | // wait until all is read... 53 | while (ADS_read_all()); 54 | 55 | // we have all values 56 | ADS_print_all(); 57 | 58 | // wait a second. 59 | delay(1000); 60 | ADS_request_all(); 61 | } 62 | 63 | 64 | void ADS_request_all() 65 | { 66 | // Serial.println(__FUNCTION__); 67 | for (int i = 0; i < 4; i++) 68 | { 69 | if (ADS[i].isConnected()) ADS[i].requestADC(idx); 70 | } 71 | } 72 | 73 | 74 | bool ADS_read_all() 75 | { 76 | for (int i = 0; i < 4; i++) 77 | { 78 | if (ADS[i].isConnected() && ADS[i].isBusy()) return true; 79 | } 80 | // Serial.print("IDX:\t"); 81 | // Serial.println(idx); 82 | for (int i = 0; i < 4; i++) 83 | { 84 | if (ADS[i].isConnected()) 85 | { 86 | val[i * 4 + idx] = ADS[i].getValue(); 87 | } 88 | } 89 | idx++; 90 | if (idx < 4) 91 | { 92 | ADS_request_all(); 93 | return true; 94 | } 95 | idx = 0; 96 | return false; 97 | } 98 | 99 | 100 | void ADS_print_all() 101 | { 102 | // Serial.println(__FUNCTION__); 103 | // TIMESTAMP 104 | now = millis(); 105 | Serial.print(now - last); 106 | last = now; 107 | Serial.println(); 108 | 109 | // PRINT ALL VALUES 110 | for (int i = 0; i < 4; i++) 111 | { 112 | for (int j = 0; j < 4; j++) 113 | { 114 | Serial.print(val[j * 4 + i]); 115 | Serial.print("\t"); 116 | } 117 | Serial.println(); 118 | } 119 | Serial.println(); 120 | } 121 | 122 | 123 | // -- END OF FILE -- 124 | 125 | -------------------------------------------------------------------------------- /examples/ADS_async_8_channel/ADS_async_8_channel.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS_async_8_channel.ino 3 | // AUTHOR: Rob Tillaart 4 | // PURPOSE: demo reading two ADS1115 modules in parallel 5 | // URL: https://github.com/RobTillaart/ADS1X15 6 | 7 | 8 | // Note all IO with the sensors are guarded by an isConnected() 9 | // this is max robust, in non critical application one may either 10 | // cache the value or only verify it in setup (least robust). 11 | // Less robust may cause the application to hang - watchdog reset ? 12 | 13 | 14 | #include "ADS1X15.h" 15 | 16 | 17 | ADS1115 ADS0(0x48); 18 | ADS1115 ADS1(0x49); 19 | // ADS1115 ADS2(0x4A); 20 | // ADS1115 ADS3(0x4B); 21 | 22 | int16_t val0[4] = { 0, 0, 0, 0 }; 23 | int16_t val1[4] = { 0, 0, 0, 0 }; 24 | // int16_t val2[4] = { 0, 0, 0, 0 }; 25 | // int16_t val3[4] = { 0, 0, 0, 0 }; 26 | int idx = 0; 27 | 28 | uint32_t lastTime = 0; 29 | 30 | 31 | void setup() 32 | { 33 | Serial.begin(115200); 34 | Serial.println(__FILE__); 35 | Serial.print("ADS1X15_LIB_VERSION: "); 36 | Serial.println(ADS1X15_LIB_VERSION); 37 | 38 | Wire.begin(); 39 | 40 | ADS0.begin(); 41 | ADS1.begin(); 42 | // ADS2.begin(); 43 | // ADS3.begin(); 44 | 45 | Serial.println(ADS0.isConnected()); 46 | Serial.println(ADS1.isConnected()); 47 | // Serial.println(ADS2.isConnected()); 48 | // Serial.println(ADS3.isConnected()); 49 | 50 | // 0 = slow 4 = medium 7 = fast but more noise 51 | ADS0.setDataRate(4); 52 | ADS1.setDataRate(4); 53 | // ADS2.setDataRate(4); 54 | // ADS3.setDataRate(4); 55 | 56 | idx = 0; 57 | ADS_request_all(); 58 | } 59 | 60 | 61 | void loop() 62 | { 63 | // wait until all is read... 64 | while (ADS_read_all()); 65 | 66 | // we have all 8 values 67 | ADS_print_all(); 68 | 69 | // wait a second. 70 | delay(1000); 71 | ADS_request_all(); 72 | } 73 | 74 | 75 | void ADS_request_all() 76 | { 77 | if (ADS0.isConnected()) ADS0.requestADC(idx); 78 | if (ADS1.isConnected()) ADS1.requestADC(idx); 79 | // if (ADS2.isConnected()) ADS2.requestADC(idx); 80 | // if (ADS3.isConnected()) ADS3.requestADC(idx); 81 | } 82 | 83 | 84 | bool ADS_read_all() 85 | { 86 | if (ADS0.isConnected() && ADS0.isBusy()) return true; 87 | if (ADS1.isConnected() && ADS1.isBusy()) return true; 88 | // if (ADS2.isConnected() && ADS2.isBusy()) return true; 89 | // if (ADS3.isConnected() && ADS3.isBusy()) return true; 90 | 91 | if (ADS0.isConnected()) val0[idx] = ADS0.getValue(); 92 | if (ADS1.isConnected()) val1[idx] = ADS1.getValue(); 93 | // if (ADS2.isConnected()) val2[idx] = ADS2.getValue(); 94 | // if (ADS3.isConnected()) val3[idx] = ADS3.getValue(); 95 | idx++; 96 | if (idx < 4) 97 | { 98 | ADS_request_all(); 99 | return true; 100 | } 101 | idx = 0; 102 | return false; 103 | } 104 | 105 | 106 | void ADS_print_all() 107 | { 108 | uint32_t now = millis(); 109 | Serial.println(now - lastTime); 110 | lastTime = now; 111 | 112 | // PRINT ALL VALUES OF ADC0 113 | for (int i = 0; i < 4; i++) 114 | { 115 | Serial.print(val0[i]); 116 | Serial.print("\t"); 117 | } 118 | // PRINT ALL VALUES OF ADC1 119 | for (int i = 0; i < 4; i++) 120 | { 121 | Serial.print(val1[i]); 122 | Serial.print("\t"); 123 | } 124 | Serial.println(); 125 | // // PRINT ALL VALUES OF ADC2 126 | // for (int i = 0; i < 4; i++) 127 | // { 128 | // Serial.print(val2[i]); 129 | // Serial.print("\t"); 130 | // } 131 | // // PRINT ALL VALUES OF ADC3 132 | // for (int i = 0; i < 4; i++) 133 | // { 134 | // Serial.print(val3[i]); 135 | // Serial.print("\t"); 136 | // } 137 | // Serial.println(); 138 | } 139 | 140 | 141 | // -- END OF FILE -- 142 | 143 | -------------------------------------------------------------------------------- /examples/ADS_async_differential/ADS_async_differential.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS_async_differential.ino 3 | // AUTHOR: Rob.Tillaart 4 | // PURPOSE: read multiple differential continuously 5 | // URL: https://github.com/RobTillaart/ADS1X15 6 | 7 | // test 8 | // connect 4 potmeters 9 | // 10 | // GND ---[ x ]------ 5V 11 | // | 12 | // 13 | // measure at x - connect to AIN0..4. 14 | // 15 | 16 | 17 | #include "ADS1X15.h" 18 | 19 | 20 | // choose your sensor 21 | // ADS1013 ADS(0x48); 22 | // ADS1014 ADS(0x48); 23 | // ADS1015 ADS(0x48); 24 | // ADS1113 ADS(0x48); 25 | // ADS1114 ADS(0x48); 26 | ADS1115 ADS(0x48); 27 | 28 | 29 | uint8_t pair = 01; 30 | int16_t val_01 = 0; 31 | int16_t val_23 = 0; 32 | 33 | 34 | void setup() 35 | { 36 | Serial.begin(115200); 37 | Serial.println(__FILE__); 38 | Serial.print("ADS1X15_LIB_VERSION: "); 39 | Serial.println(ADS1X15_LIB_VERSION); 40 | 41 | Wire.begin(); 42 | 43 | ADS.begin(); 44 | ADS.setGain(0); // 6.144 volt 45 | ADS.setDataRate(4); // 0 = slow 4 = medium 7 = fast 46 | 47 | // single shot mode 48 | ADS.setMode(1); 49 | // start with first pair 50 | pair = 01; 51 | // trigger first read 52 | ADS.requestADC_Differential_0_1(); 53 | } 54 | 55 | 56 | void loop() 57 | { 58 | if (handleConversion() == true) 59 | { 60 | Serial.print("COMP:\t"); 61 | Serial.print(val_01); 62 | Serial.print("\t"); 63 | Serial.print(val_23); 64 | Serial.println(); 65 | } 66 | 67 | // do other stuff here 68 | delay(10); 69 | } 70 | 71 | 72 | // can be changed to hold other differentials reads too. 73 | bool handleConversion() 74 | { 75 | if (ADS.isReady()) 76 | { 77 | if (pair == 01) 78 | { 79 | val_01 = ADS.getValue(); 80 | pair = 23; 81 | ADS.requestADC_Differential_2_3(); 82 | return false; // only one done 83 | } 84 | 85 | // last of series to check 86 | if (pair == 23) 87 | { 88 | val_23 = ADS.getValue(); 89 | pair = 01; 90 | ADS.requestADC_Differential_0_1(); 91 | return true; // both are updated 92 | } 93 | } 94 | return false; // default not all read 95 | } 96 | 97 | 98 | // -- END OF FILE -- 99 | 100 | -------------------------------------------------------------------------------- /examples/ADS_continuous/ADS_continuous.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS_continuous.ino 3 | // AUTHOR: Rob.Tillaart 4 | // PURPOSE: read analog input 5 | // URL: https://github.com/RobTillaart/ADS1X15 6 | 7 | // test 8 | // connect 1 potmeter 9 | // 10 | // GND ---[ x ]------ 5V 11 | // | 12 | // 13 | // measure at x (connect to AIN0). 14 | // 15 | // See https://github.com/RobTillaart/ADS1X15/issues/49 16 | // 17 | 18 | #include "ADS1X15.h" 19 | 20 | 21 | // choose your sensor 22 | // ADS1013 ADS(0x48); 23 | // ADS1014 ADS(0x48); 24 | // ADS1015 ADS(0x48); 25 | // ADS1113 ADS(0x48); 26 | // ADS1114 ADS(0x48); 27 | ADS1115 ADS(0x48); 28 | 29 | uint16_t count = 0; 30 | uint16_t value = 0; 31 | uint16_t prev = 0; 32 | uint32_t lastTime = 0; 33 | uint32_t lastSample = 0; 34 | 35 | 36 | void setup() 37 | { 38 | Serial.begin(500000); 39 | Serial.println(__FILE__); 40 | Serial.print("ADS1X15_LIB_VERSION: "); 41 | Serial.println(ADS1X15_LIB_VERSION); 42 | 43 | Wire.begin(); 44 | 45 | ADS.begin(); 46 | ADS.setGain(0); // 6.144 volt 47 | ADS.setDataRate(7); // 0 = slow 4 = medium 7 = fast 48 | ADS.setMode(0); // continuous mode 49 | ADS.readADC(0); // first read to trigger 50 | } 51 | 52 | 53 | void loop() 54 | { 55 | uint32_t now = micros(); 56 | if (now - lastSample >= 1160) // almost exact 860 SPS 57 | { 58 | lastSample = now; 59 | value = ADS.getValue(); 60 | count++; 61 | Serial.print(count); 62 | Serial.print("\t"); 63 | Serial.println(value); 64 | } 65 | if (now - 1000000 >= lastTime) 66 | { 67 | lastTime = now; 68 | count = 0; 69 | } 70 | } 71 | 72 | 73 | // -- END OF FILE -- 74 | 75 | -------------------------------------------------------------------------------- /examples/ADS_continuous_3_channel/ADS_continuous_3_channel.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS_continuous_3_channel.ino 3 | // AUTHOR: Rob.Tillaart 4 | // PURPOSE: read multiple analog inputs continuously 5 | // interrupt driven to catch all conversions. 6 | // URL: https://github.com/RobTillaart/ADS1X15 7 | // https://github.com/RobTillaart/ADS1X15/issues/49 8 | // 9 | // experimental, not tested extensively 10 | 11 | // test 12 | // connect multiple potmeters 13 | // 14 | // RDY ----------------- pin 2 (for IRQ, adjust if needed) 15 | // 16 | // GND ---[ x ]------ 5V 17 | // | 18 | // | 19 | // ADS(n) 20 | // 21 | // measure at x - connect to AIN0..1. 22 | // 23 | // for the test it is an option to have AIN2 connected to 5V and AIN3 to GND 24 | // so one can see these as references in the output. 25 | // 26 | // has an issue with the index of the channels. not not investigated yet. 27 | 28 | 29 | #include "ADS1X15.h" 30 | 31 | 32 | // choose your sensor 33 | // ADS1013 ADS(0x48); 34 | // ADS1014 ADS(0x48); 35 | // ADS1015 ADS(0x48); 36 | // ADS1113 ADS(0x48); 37 | // ADS1114 ADS(0x48); 38 | ADS1115 ADS(0x48); 39 | 40 | volatile bool RDY = false; 41 | uint8_t channel = 0; 42 | int16_t val[4] = { 0, 0, 0, 0 }; 43 | 44 | int SPS = 0; 45 | uint32_t lastTime = 0; 46 | 47 | 48 | void setup() 49 | { 50 | Serial.begin(230400); // <<<<<<<<< fast! 51 | Serial.println(__FILE__); 52 | Serial.print("ADS1X15_LIB_VERSION: "); 53 | Serial.println(ADS1X15_LIB_VERSION); 54 | 55 | Wire.begin(); 56 | Wire.setClock(400000); 57 | 58 | ADS.begin(); 59 | ADS.setGain(0); // 6.144 volt 60 | ADS.setDataRate(7); // 0 = slow 4 = medium 7 = fast 61 | 62 | // SET ALERT RDY PIN 63 | ADS.setComparatorThresholdHigh(0x8000); 64 | ADS.setComparatorThresholdLow(0x0000); 65 | ADS.setComparatorQueConvert(0); 66 | 67 | // SET INTERRUPT HANDLER TO CATCH CONVERSION READY 68 | pinMode(2, INPUT_PULLUP); 69 | attachInterrupt(digitalPinToInterrupt(2), adsReady, RISING); 70 | 71 | ADS.setMode(0); // continuous mode 72 | channel = 0; 73 | ADS.requestADC(channel); // start at 0 74 | } 75 | 76 | 77 | void loop() 78 | { 79 | // if conversion ready 80 | // request a new one and print the last one. 81 | if (RDY) 82 | { 83 | SPS++; 84 | val[channel] = ADS.getValue(); 85 | // request next channel asap 86 | channel++; 87 | if (channel >= 3) channel = 0; 88 | ADS.requestADC(channel); 89 | RDY = false; 90 | 91 | // to see it works 92 | if (SPS % 200 == 0) 93 | { 94 | for (int i = 0; i < 4; i++) 95 | { 96 | Serial.print('\t'); 97 | Serial.print(val[i]); 98 | } 99 | Serial.println(); 100 | } 101 | } 102 | 103 | 104 | // print the SPS 105 | if (millis() - lastTime >= 1000) 106 | { 107 | lastTime = millis(); 108 | Serial.print("SPS: "); 109 | Serial.println(SPS); 110 | SPS = 0; 111 | } 112 | } 113 | 114 | 115 | // interrupt service routine 116 | // kept as minimal as possible 117 | void adsReady() 118 | { 119 | RDY = true; 120 | } 121 | 122 | 123 | // -- END OF FILE -- 124 | 125 | -------------------------------------------------------------------------------- /examples/ADS_continuous_4_channel/ADS_continuous_4_channel.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS_continuous_4_channel.ino 3 | // AUTHOR: Rob.Tillaart 4 | // PURPOSE: read multiple analog inputs continuously 5 | // interrupt driven to catch all conversions. 6 | // URL: https://github.com/RobTillaart/ADS1X15 7 | 8 | // test 9 | // connect multiple potmeters 10 | // 11 | // RDY ----------------- pin 2 (for IRQ, adjust if needed) 12 | // 13 | // GND ---[ x ]------ 5V 14 | // | 15 | // 16 | // measure at x - connect to AIN0..1. 17 | // 18 | // for the test it is good to have AIN2 connected to 5V and AIN3 to GND 19 | // so one can see these as references in the output. 20 | // 21 | 22 | 23 | #include "ADS1X15.h" 24 | 25 | 26 | // choose your sensor 27 | // ADS1013 ADS(0x48); 28 | // ADS1014 ADS(0x48); 29 | // ADS1015 ADS(0x48); 30 | // ADS1113 ADS(0x48); 31 | // ADS1114 ADS(0x48); 32 | ADS1115 ADS(0x48); 33 | 34 | volatile bool RDY = false; 35 | uint8_t channel = 0; 36 | int16_t val[4] = { 0, 0, 0, 0 }; 37 | 38 | 39 | void setup() 40 | { 41 | Serial.begin(115200); 42 | Serial.println(__FILE__); 43 | Serial.print("ADS1X15_LIB_VERSION: "); 44 | Serial.println(ADS1X15_LIB_VERSION); 45 | 46 | Wire.begin(); 47 | 48 | pinMode(2, INPUT_PULLUP); 49 | attachInterrupt(digitalPinToInterrupt(2), adsReady, RISING); 50 | 51 | ADS.begin(); 52 | ADS.setGain(0); // 6.144 volt 53 | ADS.setDataRate(7); // 0 = slow 4 = medium 7 = fast 54 | 55 | // SET ALERT RDY PIN 56 | ADS.setComparatorThresholdHigh(0x8000); 57 | ADS.setComparatorThresholdLow(0x0000); 58 | ADS.setComparatorQueConvert(0); 59 | 60 | // SET INTERRUPT HANDLER TO CATCH CONVERSION READY 61 | pinMode(2, INPUT_PULLUP); 62 | attachInterrupt(digitalPinToInterrupt(2), adsReady, RISING); 63 | 64 | ADS.setMode(0); // continuous mode 65 | ADS.readADC(channel); // trigger first read 66 | } 67 | 68 | 69 | void loop() 70 | { 71 | handleConversion(); 72 | 73 | for (int i = 0; i < 4; i++) 74 | { 75 | Serial.print(val[i]); 76 | Serial.print('\t'); 77 | handleConversion(); 78 | } 79 | Serial.println(); 80 | delay(100); 81 | } 82 | 83 | 84 | // interrupt service routine 85 | // kept as minimal as possible 86 | void adsReady() 87 | { 88 | RDY = true; 89 | } 90 | 91 | 92 | void handleConversion() 93 | { 94 | if (RDY) 95 | { 96 | // save the value 97 | val[channel] = ADS.getValue(); 98 | // request next channel 99 | channel++; 100 | if (channel >= 4) channel = 0; 101 | ADS.readADC(channel); 102 | RDY = false; 103 | } 104 | } 105 | 106 | 107 | // -- END OF FILE -- 108 | 109 | -------------------------------------------------------------------------------- /examples/ADS_continuous_8_channel/ADS_continuous_8_channel.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS_continuous_8_channel.ino 3 | // AUTHOR: Rob.Tillaart 4 | // PURPOSE: read multiple analog inputs continuously 5 | // interrupt driven to catch all conversions. 6 | // URL: https://github.com/RobTillaart/ADS1X15 7 | 8 | // test 9 | // connect multiple potmeters to 2 ADS1115 10 | // 11 | // 12 | // RDY1 ----------------- pin 2 (for IRQ, adjust if needed) 13 | // 14 | // RDY2 ----------------- pin 3 (for IRQ, adjust if needed) 15 | // 16 | // 17 | // GND ---[ x ]------ 5V 18 | // | 19 | // 20 | // measure at x - connect to AIN0..1. 21 | // 22 | // for the test it is good to have AIN2 connected to 5V and AIN3 to GND 23 | // so one can see these as references in the output. 24 | // 25 | 26 | 27 | #include "ADS1X15.h" 28 | 29 | 30 | // adjust addresses if needed 31 | ADS1115 ADS_1(0x49); 32 | ADS1115 ADS_2(0x48); 33 | 34 | // two interrupt flags 35 | volatile bool RDY_1 = false; 36 | volatile bool RDY_2 = false; 37 | 38 | uint8_t channel_1 = 0; // channel from device 1 39 | uint8_t channel_2 = 0; // channel from device 2 40 | 41 | // array to hold the data. 42 | int16_t val[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 43 | 44 | 45 | void setup() 46 | { 47 | Serial.begin(115200); 48 | Serial.println(__FILE__); 49 | Serial.print("ADS1X15_LIB_VERSION: "); 50 | Serial.println(ADS1X15_LIB_VERSION); 51 | 52 | Wire.begin(); 53 | 54 | // SETUP FIRST ADS1115 55 | ADS_1.begin(); 56 | ADS_1.setGain(0); // 0 == 6.144 volt, default 57 | ADS_1.setDataRate(7); // 0 = slow 4 = medium 7 = fast 58 | 59 | // SET ALERT RDY PIN 60 | ADS_1.setComparatorThresholdHigh(0x8000); 61 | ADS_1.setComparatorThresholdLow(0x0000); 62 | ADS_1.setComparatorQueConvert(0); 63 | 64 | // SET INTERRUPT HANDLER TO CATCH CONVERSION READY 65 | pinMode(2, INPUT_PULLUP); 66 | attachInterrupt(digitalPinToInterrupt(2), adsReady_1, RISING); 67 | 68 | ADS_1.setMode(0); // 0 == continuous mode 69 | ADS_1.readADC(channel_1); // 0 == default channel, trigger first read 70 | 71 | 72 | // SETUP SECOND ADS1115 73 | ADS_2.begin(); 74 | ADS_2.setGain(0); // 0 == 6.144 volt, default 75 | ADS_2.setDataRate(7); // 7 == highest 76 | 77 | // SET ALERT RDY PIN 78 | ADS_2.setComparatorThresholdHigh(0x8000); 79 | ADS_2.setComparatorThresholdLow(0x0000); 80 | ADS_2.setComparatorQueConvert(0); 81 | 82 | // SET INTERRUPT HANDLER TO CATCH CONVERSION READY 83 | pinMode(3, INPUT_PULLUP); 84 | attachInterrupt(digitalPinToInterrupt(3), adsReady_2, RISING); 85 | 86 | ADS_2.setMode(0); // 0 == continuous mode 87 | ADS_2.readADC(channel_2); // 0 == default channel, trigger first read 88 | } 89 | 90 | 91 | void loop() 92 | { 93 | handleConversion(); 94 | 95 | for (int i = 0; i < 8; i++) 96 | { 97 | Serial.print(val[i]); 98 | Serial.print('\t'); 99 | handleConversion(); 100 | } 101 | Serial.println(); 102 | delay(100); 103 | } 104 | 105 | 106 | // catch interrupt and set flag device 1 107 | void adsReady_1() 108 | { 109 | RDY_1 = true; 110 | } 111 | 112 | // catch interrupt and set flag device 1 113 | void adsReady_2() 114 | { 115 | RDY_2 = true; 116 | } 117 | 118 | 119 | // handle conversions that are ready 120 | bool handleConversion() 121 | { 122 | bool rv = false; 123 | if (RDY_1) 124 | { 125 | // save the last value 126 | val[channel_1] = ADS_1.getValue(); 127 | // request next channel 128 | channel_1++; 129 | if (channel_1 >= 4) channel_1 = 0; 130 | ADS_1.readADC(channel_1); 131 | RDY_1 = false; 132 | rv = true; 133 | } 134 | if (RDY_2) 135 | { 136 | // save the last value 137 | val[4 + channel_2] = ADS_2.getValue(); 138 | // request next channel 139 | channel_2++; 140 | if (channel_2 >= 4) channel_2 = 0; 141 | ADS_2.readADC(channel_2); 142 | RDY_2 = false; 143 | rv = true; 144 | } 145 | return rv; 146 | } 147 | 148 | 149 | // -- END OF FILE -- 150 | 151 | -------------------------------------------------------------------------------- /examples/ADS_continuous_differential/ADS_continuous_differential.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS_continuous_differential.ino 3 | // AUTHOR: Rob.Tillaart 4 | // PURPOSE: read multiple differential continuously 5 | // URL: https://github.com/RobTillaart/ADS1X15 6 | 7 | // test 8 | // connect 4 potmeters 9 | // 10 | // RDY ----------------- pin 2 (for IRQ, adjust if needed) 11 | // 12 | // GND ---[ x ]------ 5V 13 | // | 14 | // 15 | // measure at x - connect to AIN0..3. 16 | // 17 | // adjust IRQ pin if needed 18 | 19 | 20 | #include "ADS1X15.h" 21 | 22 | 23 | // choose your sensor 24 | // ADS1013 ADS(0x48); 25 | // ADS1014 ADS(0x48); 26 | // ADS1015 ADS(0x48); 27 | // ADS1113 ADS(0x48); 28 | // ADS1114 ADS(0x48); 29 | ADS1115 ADS(0x48); 30 | 31 | 32 | // interrupt flag 33 | volatile bool RDY = false; 34 | // which pair to use for differential 35 | uint8_t pair = 01; 36 | // two values to hold differential measurements. 37 | int16_t val_01 = 0; 38 | int16_t val_23 = 0; 39 | 40 | 41 | void setup() 42 | { 43 | Serial.begin(115200); 44 | Serial.println(__FILE__); 45 | Serial.print("ADS1X15_LIB_VERSION: "); 46 | Serial.println(ADS1X15_LIB_VERSION); 47 | 48 | Wire.begin(); 49 | 50 | // SET INTERRUPT HANDLER TO CATCH CONVERSION READY 51 | pinMode(2, INPUT_PULLUP); 52 | attachInterrupt(digitalPinToInterrupt(2), adsReady, RISING); 53 | 54 | ADS.begin(); 55 | Serial.print("connected: "); 56 | Serial.println(ADS.isConnected()); 57 | ADS.setGain(0); // 6.144 volt 58 | ADS.setDataRate(0); // 0 = slow 4 = medium 7 = fast (7 = fails ) 59 | // every step is about a factor 2 slower. 60 | 61 | // SET ALERT RDY PIN (QueConvert mode) 62 | // set the MSB of the Hi_thresh register to 1 63 | ADS.setComparatorThresholdHigh(0x8000); 64 | // set the MSB of the Lo_thresh register to 0 65 | ADS.setComparatorThresholdLow(0x0000); 66 | ADS.setComparatorQueConvert(0); 67 | 68 | // continuous mode 69 | ADS.setMode(0); 70 | // start with first pair 71 | pair = 01; 72 | // trigger first read 73 | ADS.requestADC_Differential_0_1(); 74 | } 75 | 76 | 77 | void loop() 78 | { 79 | static uint32_t last = 0; 80 | if (handleConversion() == true) 81 | { 82 | uint32_t now = millis(); 83 | Serial.print(now - last); 84 | last = now; 85 | Serial.print("\tCOMP:\t"); 86 | Serial.print(val_01); 87 | Serial.print("\t"); 88 | Serial.print(val_23); 89 | Serial.println(); 90 | } 91 | 92 | // do other stuff here 93 | // delay(10); 94 | } 95 | 96 | 97 | // interrupt handler, sets the RDY flag 98 | void adsReady() 99 | { 100 | RDY = true; 101 | } 102 | 103 | 104 | // can be changed to hold other differentials or normal reads too. 105 | bool handleConversion() 106 | { 107 | if (RDY) 108 | { 109 | RDY = false; 110 | if (pair == 01) 111 | { 112 | val_01 = ADS.getValue(); 113 | pair = 23; 114 | ADS.requestADC_Differential_2_3(); 115 | return false; // only one done 116 | } 117 | 118 | // last of series to check 119 | if (pair == 23) 120 | { 121 | val_23 = ADS.getValue(); 122 | pair = 01; 123 | ADS.requestADC_Differential_0_1(); 124 | return true; // both are updated 125 | } 126 | } 127 | return false; // default not all read 128 | } 129 | 130 | 131 | // -- END OF FILE -- 132 | 133 | -------------------------------------------------------------------------------- /examples/ADS_differential/ADS_differential.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS_differential.ino 3 | // AUTHOR: Rob.Tillaart 4 | // PURPOSE: read differential 5 | // URL: https://github.com/RobTillaart/ADS1X15 6 | 7 | // test 1 8 | // connect 2 potmeters in series 9 | // 10 | // GND ---[ x ]------[ y ]---- 5V 11 | // | | 12 | // 13 | // measure at x and y (connect to AIN0 and AIN1). 14 | // x should be lower or equal to y 15 | 16 | // test 2 17 | // connect 2 potmeters parallel 18 | // 19 | // GND ---[ x ]------ 5V 20 | // | 21 | // 22 | // GND ---[ y ]------ 5V 23 | // | 24 | // 25 | // measure at x and y (connect to AIN0 and AIN1). 26 | // range from -VDD .. +VDD are possible 27 | 28 | 29 | #include 30 | 31 | ADS1115 ADS(0x48); 32 | 33 | 34 | void setup() 35 | { 36 | Serial.begin(115200); 37 | Serial.println(__FILE__); 38 | Serial.print("ADS1X15_LIB_VERSION: "); 39 | Serial.println(ADS1X15_LIB_VERSION); 40 | 41 | Wire.begin(); 42 | 43 | ADS.begin(); 44 | ADS.setGain(0); 45 | } 46 | 47 | 48 | void loop() 49 | { 50 | int16_t val_01 = ADS.readADC_Differential_0_1(); 51 | int16_t val_03 = ADS.readADC_Differential_0_3(); 52 | int16_t val_13 = ADS.readADC_Differential_1_3(); 53 | int16_t val_23 = ADS.readADC_Differential_2_3(); 54 | float volts_01 = ADS.toVoltage(val_01); 55 | float volts_03 = ADS.toVoltage(val_03); 56 | float volts_13 = ADS.toVoltage(val_13); 57 | float volts_23 = ADS.toVoltage(val_23); 58 | 59 | Serial.print("\tval_01: "); Serial.print(val_01); Serial.print("\t"); Serial.println(volts_01, 3); 60 | Serial.print("\tval_03: "); Serial.print(val_03); Serial.print("\t"); Serial.println(volts_03, 3); 61 | Serial.print("\tval_13: "); Serial.print(val_13); Serial.print("\t"); Serial.println(volts_13, 3); 62 | Serial.print("\tval_23: "); Serial.print(val_23); Serial.print("\t"); Serial.println(volts_23, 3); 63 | Serial.println(); 64 | 65 | delay(1000); 66 | } 67 | 68 | 69 | // -- END OF FILE -- 70 | 71 | -------------------------------------------------------------------------------- /examples/ADS_high_speed_differential/ADS_high_speed_differential.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS_high_speed_differential.ino 3 | // AUTHOR: Rob.Tillaart 4 | // PURPOSE: read from 2 IC's for high speed differential 5 | // interrupt driven to catch all conversions. 6 | // URL: https://github.com/RobTillaart/ADS1X15 7 | 8 | // test setup (not tested yet) 9 | // - connect 2 ADS1x15 to I2C bus 10 | // - connect potmeters to all channels 11 | // - code reads both at the same frequency 12 | // and calculates differential per pair. 13 | // as 2 ADC's go in parallel, two ADS1015 should get 14 | // 3000+ differential samples / second. 15 | // 16 | 17 | 18 | #include "ADS1X15.h" 19 | 20 | // adjust addresses if needed 21 | ADS1115 ADS_1(0x49); 22 | ADS1115 ADS_2(0x48); 23 | 24 | volatile bool RDY_1 = false; 25 | volatile bool RDY_2 = false; 26 | uint8_t channel = 0; 27 | int32_t differential[4] = { 0, 0, 0, 0 }; 28 | 29 | 30 | void setup() 31 | { 32 | Serial.begin(115200); 33 | Serial.println(__FILE__); 34 | Serial.print("ADS1X15_LIB_VERSION: "); 35 | Serial.println(ADS1X15_LIB_VERSION); 36 | 37 | Wire.begin(); 38 | 39 | // SETUP FIRST ADS1115 40 | ADS_1.begin(); 41 | ADS_1.setGain(0); // 6.144 volt 42 | ADS_1.setDataRate(7); // 0 = slow 4 = medium 7 = fast 43 | 44 | // SET ALERT RDY PIN (QueConvert mode) 45 | // set the MSB of the Hi_thresh register to 1 46 | ADS_1.setComparatorThresholdHigh(0x8000); 47 | // set the MSB of the Lo_thresh register to 0 48 | ADS_1.setComparatorThresholdLow(0x0000); 49 | ADS_1.setComparatorQueConvert(0); 50 | 51 | // SET INTERRUPT HANDLER TO CATCH CONVERSION READY 52 | pinMode(2, INPUT_PULLUP); 53 | attachInterrupt(digitalPinToInterrupt(2), adsReady_1, RISING); 54 | 55 | ADS_1.setMode(0); // continuous mode 56 | ADS_1.readADC(channel); // trigger first read 57 | 58 | 59 | // SETUP SECOND ADS1115 60 | ADS_2.begin(); 61 | ADS_2.setGain(0); // 6.144 volt 62 | ADS_2.setDataRate(7); 63 | 64 | // SET ALERT RDY PIN 65 | // set the MSB of the Hi_thresh register to 1 66 | ADS_2.setComparatorThresholdHigh(0x8000); 67 | // set the MSB of the Lo_thresh register to 0 68 | ADS_2.setComparatorThresholdLow(0x0000); 69 | ADS_2.setComparatorQueConvert(0); 70 | 71 | // SET INTERRUPT HANDLER TO CATCH CONVERSION READY 72 | pinMode(3, INPUT_PULLUP); 73 | attachInterrupt(digitalPinToInterrupt(3), adsReady_2, RISING); 74 | 75 | ADS_2.setMode(0); // continuous mode 76 | ADS_2.readADC(channel); // trigger first read 77 | } 78 | 79 | 80 | void loop() 81 | { 82 | if (handleConversion() == true) 83 | { 84 | for (int i = 0; i < 4; i++) 85 | { 86 | Serial.print(differential[i]); 87 | Serial.print("\t"); 88 | } 89 | Serial.println(); 90 | } 91 | } 92 | 93 | 94 | // catch interrupt and set flag 95 | void adsReady_1() 96 | { 97 | RDY_1 = true; 98 | } 99 | 100 | void adsReady_2() 101 | { 102 | RDY_2 = true; 103 | } 104 | 105 | 106 | // handle conversions if both are ready 107 | bool handleConversion() 108 | { 109 | if (RDY_1 == false) return false; 110 | if (RDY_2 == false) return false; 111 | 112 | // read the value of both 113 | int16_t a = ADS_1.getValue(); 114 | int16_t b = ADS_2.getValue(); 115 | differential[channel] = a - b; 116 | // request next channel 117 | channel++; 118 | if (channel >= 4) channel = 0; 119 | ADS_1.readADC(channel); 120 | ADS_2.readADC(channel); 121 | RDY_1 = false; 122 | RDY_2 = false; 123 | 124 | return true; 125 | } 126 | 127 | 128 | // -- END OF FILE -- 129 | 130 | -------------------------------------------------------------------------------- /examples/ADS_minimum/ADS_minimum.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS_minimum.ino 3 | // AUTHOR: Rob.Tillaart 4 | // PURPOSE: read analog input 5 | // URL: https://github.com/RobTillaart/ADS1X15 6 | 7 | // test 8 | // connect 1 potmeter 9 | // 10 | // GND ---[ x ]------ 5V 11 | // | 12 | // 13 | // measure at x (connect to AIN0). 14 | // 15 | // view with Serial Plotter 16 | 17 | 18 | #include "ADS1X15.h" 19 | 20 | 21 | // choose your sensor 22 | // ADS1013 ADS(0x48); 23 | // ADS1014 ADS(0x48); 24 | // ADS1015 ADS(0x48); 25 | // ADS1113 ADS(0x48); 26 | // ADS1114 ADS(0x48); 27 | 28 | ADS1115 ADS(0x48); 29 | 30 | 31 | void setup() 32 | { 33 | Serial.begin(115200); 34 | Serial.println(__FILE__); 35 | Serial.print("ADS1X15_LIB_VERSION: "); 36 | Serial.println(ADS1X15_LIB_VERSION); 37 | 38 | Wire.begin(); 39 | 40 | ADS.begin(); 41 | ADS.setGain(0); // 6.144 volt 42 | Serial.println("Voltage"); 43 | } 44 | 45 | 46 | void loop() 47 | { 48 | int16_t raw = ADS.readADC(0); 49 | Serial.println(ADS.toVoltage(raw), 3); 50 | } 51 | 52 | 53 | // -- END OF FILE -- 54 | 55 | -------------------------------------------------------------------------------- /examples/ADS_performance/ADS_performance.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS_performance.ino 3 | // AUTHOR: Rob.Tillaart 4 | // PURPOSE: read analog input 5 | // URL: https://github.com/RobTillaart/ADS1X15 6 | 7 | // TODO verify output 8 | 9 | // test 10 | // connect 1 potmeter 11 | // 12 | // GND ---[ x ]------ 5V 13 | // | 14 | // 15 | // measure at x (connect to AIN0). 16 | // 17 | // https://github.com/RobTillaart/ADS1X15/issues/53 18 | 19 | 20 | #include "ADS1X15.h" 21 | 22 | 23 | // choose your sensor 24 | // ADS1013 ADS(0x48); 25 | // ADS1014 ADS(0x48); 26 | // ADS1015 ADS(0x48); 27 | // ADS1113 ADS(0x48); 28 | // ADS1114 ADS(0x48); 29 | 30 | ADS1115 ADS(0x48); 31 | 32 | uint32_t start, d1, d2; 33 | int x; 34 | 35 | 36 | void setup() 37 | { 38 | Serial.begin(115200); 39 | Serial.println(__FILE__); 40 | Serial.print("ADS1X15_LIB_VERSION: "); 41 | Serial.println(ADS1X15_LIB_VERSION); 42 | 43 | Wire.begin(); 44 | Wire.setClock(600000); 45 | 46 | ADS.begin(); 47 | ADS.setGain(0); // 6.144 volt 48 | 49 | for (int dr = 0; dr < 8; dr++) 50 | { 51 | // 0 = slow 4 = medium 7 = fast 52 | ADS.setDataRate(dr); 53 | Serial.print("DR:\t"); 54 | Serial.println(dr); 55 | 56 | test_single_shot(); 57 | test_continuous(); 58 | 59 | Serial.print("\t\tFACTOR:\t"); 60 | Serial.println(1.0 * d1 / d2); 61 | } 62 | 63 | Serial.println("\nDone..."); 64 | } 65 | 66 | 67 | void loop() 68 | { 69 | } 70 | 71 | 72 | void test_single_shot() 73 | { 74 | Serial.print(__FUNCTION__); 75 | 76 | ADS.setMode(1); 77 | start = micros(); 78 | x = ADS.readADC(0); 79 | for (int i = 0; i < 100; i++) 80 | { 81 | x = ADS.readADC(0); 82 | } 83 | d1 = micros() - start; 84 | Serial.print("\t"); 85 | Serial.print(d1); // TIME (us) 86 | Serial.print("\t\t"); 87 | Serial.println(100000000.0 / d1); // SPS 88 | delay(100); 89 | } 90 | 91 | 92 | void test_continuous() 93 | { 94 | Serial.print(__FUNCTION__); 95 | 96 | ADS.setMode(0); 97 | start = micros(); 98 | x = ADS.readADC(0); 99 | for (int i = 0; i < 100; i++) 100 | { 101 | x = ADS.getValue(); 102 | } 103 | d2 = micros() - start; 104 | Serial.print("\t\t"); 105 | Serial.print(d2); // TIME (us) 106 | Serial.print("\t\t"); 107 | Serial.println(100000000.0 / d2); // SPS 108 | delay(100); 109 | } 110 | 111 | 112 | // -- END OF FILE -- 113 | -------------------------------------------------------------------------------- /examples/ADS_performance/performance_0.3.9.md: -------------------------------------------------------------------------------- 1 | Based upon output of **ADS_performance.ino** 2 | UNO 16 MHz. 3 | IDE 1.8.19 4 | 5 | 6 | Synchronous calls I2C **100 KHz** 7 | 8 | | DataRate | Time 100 calls | SPS | 9 | |:----------:|:----------------:|:------:| 10 | | 0 | 12861340 | 7.78 | 11 | | 1 | 6481396 | 15.4 | 12 | | 2 | 3347512 | 29.9 | 13 | | 3 | 1724380 | 58.0 | 14 | | 4 | 941032 | 106 | 15 | | 5 | 549204 | 182 | 16 | | 6 | 381340 | 262 | 17 | | 7 | 269448 | 371 | 18 | 19 | 20 | Synchronous calls I2C **400 KHz** 21 | 22 | | DataRate | Time 100 calls | SPS | 23 | |:----------:|:----------------:|:------:| 24 | | 0 | 12872804 | 7.77 | 25 | | 1 | 6402848 | 15.6 | 26 | | 2 | 3234156 | 30.9 | 27 | | 3 | 1649272 | 60.6 | 28 | | 4 | 862188 | 116 | 29 | | 5 | 468652 | 213 | 30 | | 6 | 271552 | 368 | 31 | | 7 | 173412 | 577 | 32 | 33 | 34 | Synchronous calls I2C **600 KHz** 35 | 36 | | DataRate | Time 100 calls | SPS | 37 | |:----------:|:----------------:|:------:| 38 | | 0 | 12736788 | 7.85 | 39 | | 1 | 6390104 | 15.7 | 40 | | 2 | 3223568 | 31.0 | 41 | | 3 | 1645768 | 60.8 | 42 | | 4 | 852300 | 117 | 43 | | 5 | 448520 | 223 | 44 | | 6 | 261216 | 383 | 45 | | 7 | 167660 | 596 | 46 | 47 | These are maxima of the SPS feasible, they do not include further processing. 48 | At least this test shows the effect of the I2C bus speed. 49 | 50 | -------------------------------------------------------------------------------- /examples/ADS_performance/performance_0.4.4.md: -------------------------------------------------------------------------------- 1 | Based upon output of **ADS_performance.ino** (indicative). 2 | UNO 16 MHz. 3 | IDE 1.8.19 4 | 5 | ADS1X15_LIB_VERSION: 0.4.4 6 | 7 | Synchronous calls I2C **100 KHz** 8 | 9 | | DataRate | Time 100 calls | SPS | 10 | |:----------:|:----------------:|:------:| 11 | | 0 | 12931840 | 7.73 | 12 | | 1 | 6481444 | 15.4 | 13 | | 2 | 3347556 | 29.9 | 14 | | 3 | 1724492 | 58.0 | 15 | | 4 | 940984 | 106 | 16 | | 5 | 549268 | 182 | 17 | | 6 | 381328 | 262 | 18 | | 7 | 269400 | 371 | 19 | 20 | 21 | Synchronous calls I2C **400 KHz** 22 | 23 | | DataRate | Time 100 calls | SPS | 24 | |:----------:|:----------------:|:------:| 25 | | 0 | 12824560 | 7.80 | 26 | | 1 | 6377516 | 15.7 | 27 | | 2 | 3224972 | 31.0 | 28 | | 3 | 1649100 | 60.6 | 29 | | 4 | 862148 | 116 | 30 | | 5 | 468488 | 213 | 31 | | 6 | 271568 | 368 | 32 | | 7 | 173424 | 577 | 33 | 34 | 35 | Synchronous calls I2C **600 KHz** 36 | 37 | | DataRate | Time 100 calls | SPS | 38 | |:----------:|:----------------:|:------:| 39 | | 0 | 12816404 | 7.80 | 40 | | 1 | 6374432 | 15.7 | 41 | | 2 | 3216720 | 31.1 | 42 | | 3 | 1630428 | 61.3 | 43 | | 4 | 852332 | 117 | 44 | | 5 | 448396 | 223 | 45 | | 6 | 261288 | 383 | 46 | | 7 | 165688 | 603 | 47 | 48 | These are maxima of the SPS feasible, they do not include further processing. 49 | At least this test shows the effect of the I2C bus speed. 50 | 51 | -------------------------------------------------------------------------------- /examples/ADS_pointerToFunction/.arduino-ci.yml: -------------------------------------------------------------------------------- 1 | platforms: 2 | rpipico: 3 | board: rp2040:rp2040:rpipico 4 | package: rp2040:rp2040 5 | gcc: 6 | features: 7 | defines: 8 | - ARDUINO_ARCH_RP2040 9 | warnings: 10 | flags: 11 | 12 | packages: 13 | rp2040:rp2040: 14 | url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json 15 | 16 | 17 | compile: 18 | # Choosing to run compilation tests on 2 different Arduino platforms 19 | platforms: 20 | - uno 21 | # - due 22 | # - zero 23 | # - leonardo 24 | # - m4 25 | # - esp32 26 | # - esp8266 27 | # - mega2560 28 | - rpipico 29 | -------------------------------------------------------------------------------- /examples/ADS_pointerToFunction/ADS_pointerToFunction.ino: -------------------------------------------------------------------------------- 1 | // FILE: ADS_pointerToFunction.ino 2 | // AUTHOR: Rob Tillaart 3 | // PURPOSE: replace internal ADC with external ADC by using pointer to function 4 | // URL: https://github.com/RobTillaart/ADS1X15 5 | // 6 | // WARNING ONLY TESTED ON AVR 7 | 8 | 9 | #include "Arduino.h" 10 | #include "ADS1X15.h" 11 | 12 | // adjust address if needed 13 | ADS1115 ADS(0x48); 14 | 15 | // pointer to ADC function 16 | int (*readADC)(uint8_t); 17 | 18 | 19 | void setup() 20 | { 21 | Serial.begin(115200); 22 | while(!Serial); 23 | Serial.println(__FILE__); 24 | 25 | Wire.begin(); 26 | Wire.setClock(100000); 27 | 28 | ADS.begin(); // use defaults 29 | 30 | readADC = analogRead; // start with internal 31 | } 32 | 33 | 34 | void loop() 35 | { 36 | delay(500); 37 | int x = readADC(1); 38 | Serial.println(x); 39 | if (millis() > 5000) readADC = wrapper; 40 | } 41 | 42 | // wrapper takes care 43 | int wrapper(uint8_t x) 44 | { 45 | return ADS.readADC(x); 46 | } 47 | 48 | 49 | 50 | // -- END OF FILE -- 51 | -------------------------------------------------------------------------------- /examples/ADS_read/ADS_read.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS_read.ino 3 | // AUTHOR: Rob.Tillaart 4 | // PURPOSE: read analog inputs - straightforward. 5 | // URL: https://github.com/RobTillaart/ADS1X15 6 | 7 | // test 8 | // connect 1 potmeter per port. 9 | // 10 | // GND ---[ x ]------ 5V 11 | // | 12 | // 13 | // measure at x (connect to AIN0). 14 | 15 | 16 | #include "ADS1X15.h" 17 | 18 | ADS1115 ADS(0x48); 19 | 20 | 21 | void setup() 22 | { 23 | Serial.begin(115200); 24 | Serial.println(__FILE__); 25 | Serial.print("ADS1X15_LIB_VERSION: "); 26 | Serial.println(ADS1X15_LIB_VERSION); 27 | 28 | Wire.begin(); 29 | ADS.begin(); 30 | } 31 | 32 | 33 | void loop() 34 | { 35 | ADS.setGain(0); 36 | 37 | int16_t val_0 = ADS.readADC(0); 38 | int16_t val_1 = ADS.readADC(1); 39 | int16_t val_2 = ADS.readADC(2); 40 | int16_t val_3 = ADS.readADC(3); 41 | 42 | float f = ADS.toVoltage(1); // voltage factor 43 | 44 | Serial.print("\tAnalog0: "); Serial.print(val_0); Serial.print('\t'); Serial.println(val_0 * f, 3); 45 | Serial.print("\tAnalog1: "); Serial.print(val_1); Serial.print('\t'); Serial.println(val_1 * f, 3); 46 | Serial.print("\tAnalog2: "); Serial.print(val_2); Serial.print('\t'); Serial.println(val_2 * f, 3); 47 | Serial.print("\tAnalog3: "); Serial.print(val_3); Serial.print('\t'); Serial.println(val_3 * f, 3); 48 | Serial.println(); 49 | 50 | delay(1000); 51 | } 52 | 53 | 54 | // -- END OF FILE -- 55 | 56 | -------------------------------------------------------------------------------- /examples/ADS_read_RDY/ADS_read_RDY.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS_read_RDY.ino 3 | // AUTHOR: Rob.Tillaart 4 | // PURPOSE: read analog inputs - straightforward. 5 | // URL: https://github.com/RobTillaart/ADS1X15 6 | 7 | // test 8 | // connect 1 potentiometer per port. 9 | // 10 | // GND ---[ x ]------ 5V 11 | // | 12 | // 13 | // measure at x (connect to AIN0). 14 | // 15 | 16 | // EXPERIMENTAL 17 | // 18 | // The ALERT/RDY pin is triggered when threshold is exceeded. 19 | // 20 | 21 | 22 | #include "ADS1X15.h" 23 | 24 | ADS1115 ADS(0x48); 25 | 26 | 27 | void setup() 28 | { 29 | Serial.begin(115200); 30 | Serial.println(__FILE__); 31 | Serial.print("ADS1X15_LIB_VERSION: "); 32 | Serial.println(ADS1X15_LIB_VERSION); 33 | 34 | Wire.begin(); 35 | 36 | ADS.begin(); 37 | ADS.setGain(0); // 6.144 volt 38 | ADS.setDataRate(7); // 0 = slow 4 = medium 7 = fast 39 | ADS.setMode(1); // continuous mode 40 | ADS.readADC(0); // first read to trigger 41 | 42 | // set the thresholds to Trigger RDY pin 43 | ADS.setComparatorThresholdLow(0x0000); 44 | ADS.setComparatorThresholdHigh(0x0200); 45 | ADS.setComparatorQueConvert(0); // enable RDY pin !! 46 | ADS.setComparatorLatch(0); 47 | } 48 | 49 | 50 | void loop() 51 | { 52 | ADS.setGain(0); 53 | 54 | int16_t val_0 = ADS.readADC(0); 55 | 56 | float f = ADS.toVoltage(1); // voltage factor 57 | 58 | Serial.print("\tAnalog0: "); 59 | Serial.print(val_0); 60 | Serial.print('\t'); 61 | Serial.println(val_0 * f, 3); 62 | 63 | delay(1000); 64 | } 65 | 66 | 67 | // -- END OF FILE -- 68 | 69 | -------------------------------------------------------------------------------- /examples/ADS_read_async/ADS_read_async.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS_read_async.ino 3 | // AUTHOR: Rob.Tillaart 4 | // PURPOSE: read analog inputs - asynchronous 5 | // URL: https://github.com/RobTillaart/ADS1X15 6 | 7 | // test 8 | // connect 1 potmeter per port. 9 | // 10 | // GND ---[ x ]------ 5V 11 | // | 12 | // 13 | // measure at x (connect to AIN0). 14 | // 15 | 16 | 17 | #include "ADS1X15.h" 18 | 19 | ADS1115 ADS(0x48); 20 | float f = 0; 21 | int16_t val_0; 22 | 23 | uint32_t start, stop; 24 | 25 | 26 | void setup() 27 | { 28 | Serial.begin(115200); 29 | Serial.println(__FILE__); 30 | Serial.print("ADS1X15_LIB_VERSION: "); 31 | Serial.println(ADS1X15_LIB_VERSION); 32 | delay(100); 33 | 34 | Wire.begin(); 35 | Wire.setClock(100000); 36 | 37 | ADS.begin(); 38 | ADS.setGain(0); 39 | f = ADS.toVoltage(); // voltage factor 40 | 41 | start = micros(); 42 | ADS.requestADC(0); 43 | stop = micros(); 44 | Serial.println(stop - start); 45 | delay(100); 46 | while (ADS.isBusy()); 47 | start = micros(); 48 | val_0 = ADS.getValue(); 49 | stop = micros(); 50 | Serial.println(stop - start); 51 | delay(100); 52 | 53 | ADS.requestADC(0); 54 | } 55 | 56 | 57 | void loop() 58 | { 59 | if (ADS.isBusy() == false) 60 | { 61 | val_0 = ADS.getValue(); 62 | // request a new one 63 | ADS.requestADC(0); 64 | Serial.print("\tAnalog0: "); 65 | Serial.print(val_0); 66 | Serial.print('\t'); 67 | Serial.println(val_0 * f, 3); 68 | } 69 | // simulate other tasks... 70 | delay(2000); 71 | } 72 | 73 | 74 | // -- END OF FILE -- 75 | 76 | -------------------------------------------------------------------------------- /examples/ADS_read_async_rdy/ADS_read_async_rdy.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS_read_async_rdy.ino 3 | // AUTHOR: Rob.Tillaart 4 | // PURPOSE: read analog inputs - straightforward. 5 | // URL: https://github.com/RobTillaart/ADS1X15 6 | 7 | // test 8 | // connect 1 potmeter per port. 9 | // 10 | // GND ---[ x ]------ 5V 11 | // | 12 | // 13 | // measure at x (connect to AIN0). 14 | // 15 | 16 | // EXPERIMENTAL 17 | // 18 | // The ALERT/RDY pin is triggered when threshold is exceeded. 19 | // 20 | 21 | 22 | #include "ADS1X15.h" 23 | 24 | ADS1115 ADS(0x48); 25 | float factor = 0; 26 | 27 | 28 | void setup() 29 | { 30 | Serial.begin(115200); 31 | Serial.println(__FILE__); 32 | Serial.print("ADS1X15_LIB_VERSION: "); 33 | Serial.println(ADS1X15_LIB_VERSION); 34 | 35 | Wire.begin(); 36 | 37 | ADS.begin(); 38 | ADS.setGain(0); // 6.144 volt 39 | 40 | // select slow so the led blinks visible for the eye. 41 | ADS.setDataRate(0); // 0 = slow 4 = medium 7 = fast 42 | factor = ADS.toVoltage(); // voltage factor 43 | ADS.requestADC(0); 44 | 45 | // set the thresholds to trigger ALERT/RDY pin when exceeded. 46 | ADS.setComparatorThresholdLow(0x0000); 47 | ADS.setComparatorThresholdHigh(0x0200); 48 | ADS.setComparatorQueConvert(0); // enable RDY pin !! 49 | ADS.setComparatorLatch(0); 50 | } 51 | 52 | 53 | void loop() 54 | { 55 | if (ADS.isReady()) 56 | { 57 | // read the value. 58 | int16_t value0 = ADS.getValue(); 59 | // request a new one. 60 | ADS.requestADC(0); 61 | // process the read value. 62 | Serial.print("\tAnalog0: "); 63 | Serial.print(value0); 64 | Serial.print('\t'); 65 | Serial.println(value0 * factor, 3); 66 | } 67 | // simulate other tasks... 68 | delay(2000); 69 | } 70 | 71 | 72 | // -- END OF FILE -- 73 | 74 | -------------------------------------------------------------------------------- /examples/ADS_read_comparator_1/ADS_read_comparator_1.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS_read_comparator_1.ino 3 | // AUTHOR: Rob.Tillaart 4 | // PURPOSE: read analog inputs - straightforward. 5 | // URL: https://github.com/RobTillaart/ADS1X15 6 | 7 | // test 8 | // connect 1 potmeter per port. 9 | // 10 | // GND ---[ x ]------ 5V 11 | // | 12 | // 13 | // measure at x (connect to AIN0). 14 | // 15 | // 16 | // GND ---[LED]---[ALERT_PIN]---[ R ]--- 5V 17 | // 18 | // Connect a LED (+ resistor) to ALERT/RDY pin 19 | // and see it triggered by the comparator in the configured way. 20 | // 21 | 22 | 23 | #include "ADS1X15.h" 24 | 25 | ADS1115 ADS(0x48); 26 | 27 | 28 | void setup() 29 | { 30 | Serial.begin(115200); 31 | Serial.println(__FILE__); 32 | Serial.print("ADS1X15_LIB_VERSION: "); 33 | Serial.println(ADS1X15_LIB_VERSION); 34 | 35 | Wire.begin(); 36 | 37 | ADS.begin(); 38 | 39 | // change if needed. 40 | ADS.setComparatorMode(1); // 0 = TRADITIONAL 1 = WINDOW 41 | 42 | ADS.setComparatorPolarity(0); // 0 = LOW (default) 1 = HIGH 43 | 44 | // note NON-LATCH gives only a short pulse 45 | ADS.setComparatorLatch(1); // 0 = NON LATCH 1 = LATCH 46 | 47 | ADS.setComparatorQueConvert(0); // 0 = trigger alert after 1 conversion 48 | 49 | // set the thresholds as a number... 50 | // ADS.setComparatorThresholdLow(5000); // change if needed 51 | // ADS.setComparatorThresholdHigh(20000); // change if needed 52 | 53 | // set the threshold as a voltage by using the voltage factor. 54 | float factor = ADS.toVoltage(1); // voltage factor 55 | ADS.setComparatorThresholdLow(1.234 / factor); // convert volts to number needed 56 | ADS.setComparatorThresholdHigh(3.142 / factor); // convert volts to number needed 57 | 58 | Serial.println(ADS.getComparatorThresholdLow()); 59 | Serial.println(ADS.getComparatorThresholdHigh()); 60 | } 61 | 62 | 63 | void loop() 64 | { 65 | ADS.setGain(0); 66 | 67 | int16_t value0 = ADS.readADC(0); 68 | 69 | float factor = ADS.toVoltage(1); // voltage factor 70 | 71 | Serial.print("\tAnalog0: "); 72 | Serial.print(value0); 73 | Serial.print('\t'); 74 | Serial.print(value0 * factor, 3); 75 | Serial.print('\t'); 76 | Serial.print(ADS.getComparatorThresholdLow() * factor, 3); 77 | Serial.print('\t'); 78 | Serial.print(ADS.getComparatorThresholdHigh() * factor, 3); 79 | Serial.println(); 80 | 81 | delay(100); 82 | } 83 | 84 | 85 | // -- END OF FILE -- 86 | 87 | -------------------------------------------------------------------------------- /examples/ADS_read_getError/ADS_read_getError.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS_read_getError.ino 3 | // AUTHOR: Rob.Tillaart 4 | // PURPOSE: read analog inputs and check for error. 5 | // URL: https://github.com/RobTillaart/ADS1X15 6 | 7 | // test 8 | // connect 1 potmeter per port. 9 | // 10 | // GND ---[ x ]------ 5V 11 | // | 12 | // 13 | // measure at x (connect to AIN0). 14 | 15 | 16 | #include "ADS1X15.h" 17 | 18 | ADS1115 ADS(0x48); 19 | 20 | int16_t value[4]; 21 | int err = ADS1X15_OK; 22 | float voltageFactor = 1; 23 | 24 | void setup() 25 | { 26 | Serial.begin(115200); 27 | Serial.println(); 28 | Serial.println(__FILE__); 29 | Serial.print("ADS1X15_LIB_VERSION: "); 30 | Serial.println(ADS1X15_LIB_VERSION); 31 | Serial.println(); 32 | 33 | Wire.begin(); 34 | ADS.begin(); 35 | 36 | voltageFactor = ADS.toVoltage(1); 37 | } 38 | 39 | 40 | void loop() 41 | { 42 | ADS.setGain(0); 43 | 44 | float f = ADS.toVoltage(1); // voltage factor 45 | 46 | for (int channel = 0; channel < 4; channel++) 47 | { 48 | value[channel] = ADS.readADC(channel); 49 | err = ADS.getError(); 50 | if (err != ADS1X15_OK) 51 | { 52 | Serial.print(channel); 53 | Serial.print(" returns error: "); 54 | Serial.println(err); 55 | } 56 | 57 | Serial.print("\tChannel "); 58 | Serial.print(channel); 59 | Serial.print(": "); 60 | Serial.print(value[channel]); 61 | Serial.print('\t'); 62 | Serial.println(value[channel] * voltageFactor, 3); 63 | } 64 | 65 | // optional do other things with value[channel] 66 | 67 | delay(1000); 68 | } 69 | 70 | 71 | // -- END OF FILE -- 72 | -------------------------------------------------------------------------------- /examples/ADS_setWireClock/ADS_setWireClock.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS_setWireClock.ino 3 | // AUTHOR: Rob.Tillaart 4 | // PURPOSE: read analog inputs - straightforward. 5 | // URL: https://github.com/RobTillaart/ADS1X15 6 | 7 | // test 8 | // connect 1 potentiometer per port. 9 | // 10 | // GND ---[ x ]------ 5V 11 | // | 12 | // 13 | // measure at x (connect to AIN0). 14 | // 15 | 16 | 17 | #include "ADS1X15.h" 18 | 19 | ADS1115 ADS(0x48); 20 | 21 | 22 | void setup() 23 | { 24 | Serial.begin(115200); 25 | Serial.println(__FILE__); 26 | Serial.print("ADS1X15_LIB_VERSION: "); 27 | Serial.println(ADS1X15_LIB_VERSION); 28 | 29 | ADS.begin(); 30 | 31 | Serial.println(F("\nSET\tACTUAL\n==================")); 32 | for (uint32_t speed = 50000; speed <= 1000000; speed += 50000) 33 | { 34 | ADS.setWireClock(speed); 35 | Serial.print(speed); 36 | Serial.print("\t"); 37 | Serial.println(ADS.getWireClock()); 38 | } 39 | ADS.setWireClock(100000); 40 | Serial.println(); 41 | } 42 | 43 | 44 | void loop() 45 | { 46 | ADS.setGain(0); 47 | 48 | int16_t val_0 = ADS.readADC(0); 49 | int16_t val_1 = ADS.readADC(1); 50 | int16_t val_2 = ADS.readADC(2); 51 | int16_t val_3 = ADS.readADC(3); 52 | 53 | float f = ADS.toVoltage(1); // voltage factor 54 | 55 | Serial.print("\tAnalog0: "); Serial.print(val_0); Serial.print('\t'); Serial.println(val_0 * f, 3); 56 | Serial.print("\tAnalog1: "); Serial.print(val_1); Serial.print('\t'); Serial.println(val_1 * f, 3); 57 | Serial.print("\tAnalog2: "); Serial.print(val_2); Serial.print('\t'); Serial.println(val_2 * f, 3); 58 | Serial.print("\tAnalog3: "); Serial.print(val_3); Serial.print('\t'); Serial.println(val_3 * f, 3); 59 | Serial.println(); 60 | 61 | delay(1000); 62 | } 63 | 64 | 65 | // -- END OF FILE -- 66 | 67 | -------------------------------------------------------------------------------- /examples/ADS_test_config/ADS_test_config.ino: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: ADS_test_config.ino 3 | // AUTHOR: Rob.Tillaart 4 | // PURPOSE: test config flags 5 | // URL: https://github.com/RobTillaart/ADS1X15 6 | // triggered by issue 80 7 | 8 | 9 | #include "ADS1X15.h" 10 | 11 | ADS1115 ADS(0x48); 12 | 13 | void setup() 14 | { 15 | Serial.begin(115200); 16 | Serial.println(__FILE__); 17 | Serial.print("ADS1X15_LIB_VERSION: "); 18 | Serial.println(ADS1X15_LIB_VERSION); 19 | 20 | Wire.begin(); 21 | 22 | ADS.begin(); 23 | 24 | Serial.println("\nTEST GAIN"); 25 | int gain = 16; 26 | for (int i = 0; i < 6; i++) 27 | { 28 | Serial.print(gain); 29 | ADS.setGain(gain); 30 | if (ADS.getGain() == gain) Serial.println("\tOK"); 31 | else Serial.println("\tFAIL"); 32 | } 33 | 34 | Serial.println("\nTEST DATARATE"); 35 | for (int i = 0; i < 7; i++) 36 | { 37 | Serial.print(i); 38 | ADS.setDataRate(i); 39 | if (ADS.getDataRate() == i) Serial.println("\tOK"); 40 | else Serial.println("\tFAIL"); 41 | } 42 | 43 | Serial.println("\nTEST MODE"); 44 | for (int i = 0; i < 2; i++) 45 | { 46 | Serial.print(i); 47 | ADS.setMode(i); 48 | if (ADS.getMode() == i) Serial.println("\tOK"); 49 | else Serial.println("\tFAIL"); 50 | } 51 | 52 | Serial.println("\nTEST COMP MODE"); 53 | for (int i = 0; i < 2; i++) 54 | { 55 | Serial.print(i); 56 | ADS.setComparatorMode(i); 57 | if (ADS.getComparatorMode() == i) Serial.println("\tOK"); 58 | else Serial.println("\tFAIL"); 59 | } 60 | 61 | Serial.println("\nTEST COMP POLARITY"); 62 | for (int i = 0; i < 2; i++) 63 | { 64 | Serial.print(i); 65 | ADS.setComparatorPolarity(i); 66 | if (ADS.getComparatorPolarity() == i) Serial.println("\tOK"); 67 | else Serial.println("\tFAIL"); 68 | } 69 | 70 | Serial.println("\nTEST COMP LATCH"); 71 | for (int i = 0; i < 2; i++) 72 | { 73 | Serial.print(i); 74 | ADS.setComparatorLatch(i); 75 | if (ADS.getComparatorLatch() == i) Serial.println("\tOK"); 76 | else Serial.println("\tFAIL"); 77 | } 78 | 79 | Serial.println("\nTEST COMP QUECONVERT"); 80 | for (int i = 0; i < 2; i++) 81 | { 82 | Serial.print(i); 83 | ADS.setComparatorQueConvert(i); 84 | if (ADS.getComparatorQueConvert() == i) Serial.println("\tOK"); 85 | else Serial.println("\tFAIL"); 86 | } 87 | 88 | Serial.println("\ndone..."); 89 | } 90 | 91 | void loop() 92 | { 93 | } 94 | 95 | // -- END OF FILE -- 96 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | # Syntax Colouring Map For ADS1X15 2 | 3 | # Data types (KEYWORD1) 4 | ADS1X15 KEYWORD1 5 | ADS1013 KEYWORD1 6 | ADS1014 KEYWORD1 7 | ADS1015 KEYWORD1 8 | ADS1015 KEYWORD1 9 | ADS1113 KEYWORD1 10 | ADS1114 KEYWORD1 11 | ADS1115 KEYWORD1 12 | 13 | 14 | # Methods and Functions (KEYWORD2) 15 | begin KEYWORD2 16 | reset KEYWORD2 17 | isBusy KEYWORD2 18 | isReady() KEYWORD2 19 | isConnected KEYWORD2 20 | 21 | setGain KEYWORD2 22 | getGain KEYWORD2 23 | toVoltage KEYWORD2 24 | getMaxVoltage KEYWORD2 25 | setMode KEYWORD2 26 | getMode KEYWORD2 27 | setDataRate KEYWORD2 28 | getDataRate KEYWORD2 29 | 30 | readADC KEYWORD2 31 | readADC_Differential_0_1 KEYWORD2 32 | readADC_Differential_0_3 KEYWORD2 33 | readADC_Differential_1_3 KEYWORD2 34 | readADC_Differential_2_3 KEYWORD2 35 | getValue KEYWORD2 36 | 37 | getLastRequest KEYWORD2 38 | 39 | setComparatorMode KEYWORD2 40 | getComparatorMode KEYWORD2 41 | setComparatorPolarity KEYWORD2 42 | getComparatorPolarity KEYWORD2 43 | setComparatorLatch KEYWORD2 44 | getComparatorLatch KEYWORD2 45 | setComparatorQueConvert KEYWORD2 46 | getComparatorQueConvert KEYWORD2 47 | setComparatorThresholdLow KEYWORD2 48 | getComparatorThresholdLow KEYWORD2 49 | setComparatorThresholdHigh KEYWORD2 50 | getComparatorThresholdHigh KEYWORD2 51 | 52 | getError KEYWORD2 53 | setWireClock KEYWORD2 54 | getWireClock KEYWORD2 55 | 56 | # ASYNC INTERFACE 57 | 58 | requestADC KEYWORD2 59 | requestADC_Differential_0_1 KEYWORD2 60 | requestADC_Differential_0_3 KEYWORD2 61 | requestADC_Differential_1_3 KEYWORD2 62 | requestADC_Differential_2_3 KEYWORD2 63 | 64 | 65 | # Constants (LITERAL1) 66 | ADS1X15_LIB_VERSION LITERAL1 67 | 68 | ADS1X15_INVALID_VOLTAGE LITERAL1 69 | ADS1X15_INVALID_GAIN LITERAL1 70 | ADS1X15_INVALID_MODE LITERAL1 71 | 72 | ADS1015_ADDRESS LITERAL1 73 | ADS1115_ADDRESS LITERAL1 74 | 75 | ADS1X15_GAIN_6144MV LITERAL1 76 | ADS1X15_GAIN_4096MV LITERAL1 77 | ADS1X15_GAIN_2048MV LITERAL1 78 | ADS1X15_GAIN_1024MV LITERAL1 79 | ADS1X15_GAIN_0512MV LITERAL1 80 | ADS1X15_GAIN_0256MV LITERAL1 81 | 82 | ADS1x15_COMP_MODE_TRADITIONAL LITERAL1 83 | ADS1x15_COMP_MODE_WINDOW LITERAL1 84 | 85 | ADS1x15_COMP_POL_FALLING_EDGE LITERAL1 86 | ADS1x15_COMP_POL_RISING_EDGE LITERAL1 87 | 88 | 89 | # Error Codes 90 | 91 | ADS1X15_OK KEYWORD2 92 | ADS1X15_INVALID_VOLTAGE KEYWORD2 93 | ADS1X15_ERROR_TIMEOUT KEYWORD2 94 | ADS1X15_ERROR_I2C KEYWORD2 95 | ADS1X15_INVALID_GAIN KEYWORD2 96 | ADS1X15_INVALID_MODE KEYWORD2 97 | 98 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ADS1X15", 3 | "keywords": "ADS1013, ADS1014, ADS1015, ADS1113, ADS1114, ADS1115, I2C, ADC", 4 | "description": "Arduino library for ADS1015 - I2C 12 bit ADC and ADS1115 I2C 16 bit ADC", 5 | "authors": 6 | [ 7 | { 8 | "name": "Rob Tillaart", 9 | "email": "Rob.Tillaart@gmail.com", 10 | "maintainer": true 11 | } 12 | ], 13 | "repository": 14 | { 15 | "type": "git", 16 | "url": "https://github.com/RobTillaart/ADS1X15" 17 | }, 18 | "version": "0.5.2", 19 | "license": "MIT", 20 | "frameworks": "*", 21 | "platforms": "*", 22 | "headers": "ADS1X15.h" 23 | } 24 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=ADS1X15 2 | version=0.5.2 3 | author=Rob Tillaart 4 | maintainer=Rob Tillaart 5 | sentence=Arduino library for ADS1015 - I2C 12 bit ADC and ADS1115 I2C 16 bit ADC 6 | paragraph=Should work for ADS1013, ADS1014, ADS1113 and ADS1114 7 | category=Sensors 8 | url=https://github.com/RobTillaart/ADS1X15 9 | architectures=* 10 | includes=ADS1X15.h 11 | depends= 12 | -------------------------------------------------------------------------------- /test/unit_test_001.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // FILE: unit_test_001.cpp 3 | // AUTHOR: Rob Tillaart 4 | // DATE: 2020-12-03 5 | // PURPOSE: unit tests for the SHT31 temperature and humidity sensor 6 | // https://github.com/RobTillaart/ADS1X15 7 | // 8 | 9 | // supported assertions 10 | // ---------------------------- 11 | // assertEqual(expected, actual) 12 | // assertNotEqual(expected, actual) 13 | // assertLess(expected, actual) 14 | // assertMore(expected, actual) 15 | // assertLessOrEqual(expected, actual) 16 | // assertMoreOrEqual(expected, actual) 17 | // assertTrue(actual) 18 | // assertFalse(actual) 19 | // assertNull(actual) 20 | 21 | #include 22 | 23 | #include "Arduino.h" 24 | #include "ADS1X15.h" 25 | 26 | 27 | unittest_setup() 28 | { 29 | fprintf(stderr, "ADS1X15_LIB_VERSION: %s\n", (char *) ADS1X15_LIB_VERSION); 30 | } 31 | 32 | 33 | unittest_teardown() 34 | { 35 | } 36 | 37 | 38 | unittest(test_constants_I) 39 | { 40 | assertEqual(0x48, ADS1015_ADDRESS); 41 | assertEqual(0x48, ADS1115_ADDRESS); 42 | 43 | assertEqual( 0, ADS1X15_OK); 44 | assertEqual(-100, ADS1X15_INVALID_VOLTAGE); 45 | assertEqual(-101, ADS1X15_ERROR_TIMEOUT); 46 | assertEqual(-102, ADS1X15_ERROR_I2C); 47 | assertEqual(0xFF, ADS1X15_INVALID_GAIN); 48 | assertEqual(0xFE, ADS1X15_INVALID_MODE); 49 | } 50 | 51 | 52 | unittest(test_begin) 53 | { 54 | ADS1115 ADS(0x48); 55 | 56 | Wire.begin(); 57 | 58 | assertTrue(ADS.begin()); 59 | assertTrue(ADS.isConnected()); 60 | assertTrue(ADS.isBusy()); 61 | } 62 | 63 | 64 | unittest(test_gain) 65 | { 66 | ADS1115 ADS(0x48); 67 | 68 | Wire.begin(); 69 | 70 | assertTrue(ADS.begin()); 71 | 72 | assertEqual(0, ADS.getGain()); 73 | int gains[6] = { 0,1,2,4,8,16 }; 74 | for (int i = 0; i < 6; i++) 75 | { 76 | ADS.setGain(gains[i]); 77 | assertEqual(gains[i], ADS.getGain()); 78 | } 79 | 80 | ADS.setGain(42); 81 | assertEqual(0, ADS.getGain()); 82 | } 83 | 84 | 85 | // For issue #68, #2 86 | unittest(test_gain_ADS1113) 87 | { 88 | ADS1113 ADS(0x48); 89 | 90 | Wire.begin(); 91 | 92 | assertTrue(ADS.begin()); 93 | 94 | assertEqual(2, ADS.getGain()); 95 | int gains[6] = { 0,1,2,4,8,16 }; 96 | for (int i = 0; i < 6; i++) 97 | { 98 | ADS.setGain(gains[i]); 99 | assertEqual(2, ADS.getGain()); 100 | assertEqualFloat(2.048, ADS.getMaxVoltage(), 0.001); 101 | } 102 | 103 | ADS.setGain(42); 104 | assertEqual(2, ADS.getGain()); 105 | assertEqualFloat(2.048, ADS.getMaxVoltage(), 0.001); 106 | } 107 | 108 | 109 | unittest(test_voltage) 110 | { 111 | ADS1115 ADS(0x48); 112 | 113 | Wire.begin(); 114 | 115 | assertTrue(ADS.begin()); 116 | 117 | // should test all values? 118 | ADS.setGain(0); 119 | float volts = ADS.getMaxVoltage(); 120 | float delta = abs(6.144 - volts); 121 | assertMoreOrEqual(0.001, delta); 122 | 123 | ADS.setGain(1); 124 | volts = ADS.getMaxVoltage(); 125 | delta = abs(4.096 - volts); 126 | assertMoreOrEqual(0.001, delta); 127 | 128 | ADS.setGain(2); 129 | volts = ADS.getMaxVoltage(); 130 | delta = abs(2.048 - volts); 131 | assertMoreOrEqual(0.001, delta); 132 | 133 | ADS.setGain(4); 134 | volts = ADS.getMaxVoltage(); 135 | delta = abs(1.024 - volts); 136 | assertMoreOrEqual(0.001, delta); 137 | 138 | ADS.setGain(8); 139 | volts = ADS.getMaxVoltage(); 140 | delta = abs(0.512 - volts); 141 | assertMoreOrEqual(0.001, delta); 142 | 143 | ADS.setGain(16); 144 | volts = ADS.getMaxVoltage(); 145 | delta = abs(0.256 - volts); 146 | assertMoreOrEqual(0.001, delta); 147 | } 148 | 149 | 150 | unittest(test_mode) 151 | { 152 | ADS1115 ADS(0x48); 153 | 154 | Wire.begin(); 155 | assertTrue(ADS.begin()); 156 | 157 | // test default 158 | assertEqual(1, ADS.getMode()); 159 | // test valid values 160 | ADS.setMode(0); 161 | assertEqual(0, ADS.getMode()); 162 | ADS.setMode(1); 163 | assertEqual(1, ADS.getMode()); 164 | // test out of range 165 | ADS.setMode(2); 166 | assertEqual(1, ADS.getMode()); 167 | } 168 | 169 | 170 | unittest(test_datarate) 171 | { 172 | ADS1115 ADS(0x48); 173 | 174 | Wire.begin(); 175 | assertTrue(ADS.begin()); 176 | 177 | // test default 178 | assertEqual(4, ADS.getDataRate()); 179 | // test valid values 180 | for (int i = 0; i < 8; i++) 181 | { 182 | ADS.setDataRate(i); 183 | assertEqual(i, ADS.getDataRate()); 184 | } 185 | // test out of range 186 | ADS.setDataRate(8); 187 | assertEqual(4, ADS.getDataRate()); 188 | } 189 | 190 | 191 | unittest(test_comparator_mode) 192 | { 193 | ADS1115 ADS(0x48); 194 | 195 | Wire.begin(); 196 | assertTrue(ADS.begin()); 197 | 198 | // test default 199 | assertEqual(0, ADS.getComparatorMode()); 200 | // test valid values 201 | ADS.setComparatorMode(0); 202 | assertEqual(0, ADS.getComparatorMode()); 203 | ADS.setComparatorMode(1); 204 | assertEqual(1, ADS.getComparatorMode()); 205 | // test out of range 206 | ADS.setComparatorMode(2); 207 | assertEqual(1, ADS.getComparatorMode()); 208 | } 209 | 210 | 211 | unittest(test_comparator_polarity) 212 | { 213 | ADS1115 ADS(0x48); 214 | 215 | Wire.begin(); 216 | assertTrue(ADS.begin()); 217 | 218 | // test default 219 | assertEqual(1, ADS.getComparatorPolarity()); 220 | // test valid values 221 | ADS.setComparatorPolarity(0); 222 | assertEqual(0, ADS.getComparatorPolarity()); 223 | ADS.setComparatorPolarity(1); 224 | assertEqual(1, ADS.getComparatorPolarity()); 225 | // test out of range 226 | ADS.setComparatorPolarity(2); 227 | assertEqual(1, ADS.getComparatorPolarity()); 228 | } 229 | 230 | 231 | unittest(test_comparator_latch) 232 | { 233 | ADS1115 ADS(0x48); 234 | 235 | Wire.begin(); 236 | assertTrue(ADS.begin()); 237 | 238 | // test default 239 | assertEqual(0, ADS.getComparatorLatch()); 240 | // test valid values 241 | ADS.setComparatorLatch(0); 242 | assertEqual(0, ADS.getComparatorLatch()); 243 | ADS.setComparatorLatch(1); 244 | assertEqual(1, ADS.getComparatorLatch()); 245 | // test out of range 246 | ADS.setComparatorLatch(2); 247 | assertEqual(1, ADS.getComparatorLatch()); 248 | } 249 | 250 | 251 | unittest(test_comparator_que_convert) 252 | { 253 | ADS1115 ADS(0x48); 254 | 255 | Wire.begin(); 256 | assertTrue(ADS.begin()); 257 | 258 | // test default 259 | assertEqual(3, ADS.getComparatorQueConvert()); 260 | // test valid values 261 | for (int i = 0; i < 4; i++) 262 | { 263 | ADS.setComparatorQueConvert(i); 264 | assertEqual(i, ADS.getComparatorQueConvert()); 265 | } 266 | // test out of range 267 | ADS.setComparatorQueConvert(4); 268 | assertEqual(3, ADS.getComparatorQueConvert()); 269 | } 270 | 271 | 272 | 273 | unittest_main() 274 | 275 | 276 | // -- END OF FILE -- 277 | 278 | --------------------------------------------------------------------------------