-
-
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
Arduino Micro and ADS1115 - 860SPS (Only on 1 channel ?) #49
Comments
Thanks for the issue, I try to answer asap. |
To maximize the performance you need to run in continuous mode like in the example. |
ADS.setMode(0); is not continuos mode ? By the way, do I need to use the Alert pin ? Will that bring any benefit ? Thanks a lot for your answers. |
From phone, not near my pc, so some half answers. If I see correctly your code also measures the Serial print statement. Should assign the value to a var and print it outside the time measurement. Printing takes time too. Mode(0) is continuous mode, |
I've moved the prints to the end of the loop to save time, but still same performance. Everytime I read 3 channels my timing per channel jumps to ~6500 us. Tried mode 0, mode 1... nothing, both the same result. As soon as I reduce delays on readings and time goes under 6500, the conversion gets stuck and stops reading. I'm starting to think that with this ADS I can only get 1500 us using 1 channel and not switching to another.... |
Spend some time in the code of the library and the datasheet to refresh the mind. ADS1115_CONVERSION_DELAY#define ADS1115_CONVERSION_DELAY 8 Defines the number of milliseconds between the _requestADC() and the getValue() in the continuous mode. From the latest code. int16_t ADS1X15::_readADC(uint16_t readmode)
{
_requestADC(readmode);
if (_mode == ADS1X15_MODE_SINGLE)
{
while ( isBusy() ) yield(); // wait for conversion; yield for ESP.
}
else
{
delay(_conversionDelay); // TODO needed in continuous mode?
}
return getValue();
} There is still a TODO there to investigate this conversionDelay which has low prio as the continuous mode prefers the Async methods. SPSThe max SPS is the maximum number of conversions the chip can make. The 4 channels multiplex one ADC I2C clock speedThe ADS1x15 support up to 3.4 MHz I2C clock so setting it to the highest possible value supported by your board (and cabling/pull up etc) will gain some time. Continuous modeThe advantage of continuous mode is that you do not need to send requests saving (50%?) of the communications, except for an initial request to start the continuous mode. The performance of the continuous mode is defined by the ADS.setDataRate(7); function. In your sketch above (updated for highlighting) you are using readADC() which is an explicit blocking function. You should rewrite it to use getValue() - see examples. Main questionYour main question is "how should I read 3 channels of the 4 in continuous mode?". (my interpretation). Interesting, at least as I never tried it has some challenges. Need to think that over how that could be done. (to be continued) |
3 channel thoughtsDon't know which is acceptable for you, but here some thoughts. Alternative 1:The continuous mode will "rotate" over the 4 channels with 860 SPS. Alternative 2:The continuous mode will "rotate" over the 4 channels with 860 SPS. Alternative 3:The continuous mode will "rotate" over the 4 channels with 860 SPS. Alternative 4:If performance need to be higher, consider other ADC - see my MCP_ADC lib for substantial faster ADC's which uses the SPI bus which is much faster than I2C on average. Those have less resolution, that is the price ... (to be continued) |
Did some coding and test with
//
// FILE: ADS_continuous_3_channel.ino
// AUTHOR: Rob.Tillaart
// PURPOSE: read multiple analog inputs continuously
// interrupt driven to catch all conversions.
// URL: https://github.com/RobTillaart/ADS1X15
// https://github.com/RobTillaart/ADS1X15/issues/49
//
// experimental, not tested extensively
// test
// connect multiple potmeters
//
// RDY ----------------- pin 2 (for IRQ)
//
// GND ---[ x ]------ 5V
// |
// |
// ADS(n)
//
// measure at x - connect to AIN0..3.
//
// for the test it is an option to have AIN3 connected to 5V and AIN4 to GND
// so one can see these as references in the output.
//
// has an issue with the index of the channels. not not investigated yet.
#include "ADS1X15.h"
// choose your sensor
// ADS1013 ADS(0x48);
// ADS1014 ADS(0x48);
// ADS1015 ADS(0x48);
// ADS1113 ADS(0x48);
// ADS1114 ADS(0x48);
ADS1115 ADS(0x48);
volatile bool RDY = false;
uint8_t channel = 0;
int16_t val[4] = { 0, 0, 0, 0 };
int SPS = 0;
uint32_t lastTime = 0;
void setup()
{
Serial.begin(230400); // <<<<<<<<< fast!
Serial.println(__FILE__);
Serial.print("ADS1X15_LIB_VERSION: ");
Serial.println(ADS1X15_LIB_VERSION);
pinMode(2, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(2), adsReady, RISING);
Wire.setClock(800000);
ADS.begin();
ADS.setGain(0); // 6.144 volt
ADS.setDataRate(7);
// SET ALERT RDY PIN
ADS.setComparatorThresholdHigh(0x8000);
ADS.setComparatorThresholdLow(0x0000);
ADS.setComparatorQueConvert(0);
// SET INTERRUPT HANDLER TO CATCH CONVERSION READY
pinMode(2, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(2), adsReady, RISING);
ADS.setMode(0); // continuous mode
channel = 0;
ADS.requestADC(channel); // start at 0
}
void loop()
{
// if conversion ready
// request a new one and print the last one.
if (RDY)
{
SPS++;
val[channel] = ADS.getValue();
// request next channel asap
channel++;
if (channel >= 3) channel = 0;
ADS.requestADC(channel);
RDY = false;
// to see it works
if (SPS % 200 == 0)
{
for (int i = 0; i < 4; i++)
{
Serial.print('\t');
Serial.print(val[i]);
}
Serial.println();
}
}
// print the SPS
if (millis() - lastTime >= 1000)
{
lastTime = millis();
Serial.print("SPS: ");
Serial.println(SPS);
SPS = 0;
}
}
// interrupt service routine
// kept as minimal as possible
void adsReady()
{
RDY = true;
}
// -- END OF FILE --
The output was pretty stable at ~831 SPS for 3 channels = ~275 SPC
If I write every line the SPS drops into the 500 something range. |
Added the example above in the develop branch to be merged soon. |
#50 - PR created ==> green |
Thanks a lot for all the info @RobTillaart, I really appreciate it. Regarding to your question: Q: what board do you use? We are using an Arduino Leonardo Micro. I think these boards have a 400Mhz limit on the I2C, but not sure. Will give your example a try to see if it runs on my Leonardo micro. |
By the way, on your code I see this 2 lines repeated during the setup, not sure if it's on purpose or not:
|
I have to switch the interrupt pin to 7 (2 is used for SDA/SCL in Leonardo and also reduce the SPS % to 150 because if I leave it on 200 I get no results. So:
Results:
I'm starting to think my ADS1115 is failed/not original or something like that. Cause I can only get ~860 SPS when using single channel readings.... |
Probably my mistake, had too many issues under attention today. |
Sure @RobTillaart, no hurry at all. Thanks for your time by the way. |
Additional testing: If I leave 2, 3 or 4 channels in all cases the result is the same (it doesn't matter how many, as soon as I add the channel switching):
As soon as I remove channel switch, just commenting this 2 lines:
My conclusion: It seems like channel switch is returning the SPS values to "default" or, my ADS1115 is wicked :) |
Weird, and you are using the ADS_continuous_3_channel.ino I posted above?
Changed it in the example in the develop branch, thanks. |
Hi @RobTillaart, yes, I made a couple of changes but nothing significant if I'm not wrong. Will add the code here tomorrow. By the way, on /examples/ADS_continuous_4_channel/ADS_continuous_4_channel.ino you have another mistype if I'm not wrong, in the comments, line 50:
7 is not slow, is faster. Just my 2 cents :) Will come back tomorrow with more testing and my code. Thanks. |
In case of a mismatch between code and comment, code always wins. 😁 |
Comment fixed in all examples -> in develop branch |
Hi @RobTillaart , yes , I've tested with and without pull up, still stuck on 152 max speed when switching channels, no matter if it's 2, 3 or 4 channels. And tested single shot and continuous mode. No luck unfortunately. |
That sounds not good, it mire and more looks like a faulty adc (batch). Maybe contact the supplier? |
Hi @RobTillaart , yeah, I'm gonna try getting a new ADS from some other supplier cause neither do I, I'm pretty sure it's not the library too, so thanks for your help anyway ! I really appreciate your time and dedication on helping me. |
You're welcome. |
@MopheusDG |
Hi @RobTillaart unfortunately the new batch has the same issue, but I think is the same kind of board. Can you point us to the one your are using for testing (brand, where you buy it, anything that can help identify differences) so I can check it ? Thanks ! I think you can close the issue if you want too, there's nothing from the library u can do so far so.... |
Buy mine at a local shop in Eindhoven / Netherlands.
Adafruit makes their own boards with QWIIC connectors
|
One thing to note is that Serial.print() calls also take serious time.
|
Thanks @RobTillaart will give it a try this weekend to see if there's any improvement ! |
Hi @RobTillaart tested your version using 1 potentiometer and I get the same results (861):
The problem is when adding another potentiometer to the mix. Cause I need to move de readADC(x) to the loop and that's when the SPS goes down. Thanks ! |
//
// FILE: ADS_continuous.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);
uint16_t count = 0;
uint16_t value = 0;
uint16_t prev = 0;
uint32_t lastTime = 0;
uint32_t lastSample = 0;
uint8_t channel = 0;
int val[4] = {0, 0, 0, 0};
void setup()
{
Serial.begin(500000);
Serial.println(__FILE__);
Serial.print("ADS1X15_LIB_VERSION: ");
Serial.println(ADS1X15_LIB_VERSION);
ADS.begin();
ADS.setGain(0); // 6.144 volt
ADS.setDataRate(7); // 0 = slow 4 = medium 7 = fast
ADS.setMode(0); // continuous mode
ADS.readADC(channel); // first read to trigger
lastTime = micros();
}
void loop()
{
uint32_t now = micros();
if (now - lastSample >= 1160) // almost exact 860 SPS
{
lastSample = now;
val[channel] = ADS.getValue();
channel++;
if (channel == 2) channel = 0;
ADS.requestADC(channel);
count++;
if (count % 5 == 0)
{
Serial.print(count);
Serial.print('\t');
Serial.print(val[0]);
Serial.print('\t');
Serial.print(val[1]);
Serial.print('\t');
Serial.print(val[2]);
Serial.print('\t');
Serial.print(val[3]);
Serial.println();
}
}
if (now - 1000000 >= lastTime)
{
lastTime = now;
count = 0;
}
}
// -- END OF FILE -- generates still a lot of samples
To investigate if each channel has right data. |
As expected - out of sync
|
Polling mode //
// FILE: ADS_continuous.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);
uint16_t count = 0;
uint16_t value = 0;
uint16_t prev = 0;
uint32_t lastTime = 0;
uint32_t lastSample = 0;
uint8_t channel = 0;
int val[4] = {0, 0, 0, 0};
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); // 0 = slow 4 = medium 7 = fast
ADS.setMode(1); // 0 = continuous mode 1 = polling
ADS.requestADC(channel); // first read to trigger
lastTime = micros();
}
void loop()
{
uint32_t now = micros();
if (now - lastSample >= 1160)
{
lastSample = now;
val[channel] = ADS.getValue();
channel++;
if (channel == 2) channel = 0;
ADS.requestADC(channel);
count++;
Serial.print(count);
Serial.print('\t');
Serial.print(val[0]);
Serial.print('\t');
Serial.print(val[1]);
Serial.print('\t');
Serial.print(val[2]);
Serial.print('\t');
Serial.print(val[3]);
Serial.println();
}
if (now - 1000000 >= lastTime)
{
lastTime = now;
count = 0;
}
}
// -- END OF FILE -- results seem OK, it looks stable in the plotter - no spikes however not tested for a long period.
So with polling I get about 560 samples per second for two channels |
4 channels polling, still got some 450 samples == 114 sps per channel Note the 5V has changed channel with above, so the code is not 100% perfect.
|
Hi @RobTillaart will try using your same code later to see what I get. Thanks. |
@MopheusDG |
Hi, here from #55 It looks like a hardware issue or a fake chip? |
My tests were mostly done with UNO's which is a much slower processor. Thinking out loud No clue, so counterfeit chips could be a cause. |
I don't have anything like wifi or bt enabled. And I made sure to clock just after I set the channel and just after receiving the interrupt, so that should not be a problem. I have ordered new ICs from digikey, but I'll have to solder them and add the pullups manually, as I was using a dev board. Should be able to know if the issue was due to counterfeit ICs in a couple of weeks. |
Is it for a commercial project? |
FYI, release 0.3.10 improved setting of SDA/SCL for RP2040, no change in performance code. |
Today I finally received another ADS1115 from a different supplier, I had my oscilloscope hooked up to the ALRT/Ready pin and it was showing 152Hz initially. The moment I connected the new ADS it went to ~860 Hz. It was definitely a faulty or a counterfeit chip! One thing I don't understand is the markings on the chip. The first one says 8A BOGI, whereas the new working ADS says 78 BOGI. Do you know what this supposedly Hexadecimal number means? |
Just prototyping a device for now, not sure if it'll be commercial or not lol. |
BOGI is part of the packaging Cannot explain the 8A or 78 (138 / 120) . Can you give a link to the supplier that send you the good ones? |
I am in India, I doubt this will be useful to you. Also FYI, I was using breakout boards, I had also ordered a couple of chips from Digikey, but my soldering skills failed me XD Faulty/Fake one: robu.in
Yes, was confused about the first two characters really. I have asked a friend who works at TI. Let's see if he finds out. |
Thanks for the information. |
Do you have any code on your ADS1115? |
Checked mine, they all have 0B BOGI or 08 BOGI, hard to read. |
Seems like these are internal code for manufacturing reference, but if they correlate to batch ID or something like that, there might be an issue with the current 8As |
I've uploaded some sshots of mine. Sorry for the delay, my dad had some health issues and I've stopped working on this for a while. Hope this helps. |
If I read it correctly it states 88 BOGI. |
Thanks, But, just dont know googled ADS1115 images on the internet and saw a lot of unsharp photos, a few (barely) readable 7A, 88 8A and a 95(?) |
As this issue has been silent for more than a month I close it. (Just try to reduce the number of open issues in my repositories) |
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:
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.
The text was updated successfully, but these errors were encountered: