ACS712 not accurate with a dimmer on same circuit

I'm trying to create a Grid-peak-shaving device. Simply, I have an ACS712 sensor, that reads the current in my circuit. I have also installed in circuit a dimmer that is also controlled by Arduino NANO.

The issue:
When I remove the dimmer from the circuit, the sensors current reading is very accurate. When I install the dimmer, the current measurement is off by 30%. I found this issue but I can't find a solution for it.

I moved your topic to an appropriate forum category @sakrlog.

In the future, please take some time to pick the forum category that best suits the subject of your topic. There is an "About the _____ category" topic at the top of each category that explains its purpose.

This is an important part of responsible forum usage, as explained in the "How to get the best out of this forum" guide. The guide contains a lot of other useful information. Please read it.

Thanks in advance for your cooperation.

Most likely, your program is not correctly estimating the current flow from the irregular waveform produced by the dimmer.

How did you determine the accuracy of the current measurement?

int readElSens() {
  const int RMS_INT_SCALE = 10;

  unsigned long long sum = 0;
  int n = 0;
  unsigned long start_time = millis();
  while (millis() - start_time < 200) { // in 200 ms measures 10 50Hz AC oscillations
    long v = analogRead(ELSENS_PIN) - 512;
    sum += v * v;
    n++;
  }
  return sqrt((double) sum / n) * RMS_INT_SCALE;
}

Are you also using the "RDB Dimmer library" like in the other post you cited

To make measurements accurate you have to read AC712 data many times at the each AC period.

As per @jremington You may not be able to make this work - without a dimmer the current is a nice sine wave with a dimmer the waveform is chopped up . This creates harmonics that you are probably not able to measure ( you probably need to measure 200 times a second and average ) What ever you are using to compare current may also be wrong for the same reason .

Have a study how a dimmer works to find out more

Thanks for all your help. This my code below.

#include <RBDdimmer.h>
#include "ACS712.h"

// Define the pin connected to the dimmer module
const int DIMMER_PIN = 12; // Example pin, change to your actual pin number
dimmerLamp dimmer(DIMMER_PIN);

ACS712  ACS(A0, 5.0, 1023, 66);

int brightnessLevel = 0; // Global variable to store brightness level
int decreaseRate = 10;    // Initial decrease rate

void setup() {
  // Initialize the RBDDimmer library with the specified pin
  dimmer.begin(NORMAL_MODE, ON);
  dimmer.setPower(0);
  Serial.begin(9600);
  ACS.autoMidPoint();
}

void loop() {
  int mA = ACS.mA_AC();
  Serial.print("Current (mA): ");
  Serial.println((float)mA / 1000.0);

  // Check if the current is under 10.0 mA
  if ((float)mA / 1000.0 < 10.0) {
    // Increase brightness by 5%
    brightnessLevel += 2;
    if (brightnessLevel > 100) {
      brightnessLevel = 100; // Ensure brightness level does not exceed 100%
    }
    dimmer.setPower(brightnessLevel);
    Serial.print("Brightness Level: ");
    Serial.println(brightnessLevel);
    delay(2000); // Wait for 1 second
  } 
  // Check if the current is over 10.0 mA
  else if ((float)mA / 1000.0 > 10.0) {
    // Decrease brightness by 10%
    brightnessLevel -= 2;
    if (brightnessLevel < 0) {
      brightnessLevel = 0; // Ensure brightness level does not go below 0%
    }
    dimmer.setPower(brightnessLevel);
    Serial.println(brightnessLevel);
    delay(2000); // Wait for 10 seconds (charging interval)
  } else {
    delay(2000);
  }
}

I have a UNIT-T multimeter, also I checking my solar inverter output in real-time.

@Juraj are you suggesting I use this code to read the current? Can you explain a little more what benefits does this add?

Yes!
I'm flexible to using other sensors. But after a lot of reading am sensing that there is no accurate way to do this. But then again I wonder why my multimeter doesn't give inaccurate measures as well?

@b707 thanks for taking the time to help. I'm coming from software engineering background and learning about electricity by researching. Can you explain more how can I be able to determine (from the code perspective) the AC period so I can measure in that period?

I use it in my Regulator project. I set the new period to the Triac dimmer and then I do a short read of the ACS with this function.
Then I have a function which converts the measurement to W/h.

float ratio = 1.0 - ((float) elsens / ELSENS_MAX_VALUE); // to 'guess' the 'power factor'
elsensPower = (int) (elsens * ELSENS_VALUE_COEF * cos(PF_ANGLE_SHIFT + ratio * PF_ANGLE_INTERVAL)) + ELSENS_VALUE_SHIFT;

I read an external meter too so I fine-tuned the constants to match the value measured with a professional meter.

the story: https://github.com/JAndrassy/Regulator/tree/master/util/Calc#elsenspower

EDIT: the ACS712 library is newer than my project. I think the mA_AC_sampling is similar to my function, but returns RMS already recalculated to mA

you might adjust the form factor, however that might change depending on the dimmer setting.
A (not tested) solution might be to adjust the FF if the dimmer setting changes.
e.g. a look up table dimmer 0..100% => FF

  • void setFormFactor(float formFactor = ACS712_FF_SINUS) manually sets the form factor.
    Must typical be between 0.0 and 1.0, see constants below.

The other solution is to use

  • float mA_AC_sampling(float frequency = 50, uint16_t cycles = 1) blocks ~21 ms to sample a whole period. The function returns the AC current in mA. (Note it returns a float). Its working is based upon sampling a full period and take the square root of the average sumSquared. This function is intended for signals with unknown Form Factor.

(that's about what the library can do)

I really appreciate you helping. In full honesty, as I don't understand what is form_factor(will read about it now) I will try the second solution you provided as it seems a smaller change

I skimmed through your project. It is far more complicated than my current knowledge. A question out of the blue, it seems that you project is kinda close to what I'm doing, if you are willing to assist in any way, I'm ready to buy you cup of coffee.

@robtillaart in your library, specifically in this example.

You have this loop:

 while (Serial.available() > 0)
  {
    char c = Serial.read();

    if (c == '*') ACS.setmVperAmp(ACS.getmVperAmp() + 1);
    if (c == '/') ACS.setmVperAmp(ACS.getmVperAmp() - 1);
    Serial.print("mVperAmp:\t");
    Serial.println(ACS.getmVperAmp());
  }```

I don't need the above right?

It is modular. You can remove any part without many changes to other parts.

Book with a lot of information about electronics, it filled many gaps in my knowledge.


No that loop is for calibrating the mV per Ampere.

@robtillaart I tried this solution and it worked!!

Mult -> ACS
2.1 -> 2.5
3 -> 3.25
4.2 -> 4.4
4.55 -> 4.7
6.85 -> 6.95
8.26 -> 8.4
9.15 -> 9.2

the ACS712 is always giving ~0.25 Amps higher than the multimeter. I honestly don't know which is true at the moment. Any idea why? Any way to further calib