ADS1115 high speed data rate

Hi,
I need support to increase the sample rate speed of ADS1115 using the library "Adafruit_ADS1015.h" and an ESP32 module.
I am using the example included in the library for differential measure.
The only changes made are:

  • Serial.begin(115200)
  • gain rate: setGain(GAIN_FOUR)
  • setDataRate(RATE_ADS1115_860SPS) using HEX number 0x00E0

Using command "micros()" before and after the line...
results = ads.readADC_Differential_0_1();
...I misured the time to take the value from my sensor: ~7.5ms.
With 860 sps the time should be ~1.2ms.

Have you any suggestion to reach the higher speed?
it is not mandatory use the same library, but it is almost mandatory use 1 module ADS1115!

Surfing in the web I found this post where "pylon" suggest to change the library:
see the ref. link

You will have to change the library:

On line 154 replace ADS1015_REG_CONFIG_DR_1600SPS by ADS1015_REG_CONFIG_DR_3300SPS.
On line 104 replace ADS1115_CONVERSIONDELAY by 1.

So you might get up to 860 Hz.

Someone can explaine me where I found the lines mentioned in the post?
I didn't found in the library adafruit these commands!!!

Thanks!

No. You will be fortunate if you can realize the maximum rate of 860 SPS.

I am sorry for misunderstanding, that question was only the title of the linked page!!!!
I know that the max is 860 sps. My question is: how to reach it? what I have to modify from original example of the library?
tkx

Please do not modify your original post after getting feedback. It makes the thread difficult to impossible for others to follow.

Post your code, using code tags, and post a link to the exact ADS library you are using.

If you print anything in the sample loop, you probably cannot achieve the expected sample rate.

Maybe if you explain for what application you need that sampling. The most of the applications are good for the ADS1115. If you need some more "powerfull" in sampling, check another options with SPI interface like ADS5484

I am sorry!

I am measuring the signal 50Hz of +-1V from a sensor SCT013-050.
Here the library:
Adafruit_ADS1x15

Here the sketch used,
at the end I wrote the speed in us
I found the same speed also with the "Serial.println" inside the "for"

#include <Adafruit_ADS1X15.h>
#define RATE_ADS1115_860SPS (0x00E0)
Adafruit_ADS1115 ads;  /* Use this for the 16-bit version */
int16_t results;
unsigned long t[30];

void setup(void)
{
  Serial.begin(115200);
  Serial.println("Getting differential reading from AIN0 (P) and AIN1 (N)");
  Serial.println("+/- 1.024V  1 bit = 0.5mV    0.03125mV");
  ads.setGain(GAIN_FOUR);       // 4x gain   +/- 1.024V  1 bit = 0.5mV    0.03125mV
  ads.setDataRate(RATE_ADS1115_860SPS);

  if (!ads.begin()) {
    Serial.println("Failed to initialize ADS.");
    while (1);
  }}

void loop(void)
{
  delay(2000);
  for (int i = 0; i < 16; i++) {
    t[i] = micros();
    results = ads.readADC_Differential_0_1();
    //Serial.println(micros()-t[i]);
  }
  for (int i = 0; i < (16-1); i++) {
    Serial.println(t[i+1]-t[i]);
  }
}
/*
 * Results:
 * 32715us setDataRate = default
 *  7495us setDatarate = 860sps
 */

Yes, I know that SPI is better.
Is it impossible to reach the speed 860sps by I2C with ADS1115?

Undoubtedly not. The data sheet is a legal document, and it clearly states that 860 SPS is supported.

You are assuming that your particular configuration, leaving most of the defaults intact (I2C clock rate, ADS1x15 defaults) intact, should reach that rate, and that is probably incorrect.

Note that the differential conversion requires reading two channels, and the default setting is "single shot". You may have better luck reading a single channel after setting it to continuous conversions. Also set the I2C clock to 400 kHz.

Read the data sheet carefully for more options, such as high speed I2C communications.

I come back with a lot of trial done during my few free time!

Best performance reached with ADS1X15 Rob Tillaart library (ADS1X15_LIB_VERSION: 0.3.7) with following code:

#include "ADS1X15.h"
#include <Wire.h>

ADS1115 ADS(0x48);

int clockFrequency = 800000;
int16_t results[30];
unsigned long t[30];

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

  Wire.begin();
  Wire.setClock(clockFrequency);
  
  ADS.begin();
  ADS.setGain(4);      // 1.024 volt
  ADS.setDataRate(7);  // fast
  ADS.setMode(1);      // 0=continuous mode; 1=single
}

