Git Product home page Git Product logo

ads1x15's Introduction

Arduino CI Arduino-lint JSON check GitHub issues

License: MIT GitHub release PlatformIO Registry

ADS1X15

Arduino library for I2C ADC ADS1015, ADS1115, and similar.

For using I2C ADC with Raspberry pi or other SBC with Linux OS, you can check similar library here.

Description

This library should work for the devices mentioned below, although not all sensors support all functionality.

Device Channels Resolution Max sps Comparator ProgGainAMP Notes
ADS1013 1 12 3300 N N
ADS1014 1 12 3300 Y Y
ADS1015 4 12 3300 Y Y
ADS1113 1 16 860 N N
ADS1114 1 16 860 Y Y
ADS1115 4 16 860 Y Y Tested

As the ADS1015 and the ADS1115 are both 4 channels these are the most interesting from functionality point of view as these can also do differential measurements.

0.4.0 Breaking change

Version 0.4.0 introduced a breaking change. You cannot set the pins in begin() any more. This reduces the dependency of processor dependent Wire implementations. The user has to call Wire.begin() and can optionally set the Wire pins before calling begin().

Related

I2C Address

The address of the ADS1113/4/5 is determined by to which pin the ADDR is connected to:

ADDR pin connected to Address Notes
GND 0x48 default
VDD 0x49
SDA 0x4A
SCL 0x4B

I2C multiplexing

Sometimes you need to control more devices than possible with the default address range the device provides. This is possible with an I2C multiplexer e.g. TCA9548 which creates up to eight channels (think of it as I2C subnets) which can use the complete address range of the device.

Drawback of using a multiplexer is that it takes more administration in your code e.g. which device is on which channel. This will slow down the access, which must be taken into account when deciding which devices are on which channel. Also note that switching between channels will slow down other devices too if they are behind the multiplexer.

Interface

#include "ADS1X15.h"

Initializing

To initialize the library you must call a constructor as described below.

  • ADS1x15() base constructor, should not be used.
  • ADS1013(uint8_t address, TwoWire *wire = &Wire) Constructor with device address, and optional the Wire interface as parameter.
  • ADS1014(uint8_t address, TwoWire *wire = &Wire) Constructor with device address, and optional the Wire interface as parameter.
  • ADS1015(uint8_t address, TwoWire *wire = &Wire) Constructor with device address, and optional the Wire interface as parameter.
  • ADS1113(uint8_t address, TwoWire *wire = &Wire) Constructor with device address, and optional the Wire interface as parameter.
  • ADS1114(uint8_t address, TwoWire *wire = &Wire) Constructor with device address, and optional the Wire interface as parameter.
  • ADS1115(uint8_t address, TwoWire *wire = &Wire) Constructor with device address, and optional the Wire interface as parameter.

After construction the ADS.begin() need to be called. This will return false if an invalid address is used. The function bool isConnected() can be used to verify the reading of the ADS. The function void reset() is sets the parameters to their initial value as in the constructor.

For example.

#include "ADS1X15.h"

// initialize ADS1115 on I2C bus 1 with default address 0x48
ADS1115 ADS(0x48);

void begin() {
  if (!ADS.isConnected()) {
    // error ADS1115 not connected
  }
}

I2C clock speed

The function void setWireClock(uint32_t speed = 100000) is used to set the clock speed in Hz of the used I2C interface. typical value is 100 KHz.

The function uint32_t getWireClock() is a prototype. It returns the value set by setWireClock(). This is not necessary the actual value. When no value is set getWireClock() returns 0. Need to implement a read / calculate from low level I2C code (e.g. TWBR on AVR), better the Arduino Wire lib should support this call (ESP32 does).

See - arduino/Arduino#11457

Question: Should this functionality be in this library?

Programmable Gain

  • void setGain(uint8_t gain) set the gain value, indicating the maxVoltage that can be measured Adjusting the gain allowing to make more precise measurements. Note: the gain is not set in the device until an explicit read/request of the ADC (any read call will do). See table below.
  • uint8_t getGain() returns the gain value (index).
PGA value Max Voltage Notes
0 ±6.144V default
1 ±4.096V
2 ±2.048V
4 ±1.024V
8 ±0.512V
16 ±0.256V
  • float getMaxVoltage() returns the max voltage with the current gain.
  • float toVoltage(int16_t raw = 1) converts a raw measurement to a voltage. Can be used for normal and differential measurements. The default value of 1 returns the conversion factor for any raw number.

The voltage factor can also be used to set HIGH and LOW threshold registers with a voltage in the comparator mode. Check the examples.

  float f = ADS.toVoltage();
  ADS.setComparatorThresholdLow( 3.0 / f );
  ADS.setComparatorThresholdLow( 4.3 / f );

Operational mode

The ADS sensor can operate in single shot or continuous mode. Depending on how often conversions needed you can tune the mode.

  • void setMode(uint8_t mode) 0 = CONTINUOUS, 1 = SINGLE (default) Note: the mode is not set in the device until an explicit read/request of the ADC (any read call will do).
  • uint8_t getMode() returns current mode 0 or 1, or ADS1X15_INVALID_MODE = 0xFE.

Data rate

  • void setDataRate(uint8_t dataRate) Data rate depends on type of device. For all devices the index 0..7 can be used, see table below. Values above 7 ==> will be set to the default 4. Note: the data rate is not set in the device until an explicit read/request of the ADC (any read call will do).
  • uint8_t getDataRate() returns the current data rate (index).

The library has no means to convert this index to the actual numbers as that would take 32 bytes.

Data rate in samples per second, based on datasheet is described on table below.

data rate ADS101x ADS111x Notes
0 128 8 slowest
1 250 16
2 490 32
3 920 64
4 1600 128 default
5 2400 250
6 3300 475
7 3300 860 fastest

ReadADC Single mode

Reading the ADC is very straightforward, the readADC() function handles all in one call. Under the hood it uses the asynchronous calls.

  • int16_t readADC(uint8_t pin = 0) normal ADC functionality, pin = 0..3. If the pin number is out of range, this function will return 0. Default pin = 0 as this is convenient for 1 channel devices.
// read ADC in pin 2
ADS.readADC(2);

// read ADC in pin 0 - two ways
ADS.readADC();
ADS.readADC(0);

See examples.

To read the ADC in an asynchronous way (e.g. to minimize blocking) you need call three functions:

  • void requestADC(uint8_t pin = 0) Start the conversion. pin = 0..3. Default pin = 0 as this is convenient for 1 channel devices.
  • bool isBusy() Is the conversion not ready yet? Works only in SINGLE mode!
  • bool isReady() Is the conversion ready? Works only in SINGLE mode! (= wrapper around isBusy() )
  • int16_t getValue() Read the result of the conversion.

