Reading AC current with SCT013 sensor - troubleshooting

Hi! First of all sorry about my english. Can anybody give me a help? I´m not an expert in arduino and electronics, just the basics.

I have a project with Arduino MEGA 2560 to perform AC current measurement using a 100A(max) SCT013 sensor in the 50mA model as shown in the image below:

https://www.filipeflop.com/wp-content/uploads/2017/07/IMG_2909.png

The circuit and code I'm using is this:

https://www.filipeflop.com/blog/medidor-de-corrente-sct013-com-arduino/

Basically, everything worked very well, I compared the readings with multimeter and varied values of current ​​and it is well calibrated when the arduino is connected to the PC's USB or batteries.

When I removed it from the USB and put in an external 5V power I had some weird problems. When I used a small source of 110V -> 5V it worked very well (same for USB). But I want to use a UPS system so that when the power goes out it will keep operating. So it uses two 18650 batteries, operates with 5V at the input and supposedly "regulates" also to 5V at the output, see the model below:

https://pt.aliexpress.com/item/4000859585770.html?spm=a2g0s.9042311.0.0.2742b90akAUywZ

With this configuration the reading of the arduino analog port was left with a difference, that is, even with it calibrated and without any load on the SCT013 sesor, it gives a reading of practically 0.5A and is not zeroed. And when I load it, it's far from what is expected in the reading too.

This made me wonder if it could be some filter problem in this UPS system that influences the analog ports. Do you think that if I put a 1000uf capacitor in the output of this UPS could solve the problem? OR it could be another problem?

I recorded this video to be more accurate with the information =)
https://youtu.be/tMZKf1N_RU0

Thank you very much!

It maybe ( and I’ve not followed all the links ) that the sketch uses the default power supply reference for analog inputs - with this the reading you get will vary if the supply voltage changes.
Have at look at using the internal voltage reference , which is not supply dependant .

Btw people don’t like following links and prefer posted code and decent schematics - have a look at the forum guide

Hi Hammy, thank you for your answer.
1 - I will look for some information about this interna voltage reference. =)
2 - Sorry about my links, my intention was to be more complete in information as possible.
3 - I don´t have schematic. This is a amateur project =/

My full code at the momment:

#include <SimpleTimer.h>
#include "EmonLib.h" //INCLUSÃO DE BIBLIOTECA
#include <LiquidCrystal_I2C.h>
#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>
#include "printf.h"

//Função para resetar o arduino
void (*funcReset)() = 0;

//  ***** CONFIGURAÇÕES DO LCD *****
LiquidCrystal_I2C lcd(0x27, 20, 4); // coluna, linha

//Definições do Radio
//RF24 radio(9, 10);               // nRF24L01(+) radio attached using Getting Started board CONFIG NANO
RF24 radio(53,48);                // nRF24L01(+) radio attached using Getting Started board CONFIG MEGA

RF24Network network(radio);      // Network uses that radio
int channel = 10;  //Canal do Radio entre 0 e 82 (Permitido Brasil)
const uint16_t this_node = 05;    // Address of our node in Octal format ( 04,031, etc)
const uint16_t base = 00;   // Address of the other node in Octal format
const uint16_t satelite1 = 01;       // Address of the other node in Octal format
const uint16_t satelite2 = 02;       // Address of the other node in Octal format
const uint16_t satelite3 = 03;       // Address of the other node in Octal format
const uint16_t satelite4 = 04;       // Address of the other node in Octal format

//  ***** DEFINES *****
#define VOLT_CAL1 500.0 //VALOR DE CALIBRAÇÃO (DEVE SER AJUSTADO EM PARALELO COM UM MULTÍMETRO)
#define VOLT_CAL2 500.0 //VALOR DE CALIBRAÇÃO (DEVE SER AJUSTADO EM PARALELO COM UM MULTÍMETRO)

#define voltPin1 A6 //Pino de leitura da voltage1m para sensor voltage1
#define voltPin2 A7 //Pino de leitura da voltage1m para sensor voltage1
#define ampPin1 A0 //Pino de leitura da voltage1m para sensor voltage1
#define ampPin2 A1 //Pino de leitura da voltage1m para sensor voltage1
#define ampPin3 A2 //Pino de leitura da voltage1m para sensor voltage1
#define ampPin4 A3 //Pino de leitura da voltage1m para sensor voltage1

// ******** DEFINICAO DE UTILIZAÇÃO DE SENSORES ************

bool ampSensor1 = 1;
bool ampSensor2 = 0;
bool ampSensor3 = 0;
bool ampSensor4 = 0;


