Comments (13)
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.
from ads1x15.
You could try the async code without the yield() call.
Do not know its overhead.
from ads1x15.
Differential might indeed be slower as one need to make two samples and compare them.
You need to check the datasheet what it tells about differential speed, I do not recall it from my head.
from ads1x15.
Similar / related - #49
from ads1x15.
The speed of 860 sps can only be reached in continuous mode and using interrupts to signal when data is ready.
Learned from data sheet today:
This is not 100% true, one could also set continuous mode and read the sensor with getValue() as often as possible, no need to wait for an interrupt. However one might read the ADC too often (==>results in same value).
from ads1x15.
Differential might indeed be slower as one need to make two samples and compare them.
You need to check the datasheet what it tells about differential speed, I do not recall it from my head.
From data sheet
So reading a differential 0_1 should be as fast as reading a single channel.
(not tested with hardware yet)
from ads1x15.
Thanks for the quick reply!... BTW, nifty little library you have written :)
Regarding the time cost of yield()
, that will depend on a number of runtime factors, in my case, given I am running a 133Mhz processor and not much else is going on while I read the sensor, with or without yield()
I get the same results.
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:
_ads-> requestADC_Differential_0_1(); // called only once at the beginning to kick things off ;)
.
.
.
unsigned long start=micros();
_ads->getValue();
unsigned long elapsed=micros()-start;
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 getValue()
is quicker, not each value read represents a "new" sample.
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 getValue()
still takes 250 micros.
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
an ADS111x in power-down state with a data rate set to 860 SPS can be operated by a microcontroller that instructs a single-shot conversion every 125ms (8 SPS). A conversion at 860 SPS only requires approximately 1.2 ms
although it's an assumption that something specific to 'duty cycle' might apply to existing sleep mode... the call to requestADC_Differential_0_1()
takes 160(ish) micros the rest comes from waiting. I have not benchmarked each isReady()
individually as I would expect reading the register on the ADS1115 would not throw outliers into the mix, well I could be wrong of course on the outliers :) So mileage for others may vary depending on the board and wiring/routing they use but at 400Hz I2C bus speed for my setup, those are the running times.
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) ...
from ads1x15.
Similar / related - #49
Yes similar in the sense that it's about user level performance or lack thereof. However, in my testing redefining ADS1115_CONVERSION_DELAY to a lower value has little impactl.
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.
from ads1x15.
BTW, nifty little library you have written :)
thanks!
from ads1x15.
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 getValue() is quicker, not each value read represents a "new" sample.
Use of the RDY flag with an interrupt may solve this pretty well as the interrupt comes when new data is ready.
SPI based ADS7816 would likely be a better performer in a custom implementation.
ADS7816 is "only" 12 bit - https://www.ti.com/product/ADS7816
Or ADS1118 16 bit - https://www.ti.com/product/ADS1118
Interesting as this ADS1118 data sheet does also describe the ADS1115 so I expect these to be very close related.
ADS1118
ADS1115
(Sorry, don't have a library for the 1118 )
from ads1x15.
Note ADS1118 == 3V3 device.
- https://electropeak.com/learn/interfacing-ads1118-16-bit-adc-module-with-arduino/
- https://github.com/denkitronik/ADS1118
from ads1x15.
Did some test today
UNO (16 MHz)
IDE 1.8.19
Sketch ADS_performance.ino, slightly modified to include I2C speed setting and SPS calculation.
(will be included in next release)
//
// 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 100 KHz
DataRate | Time 100 calls | SPS |
---|---|---|
0 | 12861340 | 7.78 |
1 | 6481396 | 15.4 |
2 | 3347512 | 29.9 |
3 | 1724380 | 58.0 |
4 | 941032 | 106 |
5 | 549204 | 182 |
6 | 381340 | 262 |
7 | 269448 | 371 |
Synchronous calls I2C 400 KHz
DataRate | Time 100 calls | SPS |
---|---|---|
0 | 12872804 | 7.77 |
1 | 6402848 | 15.6 |
2 | 3234156 | 30.9 |
3 | 1649272 | 60.6 |
4 | 862188 | 116 |
5 | 468652 | 213 |
6 | 271552 | 368 |
7 | 173412 | 577 |
Synchronous calls I2C 600 KHz
DataRate | Time 100 calls | SPS |
---|---|---|
0 | 12736788 | 7.85 |
1 | 6390104 | 15.7 |
2 | 3223568 | 31.0 |
3 | 1645768 | 60.8 |
4 | 852300 | 117 |
5 | 448520 | 223 |
6 | 261216 | 383 |
7 | 167660 | 596 |
These are maxima of the SPS feasible, they do not include further processing.
At least this test shows the effect of the I2C bus speed.
from ads1x15.
If no questions remain, you may close the issue.
(you can always reopen if needed or create a new topic.)
from ads1x15.
Related Issues (20)
- requestADC(pin); should have 0 as default, HOT 1
- ADS1115 reading HOT 14
- How to check if the data rate is correct? HOT 8
- ADS1115 on RP2040 Wire, 0x4B is busy HOT 14
- Arduino Micro and ADS1115 - 860SPS (Only on 1 channel ?) HOT 62
- Error during compiling HOT 5
- ESP32 work on Espressif 1.04 but No on Espressif 2,07 HOT 4
- [Query] Example for continuously reading all four channels at max sps? HOT 2
- Differential continuous mode HOT 12
- Cannot change address HOT 11
- ADS1115 value from one channel is being copied to the other HOT 6
- The use of Wire1 is not allowed for ESP32 or ESP8266 HOT 3
- Alternate I2C/TWI library or library abstraction layer HOT 8
- [question] About using ALERT RDY in ADS_continuous_differential.ino example. HOT 8
- getMaxVoltage() does not handle ADS1113 HOT 6
- interrupt driven reads HOT 6
- Differential input and gain for maximum precision. HOT 4
- wire speed HOT 22
- 10-12 Channel Continuous with interrupts. HOT 11
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ads1x15.