0.4.5 ADS1X15

This commit is contained in:
Rob Tillaart 2024-07-04 13:09:59 +02:00
parent 1fd76995da
commit d0056c7e5f
6 changed files with 111 additions and 46 deletions

View File

@ -1,7 +1,7 @@
//
// FILE: ADS1X15.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.4.4
// VERSION: 0.4.5
// DATE: 2013-03-24
// PURPOSE: Arduino library for ADS1015 and ADS1115
// URL: https://github.com/RobTillaart/ADS1X15
@ -183,8 +183,8 @@ uint8_t ADS1X15::getGain()
case ADS1X15_PGA_0_512V: return 8;
case ADS1X15_PGA_0_256V: return 16;
}
_err = ADS1X15_INVALID_GAIN;
return _err;
_error = ADS1X15_INVALID_GAIN;
return _error;
}
@ -219,8 +219,8 @@ float ADS1X15::getMaxVoltage()
case ADS1X15_PGA_0_512V: return 0.512;
case ADS1X15_PGA_0_256V: return 0.256;
}
_err = ADS1X15_INVALID_VOLTAGE;
return _err;
_error = ADS1X15_INVALID_VOLTAGE;
return _error;
}
@ -242,8 +242,8 @@ uint8_t ADS1X15::getMode(void)
case ADS1X15_MODE_CONTINUE: return 0;
case ADS1X15_MODE_SINGLE: return 1;
}
_err = ADS1X15_INVALID_MODE;
return _err;
_error = ADS1X15_INVALID_MODE;
return _error;
}
@ -402,8 +402,8 @@ int16_t ADS1X15::getComparatorThresholdHigh()
int8_t ADS1X15::getError()
{
int8_t rv = _err;
_err = ADS1X15_OK;
int8_t rv = _error;
_error = ADS1X15_OK;
return rv;
}
@ -451,7 +451,18 @@ int16_t ADS1X15::_readADC(uint16_t readmode)
_requestADC(readmode);
if (_mode == ADS1X15_MODE_SINGLE)
{
while ( isBusy() ) yield(); // wait for conversion; yield for ESP.
uint32_t start = millis();
// timeout == { 129, 65, 33, 17, 9, 5, 3, 2 }
// a few ms more than max conversion time.
uint8_t timeOut = (128 >> (_datarate >> 5)) + 1;
while (isBusy())
{
yield(); // wait for conversion; yield for ESP.
if ( (millis() - start) > timeOut)
{
return ADS1X15_ERROR_TIMEOUT;
}
}
}
else
{
@ -490,7 +501,13 @@ bool ADS1X15::_writeRegister(uint8_t address, uint8_t reg, uint16_t value)
_wire->write((uint8_t)reg);
_wire->write((uint8_t)(value >> 8));
_wire->write((uint8_t)(value & 0xFF));
return (_wire->endTransmission() == 0);
int rv = _wire->endTransmission();
if (rv != 0)
{
_error = ADS1X15_ERROR_I2C;
return false;
}
return true;
}
@ -498,15 +515,18 @@ uint16_t ADS1X15::_readRegister(uint8_t address, uint8_t reg)
{
_wire->beginTransmission(address);
_wire->write(reg);
_wire->endTransmission();
int rv = _wire->requestFrom((int) address, (int) 2);
int rv = _wire->endTransmission();
if (rv == 0)
{
rv = _wire->requestFrom((int) address, (int) 2);
if (rv == 2)
{
uint16_t value = _wire->read() << 8;
value += _wire->read();
return value;
}
}
_error = ADS1X15_ERROR_I2C;
return 0x0000;
}

View File

@ -2,7 +2,7 @@
//
// FILE: ADS1X15.h
// AUTHOR: Rob Tillaart
// VERSION: 0.4.4
// VERSION: 0.4.5
// 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.4"))
#define ADS1X15_LIB_VERSION (F("0.4.5"))
// allow compile time default address
// address in { 0x48, 0x49, 0x4A, 0x4B }, no test...
@ -27,6 +27,8 @@
#define ADS1X15_OK 0
#define ADS1X15_INVALID_VOLTAGE -100
#define ADS1X15_ERROR_TIMEOUT -101
#define ADS1X15_ERROR_I2C -102
#define ADS1X15_INVALID_GAIN 0xFF
#define ADS1X15_INVALID_MODE 0xFE
@ -194,7 +196,7 @@ protected:
void _requestADC(uint16_t readmode);
bool _writeRegister(uint8_t address, uint8_t reg, uint16_t value);
uint16_t _readRegister(uint8_t address, uint8_t reg);
int8_t _err = ADS1X15_OK;
int8_t _error = ADS1X15_OK;
TwoWire* _wire;
uint32_t _clockSpeed = 0;

