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!!!
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
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
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.
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?
860 SPS are very far from my situation! where is the bottleneck? any suggestions?
Could be that the ADS1115 goes in power-down state and goes on slowly? How to avoid to enter in power-down state?
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.
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.
/***************************************************************************
* 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
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.