in terms of code

  void setup()
  {
    // other setup things here
    ADS.setMode(1);               // SINGLE SHOT MODE
    ADS.requestADC(pin);
  }

  void loop()
  {
    if (ADS.isReady())
    {
      value = ADS.getValue();
      ADS.requestADC(pin);       // request new conversion
    }
    // do other things here
  }

See examples.

ReadADC Differential

For reading the ADC in a differential way there are 4 calls possible.

  • int16_t readADC_Differential_0_1() returns the difference between 2 ADC pins.
  • int16_t readADC_Differential_0_3() ADS1x15 only
  • int16_t readADC_Differential_1_3() ADS1x15 only
  • int16_t readADC_Differential_2_3() ADS1x15 only
  • int16_t readADC_Differential_0_2() ADS1x15 only - in software (no async equivalent)
  • int16_t readADC_Differential_1_2() ADS1x15 only - in software (no async equivalent)
// read differential ADC between pin 0 and 1
ADS.readADC_Differential_0_1(0);

The differential reading of the ADC can also be done with asynchronous calls.

  • void requestADC_Differential_0_1() starts conversion for differential reading
  • void requestADC_Differential_0_3() ADS1x15 only
  • void requestADC_Differential_1_3() ADS1x15 only
  • void requestADC_Differential_2_3() ADS1x15 only

After one of these calls you need to call

  • int16_t getValue() Read the result of the last conversion.

See examples.

lastRequestMode

Since 0.3.12 the library tracks the last request mode, single pin or differential. This variable is set at the moment of request, and keeps its value until a new request is made. This implies that the value / request can be quite old.

Values >= 0x10 are differential, values < 0x10 are single pin.

  • uint8_t lastRequest() returns one of the values below.
Value Description Notes
0xFF no (invalid) request made after call constructor.
0x00 single pin 0
0x01 single pin 1
0x02 single pin 2
0x03 single pin 3
0x10 differential pin 1 0
0x30 differential pin 3 0
0x31 differential pin 3 1
0x32 differential pin 3 2

Please note that (for now) the function does not support a descriptive return value for the following two requests:

  • readADC_Differential_0_2() ADS1x15 only - in software (no async equivalent)
  • readADC_Differential_1_2() ADS1x15 only - in software (no async equivalent)

As these are emulated in software by two single pin calls, the state would be one of the two single pin values.

ReadADC continuous mode

To use the continuous mode you need call three functions:

  • void setMode(0) 0 = CONTINUOUS, 1 = SINGLE (default). Note: the mode is not set in the device until an explicit read/request of the ADC (any read call will do).
  • int16_t readADC(uint8_t pin) or void requestADC(uint8_t pin) to get the continuous mode started.
  • int16_t getValue() to return the last value read by the device. Note this can be a different pin, so be warned. Calling this over and over again can give the same value multiple times.
void setup() {
  // configuration things here
  ADS.setMode(ADS.MODE_CONTINUOUS);
  ADS.requestADC(0);              // request on pin 0
}

void loop() {
  value = ADS.getValue()
  sleep(1)
}

See examples . By using bool isBusy() or bool isReady() one can wait until new data is available. Note this only works in the SINGLE_SHOT modus.

In continuous mode, you can't use isBusy() or isReady() functions to wait until new data available. Instead you can configure the threshold registers to allow the ALERT/RDY pin to trigger an interrupt signal when conversion data ready.

Switching mode or channel during continuous mode

When switching the operating mode or the ADC channel in continuous mode, be aware that the device will always finish the running conversion. This implies that after switching the mode or channel the first sample you get is probably the last sample with the previous settings, e.g. channel. This might be a problem for your project as this value can be in an "unexpected" range (outlier).

The robust way to change mode or channel therefore seems to be:

  1. stop continuous mode,
  2. wait for running conversion to be ready,
  3. reject the last conversion or process it "under old settings",
  4. change the settings,
  5. restart (continuous mode) with the new settings.

This explicit stop takes extra time, however it should prevent "incorrect" readings.

(need to be verified with different models)

Threshold registers

If the thresholdHigh is set to 0x0100 and the thresholdLow to 0x0000 the ALERT/RDY pin is triggered when a conversion is ready.

  • void setComparatorThresholdLow(int16_t lo) writes value to device directly.
  • void setComparatorThresholdHigh(int16_t hi) writes value to device directly.
  • int16_t getComparatorThresholdLow() reads value from device.
  • int16_t getComparatorThresholdHigh() reads value from device.

See examples.

Comparator

Please read Page 15 of the datasheet as the behaviour of the comparator is not trivial.

NOTE: all comparator settings are copied to the device only after calling readADC() or requestADC() functions.

Comparator Mode

When configured as a TRADITIONAL comparator, the ALERT/RDY pin asserts (active low by default) when conversion data exceed the limit set in the high threshold register. The comparator then de-asserts when the input signal falls below the low threshold register value.

  • void setComparatorMode(uint8_t mode) value 0 = TRADITIONAL 1 = WINDOW,
  • uint8_t getComparatorMode() returns value set.

If the comparator LATCH is set, the ALERT/RDY pin asserts and it will be reset after reading the sensor (conversion register) again. An SMB alert command (00011001) on the I2C bus will also reset the alert state. Not implemented in the library (yet)

In WINDOW comparator mode, the ALERT/RDY pin asserts if conversion data exceeds the high threshold register or falls below the low threshold register. In this mode the alert is held if the LATCH is set. This is similar as above.

Polarity

Default state of the ALERT/RDY pin is LOW, can be to set HIGH.

  • void setComparatorPolarity(uint8_t pol) Flag is only explicitly set after a readADC() or a requestADC()
  • uint8_t getComparatorPolarity() returns value set.

Latch

Holds the ALERT/RDY to HIGH (or LOW depending on polarity) after triggered even if actual value has been 'restored to normal' value.

  • void setComparatorLatch(uint8_t latch) 0 = NO LATCH, not 0 = LATCH
  • uint8_t getComparatorLatch() returns value set.

QueConvert

Set the number of conversions before trigger activates. The void setComparatorQueConvert(uint8_t mode) is used to set the number of conversions that exceed the threshold before the ALERT/RDY pin is set HIGH. A value of 3 (or above) effectively disables the comparator. See table below. To enable the conversion-ready function of the ALERT/RDY pin, it is necessary to set the MSB of the Hi_thresh register to 1 and the MSB of the Lo_thresh register to 0.

See examples.

  • void setComparatorQueConvert(uint8_t mode) See table below.
  • uint8_t getComparatorQueConvert() returns value set.
value meaning Notes
0 trigger alert after 1 conversion
1 trigger alert after 2 conversions
2 trigger alert after 4 conversions
3 Disable comparator default

Threshold registers comparator mode

Depending on the comparator mode TRADITIONAL or WINDOW the thresholds registers mean something different see - Comparator Mode above or datasheet.

  • void setComparatorThresholdLow(int16_t lo) set the low threshold; take care the hi >= lo.
  • void setComparatorThresholdHigh(int16_t hi) set the high threshold; take care the hi >= lo.
  • int16_t getComparatorThresholdLow() reads value from device.
  • int16_t getComparatorThresholdHigh() reads value from device.

