Inaccurate readings using ESP32 & SCT013 [50A/1v]

Hi,

I am trying to create a home energy monitor using my ESP32 and the SCT013 [50A/1V] CT sensor (It gives a reading of 1v when 50 amps of current goes through a wire).

I used the following guide to help me out however, the readings I get are not accurate at all. They are off by a huge margin. Even if I do not clamp my CT sensor to any wire, it still gives me some sort of reading (between 0.20 and 0.30) and not 0.

I don’t have any sort of engineering experience and am pretty lost here. I just did whatever the guide told me to do.

I searched it up a bit, and found out the issue may be the calibration number I pass in the .current() method of the EnergyMonitor object, but have no idea as to how I am supposed to calculate that number.

I have attached the circuit diagram I used and the code I uploaded to the esp32. Any help would be appreciated.

Source Code:

#include <Arduino.h>
#include "EmonLib.h"
#include <driver/adc.h>

#define HOME_VOLTAGE 220

#define ADC_INPUT 34

#define ADC_BITS  10
#define ADC_COUNTS (1<<ADC_BITS)

EnergyMonitor emon1;

unsigned long lastMeasurement = 0;
unsigned long timeFinishedSetup = 0;

void setup() {
  adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11);
  analogReadResolution(10);

  Serial.begin(115200);

  emon1.current(ADC_INPUT, 30);

  timeFinishedSetup = millis();
}

void loop() {
  unsigned long currentMillis = millis();

  if(currentMillis - lastMeasurement > 1000) {
    double amps = emon1.calcIrms(1480);

    lastMeasurement = millis();

    if(millis() - timeFinishedSetup < 10000){
      // Readings are unstable at this point so wait

    } else{
      Serial.println(amps);
    }
  }
}

Circuit Diagram:

Welcome, @Shaharyar_Ahmed to the OEM forum.

I would not rely on a 3rd party source of information. Whilst such material is published with the best of intentions, I have no indication of knowledge or skill set of the contributor. All you need to know to make a simple monitor is here in the ‘Learn’ part of “Docs”, but I cannot recommend using the ESP32 if you are looking for accuracy. For the reasons, see this piece about the ESP32 Analogue Input: [TW#12287] ESP32 ADC accuracy · Issue #164 · espressif/esp-idf · GitHub and the comments that follow. The comment made on 21 Oct 2021 says the performance has improved, but I don’t use the ESP32 so I cannot confirm this.

Also, the circuit configuration you are using, although we used it for a long time (for a reason I don’t understand), is susceptible to noise and interference. I suggest you move the components around so that one side of the current transformer is grounded - like this:

Although this refers to an Arduino (which has a much better ADC) it should work after a fashion with your ESP32. You do not need the 33 Ω Burden resistor, with a 1 V output c.t. this component is inside the c.t. housing.
You might like to read the full page where that circuit appears: CT Sensors - Interfacing with an Arduino — OpenEnergyMonitor 0.0.1 documentation

This line in your software

emon1.current(ADC_INPUT, 30);

sets the calibration for a 30 A : 1 V c.t. Yours is a 50 A : 1 V, so replace the number 30 with 50.
For any c.t. used with emonLib, the calibration is the current that would give a voltage of 1 V at the ADC input, provided that the ADC reference voltage (3.3 V in this case) is correct.
You calculate it with a knowledge of the ADC voltage per count and the transformer ratio: 50 A gives 1 V, and 3.3 V gives 1023 counts. You’ll find the maths when you look at EmonLib.cpp.

One further point, the number of samples you ask for, 1480, is most probably not an optimal value. It should be the nearest whole number to the number of measurements the ADC makes in a whole number of cycles of the mains electricity - 20 ms per cycle if you’re in the 50 Hz world. You can only find this by measurement: Use millis( ) to time say 1100 measurements (emon1.calcIrms(1100), then time it for 100 measurements. The difference between the two times will be a reasonably accurate value for 1000 measurements. From this you can calculate a good number to fit into (I suggest) between 200 ms and 300 ms of mains cycles. 1480 was the best fit for the processor and ADC used in the Arduino, the Atmel ATMega 328P.

Apologies but could you provide a detail guide on how I can calculate an accurate number for the samples to be taken?

What I understood was that I need to time how long it takes to time 1100 measurements and then time it for 100 measurements and then calculate the difference.

But I am lost on what to do after that.

The difference will be the time for 1000 measurements. Is this not clear? Then you calculate the time for one measurement by dividing the time for 1000 measurements by the number of measurements (1000).

Next, you need to know the time for one cycle of mains. It is 1/50 second or 1/60 second, depending on where you are.

Now calculate how many reading you get in one cycle. Ideally, you want a whole number of readings in a whole number of cycles, so multiply by two, or three, or four until it is as close as you think is good enough. If it comes within 0.1 of a whole number, it should be good enough. You should aim to take measurements for more than 200 ms to get a good average. More will be better, but slower showing the results.