From 668c7ce8cfa3591a036eaf1585805079c6410b7f Mon Sep 17 00:00:00 2001 From: Rob Tillaart Date: Sun, 30 Jun 2024 08:22:55 +0200 Subject: [PATCH] 0.4.4 ADS1x15 --- libraries/ADS1x15/ADS1X15.cpp | 20 ++-- libraries/ADS1x15/ADS1X15.h | 26 ++++- libraries/ADS1x15/CHANGELOG.md | 5 + libraries/ADS1x15/README.md | 102 +++++++++++++----- .../examples/ADS_COMP_POL/ADS_COMP_POL.ino | 61 +++++++++++ .../ADS_performance/ADS_performance.ino | 5 +- .../ADS_performance/performance_0.4.4.md | 50 +++++++++ libraries/ADS1x15/keywords.txt | 14 +++ libraries/ADS1x15/library.json | 2 +- libraries/ADS1x15/library.properties | 2 +- 10 files changed, 242 insertions(+), 45 deletions(-) create mode 100644 libraries/ADS1x15/examples/ADS_COMP_POL/ADS_COMP_POL.ino create mode 100644 libraries/ADS1x15/examples/ADS_performance/performance_0.4.4.md diff --git a/libraries/ADS1x15/ADS1X15.cpp b/libraries/ADS1x15/ADS1X15.cpp index 04f9c722..80bd93e4 100644 --- a/libraries/ADS1x15/ADS1X15.cpp +++ b/libraries/ADS1x15/ADS1X15.cpp @@ -1,7 +1,7 @@ // // FILE: ADS1X15.cpp // AUTHOR: Rob Tillaart -// VERSION: 0.4.3 +// VERSION: 0.4.4 // DATE: 2013-03-24 // PURPOSE: Arduino library for ADS1015 and ADS1115 // URL: https://github.com/RobTillaart/ADS1X15 @@ -24,7 +24,7 @@ // CONFIG REGISTER -// BIT 15 Operational Status // 1 << 15 +// BIT 15 Operational Status // 1 << 15 #define ADS1X15_OS_BUSY 0x0000 #define ADS1X15_OS_NOT_BUSY 0x8000 #define ADS1X15_OS_START_SINGLE 0x8000 @@ -53,7 +53,7 @@ #define ADS1X15_MODE_CONTINUE 0x0000 #define ADS1X15_MODE_SINGLE 0x0100 -// BIT 5-7 data rate sample per second // (0..7) << 5 +// BIT 5-7 data rate sample per second // (0..7) << 5 /* differs for different devices, check datasheet or readme.md @@ -69,26 +69,26 @@ differs for different devices, check datasheet or readme.md | 7 | 3300 | 860 | fastest | */ -// BIT 4 comparator modi // 1 << 4 +// BIT 4 comparator modi // 1 << 4 #define ADS1X15_COMP_MODE_TRADITIONAL 0x0000 #define ADS1X15_COMP_MODE_WINDOW 0x0010 -// BIT 3 ALERT active value // 1 << 3 +// BIT 3 ALERT active value // 1 << 3 #define ADS1X15_COMP_POL_ACTIV_LOW 0x0000 #define ADS1X15_COMP_POL_ACTIV_HIGH 0x0008 -// BIT 2 ALERT latching // 1 << 2 +// BIT 2 ALERT latching // 1 << 2 #define ADS1X15_COMP_NON_LATCH 0x0000 #define ADS1X15_COMP_LATCH 0x0004 -// BIT 0-1 ALERT mode // (0..3) +// BIT 0-1 ALERT mode // (0..3) #define ADS1X15_COMP_QUE_1_CONV 0x0000 // trigger alert after 1 convert #define ADS1X15_COMP_QUE_2_CONV 0x0001 // trigger alert after 2 converts #define ADS1X15_COMP_QUE_4_CONV 0x0002 // trigger alert after 4 converts #define ADS1X15_COMP_QUE_NONE 0x0003 // disable comparator -// _CONFIG masks +// _CONFIG masks // // | bit | description | // |:-----:|:-----------------------| @@ -131,7 +131,7 @@ void ADS1X15::reset() setMode(1); // _mode = ADS1X15_MODE_SINGLE; setDataRate(4); // middle speed, depends on device. - // COMPARATOR variables # see notes .h + // COMPARATOR variables # see notes .h _compMode = 0; _compPol = 1; _compLatch = 0; @@ -423,7 +423,7 @@ void ADS1X15::setWireClock(uint32_t clockSpeed) // TODO: get the real clock speed from the I2C interface if possible. uint32_t ADS1X15::getWireClock() { -// UNO 328 and +// UNO 328 and #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) uint32_t speed = F_CPU / ((TWBR * 2) + 16); return speed; diff --git a/libraries/ADS1x15/ADS1X15.h b/libraries/ADS1x15/ADS1X15.h index 74beb775..cd59af99 100644 --- a/libraries/ADS1x15/ADS1X15.h +++ b/libraries/ADS1x15/ADS1X15.h @@ -2,7 +2,7 @@ // // FILE: ADS1X15.h // AUTHOR: Rob Tillaart -// VERSION: 0.4.3 +// VERSION: 0.4.4 // DATE: 2013-03-24 // PURPOSE: Arduino library for ADS1015 and ADS1115 // URL: https://github.com/RobTillaart/ADS1X15 @@ -12,7 +12,7 @@ #include "Arduino.h" #include "Wire.h" -#define ADS1X15_LIB_VERSION (F("0.4.3")) +#define ADS1X15_LIB_VERSION (F("0.4.4")) // allow compile time default address // address in { 0x48, 0x49, 0x4A, 0x4B }, no test... @@ -31,6 +31,26 @@ #define ADS1X15_INVALID_MODE 0xFE +// PARAMETER CONSTANTS NOT USED IN CODE YET +// enum ? +#define ADS1X15_GAIN_6144MV 0x00 +#define ADS1X15_GAIN_4096MV 0x01 +#define ADS1X15_GAIN_2048MV 0x02 +#define ADS1X15_GAIN_1024MV 0x04 +#define ADS1X15_GAIN_0512MV 0x08 +#define ADS1X15_GAIN_0256MV 0x10 + +#define ADS1x15_COMP_MODE_TRADITIONAL 0x00 +#define ADS1x15_COMP_MODE_WINDOW 0x01 + +#define ADS1x15_COMP_POL_FALLING_EDGE 0x00 +#define ADS1x15_COMP_POL_RISING_EDGE 0x01 + +#define ADS1x15_COMP_POL_LATCH 0x00 +#define ADS1x15_COMP_POL_NOLATCH 0x01 + + + class ADS1X15 { public: @@ -56,7 +76,7 @@ public: // 0 = CONTINUOUS - // 1 = SINGLE default + // 1 = SINGLE default void setMode(uint8_t mode = 1); // invalid values are mapped to 1 (default) uint8_t getMode(); // 0xFE == invalid mode error. diff --git a/libraries/ADS1x15/CHANGELOG.md b/libraries/ADS1x15/CHANGELOG.md index 57e9047f..b983992e 100644 --- a/libraries/ADS1x15/CHANGELOG.md +++ b/libraries/ADS1x15/CHANGELOG.md @@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.4.4] - 2024-06-28 +- Fix #76, update readme.md Comparator Polarity +- added defines to replace magic numbers (not used in code yet) +- minor edits + ## [0.4.3] - 2024-06-25 - Fix #74, ALERT/RDY pin documentation - update readme.md diff --git a/libraries/ADS1x15/README.md b/libraries/ADS1x15/README.md index 56c1f44f..af9272fd 100644 --- a/libraries/ADS1x15/README.md +++ b/libraries/ADS1x15/README.md @@ -37,7 +37,7 @@ interesting from functionality point of view as these can do differential measurements. -#### Interrupts +### Interrupts Besides polling the ADS1x14 and ADS1x15 support interrupts to maximize throughput with minimal latency. For this these device has an ALERT/RDY pin. @@ -55,7 +55,7 @@ This pin can be used both for interrupts or polling, see table of examples below | ADS_read_RDY.ino | polling | -#### 0.4.0 Breaking change +### 0.4.0 Breaking change Version 0.4.0 introduced a breaking change. You cannot set the pins in **begin()** any more. @@ -64,7 +64,7 @@ The user has to call **Wire.begin()** and can optionally set the I2C pins before calling **begin()**. -#### Related +### Related - https://github.com/RobTillaart/ADC081S 10-12 bit, single channel ADC - https://github.com/RobTillaart/ADC08XS 10-12 bit, 2 + 4 channel ADC @@ -87,7 +87,7 @@ the **ADDR** is connected to: | SCL | 0x4B | | -#### I2C multiplexing +### I2C multiplexing Sometimes you need to control more devices than possible with the default address range the device provides. @@ -111,7 +111,7 @@ too if they are behind the multiplexer. #include "ADS1X15.h" ``` -#### Initializing +### Initializing To initialize the library you must call a constructor as described below. @@ -159,7 +159,7 @@ For example. ``` -#### I2C clock speed +### I2C clock speed The function **void setWireClock(uint32_t speed = 100000)** is used to set the clock speed in Hz of the used I2C interface. Typical value is 100 KHz. @@ -176,7 +176,7 @@ See - https://github.com/arduino/Arduino/issues/11457 Question: Should this functionality be in this library? -#### Programmable Gain +### Programmable Gain - **void setGain(uint8_t gain)** set the gain value, indicating the maxVoltage that can be measured Adjusting the gain allowing to make more precise measurements. @@ -210,7 +210,7 @@ Check the [examples](https://github.com/RobTillaart/ADS1X15/blob/master/examples ``` -#### Operational mode +### Operational mode The ADS sensor can operate in single shot or continuous mode. Depending on how often conversions needed you can tune the mode. @@ -220,7 +220,7 @@ Note: the mode is not set in the device until an explicit read/request of the AD - **uint8_t getMode()** returns current mode 0 or 1, or ADS1X15_INVALID_MODE = 0xFE. -#### Data rate +### Data rate - **void setDataRate(uint8_t dataRate)** Data rate depends on type of device. For all devices the index 0..7 can be used, see table below. @@ -245,7 +245,7 @@ Data rate in samples per second, based on datasheet is described on table below. | 7 | 3300 | 860 | fastest | -#### ReadADC Single mode +### ReadADC Single mode Reading the ADC is very straightforward, the **readADC()** function handles all in one call. Under the hood it uses the asynchronous calls. @@ -297,7 +297,7 @@ in terms of code: See [examples](https://github.com/RobTillaart/ADS1X15/blob/master/examples/ADS_read_async/ADS_read_async.ino). -#### ReadADC Differential +### ReadADC Differential For reading the ADC in a differential way there are 4 calls possible. @@ -326,7 +326,7 @@ After one of these calls you need to call See [examples](https://github.com/RobTillaart/ADS1X15/blob/master/examples/ADS_differential/ADS_differential.ino). -#### lastRequestMode +### lastRequestMode Since 0.3.12 the library tracks the last request mode, single pin or differential. This variable is set at the moment of request, and keeps its value until a new @@ -358,7 +358,7 @@ As these are emulated in software by two single pin calls, the state would be one of the two single pin values. -#### ReadADC continuous mode +### ReadADC continuous mode To use the continuous mode you need call three functions: @@ -394,7 +394,7 @@ Instead you can configure the threshold registers to allow the **ALERT/RDY** pin to trigger an interrupt signal when conversion data ready. -#### Switching mode or channel during continuous mode +### Switching mode or channel during continuous mode When switching the operating mode or the ADC channel in continuous mode, be aware that the device will always finish the running conversion. @@ -415,7 +415,7 @@ This explicit stop takes extra time, however it should prevent "incorrect" readi (need to be verified with different models) -#### Threshold registers +### Threshold registers (datasheet 9.3.8) _Conversion Ready Pin (ADS1114 and ADS1115 Only) @@ -435,7 +435,7 @@ the **ALERT/RDY** pin is triggered when a conversion is ready. See [examples](https://github.com/RobTillaart/ADS1X15/blob/master/examples/ADS_read_RDY/ADS_read_RDY.ino). -#### Comparator +### Comparator Please read Page 15 of the datasheet as the behaviour of the comparator is not trivial. @@ -444,7 +444,7 @@ NOTE: all comparator settings are copied to the device only after calling **readADC()** or **requestADC()** functions. -#### Comparator Mode +### Comparator Mode When configured as a **TRADITIONAL** comparator, the **ALERT/RDY** pin asserts (active low by default) when conversion data exceed the limit set in the @@ -465,16 +465,61 @@ the high threshold register or falls below the low threshold register. In this mode the alert is held if the **LATCH** is set. This is similar as above. -#### Polarity +### Polarity -Default state of the **ALERT/RDY** pin is **LOW**, can be to set **HIGH**. +Default state of the **ALERT/RDY** pin is **LOW**, which can be to set **HIGH**. - **void setComparatorPolarity(uint8_t pol)** Flag is only explicitly set after a **readADC()** or a **requestADC()** - **uint8_t getComparatorPolarity()** returns value set. -#### Latch +From tests (#76) it became clear that the behaviour of the **ALERT/RDY** pin is a bit ambiguous. +The meaning of HIGH LOW is different for **continuous** and **single** mode, see +the table below. Also different is the timing of the pulse at the **ALERT/RDY** pin. +See **ADS_COMP_POL.ino**. + +Timing of pulse from a synchronous ```ADS.readADC(0)``` call. + +| TEST | MODE | COMP_POL | ALERT/RDY PIN | Notes | +|:----:|:-----------------|:-----------|:------------------------------|:--------| +| 1 | 0 = continuous | 0 = LOW | LOW with 8 us HIGH pulse | as specified in datasheet +| 2 | 0 = continuous | 1 = HIGH | HIGH with 8 us LOW pulse | as specified in datasheet +| 3 | 1 = single | 0 = LOW | HIGH with an 8 ms LOW pulse | depends on data rate +| 4 | 1 = single | 1 = HIGH | LOW with an 8 ms HIGH pulse | depends on data rate + +See issue #76 for some screenshots. + + +#### Effect Data Rate + +| data rate | pulse length | Notes | +|:-----------:|:--------------:|:-------:| +| 0 | 125 ms | +| 1 | 62 ms | +| 2 | 32 ms | +| 3 | 16 ms | +| 4 | 8 ms | default, see in table above. +| 5 | 4.4 ms | +| 6 | 2.4 ms | +| 7 | 1.2 ms | + +Times are estimates from scope. + + +#### Conclusions + +- Conversion always generates a pulse. +- The length of the pulse in continuous mode and in single mode differs. + - In single shot mode the length of the pulse indicates the conversion time. + - In continuous mode the pulse indicates the end of conversion. +- The polarity in single mode seems to have an inverted pulse, however it is + not about the pulse, it is about the edge. +- If COMP_POL = 0, a FALLING edge indicates conversion ready. +- If COMP_POL = 1, a RISING edge indicates conversion ready. + + +### Latch Holds the **ALERT/RDY** to **HIGH** (or **LOW** depending on polarity) after triggered even if actual value has been 'restored to normal' value. @@ -482,8 +527,10 @@ even if actual value has been 'restored to normal' value. - **void setComparatorLatch(uint8_t latch)** 0 = NO LATCH, not 0 = LATCH - **uint8_t getComparatorLatch()** returns value set. +The (no-)latch is not verified in detail yet. -#### QueConvert + +### QueConvert Set the number of conversions before trigger activates. @@ -510,7 +557,7 @@ and the MSB of the Lo_threshold register to 0. See section **Threshold registers** above. -#### Threshold registers comparator mode +### Threshold registers comparator mode Depending on the comparator mode **TRADITIONAL** or **WINDOW** the thresholds registers mean something different see - Comparator Mode above or datasheet. @@ -530,21 +577,20 @@ mean something different see - Comparator Mode above or datasheet. #### Should -- remove the experimental **getWireClock()** as this is not really a library function +- Remove the experimental **getWireClock()** as this is not really a library function but a responsibility of the I2C library. -- investigate ADS1118 library which should be a similar SPI based ADC. +- Investigate ADS1118 library which should be a similar SPI based ADC. #### Could -- some **void** functions could return **bool** to be more informative? - More examples - SMB alert command (00011001) on I2C bus? -- sync order .h / .cpp +- Sync code order .h / .cpp #### Wont (unless requested) -- type flag? -- constructor for ADS1X15? No as all types are supported. +- Type flag? +- Constructor for ADS1X15? No as all types are supported. ## Support diff --git a/libraries/ADS1x15/examples/ADS_COMP_POL/ADS_COMP_POL.ino b/libraries/ADS1x15/examples/ADS_COMP_POL/ADS_COMP_POL.ino new file mode 100644 index 00000000..d21d7a94 --- /dev/null +++ b/libraries/ADS1x15/examples/ADS_COMP_POL/ADS_COMP_POL.ino @@ -0,0 +1,61 @@ +// +// FILE: ADS_COMP_POL.ino +// AUTHOR: Rob.Tillaart +// PURPOSE: read analog input +// URL: https://github.com/RobTillaart/ADS1X15/issues/76 + +#include "ADS1X15.h" + +// choose your sensor +// ADS1013 ADS(0x48); +// ADS1014 ADS(0x48); +// ADS1015 ADS(0x48); +// ADS1113 ADS(0x48); +// ADS1114 ADS(0x48); + +ADS1115 ADS(0x48); + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("ADS1X15_LIB_VERSION: "); + Serial.println(ADS1X15_LIB_VERSION); + + Wire.begin(); + + ADS.begin(); + ADS.setGain(0); // 6.144 volt + ADS.setDataRate(4); // 0..7 + + // test polarity + // data rate 4 (default) + // MODE COMP_POL ALERT/RDY PIN + // 0 = continuous 0 = LOW LOW with 8 us HIGH PULSE + // 0 = continuous 1 = HIGH HIGH with 8 us LOW pulse + // 1 = single 0 = LOW HIGH with 8 ms LOW pulse + // 1 = single 1 = HIGH LOW with 8 ms HIGH pulse + ADS.setMode(1); + ADS.setComparatorPolarity(1); + // enable ALERT/RDY pin + ADS.setComparatorThresholdHigh(0x8000); + ADS.setComparatorThresholdLow(0x0000); + ADS.setComparatorQueConvert(0); + // activate settings + ADS.requestADC(0); + + Serial.println("Voltage"); + delay(1000); +} + +void loop() +{ + // comment all in loop() to get a single pulse + int16_t raw = ADS.readADC(0); + delay(1000); + + Serial.println(ADS.toVoltage(raw), 3); + delay(1000); +} + +// -- END OF FILE -- diff --git a/libraries/ADS1x15/examples/ADS_performance/ADS_performance.ino b/libraries/ADS1x15/examples/ADS_performance/ADS_performance.ino index 2e6e1816..13eca19b 100644 --- a/libraries/ADS1x15/examples/ADS_performance/ADS_performance.ino +++ b/libraries/ADS1x15/examples/ADS_performance/ADS_performance.ino @@ -4,6 +4,8 @@ // PURPOSE: read analog input // URL: https://github.com/RobTillaart/ADS1X15 +// TODO verify output + // test // connect 1 potmeter // @@ -39,7 +41,7 @@ void setup() Serial.println(ADS1X15_LIB_VERSION); Wire.begin(); - Wire.setClock(100000); + Wire.setClock(600000); ADS.begin(); ADS.setGain(0); // 6.144 volt @@ -108,4 +110,3 @@ void test_continuous() // -- END OF FILE -- - diff --git a/libraries/ADS1x15/examples/ADS_performance/performance_0.4.4.md b/libraries/ADS1x15/examples/ADS_performance/performance_0.4.4.md new file mode 100644 index 00000000..96294141 --- /dev/null +++ b/libraries/ADS1x15/examples/ADS_performance/performance_0.4.4.md @@ -0,0 +1,50 @@ +Based upon output of **ADS_performance.ino** (indicative). +UNO 16 MHz. +IDE 1.8.19 + +ADS1X15_LIB_VERSION: 0.4.4 + +Synchronous calls I2C **100 KHz** + +| DataRate | Time 100 calls | SPS | +|:----------:|:----------------:|:------:| +| 0 | 12931840 | 7.73 | +| 1 | 6481444 | 15.4 | +| 2 | 3347556 | 29.9 | +| 3 | 1724492 | 58.0 | +| 4 | 940984 | 106 | +| 5 | 549268 | 182 | +| 6 | 381328 | 262 | +| 7 | 269400 | 371 | + + +Synchronous calls I2C **400 KHz** + +| DataRate | Time 100 calls | SPS | +|:----------:|:----------------:|:------:| +| 0 | 12824560 | 7.80 | +| 1 | 6377516 | 15.7 | +| 2 | 3224972 | 31.0 | +| 3 | 1649100 | 60.6 | +| 4 | 862148 | 116 | +| 5 | 468488 | 213 | +| 6 | 271568 | 368 | +| 7 | 173424 | 577 | + + +Synchronous calls I2C **600 KHz** + +| DataRate | Time 100 calls | SPS | +|:----------:|:----------------:|:------:| +| 0 | 12816404 | 7.80 | +| 1 | 6374432 | 15.7 | +| 2 | 3216720 | 31.1 | +| 3 | 1630428 | 61.3 | +| 4 | 852332 | 117 | +| 5 | 448396 | 223 | +| 6 | 261288 | 383 | +| 7 | 165688 | 603 | + +These are maxima of the SPS feasible, they do not include further processing. +At least this test shows the effect of the I2C bus speed. + diff --git a/libraries/ADS1x15/keywords.txt b/libraries/ADS1x15/keywords.txt index 570007ab..6880492e 100644 --- a/libraries/ADS1x15/keywords.txt +++ b/libraries/ADS1x15/keywords.txt @@ -68,6 +68,20 @@ ADS1X15_LIB_VERSION LITERAL1 ADS1X15_INVALID_VOLTAGE LITERAL1 ADS1X15_INVALID_GAIN LITERAL1 ADS1X15_INVALID_MODE LITERAL1 + ADS1015_ADDRESS LITERAL1 ADS1115_ADDRESS LITERAL1 +ADS1X15_GAIN_6144MV LITERAL1 +ADS1X15_GAIN_4096MV LITERAL1 +ADS1X15_GAIN_2048MV LITERAL1 +ADS1X15_GAIN_1024MV LITERAL1 +ADS1X15_GAIN_0512MV LITERAL1 +ADS1X15_GAIN_0256MV LITERAL1 + +ADS1x15_COMP_MODE_TRADITIONAL LITERAL1 +ADS1x15_COMP_MODE_WINDOW LITERAL1 + +ADS1x15_COMP_POL_FALLING_EDGE LITERAL1 +ADS1x15_COMP_POL_RISING_EDGE LITERAL1 + diff --git a/libraries/ADS1x15/library.json b/libraries/ADS1x15/library.json index 41d1b324..0c7bbe29 100644 --- a/libraries/ADS1x15/library.json +++ b/libraries/ADS1x15/library.json @@ -15,7 +15,7 @@ "type": "git", "url": "https://github.com/RobTillaart/ADS1X15" }, - "version": "0.4.3", + "version": "0.4.4", "license": "MIT", "frameworks": "*", "platforms": "*", diff --git a/libraries/ADS1x15/library.properties b/libraries/ADS1x15/library.properties index c04cec10..36328cd5 100644 --- a/libraries/ADS1x15/library.properties +++ b/libraries/ADS1x15/library.properties @@ -1,5 +1,5 @@ name=ADS1X15 -version=0.4.3 +version=0.4.4 author=Rob Tillaart maintainer=Rob Tillaart sentence=Arduino library for ADS1015 - I2C 12 bit ADC and ADS1115 I2C 16 bit ADC