View File

@ -5,6 +5,13 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.4.5] - 2024-07-03
- Fix #78, prevent infinite loop. (Thanks to devmirek).
- Fix #76 (again), update readme.md Comparator Polarity.
- add ADS1X15_ERROR_I2C, communication error.
- add minimal section in readme.md about error codes.
- minor edits.
## [0.4.4] - 2024-06-28
- Fix #76, update readme.md Comparator Polarity
- added defines to replace magic numbers (not used in code yet)

View File

@ -474,26 +474,33 @@ Flag is only explicitly set after a **readADC()** or a **requestADC()**
- **uint8_t getComparatorPolarity()** returns value set.
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**.
From tests (see #76) it became clear that the behaviour of the **ALERT/RDY** pin
looks ambiguous. Further investigation eventually showed that the behaviour is
logical but one should not think in "pulses", more in levels and edges.
Timing of pulse from a synchronous ```ADS.readADC(0)``` call.
In the continuous mode it looks like an 8us pulse, however this "pulse" is
actual a short time (8 us) of IDLE followed by a long time pulse of converting.
In the single shot mode it looks like the converting time is the pulse
as that is the only single change visible. This is IMHO the correct view.
#### ALERT RDY table
| MODE | COMP_POL | IDLE | START | CONVERT | READY |
|:---------------|:-----------|:-------|:----------|:----------|:----------|
| 0 = continuous | 0 = LOW | HIGH | FALLING | LOW | RISING |
| 0 = continuous | 1 = HIGH | LOW | RISING | HIGH | FALLING |
| 1 = single | 0 = LOW | HIGH | FALLING | LOW | RISING |
| 1 = single | 1 = HIGH | LOW | RISING | HIGH | FALLING |
| 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
#### Converting time by Data Rate
| data rate | pulse length | Notes |
| data rate | convert time | Notes |
|:-----------:|:--------------:|:-------:|
| 0 | 125 ms |
| 1 | 62 ms |
@ -509,14 +516,25 @@ 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.
- Conversion generates a conversion pulse with length depending on the data rate.
- In continuous mode it looks like there is a short pulse, but actual the long
period is the conversion pulse.
In short:
- if COMP_POL = 0,
- a FALLING edge indicates conversion start.
- a LOW level indicates converting.
- a RISING edge indicates conversion ready.
- a HIGH level indicates idle.
- if COMP_POL = 1,
- a RISING edge indicates conversion start.
- a HIGH level indicates converting.
- a FALLING edge indicates conversion ready.
- a LOW level indicates idle.
This interpretation is in line with all tests done in #76.
### Latch
@ -568,6 +586,23 @@ mean something different see - Comparator Mode above or datasheet.
- **int16_t getComparatorThresholdHigh()** reads value from device.
## Error codes
This section has to be elaborated.
Some functions return or set an error value.
This is read and reset by **getError()**
| Value | Define | Description |
|:-------:|:-------------------------:|:-------------:|
| 0 | ADS1X15_OK | idem.
| -100 | ADS1X15_INVALID_VOLTAGE | getMaxVoltage()
| -101 | ADS1X15_ERROR_TIMEOUT | readADC() device did not respond in time.
| -102 | ADS1X15_ERROR_I2C | I2C communication failure.
| 0xFF | ADS1X15_INVALID_GAIN | getGain()
| 0xFE | ADS1X15_INVALID_MODE | getMode()
## Future ideas & improvements
#### Must
@ -580,10 +615,11 @@ mean something different see - Comparator Mode above or datasheet.
- 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.
- improve error handling
- refactor values to be more logic.
#### Could
- More examples
- SMB alert command (00011001) on I2C bus?
- Sync code order .h / .cpp

View File

@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/ADS1X15"
},
"version": "0.4.4",
"version": "0.4.5",
"license": "MIT",
"frameworks": "*",
"platforms": "*",

View File

@ -1,5 +1,5 @@
name=ADS1X15
version=0.4.4
version=0.4.5
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library for ADS1015 - I2C 12 bit ADC and ADS1115 I2C 16 bit ADC