Future ideas & improvements

Must

  • Improve documentation (always)

Should

Could

  • More examples
  • SMB alert command (00011001) on I2C bus?
  • sync order .h / .cpp

Wont (unless requested)

  • type flag?
  • constructor for ADS1X15? No as all types are supported.

Support

If you appreciate my libraries, you can support the development and maintenance. Improve the quality of the libraries by providing issues and Pull Requests, or donate through PayPal or GitHub sponsors.

Thank you,

ads1x15's People

Contributors

chandrawi avatar chipce avatar intubun avatar robtillaart avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ads1x15's Issues

QUESTION: What's the typical conversion time?

I've got Covid lockdown brain, so I hope you'll forgive my mistakes assuming that I've erred, which is quite possible.

The datasheet says the ADS101x series run at a max of 3300 samples per second, flat out. If my math is right (and it might not be!) that puts a typical sample at 0.0003 seconds which is 0.3 miliseconds per sample I think.

I'm getting results of 1650 - 1660 mS per reading in single shot and 8980 mS per sample in continuous on an ESP32. I've tried re-coding the example several different ways and the results are broadly similar.

The exact time isn't that crucial to my application so long as it's in under about one millisecond per sample. Perhaps you can help me clear this up?

ADS1115 on RP2040 Wire, 0x4B is busy

Hi,
I have just discovered a problem in the use of the ADS1115 connected Wire0 of the RP2040.
The 3 addresses work correctly except 0x4B which is Busy.
Initially the assembly and the program was functional for the 4 addresses with Arduino Mega.
With the Raspberry Pico everything works correctly, except the address 0x4B which is seen Busy at initialization.
For information on the I2C bus there is also an RTC DS3231 which is on Wire1, but was also present on the Arduino version.
With the Raspberry Pico version I tested the presence of the 3 simultaneous addresses without any problem, only when 0x4B is connected to the assembly, it is not recognized.
I turn in circles.
Thank you for you help.

Erick
Laval in France

Check documentation carefully

The 0.2.3 version has both comparator mode and async mode added.
Need to check the documentation again if it matches the code.

[Query] Example for continuously reading all four channels at max sps?

If I read all 4 channels at 860 SPS, it should be 215 SPS per channel, 1.2ms between requesting a conversion and the interrupt on ALRT/Ready. In single shot mode, that is not the case for me, it takes a bit more than 6ms for the interrupt to occur after I switch the channel. I'm not sure if this is expected or am I doing something wrong or the chip is faulty. I can get 1.2ms delay If I read from a single channel in Continuous mode. Is there a way to achieve this 215 (At least 200) SPS from each channel while reading all 4? Can you please provide an example if so?

Thanks!!

Allow specifying I2C bus

This library hardcodes the Wire bus, so it's impossible to use this with sensors on any other I2C bus that may be available (Wire1, Wire2, etc.).

I may see if I can handle this and submit a PR...

ADS1X15 Continuous Mode AND differential (0_1) & (2_3)

Hi Rob, thanks for your libraries, I've been using many of them for years.

Is there a way to get both differential values (0_1 AND 2_3) on continuous mode?

I've been able to get.Value() on either, depending on the trigger read in setup(), but for the life of me I can't find a way to do it on both channels simultaneously...

Is there something obvious I'm missing?

Thank you Rob.

Arduino Micro and ADS1115 - 860SPS (Only on 1 channel ?)

Hi everyone, I have a question/issue with my ADS1115 and I'd like to know if my conclusion is right or not.

I wrote this small code to test the speed of the ADS1115:

#include "ADS1X15.h"

// ADS1x15 Definitions
ADS1115 ADS(0x48);

// Timing
unsigned long starttime;
unsigned long endtime ;

void setup() {
  Serial.begin(250000);
  ADS.begin();
  ADS.setGain(0);
  ADS.setDataRate(7);
  ADS.setMode(0);
  ADS.setWireClock(400000);
  if (ADS.isConnected()) ADS.readADC(0);
}

void loop() {
  starttime = micros();
  // Serial.print("Sensor 0: "); Serial.print(ADS.readADC(0));
  Serial.print(" - Sensor 1: ");  Serial.print(ADS.readADC(1));
  // Serial.print(" - Sensor 2: "); Serial.print(ADS.readADC(2));
  endtime = micros();
  Serial.print(" => Tiempo de 1 lectura: "); Serial.print(endtime - starttime);  Serial.print(" us");
  Serial.println();
  delay(1000);
}

Now, when I test this with library delay set on 8, I get: ~8726 us
#define ADS1115_CONVERSION_DELAY 8

If I set this to 1, I get: ~1700 us
#define ADS1115_CONVERSION_DELAY 1

My issue is, I need to read 3 analogs, not 1, as you can see I comment the rest of the readings to check response time PER channel. So, when I add the rest of the channels to this project, the max speed I can get is:

Now, when I test this with library delay set on 6, I get: ~ 6500 PER CHANNEL
#define ADS1115_CONVERSION_DELAY 6

Anything below a delay of 6, the reading get's stuck or star mixing results.

Conclusion: If I'm not wrong, switching channels on ADS1115 requieres an additional delay and that's what's causing the problem. Am I right ? Is there any way to improve this results ?

Thanks a lot.

ADS1013 & ADS1113 do not have gain

Must be fixed, It is no showstopper but need at least documentation.

  • in base-class with a _type check in setGain() or
  • move setGain to supporting classes.
  • GetGain() can stay in baseclass (check)

Suggestion: Add wrapper method to set I2C clock speed

I am working on a time sensitive measurement, which requires a fast sampling time (< 10 ms). During my testing with the ESP32 and the ADS1115 in continuous mode according to the "continuous_4_channels" example, I found that the reads take in average 0.8 to 1 ms longer than expected.

Since this library uses the "Wire" library, I added the following function to the ADS1X15 library:

void ADS1X15::setClock(uint32_t clockSpeed)
{
  _wire->setClock(clockSpeed);
}

This enables to set the clock speed of the I2C communication. When setting the clock speed to 1 MHz, my latency went down to < 0.1 ms. Maybe, this type of function would be handy for others as well.

PS: Thanks for your nice library!

ADS1X15::getMaxVoltage()

Dear Rob,
Thank you for set of code and thinking through all parts.

RE: float ADS1X15::getMaxVoltage()
In different Gain values, except "0" this switch is not working properly.
Change to :
float ADS1X15::getMaxVoltage()
{
switch (_gain)
{
/* case 0: return 6.144; // original and it is not correct
case 1: return 4.096;
case 2: return 2.048;
case 4: return 1.024;
case 8: return 0.512;
case 16: return 0.256; */
case ADS1X15_PGA_6_144V: return 6.144;
case ADS1X15_PGA_4_096V: return 4.096;
case ADS1X15_PGA_2_048V: return 2.048;
case ADS1X15_PGA_1_024V: return 1.024;
case ADS1X15_PGA_0_512V: return 0.512;
case ADS1X15_PGA_0_256V: return 0.256;
}
return ADS1X15_INVALID_VOLTAGE;
}
And test - all work for 1115 well.

Also, in setComparatorQueConvert
^
was letter "e" instead "a"

Small and perhaps not important things.
Thank you again for work !

ESP32 work on Espressif 1.04 but No on Espressif 2,07

On IDE 2.04 and Espressif 1.04 I can read 6 Channels with PlotChannels.ino
when I install latest Espressif 2,07 and compile the same PlotC hannels.ino script I have no error but the SW return 0 (zero) on al channel

Not working with Nano Every

Hi, this looks like a really good library :) but I can't get anything to compile for the Nano Every. AVR dude seems to have problems with the get clock (what you have listed as a prototype) and set clock functions and a few other things I think related to setting clocks for the I2C bus. I tried to copy the error messages but I not able to. Is there maybe something I can change in the header file to get it working? Thanks! :) Rainer S.

[question] About using ALERT RDY in ADS_continuous_differential.ino example.

Hi, thanks for the great library!
I want to ask about using ALERT RDY in continuous differential mode.

As the example in ADS_continuous_differential.ino, you called both setComparatorQueConvert(0) and setComparatorThreshold

  // SET ALERT RDY PIN
  ADS.setComparatorThresholdHigh(0x8000);
  ADS.setComparatorThresholdLow(0x0000);
  ADS.setComparatorQueConvert(0);

As I understand, the RDY pin state will rise when the ADC read completed/ready, but what ComparatorThreshold will affect the RDY state here? They will also rise if the signal passed the set thresholds? If I just need the ADC ready signal, just set the ADS.setComparatorQueConvert(0); will be enough?

Sorry for my bad English!
Thanks you!

10-12 Channel Continuous with interrupts.

Hi Rob, all your work on this is much appreciated! By far the most comprehensive implementation for these devices!

