-
-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Synchronous mode very slow #53
Comments
Thanks for this issue, The speed of 860 sps can only be reached in continuous mode and using interrupts to signal when data is ready. See example. Both sync an async methods loosing quite some time with polling the status. Did not study that in detail. 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. |
You could try the async code without the yield() call. |
Differential might indeed be slower as one need to make two samples and compare them. |
Similar / related - #49 |
Learned from data sheet today: |
From data sheet So reading a differential 0_1 should be as fast as reading a single channel. |
Thanks for the quick reply!... BTW, nifty little library you have written :) Regarding the time cost of So moving along... I've dug through the data sheet (what else would anyone want to do at 2am hahaha) and back to more empirical testing ofcourse... I've switched to continuous mode to figure out the cost of single shot sampling the following code sequence worked:
In continuous mode, getting the next sample over I2C takes 250 micros (or 0.25 millis) understanding that the data rate limits set still apply so while the Next I looked at benchmarking the single channel mode, there doesn't appear to be any significant difference between differential mode and single channel mode, the So, single shot mode appears to have a read penalty at the application level of 6250 micros (or 6.25 millis). I can't tell if the ADS1115 itself is responsible, but on p21 of the spec sheet it says
although it's an assumption that something specific to 'duty cycle' might apply to existing sleep mode... the call to So there is quite a delta between the claim and the facts on the ground... From what I can tell from your code, there is not much else you could do but read/write the registers, which you do. I2C could be a factor if we are saturating the bus but adding a few micros delay between each isReady() should solve that problem (it doesn't!), lower I2C bus speeds will increase the timings but in a non-linear fashion. I don't have a $10,000 logic analyzer to dig into the bus workings, but I'd say the I2C bus looks good, the clock stretching observed is marginal... the rest who knows. So is TI misrepresenting single shot mode?... would be something then ... grasping at straws here... it would not be the first time that the $2 board is using a fake chip and is not the genuine TI chip (well that never happens) ... |
The OP for #49 has a more severe case theoretically as there 3 inputs are being used. So his issue(s) if any should arise from multiplexing the inputs, all commercial ADCs seem to do that so when all the inputs are used, the theoretical bandwidth is never attainable, well not on these low end ADCs anyway. In differential mode I would have expected them to include circuitry similar to an instrumentation amplifier with good common mode rejection, etc, I guess they are multiplexing the input in differential mode as well. Be that as it may, my situation and testing on the differential mode is yielding dismal results and certainly not within any reasonable tolerance or expectation vis-a-vis the often touted bandwidth. The spec sheet is unhelpful as it seems to repeatedly refer to its maximum bandwidth without qualifying it properly in context, well at least they are not using dBs like many spec sheets to further hamper most people lol. In my estimation, the issue is not with your library, it's the chip. I regularly use and buy TI as their quality has been one of the best over the years, so not sure what gives with this ADS1115. The ADS1115 offers a lot of features which under the right circumstances would simplify circuit design so I get where they are going with it, however, the ADS1115s I have, just don't perform anywhere near what they could/should. As I said before, I also suspect that our el-cheapo boards are not using genuine TI chips... a conversation for another day of course, needless to say "they" copy everything so why not ADS1115... how else could you buy these boards for $2/piece on Aliexpress and resell them on eBay for $15 ;)... it's a wonderful conspiracy theory of course and now I sound like an apologist for TI :)) Some day I may just create a prototype board with an ADS1115 which I know to be genuine TI, however a quick look on digikey reveals that the SPI based ADS7816 would likely be a better performer in a custom implementation. |
thanks! |
Use of the RDY flag with an interrupt may solve this pretty well as the interrupt comes when new data is ready.
ADS7816 is "only" 12 bit - https://www.ti.com/product/ADS7816 Or ADS1118 16 bit - https://www.ti.com/product/ADS1118 ADS1118ADS1115(Sorry, don't have a library for the 1118 ) |
Did some test today UNO (16 MHz) Sketch ADS_performance.ino, slightly modified to include I2C speed setting and SPS calculation. //
// FILE: ADS_performance.ino
// AUTHOR: Rob.Tillaart
// PURPOSE: read analog input
// URL: https://github.com/RobTillaart/ADS1X15
// test
// connect 1 potmeter
//
// GND ---[ x ]------ 5V
// |
//
// measure at x (connect to AIN0).
#include "ADS1X15.h"
// choose your sensor
// ADS1013 ADS(0x48);
// ADS1014 ADS(0x48);
// ADS1015 ADS(0x48);
// ADS1113 ADS(0x48);
// ADS1114 ADS(0x48);
ADS1115 ADS(0x48);
uint32_t start, d1, d2;
int x;
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("ADS1X15_LIB_VERSION: ");
Serial.println(ADS1X15_LIB_VERSION);
ADS.begin();
Wire.setClock(400000);
ADS.setGain(0); // 6.144 volt
for (int dr = 0; dr < 8; dr++)
{
// 0 = slow 4 = medium 7 = fast
ADS.setDataRate(dr);
Serial.print("DR:\t");
Serial.println(dr);
test_single_shot();
test_continuous();
Serial.print("\t\tFACTOR:\t");
Serial.println(1.0 * d1 / d2);
}
Serial.println("\nDone...");
}
void loop()
{
}
void test_single_shot()
{
Serial.print(__FUNCTION__);
ADS.setMode(1);
start = micros();
x = ADS.readADC(0);
for (int i = 0; i < 100; i++)
{
x = ADS.readADC(0);
}
d1 = micros() - start;
Serial.print("\t");
Serial.print(d1);
Serial.print("\t\t");
Serial.println(100000000.0 / d1);
delay(100);
}
void test_continuous()
{
Serial.print(__FUNCTION__);
ADS.setMode(0);
start = micros();
x = ADS.readADC(0);
for (int i = 0; i < 100; i++)
{
x = ADS.getValue();
}
d2 = micros() - start;
Serial.print("\t\t");
Serial.print(d2);
Serial.print("\t\t");
Serial.println(100000000.0 / d2);
delay(100);
}
// -- END OF FILE -- Put it into a table:
Synchronous calls I2C 400 KHz
Synchronous calls I2C 600 KHz
These are maxima of the SPS feasible, they do not include further processing. |
If no questions remain, you may close the issue. |
Hi,
Based on reading the docs I set up an ADS1115 with the following:
I access the sampler asynchronously using:
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"
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?
The text was updated successfully, but these errors were encountered: