RobTillaart / ACS712

Arduino library for ACS Current Sensor - 5A, 20A, 30A
MIT License
129 stars 35 forks source link

Wemos D1 mini #43

Closed rediculum closed 9 months ago

rediculum commented 1 year ago

Hello

Have you ever tried a Wemos D1 mini with a ESP8266 board? I am trying to make it run since 3 evenings but I do not get reliable data. To regulate the correct power of the A0 pin, a 180k resistor is enough to pimp up the internal voltage divider. This allows an input voltage of 5V on A0 which comes from the ACS712. (see https://community.blynk.cc/t/solved-acs712-voltage-amps-ghost-readings/12143/69)

image

Unfortunately my output stays always around 40-50mA when I start a constant load of 230mA (12v fan on regulated power supply). My console output:

G⸮Z⸮Qp@dI⸮⸮&ϝhF⸮W⸮TWZ-%dDu@⸮JdH⸮`H⸮;lJP@wdJ⸮!DU⸮
`\"⸮⸮`\⸮*`PP@%pHXu
`D⸮⸮O⸮X⸮'
`\B`Z`H)dMD⸮⸮X
⸮Q⸮⸮⸮
dXD*M+nD⸮9%D⸮%dx@⸮0
46 <--- started Wemos D1
41
41
41
46
53
48
48
48
48
46
46
56  <- powered on 12v fan
53
53
56
51
53
53
56
53
53
53
51
41 <- powered off 12v fan
41
41
41
41
41
41
46

Is my ACS712 somehow fried? There's my complete sketch:

#include <ACS712.h>

ACS712 ACS(A0, 1, 4096, 100);

void setup() {
  Serial.begin(57600);
  ACS.autoMidPointDC();
}

void loop() {
  int mA = ACS.mA_DC();
  Serial.println(mA);
  delay(1000);
}
RobTillaart commented 1 year ago

Thanks for the issue Its late Saturday here, and I will look into this asap. Can take a few days.

RobTillaart commented 1 year ago

Did no tests with esp8266, did test mostly with Arduino Uno (5V device) and limited with ESP32 (3V3).

Can you do a basic test with e.g. 12V and a 1K resistor? That should give ~12 mA.

RobTillaart commented 1 year ago

Think the second param of the constructor should be 3.3 or 5.0.

If it is set to 5.0 the measurements of 40..50 should become 200..250 so quite in the right range.

Give it a try,

rediculum commented 1 year ago

Setting to 5.0, does just increase the value, but not correct:

97
109
97
109
109
109
109
170 <- power on 12v fan
158
158
158
158
158
158
170
158
158
158
158
97 <- power off 12v fan
109
109
109
109
109
109

I will order some ESP32 dev boards and will double check it. Did you just connect the OUT of the ACS712 directly to an ADC of the ESP32 without any resistor?

RobTillaart commented 1 year ago

I do not recall using a resistor in the tests however it was quite some time ago.

Can you print the midpoint found? Plus a raw A0 measurement of the midpoint? Do this without any load connected.

RobTillaart commented 1 year ago

What voltage does your DMM measure at the OUT pin with no load?

RobTillaart commented 1 year ago

The ACS712 OUT pin can be connected directly to the ADC of the processor. Googled several schematics and saw no resistor used in sny of them.

rediculum commented 1 year ago

Before I do further tests, let me first replace the hardware to ensure none of them is broken (Wemos and ACS). Maybe I did some mistakes in the past and fried something. Please give me some days, the parts are already shipped

RobTillaart commented 1 year ago

@rediculum Any progress made?

rediculum commented 1 year ago

Honestly I lost track and did not follow it. Maybe I come back later

RobTillaart commented 1 year ago

OK, if needed feel free to reopen / create a new issue!

elbowz commented 10 months ago

Hello

I'm trying to do the same: ESP8266 (ESP12F) + ACS712 (5 A)

Since I'm using the bare version of the ESP8266, I don't have any voltage divider already installed.

I'm using a R[ACS] = 300K and R[GND] = 75K (ACS712 powered by a 5v source).

In the code, I instantiate your class with mAcs712(A0, 1, 1023, 32) to obtain nice and fair results.

...but, I have set the mVperAmp, with a trial and error process (ie. increasing since I get the correct output). Actually, according to what is described in your README, I should set 20 mVperAmp (75/(75+300)*100), but with these settings I retrieve a too high value of A (current).

I have also tried to change the second param (volt) to 3.3 and 5, but the obtained A still tends to increase.

I hope, my setting can be helpful to someone, although I would like to understand why the correct value for mVperAmp is 32...or if a made some big mistake somewhere in the calculation.

Thanks for your project!

edit: I'm checking the current/power result with a wall power meter

RobTillaart commented 10 months ago

@elbowz Thanks for your info,

In the code, I instantiate your class with mAcs712(A0, 1, 1023, 32) to obtain nice and fair results.

Need to look into this,

RobTillaart commented 10 months ago

If you have zero current, what is the output in volts of the ACS712 ? It should be around Vcc / 2 = (ACS712 powered by a 5v source) ==> 2.5 V

RobTillaart commented 10 months ago

@elbowz What do you mean by I'm using a R[ACS] = 300K and R[GND] = 75K I do not know your schema...

(see below)

RobTillaart commented 10 months ago

OK, found Voltage divider section

image

R1 = 300K, R2 = 75K ==> voltage factor = 75 / 375 = 0.2 ==> mVperAmp corrected = 185 * 0.2 = 37 which is near to the 32 you have.

The ADC itself is not changed, mAcs712(A0, 3.3, 1023, 37) should work.

Q: can you measure the resistors with a DMM?


Your max voltage is 5V * 0.2 == 1V so the midpoint should be around 0.5V And you only use 1023/3V3 = ~310 steps of the ADC..

Note that **mAcs712(A0, 3.3, 1023, 37) == mAcs712(A0, 1, 310, 37)

You should set a new midPoint (0.5V or 165) as you do not use the full scale of the ADC.


Summary, please try mAcs712(A0, 3.3, 1023, 37) and call autoMidPoint() with zero current.

elbowz commented 10 months ago

First of all, thanks for your quick reply, but no rush or hurry :)

If you have zero current, what is the output in volts of the ACS712 ? It should be around Vcc / 2 = (ACS712 powered by a 5v source) ==> 2.5 V

Confirm: 2,490 V with my multi-meter, and a power source of ACS712 of 5.012v (Hi-Link HLK-PM01)

What do you mean by I'm using a R[ACS] = 300K and R[GND] = 75K I do not know your schema...

My apologize, you are right. Following your voltage divider schema:

ACS712 ----[ R[ACS] ]----o----[ R[GND] ]---- GND
                         |
                         |
                   ADC of processor

R[ACS] = R1
R[GND] = R2
RobTillaart commented 10 months ago

The ideal voltage divider ratio for 5V to 3.3V would be 1:2 Then you can use the whole range of the ADC.

==> R1[ACS] = 1K R2[GND] = 2K => voltage factor = 2/3 = 0.66 (is exactly 5/3V3) ==> mVperAmp corrected = 185 * 0.66 = 123

Need to add this example divider in the readme.md

elbowz commented 10 months ago

==> mVperAmp corrected = 185 * 0.2 = 37 which is near to the 32 you have.

This is my mistake! I still used 100 (correct for 20A) and not 185 (correct for 5A).

Now, I'm away from home...I'll test it just when I get back. But I think it will work like a charm!

Thanks again, for the solution and especially for the full explanation.

RobTillaart commented 10 months ago

Please let me know your final test results, For me I need to clarify that section a bit more and this is a good example

Thanks for reporting!

elbowz commented 10 months ago