//  ***** CRIAÇÃO DE INSTANCIAS *****
EnergyMonitor emon1, emon2, emon3, emon4; //CRIA UMA INSTÂNCIA PARA voltagem
//EnergyMonitor voltage2; //CRIA UMA INSTÂNCIA PARA voltagem 2

//EnergyMonitor current1; //CRIA UMA INSTÂNCIA PARA CORRENTE 1
//EnergyMonitor current2; //CRIA UMA INSTÂNCIA PARA CORRENTE 2
//EnergyMonitor current3; //CRIA UMA INSTÂNCIA PARA CORRENTE 3
//EnergyMonitor current4; //CRIA UMA INSTÂNCIA PARA CORRENTE 4


SimpleTimer timer; //TIMER

//  ***** VERIAVEIS LOCAIS *****
int acVoltage1; //Tensão 110 V
int acVoltage2; //Tnesão 220 V

float Irms1;
float Irms2;
float Irms3;
float Irms4;
float IrmsTotal; //Corrente Total A

float acPower1; //Potencia 110 W
float acPower2; //Potencia 220 W

int acPowerInst; //Potencia Total W
int acPowerAcum; //Potencia Acumulada Kw/h



//Struct de TRANSMISSÃO com replicação das variáeis locais
struct payload_t {                 // Structure of our payload
  
  int acVoltage1;   //Voltagem 110 V
  int acVoltage2;   //Voltagem 220 V
  float IrmsTotal;    //Amperagem Total A
  int acPowerInst; //Potencia Total Instantanea W
  float acPowerAcum; //Potencia Total Acumulada Kw/h
  
};

//Struct de RECEPÇÃO
struct payload_r {                 // Structure of our payload
  bool requestSAT;
};


void setup(){  

  //Inicializa monitor serial
  Serial.begin(115200); //INICIALIZA A SERIAL
  
  //ICICIALIZA TIMERS
  timer.setInterval(2000, readAC);
  timer.setInterval(2000, printSerial);
  timer.setInterval(2000, printLCD);
  

  //ICICIALIZA LCD E DA BOAS VINDAS
  lcd.init();
  lcd.backlight();
  lcd.clear(); //Limpa o LCD
  lcd.setCursor(2, 0);
  lcd.print(" MATROX  SYSTEM ");
  lcd.setCursor(4, 2);
  lcd.print(" AC MONITOR ");
  //delay(2000);
  
  warmUp();
  lcd.clear(); //Limpa o LCD
  montaLCD(); //Chama função para montar o layout do LCD
  
  //DEFINIÇÕES DE LEITURA DA CORRENTE E TENSÃO
  emon1.voltage(voltPin1, VOLT_CAL1, 1.7); //PASSA PARA A FUNÇÃO OS PARÂMETROS (PINO ANALÓGIO / VALOR DE CALIBRAÇÃO / MUDANÇA DE FASE)
  emon2.voltage(voltPin2, VOLT_CAL2, 1.7); //PASSA PARA A FUNÇÃO OS PARÂMETROS (PINO ANALÓGIO / VALOR DE CALIBRAÇÃO / MUDANÇA DE FASE)

  //Calibra cálculo de corrente (A)
  emon1.current(ampPin1, 60.6); // Era 60.607
  emon2.current(ampPin2, 55.0); // Era 60.607
  emon3.current(ampPin3, 55.0); // Era 60.607
  emon4.current(ampPin4, 55.0); // Era 60.607
  

  //Inicializa RF24
  SPI.begin();
  printf_begin();
  radio.begin();                    //ATIVA A PLACA NRF24L01
  radio.setPALevel(RF24_PA_MAX);    //NIVEL DE POTENCIA DO AMPLIFICADOR PA NO MÁXIMO
  radio.setDataRate(RF24_2MBPS);  //VELOCIDADE DE TRANSMISSÃO EM 250Kbps
  radio.setChannel(channel);        //SELECIONA O CANAL 82 (DECIMAL) - ULTIMO CANAL LIVRE DA BANDA ISM NO BRASIL
  radio.printDetails();
  network.begin(channel, this_node);
  
}

void loop(){
  
  //  ***** TIMER GLOBAL *****
  timer.run();

  // Check the network regularly
  network.update();

  //Recebe dados do RF24
  recebe();
  //Serial.println(analogRead(0));

    
}


void recebe() {
  while ( network.available() ) {     // Is there anything ready for us?
    RF24NetworkHeader header;        // If so, grab it and print it out
    network.peek(header);            //Pega o próximo cabeçalho disponivel e trata

    if (header.from_node == 0) {
      payload_r payload;
      network.read(header, &payload, sizeof(payload));
      Serial.println(""); //Pula linha
      Serial.print("Dados Recebidos de BASE: ");
      Serial.println(header.from_node);
      //Serial.println(payload.requestSAT);
      
      if (payload.requestSAT == true) {
        envia();
      }
      else {
        Serial.println("Request false");
      }
    }
    else {
      break;
    }
  }
}



void envia() {
  Serial.print("Enviando dados para Base... ");
  payload_t payload = {acVoltage1, acVoltage2, IrmsTotal, acPowerInst, acPowerAcum};
  RF24NetworkHeader header(base); //destino, header type
  header.from_node = this_node;
  bool ok = network.write(header, &payload, sizeof(payload));
  if (ok) 
    Serial.println("ok.");

  else 
    Serial.println("failed.");
    Serial.println("");
}

//FUNÇÃO PARA LEITURA DOS SENSORES AC
void readAC(){
  
  //Calcula Sensor de Tensão 1
  emon1.calcVI(17,200); //FUNÇÃO DE CÁLCULO (17 SEMICICLOS, TEMPO LIMITE PARA FAZER A MEDIÇÃO)    
  acVoltage1  = emon1.Vrms; //VARIÁVEL RECEBE O VALOR DE TENSÃO RMS OBTIDO
  if(acVoltage1 <= 3){acVoltage1=0;} //Define Tensão para ZERO pela variação na rede sem o sensor.

  //Calcula Sensor de Tensão 2
  emon4.calcVI(17,200);emon4.Vrms; //VARIÁVEL RECEBE O VALOR DE TENSÃO RMS OBTIDO
  acVoltage2  = emon4.Vrms; //VARIÁVEL RECEBE O VALOR DE TENSÃO RMS OBTIDO
  if(acVoltage1 <= 3){acVoltage1=0;} //Define Tensão para ZERO pela variação na rede sem o sensor.
  
  //Calcula Sensor de corrente 1 se habilitado
  if(ampSensor1 == true){
    Irms1 = (emon1.calcIrms(1480));   // Calcula o valor da Corrente era(1480)
    //if(Irms1 <= 0.3){Irms1=0;} //Define Corrente para  ZERO pela variação na rede sem o sensor
  }

  //Calcula Sensor de corrente 2 se habilitado
  if(ampSensor2 == true){
    Irms2 = (emon2.calcIrms(1480));   // Calcula o valor da Corrente era(1480)
    if(Irms2 <= 0.3){Irms2=0;} //Define Corrente para  ZERO pela variação na rede sem o sensor
  }

  //Calcula Sensor de corrente 3 se habilitado
  if(ampSensor3 == true){
    Irms3 = (emon3.calcIrms(1480));   // Calcula o valor da Corrente era(1480)
    if(Irms3 <= 0.3){Irms3=0;} //Define Corrente para  ZERO pela variação na rede sem o sensor
  }

  //Calcula Sensor de corrente 4 se habilitado
  if(ampSensor4 == true){
    Irms4 = (emon4.calcIrms(1480));   // Calcula o valor da Corrente era(1480)
    if(Irms4 <= 0.3){Irms4=0;} //Define Corrente para  ZERO pela variação na rede sem o sensor
  }

  //Consolida todas as correntes na variável publica
  float Irms110 = Irms1 + Irms2 + Irms3;
  float Irms220 = Irms4;
  IrmsTotal = Irms110 + Irms220;

  //Calcula potecia para sensor de tensão 1 (110V)
  acPower1 = Irms110 * acVoltage1;      // Calcula o valor da acPower Instantanea para sensor 1 de 110V
  
  //Calcula potecia para sensor de tensão 2 (220V)
  acPower2 = Irms220 * 230;      // Calcula o valor da acPower Instantanea para sensor 4 de 220V (usar variável acVoltage2 ou valor fixo)

  //Consolida potencia total na variavel publica
  acPowerInst = acPower1 + acPower2;

  //Calcula consumo global acumulado de Potencia em KW/h    
  acPowerAcum=acPowerAcum+((acPowerInst/1800)/1000); //1800 para 2 segundos //3600 para 1 segundo.

}


void printSerial(){
  Serial.println("REDE AC: ");
  
  Serial.print("Tensão 1: "); //IMPRIME O TEXTO NA SERIAL
  Serial.print(acVoltage1); //IMPRIME NA SERIAL O VALOR DE TENSÃO MEDIDO E REMOVE A PARTE DECIMAL
  Serial.println(" V."); //IMPRIME O TEXTO NA SERIAL

  Serial.print("Tensão 2: "); //IMPRIME O TEXTO NA SERIAL
  Serial.print(acVoltage2); //IMPRIME NA SERIAL O VALOR DE TENSÃO MEDIDO E REMOVE A PARTE DECIMAL
  Serial.println(" V."); //IMPRIME O TEXTO NA SERIAL

  Serial.print("Corrente 1: ");
  Serial.print(Irms1);
  Serial.println(" A.");

  Serial.print("Corrente 2: ");
  Serial.print(Irms2);
  Serial.println(" A.");

  Serial.print("Corrente 3: ");
  Serial.print(Irms3);
  Serial.println(" A.");

  Serial.print("Corrente 4: ");
  Serial.print(Irms4);
  Serial.println(" A.");
  
  Serial.print("Corrente Total: ");
  Serial.print(IrmsTotal);
  Serial.println(" A.");

  Serial.print("Potencia: ");
  Serial.print(acPowerInst);
  Serial.println(" W.");

  Serial.print("Acumulado: ");
  Serial.print(acPowerAcum);
  Serial.println(" KWh.");

  Serial.println("");
}

//FUNÇÃO PARA IMPRESSAO NO LCD
void printLCD(){
  //limpa dados do LCD
  lcd.setCursor(8, 0);
  lcd.print("        ");
  lcd.setCursor(10, 1);
  lcd.print("      ");
  lcd.setCursor(10, 2);
  lcd.print("      ");
  lcd.setCursor(9, 3);
  lcd.print("       ");

  //Imprime novos dados do LCD
  lcd.setCursor(8, 0);
  lcd.print(acVoltage1);

  lcd.setCursor(12, 0);
  lcd.print(acVoltage2);

  lcd.setCursor(10, 1);
  lcd.print(IrmsTotal,2);

  lcd.setCursor(10, 2);
  lcd.print(acPowerInst,1);

  lcd.setCursor(9, 3);
  lcd.print(acPowerAcum,2);
}

void montaLCD(){
  // coluna, linha
  lcd.setCursor(0, 0);
  lcd.print("TENSAO: ");

  lcd.setCursor(16, 0);
  lcd.print("V.");

  lcd.setCursor(0, 1);
  lcd.print("CORRENTE: ");

  lcd.setCursor(16, 1);
  lcd.print("A.");

  lcd.setCursor(0, 2);
  lcd.print("POTENCIA: ");

  lcd.setCursor(16, 2);
  lcd.print("W.");

  lcd.setCursor(0, 3);
  lcd.print("CONSUMO: ");

  lcd.setCursor(16, 3);
  lcd.print("KWh.");
}

void warmUp(){
  readAC();
  readAC();
  readAC();
}

Hammy, I used this line in SETUP:

analogReference(EXTERNAL);

And pluged in the VCC of my power supply to the IOREF PIN. But the readings got even worse:
Now with 0 amps no sensor it show 8.xx amps =/

I really think thats a electronic issue, noise or potential difference. And thats is strange because the GND is the same to all sensors and arduino.

Just to remember, in USB and batteries all works fine. It just got this strange measre when charging the batteries.

Has another clue?

analogReference(INTERNAL);

By the way, when you connected 5V to the Arduino, which pin did you use? I hope not the barrel jack, or the Vin pin. That will not work.

Hi aarg.
With INTERNAL I got a compilation error:

error: 'INTERNAL' was not declared in this scope

And I´m using the 5V pin. This is right?
Thanks

5V pin is right. Please post the updated code so we can see the whole context.

The Full coe is in my second reply in this topic. It´s already updated. =)
This is just a module of all ecosystem that I buit to monitor my house.
And this module is for monitoring the Energy voltage, current, power, etc. For this reason you´ll see some nrf24l01 code.

Thank you for the help. =)

Thanks, but please don't ever go back and edit previous posts like that. It makes the responses seem inappropriate and makes it hard to follow the real history of the the thread.

Actually, I see no analogReference() call in setup of the code you posted in reply #3.

To eliminate such confusion, please just re-post the current code in a new reply. Also when you post error messages, post the entire error listing, not just a snippet.

The forum guidelines were indicated to you in reply #2, and those are available to read in the permanent threads at the top of the forum. You should spend some time reading them because you haven't yet posted your information in the correct way, to attract help here.