Sensor de corriente eléctrica no invasivo con Arduino y SCT-013

Los sensores SCT-013 disponen de un núcleo ferromagnético partido (como une pinza) que permite abrirlo para arrollar un conductor de una instalación eléctrica sin necesidad de cortarlo.

Dentro de la familia SCT-013 existen modelos que proporcionan la medición como una salida de intensidad o de tensión. Dentro de lo posible, lo normal es que prefiramos salida por tensión porque la conexión es más sencilla.

Salida del sensor en intensidad

El SCT-013 son transformadores de intensidad, es decir, la medición se obtiene como una señal de intensidad proporcional a la corriente que circula por el cable. Pero los procesadores solo son capaces de medir tensiones.

Este problema es sencillo de resolver. Para convertir la salida en intensidad en una salida de tensión únicamente tendremos que incluir una resistencia (resistencia burden).

Excepto el modelo SCT-013-100, todos los demás modelos tienen una resistencia de burden interna para que la salida sea una señal de tensión de 1V. Por lo cual ni siquiera tendremos que preocuparnos por ello.

Únicamente en el caso del SCT-013-100, carece de resistencia burden interna, por lo que la salida es una señal de ±50mA. Una resistencia de 33Ω en paralelo con el sensor será suficiente.

Tensiones positivas y negativas

Otro problema que tenemos que resolver es que estamos midiendo corriente alterna, y la intensidad inducida en el secundario es igualmente alterna. Tras el paso por la resistencia burden (interna o externa) la salida de tensión también es alterna.

Sin embargo, como sabemos, las entradas analógicas de la mayoría de procesados, incluidos Arduino, sólo pueden medir tensiones positivas.

Para poder medir las tensiones de la salida del transformador tenemos varias opciones, de peor a mejor.

Rectificar la señal mediante un puente de diodos, y medir la onda como valores positivos. No recomendable dado que perdemos la información de si estamos en el semiperiodo negativo o positivo, además porque tendremos la caída de tensión del diodo y, aún peor, el diodo no conduce por debajo de una tensión por lo que la señal estará distorsionada en los cruces por cero.

Añadir un offset en DC mediante el uso de dos resistencias y un condensador que proporcionen un punto medio entre GND y Vcc. Mucho mejor si además añadimos un amplificador operacional como seguidor de tensión.

Añadir un ADC con entrada diferencial, que permite realizar mediciones de tensiones positivas y negativas, como el ADS1115. Es la opción que vamos a usar nosotros.

Conexión eléctrica

Ya tenemos todos los componentes para medir la intensidad de red con un sensor SCT-013. Vamos a usar un sensor con salida de tensión ±1V RMS y resistencia burden interna, junto con un ADC como el ADS1115 en modo diferencial.

Ajustando la ganancia del ADS1115 a 2.048V estaremos dentro del rango de ±1.414V. En el caso de un sensor de 30A tendremos una precisión de 1.87mA, y 6,25 mA para un sensor de 100A.

Si usáis un SCT-013-100 con salida de ±50mA, tendremos que añadir una resistencia burden externa de 33Ω y subir la ganancia del ADS1115 a 4.096V para cumplir con el rango de ±2.33V.

La conexión, vista desde Arduino, sería únicamente la alimentación del módulo ADS1115 como vimos en la entrada sobre el ADS1115.

Montaje con ADS1115

Si habéis usado el montaje con un SCT-013 con salida de ±1V RMS y ADS1115, el código necesario es similar al que vimos en la entrada sobre el ADS1115. Necesitaréis la librería de Adafruit para el ADS1115.

Para que el ADS1115 muestree a una velocidad superior, deberemos modificar la siguiente línea del fichero 'Adafruit_ADS1015.h'

 
#define ADS1115_CONVERSIONDELAY (8)
 

Por,

 
#define ADS1115_CONVERSIONDELAY (1)
 

Con esto conseguiremos bajar el tiempo de muestreo de unos 8-9 ms (unos 100 Hz) a 1.8 aprox (unos 500 Hz). Con eso nos alejamos de la frecuencia de Nyquist, y mejoramos el comportamiento de la medición.

#include <Wire.h>
#include <Adafruit_ADS1015.h>
 
Adafruit_ADS1115 ads;
  
const float FACTOR = 30; //30A/1V

const float multiplier = 0.0625F;
 
void setup()
{
  Serial.begin(9600);
 
  ads.setGain(GAIN_TWO);        // ±2.048V  1 bit = 0.0625mV
  ads.begin();
}

void printMeasure(String prefix, float value, String postfix)
{
 Serial.print(prefix);
 Serial.print(value, 3);
 Serial.println(postfix);
}
 
void loop()
{
 float currentRMS = getCorriente();
 float power = 230.0 * currentRMS;
 
 printMeasure("Irms: ", currentRMS, "A ,");
 printMeasure("Potencia: ", power, "W");
 delay(1000);
}
 
float getCorriente()
{
 float voltage;
 float corriente;
 float sum = 0;
 long tiempo = millis();
 int counter = 0;
 
 while (millis() - tiempo < 1000)
 {
   voltage = ads.readADC_Differential_0_1() * multiplier;
   corriente = voltage * FACTOR;
   corriente /= 1000.0;
 
   sum += sq(corriente);
   counter = counter + 1;
  }
 
 corriente = sqrt(sum / counter);
 return(corriente);
}

Otra versión es emplear el máximo y el mínimo de la medición, y calcular la medición a partir del valor de pico. Los resultados deberían ser similares a los vistos en el ejemplo con la suma al cuadrado. Para ello, podéis sustituir la función por la siguiente.

float getCorriente()
{
 long tiempo = millis();
 long rawAdc = ads.readADC_Differential_0_1();
 long minRaw = rawAdc;
 long maxRaw = rawAdc;
 while (millis() - tiempo < 1000)
 {
   rawAdc = ads.readADC_Differential_0_1();
   maxRaw = maxRaw > rawAdc ? maxRaw : rawAdc;
   minRaw = minRaw < rawAdc ? minRaw : rawAdc;
 }

  maxRaw = maxRaw > -minRaw ? maxRaw : -minRaw;
  float voltagePeak = maxRaw * multiplier / 1000;
  float voltageRMS = voltagePeak * 0.70710678118;
  float currentRMS = voltageRMS * FACTOR;
  return(currentRMS);
}

Montaje con resistencias y punto medio

En este caso el ejemplo es muy sencillo, únicamente tenemos que realizar la medición mediante una entrada analógica.

const float FACTOR = 30; //30A/1V

const float VMIN = 1.08;
const float VMAX = 3.92;

const float ADCV = 5.0;  //Para Vcc
//const float ADCV = 1.1; //Para referencia interna  


void setup()
{
   Serial.begin(9600);
   //analogReference(INTERNAL);
}

void printMeasure(String prefix, float value, String postfix)
{
   Serial.print(prefix);
   Serial.print(value, 3);
   Serial.println(postfix);
}

void loop()
{
   float currentRMS = getCorriente();
   float power = 230.0 * currentRMS;

   printMeasure("Irms: ", currentRMS, "A ,");
   printMeasure("Potencia: ", power, "W");
   delay(1000);
}

float getCorriente()
{
   float voltage;
   float corriente;
   float sum = 0;
   long tiempo = millis();
   int counter = 0;

   while (millis() - tiempo < 500)
   {
      voltage = analogRead(A0) * ADCV / 1023.0;
      corriente = fmap(voltage, VMIN, VMAX, -FACTOR, FACTOR);

      sum += sq(corriente);
      counter = counter + 1;
      delay(1);
   }

   corriente = sqrt(sum / counter);
   return(corriente);
}

// cambio de escala entre floats
float fmap(float x, float in_min, float in_max, float out_min, float out_max)
{
 return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

Comentarios

https://naylampmechatronics.com/blog/51_tutorial-sensor-de-corriente-ac-...

En este link se encuentra una explicacion de como utilizar el sensor no invasivo stc 013, junto con el operacional lm358.

La utilización del oeracional lm358 tiene como ventaja la utilización del semiciclo negativo de la corriente alterna, de esta forma se obtiene una lectura mas plana.

El inconveniete que encuentro con la utilización del sensor sct013 es que las medidas obtenidas son en unidades aparentes (activa + reactiva).

Para el proyecto, necesito saber la valores activos, los valores aparentes  no me vale pues en determinados momentos y sobre todo con caragas inductivas los valores que me aporta son erroneos. El  proyecto en ejecusión evalua potencias activas tanto directas (consumo casa) como inversa (placa solar).