-
-
Notifications
You must be signed in to change notification settings - Fork 31
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
Confused with usage of external ADC. #46
Comments
Maybe including a much simpler method to read the ACS712 using ADS1X15 Library might be a better solution. Like including another definition in ACS712 constructor to indicate whether your ADS1X15 library is being used to read from it like below?. ACS712(uint8_t analogPin, float volts = 5.0, uint16_t maxADC = 1023, float mVperAmpere = 100,
bool useADS1X15 = true, char nameADS1X15 = ADS1015, int pinADS1X15 = 0) |
Thanks for the issue. |
The idea of a specific constructor for the ADS1x15 sounds creative however there are at least a dozen other ADC devices. |
The example is indeed not very instructive, so there should be a new one. Your project with an ADS1x15 seems a more explicit case. Have some other tasks so I'll try later this evening (19:00 here now) |
I have no hardware nearby to test, so the code will need adjustments as I do not know the ADS1015 details from my head. Tried to keep the code minimal to read a DC current. // FILE: ACS712_ESP32_external_ADC.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo to measure mA DC with external ADC
// URL: https://github.com/RobTillaart/ACS712
#include <Arduino.h>
#include <ACS712.h>
#include <ADS1X15.h>
// I2C config
#define ADS1015_ADDRESS 0x48
#define ADS1015_SCL 22 // default SCL ESP32
#define ADS1015_SDA 21 // default SDA ESP32
// ADS1x15 config
#define SENSOR_ACS712_ADSPIN 1
// explicit params for demo
ADS1015 ads1015(ADS1015_ADDRESS, &Wire); // ADS1015 == 12 bit
// SENSOR_ACS712_ADSPIN sets pin 1 of the ADS1015, 5.0 volt, 4095 = 12 bit, 100 = mVperAmpere
ACS712 ACS(SENSOR_ACS712_ADSPIN, 5.0, 4095, 100);
// ACS712 ADC WRAPPER FOR ADS1015
uint16_t readADS1015(uint8_t pin)
{
uint16_t ADS_raw = ads1015.readADC(pin);
// Serial.print("ADS_raw: ");
// Serial.println(ADS_raw);
return ADS_raw;
}
///////////////////////////////////////////////////////////////
void setup()
{
Serial.begin(115200);
while (!Serial);
Serial.println(__FILE__);
Serial.print("ACS712_LIB_VERSION: ");
Serial.println(ACS712_LIB_VERSION);
Serial.println();
// ESP32 set wire pins explicitly
Wire.begin(ADS1015_SDA, ADS1015_SCL);
Wire.setClock(400000);
// initialize ADS1015, if fail => report
if (ads1015.begin() == false)
{
Serial.println("ADS1x15 not found. Check wires and pins. Reboot.");
while(1);
}
// verify the ADS is working in raw mode
Serial.println(readADS1015(SENSOR_ACS712_ADSPIN));
// set up the external ADC for the ACS712
ACS.setADC(readADS1015, 5.0, 4095);
}
void loop()
{
int mA = ACS.mA_DC();
Serial.println(mA);
delay(1000);
}
// -- END OF FILE -- |
Thanks for the updated code, Your code works as intended when running alone. Then we implemented it to our code but it is still adding a huge delay to the arduino ticker library when we include the Output is around -2 with ACS.autoMidPoint(0, 10); We have been using your ACS712 library before without any ADC in between and it works great. However including ADS1015 with your ADS1X15 library adding a delayed response to Ticker library behavior in random durations, as much as a up to a minute. We can be able to get a raw data from ACS712 via ADS1015 without any issues with the following code below using ADS1X15 library and we have other sensors connected to the same ADS1015 and they are working as supposed to. ACS712 raw output is around 1250. void debugInit() {
int adspin0 = ads1015.readADC(SENSOR_TMP36_ADSPIN);
int adspin1 = ads1015.readADC(SENSOR_ACS712_ADSPIN);
int adspin2 = ads1015.readADC(SENSOR_DIST_ADSPIN);
int adspin3 = ads1015.readADC(NA_ADSPIN);
Serial.print("adspin0 TMP36:");
Serial.print(adspin0);
Serial.print(" - adspin1 ACS712:");
Serial.print(adspin1);
Serial.print(" - adspin2 DIST:");
Serial.print(adspin2);
Serial.print(" - adspin3 NA:");
Serial.println(adspin3);
Serial.print("sensorCurrentValueRaw:");
Serial.println(sensorCurrentValueRaw);
Serial.println("-");
} Our code consists about 50000 lines of code and as far as I can tell it only affects the Ticker library for some reason. Not sure if the other part of our code is responsible of this issue or there is some conflict between Ticker library and Wrapper code. |
The ACS712 code for setADC() just setting a function pointer, so I expect that part is not the prime suspect.
The ADS1015 is an ADC that returns a signed 15 bit so the midpoint is around zero. So seems OK.
Test 1Can you add this line after ads1015.begin() to see what the data-rate setting is? Expect value 4. Serial.println(ads1015.getDataRate(); |
Test 2Can you add this line after ads1015.begin() ads1015.reset(); |
Have you seen this? From the GITHUB site of the ticker library: https://github.com/sstaub/Ticker Advice: for use with ESP boards and mbed based Arduino boards like Arduino Nano RP2040 Connect and Raspberry Pi Pico (using the official Arduino core) the TickTwo library https://github.com/sstaub/TickTwo is recommanded avoiding name conflicts. Don't know if you have name conflicts as mentioned here. |
in the Ticker constructor there is a strange line if (resolution == MICROS) timer = timer * 1000; If you set the timer to 1.000.000 micros (== 1 second) in the constructor, it multiplies the timer by 1000. I do not understand why there is this factor 1000, can you explain it? |
We are using built-in official ESP32 ticker library for arduino: https://github.com/espressif/arduino-esp32/tree/master/libraries/Ticker, Which is different(?) from the https://github.com/sstaub/Ticker I suppose. I will include test 1 and test 2 to our code and will report the outputs in a moment. |
Yes, very different OK, other Ticker library, I'll have a look at it. What do your calls to Ticker look like? |
I see that arguments are casted to unsigned int . |
@astorun |
@astorun Maybe such interference is only there if the ticker and I2C runs on same core? |
Nope. There are total of 5 that we coded by ourselves. 4 of them are float and the only unsigned int is the one with acs712 wrapper function. However, we are using tons of other libraries and we are not sure if they have any functions built-in with signed int.
No. We have only one I2C device and that is ADS1015. Also, after couple of hours today, we realized ESP32 hangs and restarts itself if This is our setup function below, if that helps.
|
On default, wifi is turned off during startup and it wont powered off until user requests it.
|
If that helps, we have and SPI touchscreen running with LovyanGFX and LVGL library. Not sure if it is related. Here is the code below for screen initialization.
|
that is a lot of information...
Does this mean it works for some hours and then it stops? |
Is it possible to add another I2C device (eg pcf8574) and see if that breaks the project too? |
Ok I think we found the culprit! However if we do not provide sampling value, it works as intended! From the mainpage of AC712 library, there is an description how cycles are working.
|
Sadly no, we are using a custom manufactured PCB and there is no way we can add another device. |
By your suggestion that I2C might be the issue, I increased the I2C clock from 100000 to 400000 to see if that is going to make any difference and tested with However, the issue is still persists. We reduced the wire speed to 100000 due to pcb limitation. We are opted to use 10k resistors instead of 1k on I2C SDA/SCL pins. On ADS1015 datasheet it suggests using lower resistor values for faster I2C speeds, around 2k. Not sure if that contributes the issue. |
That might be blocking indeed (not for minutes but enough to corrupt scheduling). Maybe adding a call to yield() in some loops of the ACS712 library to provide context switching and give the ticket thread a chance to run. To be continued tomorrow (for me at least) |
Thanks for the update and possible solution! We will be waiting for any update. Until then we are going to run the library without any sampling. Moreover, adding ADS1015 seems doing a better job than ESP32 internal ADC and we might not need a software smoothing at all :). |
The esp32 (s1?) has non linearities in the adc, which cannot be removed by averaging only. These need end of scale adjustments. |
Yes, as the internal ADC's of various boards are not that precise this helps to improve reading to certain extend. Problem with oversampling is that the duration of the measurement increases. Thus if you have a fluctuating signal oversampling will smooth out part of the detailed signal. Today I will create a develop branch you can test to see if the yield() solution meets your needs. . |
Created develop branch - https://github.com/RobTillaart/ACS712/tree/develop - |
We tested with develop branch and result is the same. The delay is still there. While I was looking at the library we saw a new midpoint feature specifically for DC. Decided to give it a try with a recommended value of 100. However this time we got the following error and firmware refused to work alltogether. Not sure if both issues are related. |
Also if it helps, our hardware is ESP32-S3 N8R2 |
Error 263 is a timeout google told me, one of the causes can be bad wiring. It seems to occur more often with ESP32 and other I2C devices. So it seems not a problem of the ads1x15 library, but an ESP32 one. E.g. with a Sensirion sensor Possibly the ESP32 wire library allows to set a wire timeout to shorten the delay. |
Thanks for testing, Does your code uses explicit multithreading, and have you divided the liad over the two cores based upon the losd per thread? |
Thanks for the quick reply. No, we do not have any multithreading in our application. We suspect it might be caused by our resistor choice on I2C lines that might not allowing full 400000 clock speed. We will revise our hardware and test it again to see if it is going to make any difference. |
Do you have an oscilloscope to see the sinal quality of the I2C lines? The longer the wires the smaller the pull up resistors on the SDA an SCL. My rule of thumb is Furthermore you should use shielded wire for the I2C if there is a chance of noise from motors etc. Either from your own project or the environment your product has to operate in. |
@astorun |
Sorry for the late reply. We have been extremely busy lately with the hardware itself. Today, we had the chance to try different things with the library, however it does not play out again.
We are calling the readCurrent function with ticker function within every 5ms. It is working without any issues. I believe wrapper implementation is not efficient enough to deal with the complex code structure or calling it too often causes other function to block or hang the esp32. I suggest a different implementation method of ACS712 library with ADS1X15 without using any wrapper function. We do not know how ACS712 library the works in the background, but using it with ADS1X15 causing some sort of bottleneck under specific scenarios for our application, where timing is critical. Maybe implementing another method to adjust the time between each readings or finding another method without blocking too much might solve the issue. Thanks for the help though. |
Thanks for the update, If there are no more questions you may close the issue. |
Hello,
I am trying to read ACS712 value on ESP32 board which is connected through ADS1015 pin 1.
However I cannot figure out how to use it properly since example "ACS712_20_DC_external_ADC.ino" does not provide enough context to me how to read a specific pin.
Moreover when I include "ACS.setADC(wrapperACSPin, 5.0, 4095);" Other libraries starts doing some weird stuff like delaying function executions in random durations e.g. Ticker library wont function properly. It is like ESP32 is hanging.
Sorry for being a noob here. I am providing a portion of the code I am using below to read ACS value over ADS1015 pin 1.
Thank you.
The text was updated successfully, but these errors were encountered: