Current transformer with arduino

Hello everyone,

I'm currently using a current transformer (CT) to measure the current consumption of my machines. I have based my application on the following example: OpenEnergyMonitor: CT Sensors Interface with Arduino.

The CT I'm using is from Polier. Here is the link to the product. It is a 50:1 transformer, capable of measuring up to 50A. I have chosen a burden resistor of 1 ohm, which is compatible with my calculations.

However, I am facing an issue when trying to measure the current using the EmonLib library, which is also utilized in the example mentioned above. I am uncertain about how to determine the values of the calibration constants: ICAL, VCAL, and PHASECAL.

Before using this library, I attempted to measure the current directly from the analog pin, using the same schematic as in the example but with my specific burden resistor. Unfortunately, the results were inconsistent and yielded unexpected values.

Here's my sketch :

// Pin Definitions
const int analogPin = A0; // Analog input pin connected to the CT circuit

// Constants
const float referenceVoltage = 3.3; // Arduino supply/reference voltage
const int adcResolution = 4096;     // 12-bit ADC resolution
const float burdenResistor = 1; // Burden resistor value in ohms
const float currentTransformerRatio = 50.0; // CT ratio (50:1)
const int numSamples = 1000; // Number of samples for RMS calculation

void setup() {
  Serial.begin(9600);
  analogReadResolution(12);
}

void loop() {
  float voltageSum = 0;
  
  // Sampling the analog signal
  for (int i = 0; i < numSamples; i++) {
    int analogValue = analogRead(analogPin); // Read the analog value
    float voltage = (analogValue * referenceVoltage) / adcResolution; // Convert ADC value to voltage
    float centeredVoltage = voltage - (referenceVoltage / 2); // Remove the DC offset (biasing)
    voltageSum += centeredVoltage * centeredVoltage; // Sum of squares for RMS calculation
  }

  // Calculate RMS voltage
  float rmsVoltage = sqrt(voltageSum / numSamples);

  // Calculate the current based on the burden resistor and CT ratio
  float current = (rmsVoltage / burdenResistor) * currentTransformerRatio * 1000.0;

  // Print the current value
  Serial.print("Current (A): ");
  Serial.println(current);

  delay(1000); // Delay 1 second between readings
}

Best regards
Youssef

Please post these results.

Please post your schematic. Kicad is easy to use and free.

1 Like

What primary AC currents were you measuring, what values did you obtain, and what values did you expect?

Please post a schematic of the CT/ADC input circuit. Hand drawn is fine, with pins and connections clearly labeled.

1 Like

You might let us know what current ranges you are looking at and what voltage the machines operate at.

Arduino won't measure AC. Beyond a simple current transformer, you need to use a rectifier and capacitor to convert your signal to a representative DC before applying it to A0.

I have used a ESP32-4-Channel-Mains-Current-Sensor with three SCT013 100amp sensors to monitor house 3-phase current consumption
e.g.
image

the 4-channel sensor PCB contains the circuits to offset the SCT-013 AC reading so it can be read by the ESP32 ADCs (approximate input range 0 to 3v)

you have to sample ADC readings over several cycles to get the RMS value

I have tested your code (with some slight modifications) using an Arduino Uno R4 WiFi.

I do not have a current transformer, so I used a function generator to inject a signal into pin A0.

I modified the code as follows:

  • I removed the '* 1000.0' from the formula for calculating the current (your calculation gives the results in mA, not A).
  • I altered the reference voltage to match my Arduino Uno R4 reference voltage.
  • I added lines to turn pin 12 high before the ADC measurements and low again when they were finished, so that I could monitor how long the sampling period was.
#include <digitalWriteFast.h>

// Pin Definitions
const int analogPin = A0; // Analog input pin connected to the CT circuit
const int monitorPin =12; // pin used to monitor ADC convertion time on oscilloscope

// Constants
const float referenceVoltage = 4.694; // Arduino supply/reference voltage
const int adcResolution = 4096;     // 12-bit ADC resolution
const float burdenResistor = 1; // Burden resistor value in ohms
const float currentTransformerRatio = 50.0; // CT ratio (50:1)
const int numSamples = 1000; // Number of samples for RMS calculation

void setup() {
  pinMode(monitorPin, OUTPUT);
  Serial.begin(9600);
  analogReadResolution(12);
}

void loop() {
  float voltageSum = 0;
  digitalWriteFast(monitorPin, HIGH);
  // Sampling the analog signal
  for (int i = 0; i < numSamples; i++) {
    int analogValue = analogRead(analogPin); // Read the analog value
    float voltage = (analogValue * referenceVoltage) / adcResolution; // Convert ADC value to voltage
    float centeredVoltage = voltage - (referenceVoltage / 2); // Remove the DC offset (biasing)
    voltageSum += centeredVoltage * centeredVoltage; // Sum of squares for RMS calculation
  }
  digitalWriteFast(monitorPin, LOW);
  
  // Calculate RMS voltage
  float rmsVoltage = sqrt(voltageSum / numSamples);

  // Calculate the current based on the burden resistor and CT ratio
  float current = (rmsVoltage / burdenResistor) * currentTransformerRatio;

  // Print the current value
  Serial.print("Current (A): ");
  Serial.println(current);

  delay(1000); // Delay 1 second between readings
}

Here are the results, displayed on an oscilloscope and the serial monitor simultaneously.

  • The yellow trace indicates the width of the sampling period.
  • The blue trace is a 50Hz sinewave injected into pin A0.

Input amplitude = 1V RMS, to simulate a current of 50A RMS:

Input amplitude = 500mV RMS, to simulate a current of 25A RMS:

The results vary slightly from the expected 50A/25A.
I believe this is due to the sampling period not being exactly one whole period of the waveform.

If you take the average of all the values displayed on the serial monitor then the results are pretty accurate:
Average

Sorry for the late ansewer, i have forgot to put the schematic of my application.

Here's the schematic

My burden is 1 ohm and two resistor are 10Kohms with a capacitor of 10µF

For the values i tried with an oven to measure its consumption normally i expect 6,51 A but i get 4,7 A or 4 A, and when i don't any device normally i should get 0A or 0.01 for the noise, but i get higher than the expected 0.2 or 0.1 A

Yes i did it look at the my schematic

I have said that the maximum current that my CT can measure is 50 A, but i have tried with a device of 6,51 A

Can you please post a copy of your circuit, a picture of a hand drawn circuit in jpg, png?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.

Sorry but a Fritzy image is not a schematic, especially f you have to place an addendum about component values.

Thanks.. Tom.. :smiley: :+1: :coffee: :australia:

if your SCT-013 is rated at 50amps it may already have a burden resistor built in
the 100amp SCT-013 sensors I used all have a suitable burden resistor built in - the external circuits just offset the signal for input to the ESP32 ADCs
checking the accuracy with a current clamp meter readings are within a few percent

Here's a new schematic :slight_smile:

No i use CT without a burden resistor and it's not SCT-013, I know that SCT-013 has already a burden resistor.

Here's the link of my CT : link to the product

The datasheet for the current transformer doesn't mention a burden resistor.

I think that the fact that the 5A versions use a thicker gauge wire than the 1A versions indicates that the burden resistor is user supplied.

Don't try using the current transformer without a burden resistor - dangerous voltages are generated.

I can confirm that your schematic matches the schematic suggested by openenergymonitor.org, with the caveat that you are using a reference voltage of 3.3V, not 5V.
ct-sensors-circuit1

So what's the solution if i must use this CT ?

Here's some results :
the expected value :


The value of CT with arduino :

Using this schematic :

Hello again i have tried to visualize the signal of CT from the burden resistor and i get this wave :

And the peak is approximately 583 mV :

when i calculate the value of the secondary current with Vmax, I get Isec = Vmax/burden_resistor = 583*10^-3/4.7 = 0.124 A
And Iprimary = Isec * 50 = 0.124 * 50 = 6.20 A (which is the result i expect)

But when i calculate the value of the secondary current with VRMS, i get Isec = Vrms/Burden_resistor = 378.35*10^-3/4.7 = 0.0805 A

And Iprimary = Isec * 50 = 0.0805 * 50 = 4.025 A (which is the result i get in arduino)

So the question here how can i get in the output only the maximum value the wave ?

What is 4.7?

It is the value my burden resistor, i have changed it.
Now i have found that i measure Vrms not Vmax, so i should multiply by sqrt(2) to obtain the same value as multimeter, but when i do the same thing with the other devices that have a lower current i get value greater than expected