I am trying to sample 10-12 channels (3x ADS1115) as quickly as possible. Using 860sps, 6.144 FSR, 5v supply, Arduino Mega2560 (I think I should be able to use 3 interrupt pins - 2, 3, and 18 - per #14 ). My current setup is based off of the ADS_continuous_8_channel.ino example, I simply copied/pasted to create ADS_3. Currently, the code causes a hang with 3 ADCs, I believe due to arbitration issues on the I2C bus. With the third ADC commented out, it works as expected, because it is pretty much identical to the example. The attached code has 3 channels on ADS_1 and ADS_2, and 4 channels on ADS_3. For this reason, I set the address of ADS_3 to 0x48, in hopes that it would win arbitration to make up for the slightly slower sampling (3 vs 4 channels). I was using 3 channels on the other 2 ADCs in an attempt to take advantage of some advantages discussed in #49 - the hope was to sample 10 channels with maximum SPS.

In terms of solutions, the following comment from #53 seems like it may have potential: "What might be an option is to combine async requesting a conversion and use interrupts to trigger the reading of the result. Polling a flag is faster than requesting status over I2C."

I have also played around with the ADS_async_8_channel.ino example (and 16channel variant), #24 . These examples (of course) work flawlessly for my application- but my initial goal was to reach faster sampling rates by modifying the 8channel_continuous code instead.

Should I stick with the async implementation? Is this the fastest performance possible with 3x ADS1115? Thank you!
Code:

uint32_t starttime1;
uint32_t endtime1;
uint32_t starttime2;
uint32_t endtime2;
uint32_t starttime3;
uint32_t endtime3;
uint32_t times[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

int SPS1 = 0;
int SPS2 = 0;
int SPS3 = 0;
uint32_t lastTime1 = 0;
uint32_t lastTime2 = 0;
uint32_t lastTime3 = 0;


#include "ADS1X15.h"


//  adjust addresses if needed
ADS1115 ADS_1(0x49); //VDD 1,2,3
ADS1115 ADS_2(0x4B); //SCL 4,5,6
ADS1115 ADS_3(0x48); //GND 7,8,9,10 - lowest because 4 channels, will win arbitration

//  two interrupt flags
volatile bool RDY_1 = false;
volatile bool RDY_2 = false;
volatile bool RDY_3 = false;

uint8_t channel_1 = 0;  //  channel from device 1
uint8_t channel_2 = 0;  //  channel from device 2
uint8_t channel_3 = 0;  //  channel from device 2

//  array to hold the data.
int16_t val[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };


void setup() {


  Serial.begin(115200);
  Serial.println(__FILE__);
  Serial.print("ADS1X15_LIB_VERSION: ");
  Serial.println(ADS1X15_LIB_VERSION);

  Wire.begin();

  //  SETUP FIRST ADS1115
  ADS_1.begin();
  ADS_1.setGain(0);      //  6.144 volt
  ADS_1.setDataRate(7);  //  0 = slow   4 = medium   7 = fast
  ADS_1.setWireClock(400000);

  //  SET ALERT RDY PIN
  ADS_1.setComparatorThresholdHigh(0x8000);
  ADS_1.setComparatorThresholdLow(0x0000);
  ADS_1.setComparatorQueConvert(0);

  //  SET INTERRUPT HANDLER TO CATCH CONVERSION READY
  pinMode(18, INPUT_PULLUP); //ADC1 whjte wire
  attachInterrupt(digitalPinToInterrupt(18), adsReady_1, RISING);

  ADS_1.setMode(0);             //  continuous mode
  ADS_1.requestADC(channel_1);  //  trigger first read


  //  SETUP SECOND ADS1115
  ADS_2.begin();
  ADS_2.setGain(0);  //  6.144 volt
  ADS_2.setDataRate(7);
  ADS_2.setWireClock(400000);

  //  SET ALERT RDY PIN
  ADS_2.setComparatorThresholdHigh(0x8000);
  ADS_2.setComparatorThresholdLow(0x0000);
  ADS_2.setComparatorQueConvert(0);

  //  SET INTERRUPT HANDLER TO CATCH CONVERSION READY
  pinMode(2, INPUT_PULLUP); //ADC2 yellow wire
  attachInterrupt(digitalPinToInterrupt(2), adsReady_2, RISING);

  ADS_2.setMode(0);             //  continuous mode
  ADS_2.requestADC(channel_2);  //  trigger first read


 //  SETUP THIRD ADS1115
 ADS_3.begin();
 ADS_3.setGain(0);      //  6.144 volt
 ADS_3.setDataRate(7);  //  0 = slow   4 = medium   7 = fast
 ADS_3.setWireClock(400000);

 //  SET ALERT RDY PIN
 ADS_3.setComparatorThresholdHigh(0x8000);
 ADS_3.setComparatorThresholdLow(0x0000);
 ADS_3.setComparatorQueConvert(0);

 //  SET INTERRUPT HANDLER TO CATCH CONVERSION READY
 pinMode(3, INPUT_PULLUP); //ADC3 purple wire
 attachInterrupt(digitalPinToInterrupt(3), adsReady_3, RISING);

 ADS_3.setMode(0);             //  continuous mode
 ADS_3.requestADC(channel_3);  //  trigger first read
}


void loop() {
  handleConversion();

  //mine
  String serial_out = "";
  String time_out = "";

  Serial.println("DEBUG: Entering Loop");
  for (int i = 0; i < 10; i++) {
    serial_out = serial_out + '\t' + val[i];
    time_out = 't' + time_out + '\t' + times[i];
    //Serial.print(val[i]);
    //Serial.print('\t');
    handleConversion();
  }
  //Serial.println();

  //Mine
  Serial.println(serial_out);
  Serial.println(time_out);
  
}


//  catch interrupt and set flag device 1
void adsReady_1() {
  RDY_1 = true;
}

//  catch interrupt and set flag device 1
void adsReady_2() {
  RDY_2 = true;
}

void adsReady_3() {
  RDY_3 = true;
}


//  handle conversions that are ready
bool handleConversion() {
  bool rv = false;
  if (RDY_1) {
    //  save the last value
    SPS1++;
    val[channel_1] = ADS_1.getValue();

    endtime1 = micros();
    times[channel_1] = endtime1 - starttime1;

    //  request next channel
    channel_1++;
    if (channel_1 >= 3) channel_1 = 0;

    starttime1 = micros();

    ADS_1.requestADC(channel_1);
    RDY_1 = false;
    rv = true;

    
    if (SPS1 % 200 == 0) {
      for (int i = 0; i < 3; i++) {
        Serial.print('\t');
        Serial.print(val[i]);
      }
      Serial.println();
    }

    if (millis() - lastTime1 >= 1000) {
      lastTime1 = millis();
      Serial.print("SPS1: ");
      Serial.println(SPS1);
      SPS1 = 0;
    }
    

  }
  if (RDY_2) {
    SPS2++;
    //  save the last value
    val[3 + channel_2] = ADS_2.getValue();

    endtime2 = micros();
    times[3 + channel_2] = endtime2 - starttime2;

    //  request next channel
    channel_2++;
    if (channel_2 >= 3) channel_2 = 0;

    starttime2 = micros();

    ADS_2.requestADC(channel_2);
    RDY_2 = false;
    rv = true;

    
    if (SPS2 % 200 == 0) {
      for (int i = 3; i < 6; i++) {
        Serial.print('\t');
        Serial.print(val[i]);
      }
      Serial.println();
    }
    if (millis() - lastTime2 >= 1000) {
      lastTime2 = millis();
      Serial.print("SPS2: ");
      Serial.println(SPS2);
      SPS2 = 0;
    }
    
  }
 if (RDY_3) {
   SPS3++;
   //  save the last value
   val[6 + channel_3] = ADS_3.getValue();

   endtime3 = micros();
   times[6 + channel_3] = endtime3 - starttime3;

   //  request next channel
   channel_3++;
   if (channel_3 >= 4) channel_2 = 0;

   starttime3 = micros();

   ADS_3.requestADC(channel_3);
   RDY_3 = false;
   rv = true;
   
   if (SPS3 % 200 == 0) {
     for (int i = 6; i < 10; i++) {
       Serial.print('\t');
       Serial.print(val[i]);
     }
     Serial.println();
   }
   if (millis() - lastTime3 >= 1000) {
     lastTime3 = millis();
     Serial.print("SPS3: ");
     Serial.println(SPS3);
     SPS3 = 0;
   }
   
   
 }

  return rv;
}

ADS1X15::setWireClock() and high-speed mode

Issue #22 added this handy method for setting the I2C clock, however, it might be incomplete.

Section 9.5.1.3 (page 23) of the datasheet says that while the ADS111x supports all three speed modes, high-speed mode (>400kHz) must be activated:

To activate high-speed mode, send a special address byte of 00001xxx following the START condition, where xxx are bits unique to the Hs-capable master. This byte is called the Hs master code, and is different from normal address bytes; the eighth bit does not indicate read/write status. The ADS111x do not acknowledge this byte; the I2C specification prohibits acknowledgment of the Hs master code. Upon receiving a master code, the ADS111x switch on Hs mode filters, and communicate at up to 3.4 MHz. The ADS111x switch out of Hs mode with the next STOP condition.

It'd be pretty slick to see the ADS1X15::setWireClock() method perform this activation.

ADS1115 value from one channel is being copied to the other

Hi, I'm developing a project using the ADS1115. I'm facing an issue with copying values between two channels; it seems that the value from one channel is being copied to the other. I'm using a sample rate of 860 fps. Below is the acquireData function for reference:

void acquireData(data_t* data) {
   read_data = true; 
   while(read_data){ //wait until the data is read and convReady is true which means that the value is ready.
      if(convReady) //convReady is connected to alertReady PIN
      {
        data->adc[0]  = ADS.getValue();
        ADS.requestADC(1);
        convReady = false;
        read_data = false;
      }
  }

  read_data = true;
  while(read_data){
      if(convReady)
      {
         data->adc[1] = ADS.getValue();
         ADS.requestADC(0);
        convReady = false;
        read_data = false;
      }
  }

}

Please note that the first time the program is executed I'm calling ADS.requestADC(0), do you have any suggestions or ideas about this issue.
Thank you in advance.

getMaxVoltage() does not handle ADS1113

Perhaps related to this issue.
ADS1113 has no gain control and the maximum voltage is fixed to ±2.048 V.

Usually, to convert the ADC readings to a voltage you would write:

float voltage = _ads1113.toVoltage(_ads1113.readADC(0));

but toVoltage() calls getMaxVoltage() and this does not handle the ADC1113:

float ADS1X15::getMaxVoltage()
{
  switch (_gain)
  {
    case ADS1X15_PGA_6_144V: return 6.144;
    case ADS1X15_PGA_4_096V: return 4.096;
    case ADS1X15_PGA_2_048V: return 2.048;
    case ADS1X15_PGA_1_024V: return 1.024;
    case ADS1X15_PGA_0_512V: return 0.512;
    case ADS1X15_PGA_0_256V: return 0.256;
  }
  _err = ADS1X15_INVALID_VOLTAGE;
  return _err;
}

because in the inizialization:

ADS1113::ADS1113(uint8_t address, TwoWire *wire)
{
  _address = address;
  _wire = wire;
  _config = ADS_CONF_NOCOMP | ADS_CONF_NOGAIN | ADS_CONF_RES_16 | ADS_CONF_CHAN_1;
  _conversionDelay = ADS1115_CONVERSION_DELAY;
  _bitShift = 0;
  _maxPorts = 1;
}

the ADS_CONF_NOGAIN would prevent any handling of the gain, falling back to a wrong one (ADS1X15_PGA_6_144V):

void ADS1X15::setGain(uint8_t gain)
{
  if (!(_config & ADS_CONF_GAIN)) gain = 0;
  switch (gain)
  {
    default:  //  catch invalid values and go for the safest gain.
    case 0:  _gain = ADS1X15_PGA_6_144V;  break;
    case 1:  _gain = ADS1X15_PGA_4_096V;  break;
    case 2:  _gain = ADS1X15_PGA_2_048V;  break;
    case 4:  _gain = ADS1X15_PGA_1_024V;  break;
    case 8:  _gain = ADS1X15_PGA_0_512V;  break;
    case 16: _gain = ADS1X15_PGA_0_256V;  break;
  }
}

uint8_t ADS1X15::getGain()
{
  if (!(_config & ADS_CONF_GAIN)) return 0;
  switch (_gain)
  {
    case ADS1X15_PGA_6_144V: return 0;
    case ADS1X15_PGA_4_096V: return 1;
    case ADS1X15_PGA_2_048V: return 2;
    case ADS1X15_PGA_1_024V: return 4;
    case ADS1X15_PGA_0_512V: return 8;
    case ADS1X15_PGA_0_256V: return 16;
  }
  _err = ADS1X15_INVALID_GAIN;
  return _err;
}

To ensure compatibility of the library across all the supported devices, I think it should handle the ADS1113 properly and getMaxVoltage() should return 2.048, perhaps forcing the "gain" to ADS1X15_PGA_2_048V.

interrupt driven reads

Moin Rob.

Thanks for the nice lib.

Just a note, not a real issue.

I was looking for an example of interrupt driven conversions. Looking into the example file name list, I found nothing. Looking into the main .MD page: again nothing.

It needed a text search throu the examples.

Not that a big deal, but from a "marketing" standpoint I think interrupt driven conversions (like in ADS_continuous_4_channel) should be displayed very prominently. Isn't it what we all want?

mfg.

ADS1115 resolution question

Hi there! I’m working on a project and using this Arduino library. I’m using a differential sensor and saw that I cannot see some of the data between readings. Is there anything I could add using Arduino code to see the full resolution? I saw that there was a mention of potential future work on the differential side of things, and was wondering if this referring to resolution. Thanks!

The use of Wire1 is not allowed for ESP32 or ESP8266

the first line of the function definition "bool ADS1X15::begin(int sda, int scl)" used for ESP32 and ESP8266 microcontrollers forces the use of the "Wire" object, but the constructors allow the selection of the TwoWire object that you want to use.

1

Synchronous mode very slow

Hi,
Based on reading the docs I set up an ADS1115 with the following:

    _ads=new ADS1115(_addr);
    // initialize the Analog2Digital sampler
    volatile bool status=_ads->begin();
    _ads->setGain(ADS1x15_GAIN_4_096_VOLTS);
    // set the highest datarate, 860 samples/sec
    // see https://github.com/RobTillaart/ADS1X15       
    _ads->setDataRate(7);   
    // single shot mode
    _ads->setMode(1);
    // set the I2C bus frequency
    _ads->setWireClock(400000);

I access the sampler asynchronously using:

unsigned long start=micros();
_ads-> requestADC_Differential_0_1()
while(!_ads->isReady(){
    yield();
}
unsigned long elapsed=micros()-start;
_ads->getValue();

so to be fair, I wasn't expecting to be able to take 860 samples per second this way, but my benchmarking was a bit disappointing... it takes at least 6300 micros (6.3 millis) to get a sample. I could be doing something wrong but it doesn't seem like it...

To satisfy my curiousity, i switched to a synchronous blocking read like so"

unsigned long start=micros();
_ads->readADC_Differential_0_1()
unsigned long elapsed=micros()-start;

synchronous reads take at least 6500 micros (6.5 millis). My I2C clock is anywhere between 300-400kHZ, lots of clock stretching going on so hard to be more precise with that number. Also, if it makes a difference running on an RP2040 pico, this is the only I2C device on the bus...

so by my math, we are looking at 150 samples per sec ... I haven't dug into the data sheet and perhaps differential mode is slower, the performance numbers you list, i.e. 860 s/sec, don't seem to be achievable in my case... suggestions?

can isBusy() also verify connected() ?

In #24 it becomes clear that if isBusy() is used in a loop it might incorrectly return true if the sensor is not connected.

Strategy may be to test connect or set error flag. Needs some investigation.

  • might change signature?
  • performance penalty?
  • affects underlying readRegister

Documentation clarification. In latch mode, alert pin goes high only after readADC?

I think this might just be and issue about clarifying the documentation.

Here's the setup:

  • I'm using the traditional + latch mode,
  • Switch connected to A0. When the switch is pressed A0 goes HIGH,
  • ALERT pin is connected to D2,
  • When A0 goes HIGH I want the ALERT pin to trigger an interrupt attached to D2,
  • When the interrupt is called I set a flag so that something happens in loop(), in this case print "foo".

Issue?

  • In the code below, when ADS.readADC(0) is called before if (read_ADC){...} everything goes as intended,
  • If it is called within, i.e. if (read_ADC) { ADS.readADC(0); ...} then what's inside the if then the ALERT pin doesn't go HIGH, the interrupt on D2 is not executed so do_thing remains false, and nothing happens.
  • So it appears that you have to readADC() to both make ALERT go HIGH and immediately low again? Why call it LATCH mode? It seems like it simultaneously goes high and then low after readADC().
  • In other words, I thought the whole point of the traditional mode with latch was that like an interrupt ALERT goes high without the need to constantly readADC() in the loopis called and instead serves to reset ALERT.

I thought that the order of event was

  • A0 goes HIGH, triggering an interrupt and ALERT goes HIGH, regardless of if you're in LATCH mode or not.
  • After ALERT goes HIGH, you need to readADC() so that it goes low again.

Here's the code in question.

#include <avr/interrupt.h>
#include <Wire.h>
#include <ADS1X15.h>

ADS1115 ADS(0x48);

volatile bool do_thing = false;

void setup()
{
  pinMode(2, INPUT);
  attachInterrupt(digitalPinToInterrupt(2), foo, RISING);

  Serial.begin(115200);

  Wire.begin();
  Wire.setClock(400000);

  ADS.begin();
  ADS.setGain(0);
  ADS.setComparatorMode(0);
  ADS.setComparatorPolarity(0);
  ADS.setComparatorLatch(1);
  ADS.setComparatorQueConvert(0);
  ADS.setComparatorThresholdLow(2000);
  ADS.setComparatorThresholdHigh(30000);

}

void loop()
{
  int16_t val_0 = ADS.readADC(0);   // code works as intended if here

  if (do_thing) {
    // int16_t val_0 = ADS.readADC(0);   // code doesn't work as intended if here

    Serial.println("foo");
    do_thing = false;
  }
}

void foo() {
  do_thing = true;
}

Read 4 channel asynchronous

Hi ,

How can I read 4 channels asynchronus ?
The problem is the readout for each value see line below ;

 int16_t value = ADS.getValue(i); 

and gives the following error ; "invalid types 'int16_t {aka int}[int]' "

I have the followiing sketch to test ;

//

#include "ADS1X15.h"

ADS1115 ADS(0x48);
float f = 0;

void setup()
{
  Serial.begin(115200);
  Serial.println(__FILE__);
  Serial.print("ADS1X15_LIB_VERSION: ");
  Serial.println(ADS1X15_LIB_VERSION);

  ADS.begin();
  ADS.setGain(0);
  f = ADS.toVoltage();      // voltage factor
  ADS.requestADC(0);
}

void loop()
{
  if (ADS.isBusy() == false)
  {
    for (int i = 0; i < 4; i++) {
      int16_t value = ADS.getValue(i);
      ADS.requestADC(i);  // request a new one
      Serial.print("\tAnalog0: ");
      Serial.print(value[i]);
      Serial.print('\t');
      Serial.println(value[i] * f, 3);
    }
  }
  // simulate other tasks...
  delay(2000);
}

// -- END OF FILE --

Klass

Error during compiling

I'm receiving the following error when compiling a program which uses the ADS1X15.h file:
Compilation error: call to 'bool Adafruit_ADS1X15::begin(uint8_t, TwoWire*)' uses the default argument for parameter 1, which is not yet defined

Specifically it is coming in twice as follows:
In file included from G:\My Drive\My Documents\3D Print Files\Analyzer\files\o2_analyzer\o2_analyzer.ino:25:0:
C:\Users\bridg\OneDrive\Documents\Arduino\libraries\Adafruit_ADS1015/Adafruit_ADS1015.h:157:31: error: expected primary-expression at end of input
bool begin(uint8_t i2c_addr = ADS1X15_ADDRESS, TwoWire wire = &Wire);
^
G:\My Drive\My Documents\3D Print Files\Analyzer\files\o2_analyzer\o2_analyzer.ino: In function 'void setup()':
G:\My Drive\My Documents\3D Print Files\Analyzer\files\o2_analyzer\o2_analyzer.ino:98:13: error: call to 'bool Adafruit_ADS1X15::begin(uint8_t, TwoWire
)' uses the default argument for parameter 1, which is not yet defined
ads.begin(); // ads1115 start
^

exit status 1

Can anyone explain how I can resolve this error (I'm very new, sorry if this is an easy fix I just don't know how to do yet)?

Thank you.

ADS1013 broken

Nevermind - in case someone runs across an issue of the ADS1013 not apparently working correctly, keep in mind that it is a single channel only with one differential channel. One datasheet I have seems to elude that you can use both for single-ended purposes, and that is not the case.

Support for missing differential readings

Not supported differential reads in the chips are the

  • readADC_Differential_0_2()
  • readADC_Differential_1_2()

These might be implemented in the future.
Similar for the request...() functions.

int16_t readADC_Differential_0_2()
{
  return ADS.readADC(2) - ADS.readADC(0);
}

int16_t readADC_Differential_0_2()
{
  return ADS.readADC(2) - ADS.readADC(0);
}

ADS1115 Data Rate question

Hello Rob, firstly thank you for the library and your effort.
I have an issue regarding the data rate in the library, when I set the data rate to a slowest rate value for example 4 it does not respond with 128 samples/second, it gives around 250~300.
Also when I set the rate to 7 (860 samples/second) it gives around 817 sps, please find the below the snippet of code I'm using, I need to know the source of the problem, is it a hardware issue or software, thank you in advance.

Environment:

  • ESP32
  • ADS1115

Arduino Code:

#include "ADS1X15.h"

ADS1115 ADS(0x48);
float f = 0;
volatile bool convReady = false;

void convReadyAlert(){
   convReady = true;
}
void setup() 
{
  Serial.begin(115200);
  Serial.println(__FILE__);
  Serial.print("ADS1X15_LIB_VERSION: ");
  Serial.println(ADS1X15_LIB_VERSION);
  
  ADS.begin(21,22); // SDA, SCL
  ADS.setGain(1);     
  ADS.setDataRate(4);  // DATA RATE
  ADS.setMode(0); 
  // set the thresholds to Trigger RDY pin
  ADS.setComparatorThresholdLow(0x0000);
  ADS.setComparatorThresholdHigh(0x8000);
  ADS.setComparatorQueConvert(0);             // enable RDY pin !!
  
  pinMode(23, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(23), convReadyAlert, RISING);
  ADS.requestADC(0);
}

void loop() 
{
  if (convReady)
  { 
    int16_t val_0 = ADS.getValue();
    Serial.print("\Value: ");
    Serial.println(val_0 * f, 3);
    convReady = false;
    ADS.requestADC(0);
    
  }
}

wire speed

hi

first: thank you for this library =)

I tested it today and found that the wire speed has a great influence on microcontroller performance.
One factor is the time needed to transmit the data, but the other is the time it take to handle the pull-requests (aka ADS.isready) to the ADS1X15.

I was able to set the wire speed up to 1.2 MHz (adafruit feather M0 adalogger). The program was able to make pull-requests around 14'000 times per second and change the DAC output as often, while reading 600 samples per second from an ADS1115. At 400 kHz it managed to do that only around 6'000 times per second.

When i changed the code so that it would only do pull-requests every four cycles it did rund almost times faster.

Is it possible to increase the speed further?
The ADS1X15 does have an high speed mode at up to 3.4 MHz, but I am not sure if the wire can run that fast.
(I did test different pullups on SCL and SDA. There was no difference between 10k and 1.5 k Resistors)

Cannot change address

Hi, I am developing a customized PCB that uses ESP32S3 SoC and communicate with an ADS1115 via I2C on PlatformIO. I happened to have the address of my ADS1115 set to 0x49 by connecting the ADDR pin to VDD. Therefore, I used the following code to define my ADS1115 object:

ADS1115 ads(0x49);

I then have the following code to check if the connection is success in setup():

if (!ads.isConnected())
{
	ESP_LOGE(TAG, "Failed to initialize ADS1115.");
	while (1);
}
ESP_LOGV(TAG, "ADS1115 initialized.");

However, this doesn't seem to work since I am receiving the following message from my serial port:

[ 1206][E][main.cpp:109] sensorInit(): [MY_APP] Failed to initialize ADS1115.

In contrast, if I use a normal ESP32S3 devkit and a commercial-available ADS1115 module that pulls down ADDR, I can modify the code to either one of the following and make it work:

ADS1115 ads(0x48); // First approach
ADS1115 ads; // Second approach

The example of the successful output:

[ 1215][V][main.cpp:112] sensorInit(): [MY_APP] ADS1115 initialized.

I also noticed the following comment in ADS1X15.h

//  allow compile time default address
//  address in { 0x48, 0x49, 0x4A, 0x4B }, no test...
#ifndef ADS1015_ADDRESS
#define ADS1015_ADDRESS                   0x48
#endif

Does that mean that it is expected to see this behavior with a non-default address?

Thank you very much!

4channel continues read

I cannot find a way to get the continues read example to 4 channels (or even dual ads1115)

How to select the channels to readout ? there is only (ADS.getLastValue()); ?

How to check if the data rate is correct?

Hi, I just bought an ADS 1015, and I set the data rate to option 1 in the code. However, when I read the serial output with my laptop, the data rate looks lower than the target rate. For instance, it will give me about 160Hz while it is set to 250Hz. So, how do you check if you acquire the correct data rate? Thanks.

#include "ADS1X15.h"

// choose you 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);

  ADS.begin();
  ADS.setGain(1); // 6.144 volt
  ADS.setDataRate(1);
  Serial.println("Voltage");
  ADS.requestADC(0);
}