void loop()
{
  delay(2000);
  for (int i = 0; i < 5; i++) {
    t[i] = micros();
    results[i] = ADS.readADC(0);
  }
  for (int i = 0; i < (4); i++) {
    Serial.print(results[i]);
    Serial.print("\t");
    Serial.println(t[i+1]-t[i]);
  }
  Serial.println("");
}

Here below the time to read the sensor in micro seconds with some modifications:

* clockFrequency = 100000; & setMode(0);
8986
9000
9000
9000
* clockFrequency = 400000; & setMode(0);
8268
7985
8000
8000
* clockFrequency = 400000; & setMode(1);
6709
6690
6689
6683
* clockFrequency = 800000; & setMode(1);
6572
6596
6587
6591
* clockFrequency = 2000000; & setMode(1);
6573
6586
6589
6591
* clockFrequency = 3400000; & setMode(1);
6572
6582
6589
6583

Thoughts and questions:

  1. According to the technical datasheet of ADS1115 https://www.ti.com/lit/ds/symlink/ads1115.pdf (SPS output rate using ads1115 - #2 by gilshultz) are defined 3 levels of clock speed: 100kHz, 400kHz (fast mode) and 3.4MHz (high speed mode). I reach the best performance at 800kHz with 150 SPS. Higher freq doesn't give advantages.
    Are there any command to speedup really the clock?

  2. 860 SPS are very far from my situation! where is the bottleneck? any suggestions?

  3. Could be that the ADS1115 goes in power-down state and goes on slowly? How to avoid to enter in power-down state?

Thanks for your support

Why have you set single shot mode? What happens with continuous?

with continuous mode the time is higher.
In my post I have written the results with some combinations: with freq 400kHz setMode(0) is slower than setMode(1), 8 vs 6,7 us!

Once again "use the source" - look at the library source code to see what is happening.

What processor are you running? In single shot mode the library code does a yield() call. On a classic AVR based Arduino this is basically a no-op. On an ESP8266 this gives up control of the processor to the background processing (WiFi etc) for an indeterminate amount of time. Not sure what an ESP32 does, since it has dual cores and the background tasks usually run on a different core than "user" code.

In continuous mode the library code does an unconditional delay of 8ms, which limits the max rate to 125 SPS.

thank you oldcurmudgeon,
if I have well understood the limit could be my ESP32 board.

In continuous mode the library code does an unconditional delay of 8ms, which limits the max rate to 125 SPS.

Is it possible reduce the dalay of 8 ms?

Change to a different library that doesn't do that. For example ADS1115_WE by Wollenwald.

Single shot mode will not get to the maximum data rate - from the data sheet...

The ADS111x have two available conversion modes: single-shot and continuous-conversion. In single-shot
mode, the ADC performs one conversion of the input signal upon request, stores the conversion value to an
internal conversion register, and then enters a power-down state. This mode is intended to provide significant
power savings in systems that only require periodic conversions or when there are long idle periods between
conversions. In continuous-conversion mode, the ADC automatically begins a conversion of the input signal as
soon as the previous conversion is completed. The rate of continuous conversion is equal to the programmed
data rate. Data can be read at any time and always reflect the most recent completed conversion.

The ALERT/RDY pin can be used to indicate the end of conversion, so you know when to read the data. See the examples with the library above.

1 Like

Here is code that I modified from the example.

/***************************************************************************
* Based on example sketch Conv_Ready_Alert_Pin_Controlled 
* from the ADS1115_WE library
*
* See the example for more omformation I have deleted most of the
* comments to limit the length of the text
*
* This sketch shows how you can use the alert pin as conversion ready alert pin.
* It works in continuous mode 
* Please note that you need to enable the alert pin with setAlertPinMode. Choose any 
* parameter except ADS1115_DISABLE_ALERT.
*  
* Further information can be found on:
* https://wolles-elektronikkiste.de/ads1115 (German)
* https://wolles-elektronikkiste.de/en/ads1115-a-d-converter-with-amplifier (English)
* 
***************************************************************************/
#include <Streaming.h>   //  from "Streaming by Mikal Hart" in library manager

#include<ADS1115_WE.h> 
#include<Wire.h>
#define I2C_ADDRESS 0x48

volatile bool convReady = false;

ADS1115_WE adc = ADS1115_WE(I2C_ADDRESS);

