adafruit / Adafruit_ADS1X15

Driver for TI's ADS1015: 12-bit Differential or Single-Ended ADC with PGA and Comparator
Other
289 stars 301 forks source link

Stuck on while loop #75

Open e-labInnovations opened 2 years ago

e-labInnovations commented 2 years ago

Sometimes Arduino stuck on

while (!conversionComplete())
;

I think the ads1115 not responding due to some AC spikes on the input.
I am planning to add time check also in the while (!conversionComplete()) code. If I am wrong, please correct me.

caternuson commented 2 years ago

Is the problem repeatable? Are you seeing the issue running example sketches from the library?

e-labInnovations commented 2 years ago

@caternuson I am not using the exact example code, but the code from the example

caternuson commented 2 years ago

OK, we can look at adding some kind of timeout mechanism to the "wait for conversion complete" logic.

What behavior do you want if it times out? Specifically - how should the various readADC_*() functions behave if the wait times out?

Minxster commented 2 years ago

The project I'm working on can have the ADS1115 reporting data for 10hrs or more (once a second). And every now and then it would get stuck in the while loop for no apparent reason. So I added in my own while loop to check for conversionComplete(), before Raw_ADC = ADS1115_a.readADC_SingleEnded(0);... This helped my code skip over this situation if there was a problem, but the question I have is what can cause this to happen? Is there some form of reset command we can send when the conversionComplete() is stuck?

caternuson commented 2 years ago

The conversionComplete() method is nothing more than a register read: https://github.com/adafruit/Adafruit_ADS1X15/blob/2f58faf6e28108f46223940dfc7d8540303765bc/Adafruit_ADS1X15.cpp#L370-L372

However, it assumes the I2C comms are all good. If there's an AC spike, or some other phenomenon, causing the I2C comms to hiccup or get stuck, then it could potentially just loop forever. The only potential reset option would also rely on I2C comms still working (see RESET AND POWER-UP section in datasheet).

The fix could be simple. Instead of blindly looping forever, only loop for a certain amount of time. If the time out is reached before conversion complete, then give up.

The question is still what is a good behavior for when that occurs.

Minxster commented 2 years ago

It's a little strange for me as my other I2C module (EMC2101) kept on reading perfectly fine during the hiccup. I am using a TCA9548A dev board (Seeed) but this is set to openAll(), so no channel switching is happening... But this freeze-up could last a few seconds to a minute, then starts to work again. Other times I had to fully reset my ESP32 to force it to reboot.

My skill levels are below "novice", and I did take a look at the datasheet, what's the best way to send a reset command (06h) to the module? At least I could then attempt this if/when there is freeze?

As for default behaviour, maybe a default of 1 second? But have a definition/function that allows this to be changed at runtime?

caternuson commented 2 years ago

I imagine being able to set the actual timeout value would be supported. Question is more what the readADC_*() functions should return if the timeout is reached. How would you distinguish between an actual ADC value and a timeout?

Minxster commented 2 years ago

NaN?

Minxster commented 2 years ago

Just on thinking about how best to reset the module, I note that in the EMC2101, during begin() there is this: if (i2c_dev) { delete i2c_dev; // remove old interface }

Would this be a good idea for the ADS1X15, if we find that the module is stuck in a loop, we could re-begin()? Or would you be able to advise on how best to send the 06h reset command?

Minxster commented 2 years ago

Ok, so NaN is really a bad/stupid idea... But what about returning some form of NULL? nullptr?

I've been back looking over differing bits of code (of mine) and have even gone off to look a DFRobot's ADS1115 to try and get my head around things. But I'm still kind of stuck with the idea that if the Adafruit module has locked, up for some reason, it can be hard to find out if some form of reset is needed?