void loop()
{
  if (ADS.isReady())
  {
    int16_t value = ADS.getValue();
    ADS.requestADC(0);
    Serial.println(value);
  }
}

Differential continuous mode

Sorry for writing it as an issue ... i did see your example for differential cont mode reading 0-1 & 0-2. And also your discussion about this in issue #29

Im still unsure about the following:

If i read just one pair in continuous mode, do i still need the interrupt?

Cause this doesnt work in my case:

ADS.setMode(CONT);
ADS.requestADC_Differential_0_1();

and in loop

ADS.getValue();

I understand that this could cause reading the same value multiple times without the Int, but does your library work without the int? In my case i need the sample at a given time, so it doesnt matter if it is the last or a new one.

In single channel polling it should be not necessary to do a requestADC_Differential_0_1() after every getValue(), no?

and 2nd ... for the interrupt its necessary to connect the ADS int pin to one of the arduino inputs, right?

(added link to issue reference + code tags)

Library compatible for STM32F407

Hey,
i'm using your Library with PlatormIO on my Black STM32F407VE. It works good, but the Datarate is a bit too low. I only archive 1375 SPS with the ADS1015.

int x;
int16_t result[600];
long start, end;

void setup()
{
  Serial.begin(115200);
  Serial.println(__FILE__);
  Serial.print("ADS1X15_LIB_VERSION: ");
  Serial.println(ADS1X15_LIB_VERSION);

  ADS.begin();
  ADS.setGain(0);  // 6.144 volt
  ADS.setDataRate(7);
  ADS.setWireClock(400000);

}

void loop()
{
    start = micros();
  for (int i = 0; i < 600; i++)
  {
    
    result[i] = ADS.readADC_Differential_0_1();
    
  }

  end = micros();

  for (int i = 0; i<600; i++){
    Serial.print("Differential: "); Serial.print(result[i]); Serial.print("("); Serial.print(ADS.toVoltage(result[i])); Serial.println("mV)");
  }
  Serial.print("Dauer pro Messung in Mikrosekunden:\t");
  Serial.println((end - start)/600.);

  Serial.println("\nDone...");
  delay(2000);
}

Do you know, where my Problem is?

Thank you very much!

Add code for Comparator mode

Library supports normal ADC and Differential measurements. The ADS 1014/1015/1114/1115 have also a Comparator mode.

  • config field to indicate Comparator supported
  • get/set ComparatorMode(..)
  • get/set Polarity
  • get/set Latch
  • get/set low + high threshold
  • example how Comparator can be used.
  • check optional differences between the 4 devices worth to support (other than #pins)

ADS1115 reading

hello, I'm working on a project where Im using the ads1115 with esp32 .
Im using ESPIDF v4.2 in let me know if you getting feel any update or need to change here.

	// Select configuration register(0x01)
	// AINP = AIN0 reading voltage 
	// Continuous conversion mode, 128 SPS(0xC1, 0x83)

hardware is fine and working I checked in Arduino IDE but here I'm only getting reading 0x5E, 0x5E

static esp_err_t i2c_master_sensor_test(i2c_port_t i2c_num, uint8_t *data_h, uint8_t *data_l)
{
    int ret;
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, 0x90, 0x01);
    i2c_master_write_byte(cmd, 0x01, 0x01);
    i2c_master_write_byte(cmd, 0xC1, 0x01);
    i2c_master_write_byte(cmd, 0x83, 0x00);
    i2c_master_stop(cmd);
    ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);
    if (ret != ESP_OK) {
        return ret;
    }

    vTaskDelay(30 / portTICK_RATE_MS);
    cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, 0x91, 0x01);
    i2c_master_write_byte(cmd, 0x00, 0x01);
    i2c_master_read_byte(cmd, data_h, 0x00);
    i2c_master_read_byte(cmd, data_l, 0x01);
    i2c_master_stop(cmd);
    ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);

    printf(" >> data_h: %X\n", *data_h);
    printf(" >> data_l: %X\n", *data_l);
    return ret;
}