#ifdef ESP8266
// setup for esp8266
const uint8_t interruptPin = D5;  // pin2 is default SDA 
// Interrupt service routine for external interrupt 
// Make sure it is in RAM
void IRAM_ATTR convReadyAlert(){
   convReady = true;
}
#else
  // assume an AVR UNO, MEGA, classic NANO etc
const uint8_t interruptPin = 3;  
void convReadyAlert(){
   convReady = true;
}
#endif

struct ConvertData {
  uint32_t cvtTime;
  float    voltage;
  } ;

ConvertData readData[4];   
unsigned long oldTime,currTime;

void setup() {
  Wire.begin();
  Wire.setClock(400000);
  Serial.begin(9600);
  pinMode(interruptPin, INPUT_PULLUP);
  if(!adc.init()){
    Serial.println("ADS1115 not connected!");
  }

  /* Set the voltage range of the ADC to adjust the gain
   * Please note that you must not apply more than VDD + 0.3V to the input pins!
  */
  adc.setVoltageRange_mV(ADS1115_RANGE_6144); //comment line/change parameter to change range

  /* Set the inputs to be compared
  */
  adc.setCompareChannels(ADS1115_COMP_0_GND); //comment line/change parameter to change channels

  adc.setAlertPinMode(ADS1115_ASSERT_AFTER_1); //needed in this sketch to enable alert pin (doesn't matter if you choose after 1,2 or 4)

  /* Set the conversion rate in SPS (samples per second)
  */
  adc.setConvRate(ADS1115_860_SPS); //comment line/change parameter to change SPS

  adc.setMeasureMode(ADS1115_CONTINUOUS); // the conversion ready alert pin also works in continuous mode

  adc.setAlertPinToConversionReady(); //needed for this sketch

  Serial.println("ADS1115 Example Sketch - Continuious, Conversion Ready Alert Pin controlled");
  Serial.println();
  attachInterrupt(digitalPinToInterrupt(interruptPin), convReadyAlert, FALLING);
  oldTime = micros();
}

uint8_t count;
void loop() {
  count = 0;
  while(count<4) {  // get 4 readings
    if(convReady){
      currTime = micros();
      readData[count].voltage = adc.getResult_V(); // alternative: getResult_mV for Millivolt
      readData[count].cvtTime = currTime - oldTime;
      count++;                  // get next reading
      oldTime = currTime;
      convReady = false;  //reset ready indicator
      }
        
  }
  Serial<<"Time uSec  Voltage"<<endl;
  for (uint8_t i=0;i<4;i++) {  // display 4 readings
    Serial <<readData[i].cvtTime <<"  "<< readData[i].voltage <<endl;
  }
  delay(1000);  // delay to change voltage
  convReady = false;  //reset ready indicator
  oldTime = micros();
}

Here is some output from an ESP8266.
Time uSec Voltage
80 0.15
1215 0.15
1216 0.15
1216 0.15
Time uSec Voltage
78 0.28
1216 0.28
1215 0.28
1216 0.28
Time uSec Voltage
80 1.41
1216 1.41
1216 1.42
1216 1.42
Time uSec Voltage
76 2.81
1216 2.81
1215 2.81
1216 2.82
Time uSec Voltage
74 3.28
1216 3.28
1216 3.28
1216 3.28

The first time is low because apparently a conversion was almost complete. The rest are about 1.216msec which is a sample rate of about 822 SPS

2 Likes

great oldcurmudgeon,
It seems perfect!
I will try with my ESP32 and I will post the results.
thanks

Hi, good news, I confirm that the sketch of oldcurmudgeon is correct
these are my results:

104  -0.02 
1250  -0.00
1251  0.01 
1250  0.02 
1251  0.03 
1251  0.03 
1250  0.03 
1251  0.03 
1250  0.01 
1251  0.00 
1251  -0.01
1250  -0.02
1251  -0.03
1250  -0.04
1251  -0.03
1250  -0.03
1251  -0.02
1251  -0.00
1250  0.01 

The topic can be considered fixed!

thanks again oldcurmudgeon!

I just want to add to this discussion, that in my case it really was a bad or fake IC / module. Which was interesting, because the main IC even had the Texas Instruments Logo printed on it. But measuring the Alert/Ready pin with an oscilloscope showed that the timings where no where near the expected value (up to 6 times slower). And replacing the module with a certified one eliminated the error instantaneously.
I also want to add that switching between continuous and single shot mode made no big difference, other than the 25us start up time stated in the datasheet.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.