The ideal voltage divider ratio for 5V to 3.3V would be 1:2 Then you can use the whole range of the ADC.

==> R1[ACS] = 1K R2[GND] = 2K => voltage factor = 2/3 = 0.66 (is exactly 5/3V3) ==> mVperAmp corrected = 185 * 0.66 = 123

Need to add this example divider in the readme.md

Wait, I'm not sure to understand, but ESP8266 ADC pin have a max Voltage of 1 V with 10 bit resolution. do you still think that my voltage divider is wrong?

RobTillaart commented 10 months ago

but ESP8266 ADC pin have a max Voltage of 1 V

My ESP8266 can go to 3V3 (but its on a board, not the bare chip...

more notes needed ;)

RobTillaart commented 10 months ago

Snippet of the new notes

For a 5 A type sensor, 185 mV/A would be the normal value. After using a voltage divider one need to adjust the mVperAmp.

R1 (ACS) R2 (GND) voltage factor mVperAmp corrected notes
10200 4745 4745 / (10200 + 4745) = 0.3175 185 * 0.3175 = 31.75
4745 10200 10200 / (10200 + 4745) = 0.6825 185 * 0.6825 = 68.25
10200 9800 9800 / (10200 + 9800) = 0.4900 185 * 0.4900 = 49.00
1000 2200 2200 / (1000 + 2200) = 0.6875 185 * 0.6875 = 127.2 5V -> 3V3 ADC
300 75 75 / (300 + 75) = 0.2000 185 * 0.6875 = 92.5 5V -> 1V ADC (WRONG!!!!)
300 75 75 / (300 + 75) = 0.2000 185 * 0.2000 = 37 5V -> 1V ADC (correct one)
RobTillaart commented 10 months ago

Similar table for the 20A and 30A sensor

RobTillaart commented 10 months ago

Wait, I'm not sure to understand, but ESP8266 ADC pin have a max Voltage of 1 V with 10 bit resolution. do you still think that my voltage divider is wrong?

No, your voltage divider is optimal. The call that should work is (by latest insights) mAcs712(A0, 1.0, 1023, 92.5)

that gives mV / AMP: 92.50 mA/step : 10.57

10.57 *1023 == 10A == +- 5A so that matches the range...

elbowz commented 9 months ago

My ESP8266 can go to 3V3 (but its on a board, not the bare chip...

Be careful, the Esp8266 devboards (eg. NodeMCU), already have a voltage divider inside for the ADC pin. So if you want to use it, you shouldn't add another voltage divider (in front), because this adds resistors in parallel to the already existing ones (you have to recalculate the resulting resistance). I think it would be better to add a single R = 180kOhm in front of the ADC pin of the devboard:

https://arduino.stackexchange.com/a/71952

mA/step : 10.57

How do you get this value? I guess 1000/92,50, but I get 10,81 (just for understand)

One thing that I can suggest to better explain in the README.md, is how to choose the voltage value:

Volts is the voltage used by the (Arduino) internal ADC.

I don't know what to set for my ESP8266 between 3v3 (power source) or 1v (the max voltage accepted by the ADC).

Results

Using: mAcs712(A0, 1.0, 1023, 92.5)

and DMM measured resistances: R1 (ACS) = 302.5K
R2 (GND) = 74.6

mAcs712.autoMidPoint() return 470 with 2.45v measured at the ACS output pin.

The current (A) is still wrong: Power wall meter ESP+ACS
1.74 0.65
3.40 1.30

I have to check everything again...but try to keep an eye on it if you want.

edit: I have tried with mAcs712(A0, 3.3, 1023, 92.5) but now the current (A) is too high

The current (A) is still wrong: Power wall meter ESP+ACS
1.74 2.30
3.40 4.46

also with mAcs712(A0, 3.3, 1023, 37)...I get the higher values (eg. 5.80A)

RobTillaart commented 9 months ago

My ESP8266 can go to 3V3 (but its on a board, not the bare chip...

Be careful, the Esp8266 devboards (eg. NodeMCU), already have a voltage divider inside for the ADC pin. So if you want to use it, you shouldn't add another voltage divider (in front), because this adds resistors in parallel to the already existing ones (you have to recalculate the resulting resistance). I think it would be better to add a single R = 180kOhm in front of the ADC pin of the devboard: https://arduino.stackexchange.com/a/71952

Thanks for this insight.


mA/step : 10.57 How do you get this value? I guess 1000/92,50, but I get 10,81 (just for understand) One thing that I can suggest to better explain in the README.md, is how to choose the voltage value:

ACS712 ACS4(A0, 1, 1023, 92.5);

mV per step = 1000 mV / steps = 0.9775 mV per step (0.9775 mV/step) / (92.5 mV / Ampere) = 0.9775 / 92.5 *(Ampere / step) = 0.0105678 A/step = 10.57 mA / step.


Volts is the voltage used by the (Arduino) internal ADC. I don't know what to set for my ESP8266 between 3v3 (power source) or 1v (the max voltage accepted by the ADC).

As you have a bare ESP8266 it should be 1V ADC with 1023 steps.


and DMM measured resistances: R1 (ACS) = 302.5K R2 (GND) = 74.6

so the factor is 74.6 / 377.1 = 0.1978 (so within 1% of 0.2 which you want.)


mAcs712.autoMidPoint() return 470 with 2.45v measured at the ACS output pin.

That is ~1% lower than expected (2.45 / 5.0 = 0.49)


The voltage of the ADC is 1.0 The steps of the ADC is 1023 The mVperAmp corrected = 185 * 0.1978 = 36.59

==> I would try this one mAcs712(A0, 1.0, 1023, 36.59)


This line in the table above is incorrect as the factor is not 0.6875 it should be 0.2000

300 | 75 | 75 / (300 + 75) = 0.2000 | 185 * 0.6875 = 92.5 | 5V -> 1V ADC -- | -- | -- | -- | --

(I added a line above in the table, sorry for the inconvenience)

elbowz commented 9 months ago

mV per step = 1000 mV / steps = 0.9775 mV per step (0.9775 mV/step) / (92.5 mV / Ampere) = 0.9775 / 92.5 *(Ampere / step) = 0.0105678 A/step = 10.57 mA / step.

Thank you! It's clear, now :)

Volts is the voltage used by the (Arduino) internal ADC. I don't know what to set for my ESP8266 between 3v3 (power source) or 1v (the max voltage accepted by the ADC).

As you have a bare ESP8266 it should be 1V ADC with 1023 steps.

Ok, so the voltage is the max voltage accepted by the ADC pin (and not the power supply).

and DMM measured resistances: R1 (ACS) = 302.5K R2 (GND) = 74.6

so the factor is 74.6 / 377.1 = 0.1978 (so within 1% of 0.2 which you want.)

mAcs712.autoMidPoint() return 470 with 2.45v measured at the ACS output pin.

That is ~1% lower than expected (2.45 / 5.0 = 0.49)

The voltage of the ADC is 1.0 The steps of the ADC is 1023 The mVperAmp corrected = 185 * 0.1978 = 36.59

==> I would try this one mAcs712(A0, 1.0, 1023, 36.59)

This line in the table above is incorrect as the factor is not 0.6875 it should be 0.2000 300 | 75 | 75 / (300 + 75) = 0.2000 | 185 * 0.6875 = 92.5 | 5V -> 1V ADC -- | -- | -- | -- | --

(I added a line above in the table, sorry for the inconvenience)

I appreciated all the explained steps to get to the correct values to use: mAcs712(A0, 1.0, 1023, 36.59)

Power wall meter ESP+ACS
0.43 0.25
1.74 1.62
3.40 3.27

Now, the obtained results are pretty good :)

Thank you!

RobTillaart commented 9 months ago

The values seem to be ~4% too low. So if you try 36.59 x 1.04 = 38.05 it will probably even be better.

However you might need to make more measurements to optimize the actual working range of your project.

elbowz commented 9 months ago

Yes, you are right.

But why, on low current (A) the error is more? (First row of my table)

and mainly I don't understand because loads about 20 - 50 Watt (0.09 - 022 A) give 0 A on ACS, is it normal?

RobTillaart commented 9 months ago

But why, on low current (A) the error is more? (First row of my table)

See the ADC curve of the ESP8266 on this site (sorry for all the spam). It has two dead zones, one at the low end and a second at the high end, it is just not linear over the whole range.

At the top end you can correct a little by stating mAcs712(A0, 0.995, 1023, 36.59) use e.g. 0.995 V instead of 1.0V At the bottom end is harder to fix. I do not know a quick fix for that (nor a slow one).

and mainly I don't understand because loads about 20 - 50 Watt (0.09 - 022 A) give 0 A on ACS, is it normal?

Measure the actual voltage and you see it is in the dead zone at the bottom side.

A scale of 5A in 1023 steps is ~5mA / step
1023 steps is 1 V is ~1mV / step.

0.09 A == 2 steps ==> 2 mV 0.22 A == 4.5 steps ==> 9 mV

The curve only swing up at about 0.15V = 150 mV so both are in the dead zone.

RobTillaart commented 9 months ago

Solution for low currents is external ADC e.g. an ADS1115. (as this one is pretty linear)

elbowz commented 9 months ago

See the ADC curve of the ESP8266 on this site (sorry for all the spam). It has two dead zones, one at the low end and a second at the high end, it is just not linear over the whole range.

* https://microcontrollerslab.com/esp8266-nodemcu-adc-tutorial-measure-analog-voltage/

At the top end you can correct a little by stating mAcs712(A0, 0.995, 1023, 36.59) use e.g. 0.995 V instead of 1.0V At the bottom end is harder to fix. I do not know a quick fix for that (nor a slow one).

ooohh shit, I didn't know this. Thank you!

...but, we work in the middle of the ADC, or am I wrong? ACS712 give 2.5V in output without a load, so 0.5v on the ADC, thanks to the voltage divider. There isn't the dead zone in that area.

What I miss?

Maybe, I'm wasting your time, and going OT.

RobTillaart commented 9 months ago

mmmm you have a good point. There is no dead zone in the middle, my mistake.

And if you print those low current with more decimals does that differ? Does it work for "larger" current? (no, it is not off topic, it eats time, not wasting time as I'm still learning)

elbowz commented 9 months ago

And if you print those low current with more decimals does that differ?

At low loads (~ 0.14 A), mAcs712.mA_AC() returns 0.00A. How can I increase the precision of float? btw, 0.14 A => 140 mA, the decimals should be enough.

Does it work for "larger" current?

I don't have many different loads to test...but between 1.74A and 1.76A (on wall mounted power meter), we have a similar change returned by mAcs712.mA_AC(). The values are unstable, but the average is higher at 1.76A.

Unfortunately, I don't have an oscilloscope, and with AC current it's hard to read the raw value (volt) you get from the ACS712.

IMHO, the problem is the ACS712. For what I know, it's an inaccurate tool for measuring current...or it could be some mistake in my code or wiring.

Anyway, for my use case, is more than enough :)

With an ESP32 or an Arduino (ie. more accurate ADC), are you able to read low current like 0.14 A on AC?

RobTillaart commented 9 months ago

How can I increase the precision of float? btw, 0.14 A => 140 mA, the decimals should be enough.

Serial.print(someFloat, 4); // extra parameter

RobTillaart commented 9 months ago

IMHO, the problem is the ACS712. For what I know, it's an inaccurate tool for measuring current...or it could be some mistake in my code or wiring.

You can improve on that with the library - from readme.md

Configuration BUS and SHUNT

Note: The internal conversions runs in the background in the INA219. If a conversion is finished the measured value is stored in the appropriate register. The last obtained values can always be read from the registers, so they will not block. Result can be that you get the very same value if no new data is available yet. This is especially true if you increase the number of samples. (See also discussion in #11).

Using more samples reduces the noise level, but one will miss the faster changes in voltage or current. Depending on your project needs you can choose one over the other.

As a rule of thumb one could take the time between two I2C reads of a register as an upper limit. This would result in a fresh measurement every time one reads the register. NB it is always possible to average readings fetched from the device in your own code.

Use one of these three so set bus resolution and sampling.

Use one of these three so set shunt resolution and sampling.

Resolution samples table

mask = both resolution + averaging multiple samples. minus - == don't care

bit mask value resolution samples conversion time
0-00 0 / 4 9 bit 1 sample 84 μs
0-01 1 / 5 10 bit 1 sample 148 μs
0-10 2 / 6 11 bit 1 sample 276 μs
0-11 3 / 7 12 bit 1 sample 532 μs
1000 8 12 bit 1 sample 532 μs
1001 9 12 bit 2 samples 1.06 ms
1010 10 12 bit 4 samples 2.13 ms
1011 11 12 bit 8 samples 4.26 ms
1100 12 12 bit 16 samples 8.51 ms
1101 13 12 bit 32 samples 17.02 ms
1110 14 12 bit 64 samples 34.05 ms
1111 15 12 bit 128 samples 68.10 ms
elbowz commented 9 months ago

Serial.print(someFloat, 4);

0.14A measured => 0.00000 mA no change...btw, if this had solved the problem, I would have even more questions ;)

elbowz commented 9 months ago

IMHO, the problem is the ACS712. For what I know, it's an inaccurate tool for measuring current...or it could be some mistake in my code or wiring.

You can improve on that with the library - from readme.md

Configuration BUS and SHUNT

I think, I'll keep my little project as is...more than enough for me :)

I'll keep subscribed to the issue, in case someone fixes it or gets different results with the ESP8266 :)

Thanks again for all your time, your support and your open source source project!

RobTillaart commented 9 months ago

I think, I'll keep my little project as is...more than enough for me :)

If there are no more questions, you may close the issue.

Thanks again for all your time, your support and your open source source project!

You're welcome

elbowz commented 9 months ago

Only this:

With an ESP32 or an Arduino (ie. more accurate ADC), are you able to read low current like 0.14 A on AC?

edit: I don't find the button to close the issue

RobTillaart commented 9 months ago

With an ESP32 or an Arduino (ie. more accurate ADC), are you able to read low current like 0.14 A on AC?

Lets start again.

image

0.14 A == 140 mA
An ACS712 5Amp version at 10bits ADC has 26.4 mA per step, so it should measure about 5 or 6 steps.

What might be interesting for you, I have just released the initial version 0.1.0 of my INA3221, library

It is a 3 channel device and meant for currents up to 1.6 A so 0.14 amps is about 1/10 of the scale. Maybe more interesting than the ACS712 for low currents?

elbowz commented 9 months ago

Sorry, I would just like to know if you have tested practically/empirically with an ESP32, because according to your table the ESP8266 should also measure 140 mA, that's all.

Just a Yes or No :)

INA3221 seems interesting, thanks for the related info, I'll keep an eye on it.

edit: in one of the first posts of this issue you wrote:

Did no tests with esp8266, did test mostly with Arduino Uno (5V device) and limited with ESP32 (3V3).

Hence this, my question...but, it doesn't matter, it was just curiosity. Thanks again!!

Please close the issue yourself, I don't have the button to do that.

RobTillaart commented 9 months ago

Sorry, I would just like to know if you have tested practically/empirically with an ESP32, because according to your table the ESP8266 should also measure 140 mA, that's all. Just a Yes or No :)

Yes