(added code tags for readability)

Alternate I2C/TWI library or library abstraction layer

Hello Rob,

Thank you for your ADS1X15 library! Your work helped me test the performance of the ADS1015 and confirm that it will work well for my needs.

My organization has an existing ATmega328P (AVR) codebase with a custom I2C library, and I needed to add ADS1015 support to our application. The MIT licensing of your library could work for us. We couldn't use the underlying Arduino or Wire (TwoWire) libraries, though.

Are you aware of alternate I2C libraries with MIT or BSD or similar licensing that implement the same interface as the Wire library, so that your ADS1X15 library could operate unmodified? My searches weren't fruitful.

Is there a possibility of abstracting the I2C access so that the user of the library could provide their own adapter between the available I2C library and your ADS1X15 library? This idea is inspired by how the U8g2 display library can be ported to new platforms. (This worked very well for me just recently.)

Is the idea of forking your library and replacing the Wire function calls with similar calls into my custom I2C library sensible? The fork would be publicly accessible as is your library. It would have function calls into my private I2C library, though, and therefore wouldn't be useful to others.

Is the best approach for me to write my own ADS1015 library upon my custom I2C library? While this likely would require the most time investment, the questions surrounding licensing would be simpler.

Thank you for your work and your ideas/suggestions!

Gratefully,
Tim Mason

ALRT Pin number?

This really isn't a issue, but I can't find what pin on the MCU the library looks at for reading the data ready state/pin. Am I just missing it? Is there a way to set the pin it watches? Thanks

Differential input and gain for maximum precision.

Hi, I have a question about the gain and differential. There is a voltage that varies around a bias. I want to measure this voltage in reference to the bias with as much precision as possible. If I use the differential input will the gain setting amplify the result of the differential and therefore improve precision or will it amplify the inputs and then get the differential voltage?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.