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.
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;
}
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 .
#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);
}
}
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.
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.
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.
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?
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