¿Cómo medir la potencia real de CA y la potencia aparente con Arduino?


Cuando se habla de potencia en corriente alterna (CA), es más complicado, ya que implica forma de onda y diferencia de fase, pero básicamente, hay 3 términos para la alimentación de CA: la potencia aparente , la potencia activa y la potencia reactiva . 

  • La potencia aparente se refiere a la potencia total en un circuito de CA que incluye la potencia disipada y absorbida. Este término es importante para el diseño de generadores de energía y cables para asegurarse de que todo el cableado y la energía puedan soportar todo tipo de cargas. La potencia aparente se puede calcular multiplicando el valor de voltaje de raíz cuadrada media (RMS) y el valor de corriente (RMS).
  • El segundo término es el Poder Activo / Real . Es la potencia real consumida por la carga. La potencia activa se puede calcular promediando el producto de los valores instantáneos de forma de onda de voltaje y corriente. 
  • El tercer término es la potencia reactiva, que se refiere a la potencia que se desperdicia y que la carga no utiliza como trabajo útil debido a la diferencia de fase entre las formas de onda de voltaje y corriente. Cuando la potencia reactiva se suma a la potencia activa, le dará la potencia aparente. 

Usaremos un Arduino para medir la  potencia aparente y la potencia real por lo que para medir la energía de CA , necesitamos usar 2 sensores separados que son el módulo de voltaje de CA monofásico y el módulo de corriente de CA. 

Cada módulo puede encajar en el pin de entrada analógica Arduino  . Para un Arduino UNO, hay  6 pines de entrada analógicas  (A0-A5)pero para un Arduino NANO tiene 8 pines, mientras que Arduino MEGA tiene 16 pines de entrada. Los pines de entrada analógica asignarán voltajes de entrada entre 0 y 5 V en valores enteros entre 0 y 1023 con una resolución de 4,9 mV por unidad (5,00 V / 1024 unidades). 

!Cuidado ! Asumimos que tiene los conocimientos básicos de electricidad y sabe a qué se enfrenta. Es posible que necesite la orientación de personas con experiencia si es nuevo en el trabajo eléctrico. La seguridad y la precaución deben tenerse siempre en cuenta. No seremos responsables de nada que le suceda.

Puede medir voltaje CA como 110Vac, 220Vac y 240Vac mediante el uso de la disposición en el mercado  individual  Fase V de CA módulo de voltaje. Puede detectar la forma de onda instantánea para el valor de voltaje. La señal se puede utilizar con el sensor de corriente CA para determinar más información útil, como el  factor de potencia, la dirección del flujo de corriente, la potencia real y la potencia aparente. 

Es posible que deba precalibrar el módulo. Mediante el uso del potenciómetro trimpot, se puede ajustar la amplitud de la forma de onda de voltaje. Se recomienda utilizar un segundo medidor que lea el voltaje RMS para facilitar la calibración. 

Módulo de voltaje CA monofásico

Este módulo ZMPT101 B está equipado con un transformador de voltaje de alta precisión ZMPT101B y un circuito de amplificador operacional. Puede medir voltaje CA dentro de 250V. La señal de salida correspondiente se puede ajustar utilizando el potenciómetro de ajuste. 

La imagen tiene un atributo ALT vacío; su nombre de archivo es 51tDdSO3u+L._AC_SL1000_.jpg

Estas resumidamente algunas de sus características:

  • Módulo de transformador de voltaje monofásico activo Sensor de voltaje de salida de CA
  • Equipado con la serie ZMPT101B de transformador de voltaje de alta precisión y corriente de amplificador operacional de alta precisión, fácil de 250V dentro de la adquisición de señal de alimentación de CA
  • Transformador de voltaje: Transformador de micro voltaje de precisión a bordo
  • Salida de voltaje de modo: el módulo puede medir el voltaje de CA dentro de 250 V, el modo de salida correspondiente se puede ajustar
  • Circuito amplificador operacional: circuito amplificador integrado de alta precisión, la señal para hacer el muestreo exacto y la compensación adecuada y otras funciones

El sensor de Intensidad

El segundo sensor del que queremos hablar es el Módulo Sensor de Corriente. El sensor de corriente ampliamente utilizado que es compatible con Arduino es el módulo de sensor de corriente ACS712 . Utiliza el fenómeno de efecto hall cuyo voltaje se produce a partir del movimiento de la corriente dentro de la región del campo magnético. El voltaje producido por el efecto hall es directamente proporcional a la corriente aplicada, lo que lo hace adecuado para estimar la corriente aplicada a partir del voltaje detectado.

El módulo de sensor de corriente estándar  ACS712  se vende en tres versiones de   5A, 20A y 30A  que sons adecuadas para la mayoría de las aplicaciones.  El módulo 5A tiene una resolución de 185 mV / amperio, el módulo 20A tiene 100 mV / amperio, mientras que el módulo 30A tiene una resolución de 66 mV / amperio.

Estos módulos requieren contacto directo, lo cual podria ser un gran inconveniente pues debe conectarse en serie al valor medido . El cableado del sistema existente debe modificarse para que el módulo encaje en el sistema existente. 

Si no tiene experiencia con la alimentación de CA, personalmente no recomiendo este módulo. Este módulo es aceptable para CC de bajo voltaje, pero puede ser  peligroso en CA si no se toma en serio ,por lo que una alternativa es usar un tipo de sensor de efecto Hall con transformador de núcleo dividido (como se muestra en la imagen de la izquierda). Es el   módulo HSTS016L del sensor de núcleo dividido de efecto Hall . El modelo va desde 10A hasta 200A . Con el tipo de sensor de corriente de núcleo dividido, no se requiere alteración en el sistema existente. !!! El voltaje de salida de este sensor es de  2,5 V +/- 0,625 V  con una precisión decente. Recomiendo encarecidamente este sensor para medir la corriente alterna en caso de no tener experiencia con BT.

YHDC Hall Split Core Current Sensor HSTS016L ±10A/2.5±0.625V

Codigo arduino

Para fines de demostración, usaremos el sensor de núcleo dividido de efecto Hall que no requiere contacto eléctrico con el sistema de cableado existente, lo que definitivamente es una forma más segura  !!!Las señales detectadas por Arduino están en valores analógicos. A continuación se muestran las señales detectadas por el voltaje (azul) y el sensor de corriente (rojo). Puede copiar el siguiente código para probar el suyo. Puede ver la forma de onda en Serial Plotter. Conecte el módulo de voltaje en el pin A2 de Arduino mientras que el módulo de corriente en el pin A3 . La magnitud del voltaje (onda azul) se puede calibrar mediante el módulo de voltaje de CA utilizando el potenciómetro integrado y se puede comparar con el voltímetro RMS de referencia. Para una onda sinusoidal pura como esta, el valor RMS en el voltímetro multiplicado por la raíz cuadrada 2 es igual al voltaje máximo(magnitud desde la mitad de la oscilación). La magnitud de la onda de corriente (onda roja) está sujeta a su carga aplicada. Puede modificar el código Arduino para aumentar su magnitud con fines de visualización. El patrón de onda de CA puede no ser 100% suave como una onda de voltaje y está sujeto a la carga sobre cómo se extrae la corriente. El cambio de fase o la diferencia de fase entre el voltaje y la corriente también están sujetos a la carga aplicada.

float vAnalogRead;
float iAnalogRead;
int voltageInputPin = A2; // Analog input pin for voltage sensor
int currentInputPin = A3; // Analog input pin for current sensor
int currentOffset = 0; // key in value for current offset setting
int voltageOffset = 0; // key in value for voltage offset setting
float virtualMagnification = 5; // to increase the magnification of current value in display

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


 void loop()
{
vAnalogRead = analogRead(voltageInputPin) – 512 + voltageOffset;
iAnalogRead = virtualMagnification*(analogRead(currentInputPin) – 512) + currentOffset;
 Serial.print(vAnalogRead)
;Serial.print(” “);
Serial.println(iAnalogRead);delay(300); 
}

 El punto medio para Ambas ondas debería estar técnicamente en 512 (valor analógico) y fluctúa entre 0 y 1023 de forma predeterminada. Sin embargo, he modificado el código para que las ondas oscilen en el punto medio del  valor 0  entre 512 y -512 para facilitar el cálculo más adelante. Antes de continuar, es necesario realizar una calibración antes de la medición,  ya que algunos módulos pueden tener un error de desviación diferente. Puede ir a la publicación de sensores individuales para obtener más información.

Cómo se procesa la señal

Necesitamos determinar los 2 valores de potencia de CA, el valor de potencia de CA RMS  y el valor de potencia de CA activa . Antes de continuar, comencemos con la calibración inicial de ambos sensores. Necesitamos minimizar cualquier error potencial de desviación o inexactitud tanto como sea posible. Los sensores son muy sensibles, asegúrese de utilizar conectores ajustados y terminales de cable. 

Necesitamos una calibración de 2 veces para cada sensor de módulo . Ambas calibraciones deben realizarse sin medir la corriente y el voltaje. La primera calibración es asegurarse de que cuando no se mide voltaje o corriente, se muestra exactamente en el punto 0. Es una calibración de valor analógico. Es posible que algunos módulos no se muestren exactamente en el valor analógico 512 (lo he cambiado al punto 0 usando el código Arduino para una fácil comprensión) cuando no se detecta ningún valor. Necesitamos agregar un valor de compensación para que esto vuelva a ajustarlo al origen cuando no se detecta ningún valor.

La segunda calibración es para eliminar aún más el valor de la señal falsa durante el cálculo RMS. Incluso después de que se realiza la primera calibración, todavía hay algún ruido fantasma o eléctrico menor incluso cuando no se miden voltaje ni corriente. Tenemos que agregar otro desplazamiento para llegar al valor cero en la etapa final de visualización. Esta segunda calibración debe realizarse solo después de que la primera calibración entre en vigor. Ambas calibraciones se pueden realizar manualmente (la forma más difícil) o automáticamente presionando el botón SELECT en el protector de la pantalla LCD y espere unos 5 segundos. Por eso es necesario tener el escudo para que funcione. ¡Puede comprar en nuestro enlace de afiliado aquí !

El cálculo de la potencia cuadrática media de la raíz

La  potencia de CA RMS  es el producto de los   valores de voltaje CA RMS  y  corriente CA RMS . El voltaje CA RMS y la corriente CA RMS se calculan por separado. Al encontrar la potencia de CA RMS, el voltaje RMS y la corriente RMS se encuentran indirectamente. 

Nuestro código está diseñado para calcular o mostrar un valor que se deriva de un  promedio de 1000 muestras por conjunto. Encontré un problema de que un tiempo de grabación de muestra más corto (menos de 1 milisegundo para 1 lectura de muestra) podría retrasar el tiempo de procesamiento, lo que hizo que el tiempo de visualización se ralentizara. He configurado que cada muestra se registre cada 1 milisegundo (0,001 segundos). En otras palabras, el conjunto completo total equivale a 50 ondas con cada onda dividida en 20 secciones o lecturas (para 50 Hz). Técnicamente, debería durar 1 segundo para 1 conjunto de lectura. También es adecuado para el sistema de 60 Hz, ya que el tiempo de medición para 1 juego de lectura es de 1 segundo.

Cada valor analógico de muestra individual se eleva al  cuadrado  inicialmente y una vez que se  acumulan los valores  de 1000 muestras , el  valor promedio de las 1000 muestras se establece   en raíz cuadrada para obtener el   valor analógico RMS (para 1 sensor). Convierta el valor analógico RMS en voltaje medido o valor actual. Realice el cálculo similar por separado para el otro sensor y multiplique ambos valores RMS para convertirlos en energía CA RMS. A continuación se muestra un ejemplo de cómo funciona el código. Tomo un  cuarto de onda como ejemplo .

En la conversión de  voltaje RMS , multiplico  el valor analógico RMS por 2 . Durante la calibración de este módulo, reduje la amplitud de onda a la mitad (es por eso que en el código es necesario multiplicar por 2) porque la onda de voltaje comenzó a distorsionarse o cortarse cerca de 250Vac, lo que puede dar inexactitud en la medición. Puede aumentar el voltaje de suministro al módulo para eliminar el efecto de corte (según el manual del módulo) pero creo que lo dejaré así ya que no voy a agregar suministro de voltaje adicional. En cuanto a la conversión de corriente RMS, el mV / A es la clasificación del sensor de corriente y lo dejo como el símbolo de la unidad. 1023 es la conversión de valor analógico, mientras que 5000 es el valor de voltaje en mV. Para obtener más información sobre esto, puede ir a mi publicación sobre el sensor de CA  aquí..

El cálculo de la potencia instantánea

Active o Real Power  es más simple en comparación con RMS Power.  Es el  valor promedio  de todas las  multiplicaciones  de  voltaje instantáneo  y   valor de corriente instantánea . Los valores analógicos de tensión y corriente   se convierten primero en  valores de tensión y corriente medidos . Luego, el voltaje se multiplica por su valor de corriente instantánea y se convierte en una lectura de muestra. 

Similar al método de potencia RMS, la potencia activa también se deriva de un promedio de 1000 muestras por conjunto. Cada muestra se registra cada milisegundo, es decir, el conjunto completo total equivale a 50 ondas con cada onda dividida en 20 secciones o lecturas (para 50 Hz). 

Puede ser interesante añadir una pantalla LCD de 16X2   que se puede colocar directamente en la parte superior de la placa Arduino sin la necesidad de cableado adicional para la pantalla LCD. Sin la pantalla LCD, solo puede monitorear el valor de corriente medido en la PC a través del Monitor en serie. 

La buena noticia es que no necesita calibrar manualmente la configuración de compensación si tiene la pantalla LCD  con usted. A continuación, adjuntamos el código que utiliza la función del botón que podría  calibrarse automáticamente  por sí mismo cuando presionó el  botón SELECT . Puede descargar desde el final de esta página a continuación.  

Conexión de hardware

Es posible que deba encontrar una manera de colocar el cable del sensor de CA en el pin Arduino. El cable del sensor que compré venía presoldado en la punta, lo que facilita el acceso a los pines de Arduino. Abra el módulo de corriente Split Core y se mostrará un símbolo de flecha que indica el camino del flujo de corriente. Una vez que todo esté listo, asegúrese de que el núcleo partido esté bien cerrado.  

Asegúrese de que debajo del sensor de voltaje no haya conductores expuestos o placas de metal que puedan causarle un cortocircuito accidental en el terminal del módulo. Debe obtener el fusible rápido de baja corriente para el cable del sensor de voltaje, mientras que el MCB o el fusible de corriente nominal suficiente según su carga para protegerlo contra cualquier posible cortocircuito y riesgo de incendio.

Para conectar el cableado entre la placa Arduino y el módulo, necesita los  cables de línea dupont macho a hembra . ¡Puedes conseguirlo en nuestro enlace de afiliado aquí ! 

Necesita el conector que pueda asegurar los cables y aislarlos del contacto accidental. ¡Obtenga el  conector rápido  en nuestro enlace de afiliado  aquí  !

Código final Arduino

El paso final sería agregar el código fuente a la placa Arduino. Supongo que ha instalado el software Arduino. Si no ha instalado el software, el enlace  aquí  puede llevarlo al sitio oficial de descarga. Una vez que haya descargado el software, puede descargar el archivo de código (.ino) para esta aplicación a continuación (haga clic con el botón derecho en el enlace para guardar). 

Hay 2  archivos de códigos fuente adjuntos  que son código fuente con y sin función de protección de pantalla LCD. Si no tiene el protector de pantalla LCD con usted, elija el código que no tiene el protector de pantalla LCD, pero debe calibrar manualmente e ingresar los 2 valores de compensación para ambos sensores. Sin embargo, le recomiendo encarecidamente que obtenga un protector de pantalla LCD.

Con el protector de pantalla LCD, una vez que el código se carga en la placa Arduino, el valor actual se mostrará en la pantalla LCD. Hemos agregado la función de autocalibrado, una vez que se presiona el botón SELECT, el valor regresa al punto cero exacto. Puede que tenga que esperar entre 5 y 8 segundos hasta que se vuelvan a calibrar todos los valores. Si la primera pulsación no está satisfecha, puede repetir pulsando de nuevo .

Proceso de calibracion 

Una vez que el código se carga en el Arduino, si tiene un protector de pantalla LCD adjunto, verá la corriente, el voltaje, la potencia activa y el valor de potencia aparente. Asegúrese de apagar la fuente de voltaje de CA  que está midiendo. Presione el botón SELECT del protector de pantalla LCD y espere 5 segundos. Debería llegar a  0 voltios . Lo mismo para la corriente CA que muestra 0A . Para las personas que no tienen el protector de pantalla LCD, puede compensar manualmente ingresando el valor de compensación en el código y volver a cargarlo. Hay 2 valores de compensación (voltageOffset1 y voltageOffset2) que se deben calibrar. Haga lo mismo para el módulo de corriente CA para 2 valores de compensación (currentOffset1 y currentOffset2) y finalmente es el powerOffset.

Ajuste de voltaje de CA del potenciómetro de trimpot 

Esta configuración es para ajustar la magnitud de la onda de voltaje de CA. A diferencia de la corriente CA, calculamos y obtenemos la corriente esperada, pero para el voltaje CA, necesitamos un voltaje de referencia para el ajuste.

Una vez realizada la calibración, debería ver el valor 0 voltios cuando no se detecta voltaje. Ahora, encienda la fuente de voltaje y encienda el lector de voltaje de referencia (el multímetro o el medidor de energía). Compare ambos valores de voltaje. Gire el potenciómetro de ajuste (trimpot) con un destornillador pequeño para reducir o aumentar el valor de voltaje detectado por Arduino. Debe girar el potenciómetro hasta que el voltaje que se muestra en la pantalla LCD Shield o Monitor serial sea el mismo que el valor de referencia de voltaje en el medidor de voltaje o energía. ¡¡¡Y felicitaciones, ya está hecho !!!!

Si realmente lee los códigos, en realidad hemos reducido la amplitud de onda potencial a la mitad (en la fórmula es por 2). 

RMSVoltageMean = (sqrt (voltageMean)) * 2;

Es por eso que cuando se aplica voltaje de monitoreo, el valor medido es alto y es necesario reducirlo. La amplitud de onda completa (x 1) se distorsiona cuando está cerca de 250 V, lo que nos hizo tener esta opción para superar el problema de distorsión.

Resultado: en monitor de serie

Para archivos de código Arduino, recuerde hacer clic derecho> Guardar enlace como …  Puede modificar el código interno como desee. ¡Feliz codificación! 

AC Power.ino

// AC Power Monitoring By Solarduino 

// Note Summary
// Note :  Safety is very important when dealing with electricity. We take no responsibilities while you do it at your own risk.
// Note :  This AC Power Monitoring Code needs AC current module and AC Voltage Module to determine AC Power value. 
// Note :  This Code monitors RMS Voltage, RMS current, RMS AC Power (Apparent Power) and Instantaneous AC Power (Active Power)
// Note :  The value shown in Serial Monitor is refreshed every second, can be used for 50Hz and 60Hz.
// Note :  The frequency is measured by counting time and average it for every 50 samples taken (1 sample is 1 cycle for 50Hz by default).
// Note :  You have to manually calibrate 5 offsets readings : voltageOffset1,voltageOffset2,currentOffset1,currentOffset2 & powerOffset.  
// Note :  The unit provides reasonable accuracy and may not be comparable with other expensive branded and commercial product.
// Note :  All credit shall be given to Solarduino.

/*/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/////////////*/


        /* 0- General */

        int decimalPrecision = 2;                         // decimal places for all values shown in LED Display & Serial Monitor

        /* 1- AC Voltage Measurement */
        
        int voltageOffset1  = 0;                          // key in offset value
        int voltageOffset2  = 0;                          // key in offset value
        int VoltageAnalogInputPin = A2;                   // Which pin to measure voltage Value
        float voltageSampleRead  = 0;                     /* to read the value of a sample*/
        float voltageLastSample  = 0;                     /* to count time for each sample. Technically 1 milli second 1 sample is taken */
        float voltageSampleSum   = 0;                     /* accumulation of sample readings */
        float voltageSampleCount = 0;                     /* to count number of sample. */
        float voltageMean ;                               /* to calculate the average value from all samples*/ 
        float RMSVoltageMean ;                            /* square roof of voltageMean*/


        /* 2- AC Current Measurement */

        int currentOffset1  = 0;                          // key in offset value
        int currentOffset2  = 0;                          // key in offset value
        int CurrentAnalogInputPin = A3;                   // Which pin to measure Current Value
        float mVperAmpValue = 31.25;                      // If using ACS712 current module : for 5A module key in 185, for 20A module key in 100, for 30A module key in 66
                                                          // If using "Hall-Effect" Current Transformer, key in value using this formula: mVperAmp = maximum voltage range (in milli volt) / current rating of CT
                                                          /* For example, a 20A Hall-Effect Current Transformer rated at 20A, 2.5V +/- 0.625V, mVperAmp will be 625 mV / 20A = 31.25mV/A */
        float currentSampleRead  = 0;                     /* to read the value of a sample*/
        float currentLastSample  = 0;                     /* to count time for each sample. Technically 1 milli second 1 sample is taken */
        float currentSampleSum   = 0;                     /* accumulation of sample readings */
        float currentSampleCount = 0;                     /* to count number of sample. */
        float currentMean ;                               /* to calculate the average value from all samples*/ 
        float RMSCurrentMean =0 ;                         /* square roof of currentMean*/
        float FinalRMSCurrent ;                           /* the final RMS current reading*/


        /* 3- AC Power Measurement */
        
        int powerOffset =0;                               // key in offset value
        float sampleCurrent1 ;                            /* use to calculate current*/
        float sampleCurrent2 ;                            /* use to calculate current*/
        float sampleCurrent3 ;                            /* use to calculate current*/
        float apparentPower;                              /* the apparent power reading (VA) */
        float realPower = 0;                              /* the real power reading (W) */
        float powerSampleRead  = 0;                       /* to read the current X voltage value of a sample*/
        float powerLastSample   = 0;                      /* to count time for each sample. Technically 1 milli second 1 sample is taken */       
        float powerSampleCount  = 0;                      /* to count number of sample. */
        float powerSampleSum    = 0;                      /* accumulation of sample readings */         
        float powerFactor = 0;                            /* to display power factor value*/ 


void setup()                                              /*codes to run once */

{                                      

        /* 0- General */
        
        Serial.begin(9600);                               /* to display readings in Serial Monitor at 9600 baud rates */

}


void loop()                                                                                       /*codes to run again and again */
{                                      


        /* 1- AC Voltage Measurement */
 
        if(millis() >= voltageLastSample + 1 )                                                    /* every 1 milli second taking 1 reading */
          {
            voltageSampleRead = 2*(analogRead(VoltageAnalogInputPin)- 512) + voltageOffset1;      /* read the sample value */           
            voltageSampleSum = voltageSampleSum + sq(voltageSampleRead) ;                         /* accumulate value with older sample readings*/     
            voltageSampleCount = voltageSampleCount + 1;                                          /* to move on to the next following count */
            voltageLastSample = millis() ;                                                        /* to reset the time again so that next cycle can start again*/ 
          }
        
        if(voltageSampleCount == 1000)                                                            /* after 1000 count or 1000 milli seconds (1 second), do the calculation and display value*/
          {           
            voltageMean = voltageSampleSum/voltageSampleCount;                                    /* calculate average value of all sample readings taken*/
            RMSVoltageMean = sqrt(voltageMean)+ voltageOffset2;                                   /* square root of the average value*/
            Serial.print("Voltage RMS: ");
            Serial.print(RMSVoltageMean,decimalPrecision);
            Serial.println("V  ");
            voltageSampleSum =0;                                                                  /* to reset accumulate sample values for the next cycle */
            voltageSampleCount=0;                                                                 /* to reset number of sample for the next cycle */
          }


        /* 2- AC Current Measurement */
        
        if(millis() >= currentLastSample + 1)                                                     /* every 1 milli second taking 1 reading */
          {
            currentSampleRead = analogRead(CurrentAnalogInputPin)-512 + currentOffset1;           /* read the sample value */
            currentSampleSum = currentSampleSum + sq(currentSampleRead) ;                         /* accumulate value with older sample readings*/
            currentSampleCount = currentSampleCount + 1;                                          /* to move on to the next following count */
            currentLastSample = millis();                                                         /* to reset the time again so that next cycle can start again*/ 
          }
        
        if(currentSampleCount == 1000)                                                            /* after 1000 count or 1000 milli seconds (1 second), do the calculation and display value*/
          {       
            currentMean = currentSampleSum/currentSampleCount;                                    /* calculate average value of all sample readings taken*/
            RMSCurrentMean = sqrt(currentMean)+currentOffset2 ;                                   /* square root of the average value*/
            FinalRMSCurrent = (((RMSCurrentMean /1024) *5000) /mVperAmpValue);                    /* calculate the final RMS current*/
            Serial.print("Current RMS: ");
            Serial.print(FinalRMSCurrent,decimalPrecision);
            Serial.println(" A  ");
            currentSampleSum =0;                                                                  /* to reset accumulate sample values for the next cycle */
            currentSampleCount=0;                                                                 /* to reset number of sample for the next cycle */
          }

       
        /* 3- AC Power with Direction */

        if(millis() >= powerLastSample + 1)                                                       /* every 1 milli second taking 1 reading */
          {
            sampleCurrent1 = analogRead(CurrentAnalogInputPin)-512+ currentOffset1;
            sampleCurrent2 = (sampleCurrent1/1024)*5000;
            sampleCurrent3 = sampleCurrent2/mVperAmpValue;
            voltageSampleRead = 2*(analogRead(VoltageAnalogInputPin)- 512)+ voltageOffset1 ;
            powerSampleRead = voltageSampleRead * sampleCurrent3 ;                                /* real power sample value */
            powerSampleSum = powerSampleSum + powerSampleRead ;                                   /* accumulate value with older sample readings*/
            powerSampleCount = powerSampleCount + 1;                                              /* to move on to the next following count */
            powerLastSample = millis();                                                           /* to reset the time again so that next cycle can start again*/ 
          }
        
        if(powerSampleCount == 1000)                                                              /* after 1000 count or 1000 milli seconds (1 second), do the calculation and display value*/
          {
            realPower = ((powerSampleSum/powerSampleCount)+ powerOffset) ;                        /* calculate average value of all sample readings */
            Serial.print("Real Power (W): ");
            Serial.print(realPower);
            Serial.println(" W  ");           
            apparentPower= FinalRMSCurrent*RMSVoltageMean;                                       /*Apparent power do not need to recount as RMS current and RMS voltage values available*/
            Serial.print("Apparent Power (VA): ");
            Serial.print(apparentPower,decimalPrecision);
            Serial.println(" VA ");
            powerFactor = realPower/apparentPower;    
            if(powerFactor >1 || powerFactor<0)
            {
              powerFactor = 0;
            }
            Serial.print("Power Factor: ");
            Serial.println(powerFactor,decimalPrecision);  
            Serial.println(" ");                                           
            powerSampleSum =0;                                                                    /* to reset accumulate sample values for the next cycle */
            powerSampleCount=0;                                                                   /* to reset number of sample for the next cycle */
          }
  
}









lcd (AP Power with LCD Disply.ino)

// AC Power Monitoring with LCD By Solarduino 

// Note Summary
// Note :  Safety is very important when dealing with electricity. We take no responsibilities while you do it at your own risk.
// Note :  This AC Power Monitoring Code needs AC current module and AC Voltage Module to determine AC Power value. 
// Note :  This Code monitors RMS Voltage, RMS current, RMS AC Power (Apparent Power) and Instantaneous AC Power (Active Power)
// Note :  The value shown in Serial Monitor is refreshed every second, can be used for 50Hz and 60Hz.
// Note :  The frequency is measured by counting time and average it for every 25 samples taken (1 sample is 1 cycle).
// Note :  The auto calibration (voltageOffset1 & currentOffset1) is using averaged analogRead value of 1000 samples.
// Note :  The auto calibration (voltageOffset2 & currentOffset2) is using calculated RMS value including Offset1 value for calibration.    
// Note :  The unit provides reasonable accuracy and may not be comparable with other expensive branded and commercial product.
// Note :  All credit shall be given to Solarduino.

/*/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/////////////*/


        /* 0- General */

        int decimalPrecision = 2;                         // decimal places for all values shown in LED Display & Serial Monitor

        /* 1- AC Voltage Measurement */
        
        int VoltageAnalogInputPin = A2;                   // Which pin to measure voltage Value
        float voltageSampleRead  = 0;                     /* to read the value of a sample*/
        float voltageLastSample  = 0;                     /* to count time for each sample. Technically 1 milli second 1 sample is taken */
        float voltageSampleSum   = 0;                     /* accumulation of sample readings */
        float voltageSampleCount = 0;                     /* to count number of sample. */
        float voltageMean ;                               /* to calculate the average value from all samples*/ 
        float RMSVoltageMean ;                            /* square roof of voltageMean*/

              /*1.1 Offset AC Voltage */
    
              int voltageOffsetRead = 0;                  /* to change the mode for offset */
              float voltageOffset1 = 0;                   // to Offset deviation and accuracy. Offset any fake current when no current operates. 
                                                          // Offset will automatically callibrate when SELECT Button on the LCD Display Shield is pressed.
                                                          // If you do not have LCD Display Shield, look into serial monitor to add or minus the value manually and key in here.
              float voltageOffset2 = 0;                   // to offset value due to calculation error from squared and square root.
              float voltageSampleSumOffset =0;            /* accumulation of sample readings for offset */
              float offsetVoltageMean = 0;                /* to calculate the average value from all samples for offset, in analog values*/
              float voltageOffsetLastSample = 0;          /* to count time for each sample for offset purpose. */
              float voltageOffsetSampleCount = 0;         /* to count number of sample for offset. */


        /* 2- AC Current Measurement */

        int CurrentAnalogInputPin = A3;                   // Which pin to measure Current Value
        float mVperAmpValue = 31.25;                      // If using ACS712 current module : for 5A module key in 185, for 20A module key in 100, for 30A module key in 66
                                                          // If using "Hall-Effect" Current Transformer, key in value using this formula: mVperAmp = maximum voltage range (in milli volt) / current rating of CT
                                                          /* For example, a 20A Hall-Effect Current Transformer rated at 20A, 2.5V +/- 0.625V, mVperAmp will be 625 mV / 20A = 31.25mV/A */
        float currentSampleRead  = 0;                     /* to read the value of a sample*/
        float currentLastSample  = 0;                     /* to count time for each sample. Technically 1 milli second 1 sample is taken */
        float currentSampleSum   = 0;                     /* accumulation of sample readings */
        float currentSampleCount = 0;                     /* to count number of sample. */
        float currentMean ;                               /* to calculate the average value from all samples*/ 
        float RMSCurrentMean =0 ;                         /* square roof of currentMean*/
        float FinalRMSCurrent ;                           /* the final RMS current reading*/


              /*2.1 Offset AC Current */
    
              int currentOffsetRead = 0;                  /* to change the mode for offset */
              float currentOffset1 = 0;                   // to Offset deviation and accuracy. Offset any fake current when no current operates. 
                                                          // Offset will automatically callibrate when SELECT Button on the LCD Display Shield is pressed.
                                                          // If you do not have LCD Display Shield, look into serial monitor to add or minus the value manually and key in here.
                                                          // 26 means add 26 to all analog value measured
              float currentOffset2 = 0;                   // to offset value due to calculation error from squared and square root.
              float currentSampleSumOffset = 0;           /* accumulation of sample readings for offset */
              float offsetCurrentMean = 0;                /* to calculate the average value from all samples for offset, in analog values*/
              float currentOffsetLastSample = 0;          /* to count time for each sample for offset purpose. */
              float currentOffsetSampleCount = 0;         /* to count number of sample for offset. */


        /* 3- AC Power Measurement */
        
        float sampleCurrent1 ;                            /* use to calculate current*/
        float sampleCurrent2 ;                            /* use to calculate current*/
        float sampleCurrent3 ;                            /* use to calculate current*/
        float apparentPower;                              /* the apparent power reading (VA) */
        float realPower = 0;                              /* the real power reading (W) */
        float powerSampleRead  = 0;                       /* to read the current X voltage value of a sample*/
        float powerLastSample   = 0;                      /* to count time for each sample. Technically 1 milli second 1 sample is taken */       
        float powerSampleCount  = 0;                      /* to count number of sample. */
        float powerSampleSum    = 0;                      /* accumulation of sample readings */         
        float powerFactor = 0;                            /* to display power factor value*/ 


              /*3.1 Offset AC Power */
    
              int powerOffsetRead = 0;                    /* to change the mode for offset */
              float powerOffset = 0;                      // to Offset deviation and accuracy. Offset any fake current when no current operates. 
                                                          // Offset will automatically callibrate when SELECT Button on the LCD Display Shield is pressed.
                                                          // If you do not have LCD Display Shield, look into serial monitor to add or minus the value manually and key in here.
              float powerOffsetLastSample = 0;            /* to count time for each sample for offset purpose. */
              float powerOffsetSampleCount = 0;           /* to count number of sample for offset. */

        
        /* 4 - LCD Display  */

        #include<LiquidCrystal.h>                   /* Load the liquid Crystal Library (by default already built-it with arduino solftware)*/
        LiquidCrystal LCD(8,9,4,5,6,7);             /* Creating the LiquidCrystal object named LCD. The pin may be varies based on LCD module that you use*/
        unsigned long startMillisLCD;               /* start counting time for LCD Display */
        unsigned long currentMillisLCD;             /* current counting time for LCD Display */
        const unsigned long periodLCD = 1000;       // refresh every X seconds (in seconds) in LED Display. Default 1000 = 1 second 
        int page = 1;                               /* flip page to display values*/

void setup()                                              /*codes to run once */

{                                      

        /* 0- General */
        
        Serial.begin(9600);                               /* to display readings in Serial Monitor at 9600 baud rates */

        /* 4 - LCD Display  */

        LCD.begin(16,2);                                  /* Tell Arduino that our LCD has 16 columns and 2 rows*/
        LCD.setCursor(0,0);                               /* Set LCD to start with upper left corner of display*/  
        startMillisLCD = millis();                        /* Start counting time for LCD display*/

}


void loop()                                                                                       /*codes to run again and again */
{                                      

        /* 0- General */


              /* 0.1- Button Function */
        
              int buttonRead;
              buttonRead = analogRead (0);                                                        // Read analog pin A0. Pin A0 automatically assigned for LCD Display Button function (cannot be changed)

              /*Right button is pressed */
              if (buttonRead < 60) 
              {   LCD.setCursor(0,0); LCD.print ("PRESS <SELECT>   "); }       
     
              /* Up button is pressed */
              else if (buttonRead < 200) 
              {   
              page = 1;
              }    
                 
              /* Down button is pressed */
              else if (buttonRead < 400)
              {   
              page = 2;
              }      
     
              /* Left button is pressed */
              else if (buttonRead < 600)
              {   LCD.setCursor(0,0); LCD.print ("PRESS <SELECT>   "); } 
     
              /* Select button is pressed */
              else if (buttonRead < 800)
              {   
              currentOffsetRead = 1;                                                              // to activate offset for current  
              voltageOffsetRead = 1;                                                              // to activate offset for voltage
              powerOffsetRead = 1;                                                                // to activate offset for power
              LCD.setCursor(0,0);                                                                 /* set display words starting at upper left corner*/
              LCD.print ("INITIALIZING..... ");
              LCD.setCursor(0,1);                                                                 /* set display words starting at lower left corner*/
              LCD.print ("WAIT 5 SEC ..... ");
              }


        /* 1- AC Voltage Measurement */
 
        if(millis() >= voltageLastSample + 1 )                                                    /* every 1 milli second taking 1 reading */
          {
            voltageSampleRead = 2*(analogRead(VoltageAnalogInputPin)- 512) + voltageOffset1;      /* read the sample value */
            voltageSampleSumOffset = voltageSampleSumOffset + voltageSampleRead;                  /* values accumulate for offset purpose every milli second */
            
            voltageSampleSum = voltageSampleSum + sq(voltageSampleRead) ;                         /* accumulate value with older sample readings*/     
            voltageSampleCount = voltageSampleCount + 1;                                          /* to move on to the next following count */
            voltageLastSample = millis() ;                                                        /* to reset the time again so that next cycle can start again*/ 
          }
        
        if(voltageSampleCount == 1000)                                                            /* after 1000 count or 1000 milli seconds (1 second), do the calculation and display value*/
          {
            offsetVoltageMean = voltageSampleSumOffset/voltageSampleCount;                        /* average the offset reading*/
            
            voltageMean = voltageSampleSum/voltageSampleCount;                                    /* calculate average value of all sample readings taken*/
            RMSVoltageMean = sqrt(voltageMean)+ voltageOffset2;                                   /* square root of the average value*/
            Serial.print(" The Voltage RMS value is: ");
            Serial.print(RMSVoltageMean,decimalPrecision);
            Serial.println(" V ");
            voltageSampleSum =0;                                                                  /* to reset accumulate sample values for the next cycle */
            voltageSampleCount=0;                                                                 /* to reset number of sample for the next cycle */
            voltageSampleSumOffset=0;
          }
 

              /* 1.1 - Offset AC Voltage */
                  
              if(voltageOffsetRead == 1)                                                          /* Run this code when button SELECT is pressed */
                {
                  voltageOffset1 = 0; 
                  if(millis()>= voltageOffsetLastSample + 1)                                      /* keep countng time for offset1*/
                    {                                                                            
                      voltageOffsetSampleCount = voltageOffsetSampleCount + 1;                    /* 1 milli second add 1 count*/                                                      
                      voltageOffsetLastSample = millis();                                         /* to reset the time again so that next cycle can start again*/                                  
                    }                                                                                 
                  if(voltageOffsetSampleCount == 2000)                                            /* after 2 seconds, run this codes.  */
                    {                                                                            
                      voltageOffset1 = -1*(offsetVoltageMean);                                    /* set the offset values */
                      voltageOffsetRead = 2;                                                      /* go for second offset Settings */                     
                      voltageOffsetSampleCount = 0;                                               /* to reset the time again so that next cycle can start again */                                                             
                    } 
                }   
                    
              if(voltageOffsetRead == 2)                                                          /* Run this code after first offset done */
                {
                  voltageOffset2 = 0;                                                             /* set back currentOffset2 as default*/
                  if(millis()>= voltageOffsetLastSample + 1)                                      /* keep countng time for offset2*/
                    {                                                                            
                      voltageOffsetSampleCount = voltageOffsetSampleCount + 1;                                                                          
                      voltageOffsetLastSample = millis();                                                                          
                    }                                                                                
                  if(voltageOffsetSampleCount == 2000)                                            /* after 2 seconds, run this codes.  */
                    {                                                                            
                      voltageOffset2 = - RMSVoltageMean;                                          /* set the offset values */
                      voltageOffsetRead = 0;                                                      /* change the offset mode to original, wait until the button is pressed again */                     
                      voltageOffsetSampleCount = 0;                                               /* to reset the time again so that next cycle can start again */ 
                    }                                                                             
                } 


        /* 2- AC Current Measurement */
        
        if(millis() >= currentLastSample + 1)                                                     /* every 1 milli second taking 1 reading */
          {
            currentSampleRead = analogRead(CurrentAnalogInputPin)-512 + currentOffset1;           /* read the sample value */
            
            currentSampleSumOffset = currentSampleSumOffset + currentSampleRead;                  /* accumulate offset value */
            
            currentSampleSum = currentSampleSum + sq(currentSampleRead) ;                         /* accumulate value with older sample readings*/
            currentSampleCount = currentSampleCount + 1;                                          /* to move on to the next following count */
            currentLastSample = millis();                                                         /* to reset the time again so that next cycle can start again*/ 
          }
        
        if(currentSampleCount == 1000)                                                            /* after 1000 count or 1000 milli seconds (1 second), do the calculation and display value*/
          {
            offsetCurrentMean = currentSampleSumOffset/currentSampleCount;                        /* average offset value*/
            
            currentMean = currentSampleSum/currentSampleCount;                                    /* calculate average value of all sample readings taken*/
            RMSCurrentMean = sqrt(currentMean)+currentOffset2 ;                                   /* square root of the average value*/
            FinalRMSCurrent = (((RMSCurrentMean /1024) *5000) /mVperAmpValue);                    /* calculate the final RMS current*/
            Serial.print(" The Current RMS value is: ");
            Serial.print(FinalRMSCurrent,decimalPrecision);
            Serial.println(" A ");
            currentSampleSum =0;                                                                  /* to reset accumulate sample values for the next cycle */
            currentSampleCount=0;                                                                 /* to reset number of sample for the next cycle */
            currentSampleSumOffset=0;                                                             /* to reset accumulate offset value for the next cycle*/
          }

              /* 2.1 - Offset AC Current */
                  
              if(currentOffsetRead == 1)                                                          /* Run this code when button SELECT is pressed */
                {
                  currentOffset1 = 0;                                                             /* set currentOffset back to default value*/
                  if(millis()>= currentOffsetLastSample + 1)                                      /* keep countng time for offset1*/
                    {                                                                            
                      currentOffsetSampleCount = currentOffsetSampleCount + 1;                                                                          
                      currentOffsetLastSample = millis();                                                                          
                    }                                                                                 
                  if(currentOffsetSampleCount == 2000)                                            /* after 2 seconds, run this codes.  */
                    {                                                                            
                      currentOffset1 = - offsetCurrentMean;                                       /* set the offset values */
                      currentOffsetRead = 2;                                                      /* go for second offset Settings */                     
                      currentOffsetSampleCount = 0;                                               /* to reset the time again so that next cycle can start again */                                                             
                    } 
                }   
                
              if(currentOffsetRead == 2)                                                          /* Run this code after first offset done */
                {
                  currentOffset2 = 0;                                                             /* set back currentOffset2 as default*/
                  if(millis()>= currentOffsetLastSample + 1)                                      /* keep countng time for offset2*/
                    {                                                                            
                      currentOffsetSampleCount = currentOffsetSampleCount + 1;                                                                          
                      currentOffsetLastSample = millis();                                                                          
                    }                                                                             
                          
                  if(currentOffsetSampleCount == 2000)                                            /* after 2 seconds, run this codes.  */
                    {                                                                            
                      currentOffset2 = - RMSCurrentMean;                                          /* set the offset values */
                      currentOffsetRead = 0;                                                      /* change the offset mode to original, wait until the button is pressed again */                     
                      currentOffsetSampleCount = 0;                                               /* to reset the time again so that next cycle can start again */ 
                    }                                                                             
                } 
       
        /* 3- AC Power with Direction */

        if(millis() >= powerLastSample + 1)                                                       /* every 1 milli second taking 1 reading */
          {
            sampleCurrent1 = analogRead(CurrentAnalogInputPin)-512+ currentOffset1;
            sampleCurrent2 = (sampleCurrent1/1024)*5000;
            sampleCurrent3 = sampleCurrent2/mVperAmpValue;
            voltageSampleRead = 2*(analogRead(VoltageAnalogInputPin)- 512)+ voltageOffset1 ;
            powerSampleRead = voltageSampleRead * sampleCurrent3 ;                                /* real power sample value */
            powerSampleSum = powerSampleSum + powerSampleRead ;                                   /* accumulate value with older sample readings*/
            powerSampleCount = powerSampleCount + 1;                                              /* to move on to the next following count */
            powerLastSample = millis();                                                           /* to reset the time again so that next cycle can start again*/ 
          }
        
        if(powerSampleCount == 1000)                                                              /* after 1000 count or 1000 milli seconds (1 second), do the calculation and display value*/
          {
            realPower = ((powerSampleSum/powerSampleCount)+ powerOffset) ;                        /* calculate average value of all sample readings */
            Serial.print(" The Real Power (W) is: ");
            Serial.print(realPower);
            Serial.println(" W ");           
            apparentPower= FinalRMSCurrent*RMSVoltageMean;                                       /*Apparent power do not need to recount as RMS current and RMS voltage values available*/
            Serial.print(" The Apparent Power (VA) is: ");
            Serial.print(apparentPower,decimalPrecision);
            Serial.println(" VA ");
            powerFactor = realPower/apparentPower;    
            if(powerFactor >1 || powerFactor<0)
            {
              powerFactor = 0;
            }
            Serial.print(" The Power Factor is: ");
            Serial.println(powerFactor,decimalPrecision);                                             
            powerSampleSum =0;                                                                    /* to reset accumulate sample values for the next cycle */
            powerSampleCount=0;                                                                   /* to reset number of sample for the next cycle */
          }
 

              /* 3.1 - Offset AC Power */

              if(powerOffsetRead == 1)                                                            /* Run this code after first offset done */
                {                          
                  powerOffset = 0;                                                                /* set back currentOffset2 as default*/
                  if(millis()>= powerOffsetLastSample + 1)                                        /* keep countng time for offset2*/
                    {                                                                            
                      powerOffsetSampleCount = powerOffsetSampleCount + 1;                                                                          
                      powerOffsetLastSample = millis();                                                                          
                    }                                                                                                      
                  if(powerOffsetSampleCount == 5000)                                              /* after 5 seconds, run this codes.  */
                    {                                                                            
                      powerOffset = -realPower;                                                
                      powerOffsetRead = 0;                                                        /* change the offset mode to original, wait until the button is pressed again */                     
                      powerOffsetSampleCount = 0;                                                 /* to reset the time again so that next cycle can start again */ 
                    }                                                                             
                } 


        /* 4 - LCD Display  */
        
        currentMillisLCD = millis();                                                              /* Set current counting time */
        if (currentMillisLCD - startMillisLCD >= periodLCD && page ==1)                           /* for every x seconds, run the codes below*/
          {
            LCD.setCursor(0,0);                                                                   /* Set cursor to first colum 0 and second row 1  */
            LCD.print("I=");
            LCD.print(FinalRMSCurrent,decimalPrecision);                                          /* display current value in LCD in first row  */
            LCD.print("A  ");
            LCD.print("V=");
            LCD.print(RMSVoltageMean,decimalPrecision);                                          /* display current value in LCD in first row  */
            LCD.print("V     ");   
            LCD.setCursor(0,1); 
            LCD.print(realPower,decimalPrecision);
            LCD.print("W ");
            LCD.print(apparentPower,decimalPrecision);                                            /* display current value in LCD in first row  */
            LCD.print("VA    ");
            startMillisLCD = currentMillisLCD ;                                                   /* Set the starting point again for next counting time */
          }
          
        if( currentMillisLCD - startMillisLCD >= periodLCD && page ==2)
         {
            LCD.setCursor(0,0);                                                                   /* Set cursor to first colum 0 and second row 1  */
            LCD.print("PF=");
            LCD.print(powerFactor,decimalPrecision);
            LCD.print("            "); 
            LCD.setCursor(0,1); 
            LCD.print("                "); 
            startMillisLCD = currentMillisLCD ;                                                   /* Set the starting point again for next counting time */
          }

      
    
}

Fuente : solarduino.com/how-to-measure-ac-power-with-arduino/

Aplicaciones del SCT-013


 El sensor SCT-013 es un sensor de corriente no invasivo cuya principal utilidad es medir la intensidad en corriente alterna que atraviesa un conductor sin necesidad de interconectarlo en serie. Podemos emplear estos sensores con un microcontrolador como Arduino para medir la intensidad o potencia consumida por una carga.

Una de las ventajas más interesantes es su precio, pero sin duda  otra facilidad innegable es que no tenemos que manipular el cable ya que se trata de un sensor de corriente alterna no invasivo.

La precisión del sensor puede ser de 1-2%, pero para ello es muy importante que el núcleo ferromagnético se cierre adecuadamente. Hasta un pequeño hueco de aire puede introducir desviaciones del 10%.

Como desventaja, al ser una carga inductiva, el SCT-013 introduce una variación del ángulo de fase cuyo valor es función de la carga que lo atraviesa, pudiendo llegar a ser de hasta 3º.

SCT-013 principio de funcionamiento

Un factor importante dentro de los transformadores de corriente es el número de espiras o número de vueltas que da el cable al núcleo ferromagnético. Conociendo estos datos y la corriente que circula por uno de los devanados podemos calcular la corriente por el otro devanado.

Esto es debido a que guardan la siguiente relación:

\frac{N_p}{N_s}=\frac{I_s}{I_p}=\frac{V_p}{V_s}

A esta fórmula se le llama relación de transformación porque relaciona el número de espiras del primario (Np), del secundario (Ns), las intensidades del primario (Ip), del secundario (Is), el voltaje del primario (Vp) y del secundario (Vs).

En el caso del sensor de corriente alterna SCT-013 el devanado primario es el cable del aparato que queremos medir y el número de vueltas sería uno. El devanado secundario tiene 2.000 vueltas.

Si aplicamos la relación de transformación a esta situación y suponiendo que queremos medir una intensidad de 10 Amperios, el resultado sería el siguiente.

\frac{N_p}{N_s}=\frac{I_s}{I_p}\Rightarrow I_s=\frac{N_p\times I_p}{N_s}=\frac{1\times 10}{2000}=0,005 A

Como se puede comprobar se produce una transformación de energía pues hemos bajado de 10 A (imposible de medir esta corriente con Arduino) hasta los 0,005 A

Ahora nos faltaría conocer cómo medir la intensidad con Arduino a través de una resistencia de carga o resistencia burden (su función es convertir la corriente en un voltaje limitado que podamos medir, por ejemplo, con Arduino.).

Pero antes de meternos en ello, vamos a ver los tipos de sensores de corriente alterna SCT-013 que podemos encontrar.

Podemos comprar diferentes tipos de sensores de corriente alterna SCT-013 que se pueden organizar en dos grupos. Los que proporcionan una corriente o los que proporcionan un voltaje. La gran diferencia entre ellos es que en los primeros no viene incluida una resistencia de carga y en los segundos sí. Solo el SCT-013-000 es que nos proporciona una corriente y no tiene resistencia de carga. pudiendo medir una corriente de entre 50 mA y 100 A.

El resto de la familia de sensores SCT-013 si que tienen incluida la resistencia de carga. Podemos encontrar varios modelos pero todos tienen un voltaje de salida entre 0V y 1V y por tanto elegir uno u otro sensor SCT-013 dependerá de las necesidades según la intensidad de corriente del circuito a medir.

Con Arduino y otra placas como NodeMCU, solo podemos medir voltajes. Si además ese voltaje varía entre un mínimo y un máximo, solo podremos hacerlo a través de una entrada analógica. Por otro lado, en estos cálculos debemos conocer el consumo aproximado del aparato que vamos a medir. Esto nos permitirá ajustar la precisión. El SCT-013-000 puede medir desde 50 mA hasta los 100 A. El objetivo de calcular la resistencia de carga es obtener un valor de resistencia que nos permita leer el voltaje de la corriente que pasa por el sensor SCT-013-000. Debemos de conseguir la máxima resolución posible y para ello debemos conocer la potencia aproximada del aparato o electrodoméstico que vamos a medir.

El consumo aproximado en vatios deberemos sacarlo de las características técnicas del electrodoméstico o aparato que quiera medir. Como ejemplo hagamos los calculos para una carga de 1kw :

  • Calculo de la corriente :Para una carga de 1kw hacemos los cálculos para 1.000W y un voltaje típico, 220V, calculamos la corriente.
P=V\times I_{RMS}\Rightarrow I_{RMS}=\frac{P}{V}=\frac{1000}{220}=4,54A
  • Convertir la corriente máxima eficaz en corriente de pico.La corriente que hemos obtenido en el paso anterior es corriente eficaz. Ahora hay que convertirla en corriente de pico con la siguiente fórmula.
I_{RMS}=\frac{I_{pico}}{\sqrt{2}}\Rightarrow I_{pico}=I_{RMS}\times \sqrt{2}=4,54\times \sqrt{2}=6,42A
  • Calcular la corriente de pico en el devanado secundario. Con la fórmula de relación de transformación que hemos visto antes, podemos calcular la corriente de pico en el devanado secundario.
\frac{N_p}{N_s}=\frac{I_s}{I_p}\Rightarrow I_s=\frac{N_p\times I_p}{N_s}=\frac{1\times 6,42}{2000}=0,00321 A
  • Maximizar la resolución con el máximo valor de la entrada analógica.En este punto entra en juego la placa que estés utilizando ya que depende de cada placa la referencia interna de la entrada analógica. Esta referencia se llama AREF y nos informa del voltaje máximo que podemos medir en una entrada analógica. Por ejemplo, NodeMCU y Arduino MKR1000 utilizan 3,3V y Arduino UNO utiliza 5V. En este ejemplo vamos a utilizar el AREF de Arduino UNO, 5V. La idea es aplicar la Ley de Ohm pero utilizando la mitad de voltaje. Lo que hemos hecho en los pasos anteriores es calcular la corriente de pico lo que significa que todavía tenemos una onda sinusoidal que varía de positivo a negativo. El objetivo es ajustar la resistencia para que se cumpla la Ley de Ohm y tengamos un voltaje entre 2,5V y -2,5V ya que la corriente la tenemos fija. Por eso, como veremos ahora en la fórmula, debemos dividir AREF entre dos.
R_{carga}=\frac{\frac{AREF}{2}}{I_{pico}}=\frac{\frac{5}{2}}{0,00321}=778\Omega
  • Obteniendo un valor coherente para la resistencia de carga.El valor que nos ha dado para la resistencia de carga es de 778Ω. Este valor no es un valor que podamos encontrar fácilmente. Por eso debemos utilizar varias resistencias en serie que sean más comunes para conseguir un valor aproximado .También se podría hacer con resistencias en paralelo: por ejemplo, podemos poner en serie dos resistencias de 330Ω y una de 100Ω. Esto nos daría un valor de 760Ω más o menos aproximado al que habíamos calculado. Siempre que lo hagas quédate por debajo del valor calculado. Esto evitará que nos salgamos del límite de voltaje establecido por AREF ya que podemos llegar a dañar la placa de desarrollo con el sensor SCT-013.

RESUMEN: 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 tanto si elegimos el adecuado 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 aunque a efectos prácticos una resistencia de 33Ω en paralelo con el sensor será suficiente.

Offset

En la resistencia de carga vamos a tener un voltaje que varía de 2,5V a -2,5V que sigue siendo una señal sinusoidal por lo que el problema que existe es que ni Arduino ni NodeMCU leen voltajes negativos. Así que tenemos que modificar la señal para que pase a estar en el rango de 0V a 5V.

Eso se hace añadiendo un offset en DC a nuestra señal bastando con sumar 2,5V y estaría resuelto. Esto lo haremos a través de un circuito conocido como circuito offset en DC que básicamente consiste en poner un divisor de tensión y un condensador. El condensador tiene que ser de 10μF y unos pocos cientos de voltios. Esto hace que la reactancia sea baja y la corriente alterna evite la resistencia.

El valor de las resistencias del divisor de tensión puede ser 10kΩ siempre y cuando lo alimentemos a través de la red eléctrica. Si su dispositivo va a funcionar con pilas utilize unas resistencias de 470kΩ para que el consumo sea mínimo.

El circuito

Con todo lo que hemos visto, ya podemos montar el circuito eléctrico donde conectemos el SCT-013 y Arduino.

Antes de ver como conectar los componentes vamos a echar un vistazo al conector que viene incluido en toda la familia SCT-013. Se trata del típico conector de audio que tenemos en todos los auriculares, conocido como jack. Cada tipo de jack hembra es diferente. Deberemos investigar como se hacen las conexiones o bien cortar el cable; encontrará dos cables, uno rojo y otro blanco. Estos colores pueden variar dependiendo del fabricante y del modelo.

En el siguiente esquema vemos el montaje del circuito de offset y la resistencia de carga con un sensor SCR-013-000. Obviamente si usamos otro sensor podemos eliminar la resistencia de carga , y por tanto haciendo mas sencillo el circuito al estar dicha resistencia integrada y calibrada en el propio sensor

SCT-013 ARDUINO-UNO

Por último vamos a ver cómo tenemos que abrazar los cables de alta tensión con el sensor de corriente alterna SCT-013. No vale de cualquier forma, hay que hacerlo de una manera determinada ya que de lo contrario, no estaremos midiendo correctamente el consumo.

Lo más importante es que tenemos que abrazar solo uno de estos cables, en caso contrario la medición será cero. Esto es debido a que por uno de los cables la corriente fluye en un sentido y por el otro cable fluye en sentido contrario. Si abrazamos los dos cables un flujo magnético compensará al otro flujo magnético y se anulará.

Es importante utilizar cables de buena calidad. Por tu seguridad y para conseguir una buena precisión.

Seguramente encuentre tres cables cuando quites la funda que cubre todo. Los colores de la fase suelen ser azul o negro y para el neutro marrón. En uno de estos cables es donde tienes que abrazar el sensor SCT-013(no el de masa) . El tercer cable suele ser de color verde y amarillo y sirve para la toma de tierra por lo que no daría ninguna lectura en caso de abrazar este cable.

Calibración del sensor de corriente alterna SCT-013

Debemos partir del concepto de que nuestros aparatos no son perfectos. Es imposible fabricar cualquier cosa con absoluta precisión. Hay una relación directamente proporcional (incluso exponencial) entre precisión y precio. Cuanto más preciso más caro es el aparato.

Hay tres factores importantes a tener en cuenta y que influyen en la precisión (fuente Open Energy Monitor):

  • La relación de transferencia del transformador
  • El valor de la resistencia de carga y su tolerancia
  • La precisión del ADC a la hora de medir el voltaje en la resistencia de carga

La idea es empezar con la teórica y luego corregir ese valor con la fase experimental. Mucho ojo en la parte experimental. Vamos a trabajar con alto voltaje y puede ser muy peligroso. SI NO ESTÁ SEGURO NO HAGA LA PARTE EXPERIMENTAL.

Proceso de calibración

El proceso de calibración es sencillo. Solo tenemos que aplicar la siguiente fórmula.

F_{calibracion}=\frac{\frac{I_{2RMS}}{I_{1RMS}}}{R_{carga}}

Lo que hacemos es calcular el factor de calibración dividiendo el factor de transformación (corriente máxima eficaz dividida entre la corriente mínima eficaz) entre la resistencia de carga.

El valor que nos da sería el valor que tenemos que poner en el sketch del SCT-013. Si sustituimos los valores para la resistencia de carga que hemos calculado quedaría de la siguiente manera.

F_{calibracion}=\frac{\frac{I_{2RMS}}{I_{1RMS}}}{R_{carga}}=\frac{\frac{100}{0.05}}{760}=2,63

Este sería el valor teórico. Ya tendríamos algo por donde empezar. Para asegurarnos de que realmente este factor de calibración es bueno sería interesante conectar un aparato del cual sepamos su consumo aproximado.Por ejemplo, podemos utilizar una bombilla incandescente. Se recomienda una con bastante potencia para no perder resolución. El sensor SCT-013 nos dará una resolución de 2 decimales por lo tanto, si queremos calibrar bien este sensor debemos utilizar un aparato que consuma más de 20W.

A efectos prácticos tenemos que medir la corriente real con la corriente que está dando el sensor SCT-013 para lo cual podemos usar diferentes métodos.

  • Midiendo el voltaje de la red eléctrica :Para medir el voltaje necesitarás un multímetro. Lo primero es configurar el aparato correctamente. Tienes que seleccionar voltaje en alterna y el rango correspondiente a 220V. Además tienes que conectar el cable rojo (suele ser de este color) en voltios y el cable negro en COM. Una vez configurado debes meter las dos puntas en un enchufe. Cada una en un agujero. Da lo mismo en que agujero metas la punta. La diferencia es que te dará o positivo o negativo. Esto te dará un valor de voltaje y es el que tienes que apuntar y actualizar en el sketch.Las mediciones en este punto dependen mucho de la calidad del multímetro. Este es otro caso claro donde el precio tiene que ver mucho con la precisión.
  • Midiendo la corriente alterna con el multímetro: La corriente es algo más complicado ya que tenemos que cortar el cable y poner el mutímetro en serie con el cable, como si fuera una resistencia. En estos casos es interesante tener una clema, bornera o ficha de empalme. Eso sí, que soporte la corriente que va a pasar por la bornera. No pongas una de electrónica porque puedes dañar la instalación. Antes de nada vamos a ver cómo configurar el multímetro para medir una corriente alterna. Es diferente a la configuración de voltaje en alterna. Es importante que también tengas conectado el sensor de corriente alterna SCT-013 para poder comparar una medida y otra. Cuando mido con el multímetro obtengo el siguiente resultado. ida de 0,33A. Si hacemos los cálculos para obtener la potencia se obtiene lo siguiente P=V x I=230v x 0,33a=75,9w. Con los datos obtenidos anteriormente donde teníamos una potencia de unos 120W, comprobamos que este factor de calibración hay que ajustarlo. Por lo tanto, el factor de calibración está mal. Hay que corregirlo. Pero ahora que tenemos los datos experimentales resulta sencillo. Si el valor obtenido a través del sensor de corriente alterna SCT-013 es mayor, baja el factor de corrección. Ajusta dicho valor hasta conseguir un dato aproximado al que has obtenido en el multímetro. Solo es cuestión de ir modificando y cargando el código en la placa hasta que tener un valor correcto. No te olvides de modificar también el valor del voltaje obtenido. Al final con un factor de calibración de 1.6 y un voltaje de 230V consigo ajustarme a la corriente que nos mostraba el multímetro.

Código final para obtener la potencia con el sensor SCT-013

Gracias a Emonlib no tenemos que hacer cálculos complejos pues podemos ayudarnos en esta tarea de una librería. En concreto vamos a utilizar Emonlib creado por el proyecto Open Energy Monitor. Open Energy Monitor es un proyecto que nos proporciona diferente hardware para medir el consumo en multitud de dispositivos y aparatos. Han creado sus propias placas compatibles con Arduino. Para inlcuir esta libreria Abra el gestor de librería y busque Emonlib. También puede descargarlo desde el repositorio en GitHub.Con unas pocas líneas de código obtendremos de una forma muy sencilla la potencia que está consumiendo el aparato. Lo primero es el voltaje de tu red eléctrica.

En la función setup() iniciamos la comunicación serie para poder mostrar los datos a través del monitor serie.

Luego iniciamos el objeto que hemos creado de la clase EnergyMonitor con la función current(pinAnalogico, factorCalibracion). Esta función admite dos parámetros:

  • pinAnalogico: es el pin analógico donde hemos conectado el sensor de corriente alterna SCT-013.
  • factorCalibracion: es un valor que tenemos que calcular para corregir errores de diferentes tipos como la tolerancia de la resistencia de carga o del propio sensor SCT-013.

El pin analógico no tiene duda. Según el esquema mostrado más arriba vamos a utilizar el A0 así que pasamos como argumento un 0. El factor de corrección de momento lo dejamos a 2,6. En el siguiente apartado veremos como se calcula.

Por último en la función loop() obtenemos la corriente eficaz llamando a la función calcIrms(numMuestras). Esta función admite un parámetro:

  • numMuestras: indica cuantas muestras tiene que tomar para calcular la corriente eficaz.

El número de muestras es importante. Como hemos estado hablando a lo largo de todo este artículo, estamos trabajando con una señal sinusoidal. Esto quiere decir que tiene ciclos que se van repitiendo en el tiempo.

El número de muestras indica el número de veces que se va a leer la señal para obtener el valor de la corriente eficaz. Es interesante que estas muestras sean en ciclos completos. Según la velocidad de acceso a los pines analógicos con Arduino UNO, aproximadamente podemos medir 106 muestras en cada ciclo. Si está utilizando otro microcontrolador este valor puede variar.

Si queremos medir 14 ciclos (un valor recomendado por el proyecto Open Energy Monitor), tendremos que medir 14\times 106 = 1484 muestras . De aquí viene el valor que se pasa a la función calcIrms().

Por último mostramos toda esta información a través del monitor serie.

// Include Emon Library
#include "EmonLib.h"
 
// Crear una instancia EnergyMonitor
EnergyMonitor energyMonitor;
 
// Voltaje de nuestra red eléctrica
float voltajeRed = 230.0;
 
void setup()
{
  Serial.begin(9600);
 
  // Iniciamos la clase indicando
  // Número de pin: donde tenemos conectado el SCT-013
  // Valor de calibración: valor obtenido de la calibración teórica
  energyMonitor.current(0, 1.6);
}
 
void loop()
{
  // Obtenemos el valor de la corriente eficaz
  // Pasamos el número de muestras que queremos tomar
  double Irms = energyMonitor.calcIrms(1484);
 
  // Calculamos la potencia aparente
  double potencia =  Irms * voltajeRed;
 
  // Mostramos la información por el monitor serie
  Serial.print("Potencia = ");
  Serial.print(potencia);
  Serial.print("    Irms = ");
  Serial.println(Irms);
}

Si no deseamos usar la librería también podemos realizar los cálculos internos nosotros mismos, si bien el código ahora ya no queda tan claro como la version anterior:

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;
}

Mejora

Añadir un ADC con entrada diferencial, nos permite realizar mediciones de tensiones positivas y negativas, como el ADS1115. Esta es la opción que vamos a comentar como mejora.

  •  Este convertidor analógico digital tiene una resolución de 16 bits y una interfaz I2C para un control cómodo.
  • El módulo es adecuado para todos los microcontroladores actuales con 2.0V – 5.5V, el uso con Raspberry es posible sin problemas.
  • La frecuencia de muestro del módulo es programable hasta 860/s.
  • Gracias a la PGA interna, es posible amplificar hasta 16 veces la señal analógica.

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.

Si no queréis usar un ADC externo, podéis usar la solución más convencional, que es añadir un circuito que nos permita añadir un offset central como vimos al principio del post.

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émios 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

Por,

#define ADS1115_CONVERSIONDELAY

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);
}

Otros sensores diferentes al SCT-013

Aunque depende mucho de las necesidades del aparato que quieras medir, estos sensores invasivos (debes alterar el cable que conecta el aparato) pueden ser una buena alternativa.

  • Interruptor Sonoff WiFi y medidor de corriente de Itead
  • ACS712
  • Pololu ACS714

Cualquiera de estos sensores puede hacer la misma función. Solo tendrás que elegir aquel que se amolde mejor a las necesidades de corriente.

Fuentes: https://adafruit.com, http:// opennergymonitor.com, http:// luisllamas.es,http:// programarfacil.es

Medidor de energia con Arduino


El autor de esta idea perteneze a un pueblo de Odisha, India, donde los cortes de energía frecuentes son muy comunes. Obstaculiza la vida de todos. Durante su de infancia, continuar con los estudios después del anochecer fue un verdadero desafío. Debido a este problema diseño un sistema solar para su casa de forma experimental. Uso un panel solar de 10 Watt, 6V para iluminar algunos LED brillantes. Después de enfrentar muchas dificultades, el proyecto tuvo éxito. Luego decidio monitorear el voltaje, la corriente, la potencia y la energía involucradas en el sistema. Esto trajo la idea de diseñar un MEDIDOR DE ENERGÍA. Uso ARDUINO como el corazón de este proyecto porque es muy fácil escribir código en su IDE y hay una gran cantidad de bibliotecas de código abierto disponibles en Internet que se pueden usar de acuerdo con el requisito.

Características:
1-Monitoreo de energía por pantalla LCD
2. Envio de lecturas a través de Internet (carga Xively)
3. Registro de datos en una tarjeta SD

Piezas necesarias:

Piezas necesarias:

Potencia y energía

  1. ARDUINO UNO
  2. ARDUINO ETHERNET SHIELD
  3. LCD DE CARACTERES 16×2
  4. SENSOR DE CORRIENTE ACS 712
  5. RESISTENCIAS (10k, 330ohm)
  6. POTENCIOMETRO 10K
  7. CABLES DE PUENTE
  8. CABLE ETHERNET
  9. PANEL DE PAN

Potencia:
potencia es el producto del voltaje (voltios) y la corriente (Amp).P = VxI La unidad de potencia es Watt o KW

Energía:
Energía es producto de la potencia (Watt) y el tiempo (Hora) E = Pxt
Unidad de energía es Watt Hora o Kilovatios hora (kWh)
De la fórmula anterior, queda claro que para medir la energía necesitamos tres parámetros:
1. Voltaje
2. Corriente
3. Tiempo

Medición de voltaje

Medida de voltaje

El voltaje se mide con la ayuda de un circuito divisor de voltaje.Como el voltaje de entrada del pin analógico ARDUINO está restringido a 5V, diseño el divisor de voltaje de tal manera que el voltaje de salida debería ser inferior a 5V.Labatería utilizada para almacenar la potencia del panel solar es de 6 V, 5,5 Ah, por lo que tenemps que reducir este 6,5 V a un voltaje inferior a 5 V.
Usaremos R1 = 10k y R2 = 10K. El valor de R1 y R2 puede ser menor, pero el problema es que cuando la resistencia es baja, el flujo de corriente más alto lo atraviesa, como resultado, una gran cantidad de energía (P = I ^ 2R) se disipa en forma de calor. Por lo tanto, se pueden elegir diferentes valores de resistencia, pero se debe tener cuidado para minimizar la pérdida de potencia a través de la resistencia.

Vout = R2 / (R1 + R2) * Vbat
Vbat = 6.5 cuando está completamente cargado
R1 = 10k y R2 = 10k
Vout = 10 / (10 + 10) * 6.5 = 3.25v que es inferior a 5v y adecuado para el pin analógico ARDUINO

NOTA
Hemos mostrado que la batería de 9 voltios en el circuito de la placa desnuda es solo por ejemplo para conectar los cables. Se utiliza una batería de plomo-ácido de 6 voltios y 5,5 Ah.

Calibración de voltaje:
Cuando la batería está completamente cargada (6.5v) obtendremos un Vout = 3.25v y un valor más bajo para otro voltaje de batería más bajo.

ARDUINO ADC convierte la señal analógica a la correspondiente aproximación digital.
Cuando el voltaje de la batería es de 6.5v, obtuve 3.25v del divisor de voltaje y sample1 = 696 en el monitor en serie, donde sample1 es el valor ADC corresponde a 3.25v

Para una mejor comprensión, he adjuntado la simulación en tiempo real del circuito 123D para la calibración de medición de voltaje:

3.25v equivalente a 696
1 es equivalente a 3.25 / 696 = 4.669mv
Vout = (4.669 * sample1) / 1000 volt
Voltaje real de la batería = (2 * Vout) volt

CÓDIGO ARDUINO:

// tomando 150 muestras del divisor de voltaje con un intervalo de 2seg y luego promediar los datos de muestras

for (int i = 0; i <150; i ++)
{
sample1 = sample1 + analogRead (A2); // lee el voltaje del circuito divisor
delay (2);
}
muestra1 = muestra1 / 150;
voltaje = 4.669 * 2 * muestra1 / 1000;


Medición de corriente

Medida de corriente
Medida de corriente

Para la medición de corriente utilicé un sensor de corriente de efecto Hall ACS 712 (20 A). Hay diferentes sensores de rango de corriente ACS712 disponibles en el mercado, así que elija según sus necesidades. En el diagrama de la placa de pruebas, he mostrado el LED como una carga, pero la carga real es diferente.
PRINCIPIO DE FUNCIONAMIENTO:

El efecto Hall es la producción de una diferencia de voltaje (el voltaje de Hall) a través de un conductor eléctrico, transversal a una corriente eléctrica en el conductor y un campo magnético perpendicular a la corriente.
Para saber más sobre el sensor de efecto Hall, haga clic aquí.
La hoja de datos del sensor ACS 712 se encuentra aquí.

De la hoja de datos
1. El ACS 712 mide 20 amperios positivos y negativos, correspondientes a la salida analógica 100 mV / A
2. Ninguna corriente de prueba a través del voltaje de salida es VCC / 2 = 5v / 2 = 2.5V

Calibración:
La lectura analógica produce un valor de 0-1023, lo que equivale a 0v a 5v Por lo que la lectura analógica 1 = (5/1024) V = 4.89. Valor mv = (4.89 * Valor de lectura analógica) / 1000 V. Pero según las hojas de datos, la compensación es 2.5V (Cuando la corriente es cero, obtendrá 2.5V de la salida del sensor)
Valor real = (valor-2.5) V Corriente en amperios = real valor * 10

CÓDIGO ARDUINO:

// tomar 150 muestras de sensores con un intervalo de 2 segundos y luego promediar los datos de muestras recolectados
for (int i = 0; i <150; i ++)
{
sample2 + = analogRead (A3); // lee la corriente del sensor
delay (2);
}
muestra2 = muestra2 / 150;
val = (5.0 * muestra2) /1024.0;
actualval = val-2.5; // el voltaje de compensación es 2.5v
amps = actualval * 10;

Medición del tiempo

Para la medición del tiempo no se necesita ningún hardware externo, ya que ARDUINO tiene un temporizador incorporado.

La función millis () devuelve el número de milisegundos desde que la placa Arduino comenzó a ejecutar el programa actual.

CÓDIGO ARDUINO:

milisec largo = milis (); // calcula el tiempo en milisegundos
long time = milisec / 1000; // convierte milisegundos a segundos



Cómo ARDUINO calcula la potencia y la e


totamps = totamps + amperios; // calcular amperios totales
avgamps = totamps / time; // amperios promedio
amphr = (avgamps * tiempo) / 3600; // amperio-hora
vatio = voltaje * amperios; // potencia = voltaje *
energía actual = (vatios * tiempo) / 3600; Watt-sec se convierte nuevamente a Watt-Hr dividiendo 1 hora (3600 segundos)
// energía = (vatio * tiempo) / (1000 * 3600); para leer en kWhA

Salida visual

Todos los resultados se pueden visualizar en el monitor en serie o utilizando una pantalla LCD.
Utilicé una pantalla LCD de 16×2 caracteres para mostrar todos los resultados obtenidos en los pasos anteriores. Para los esquemas, consulte el circuito de la placa de pan que se muestra arriba.

Conecte la pantalla LCD con ARDUINO como se indica a continuación:

LCD -> Arduino
1. VSS -> Arduino GND
2. VDD -> Arduino + 5v
3. VO -> Arduino GND pin + Resistencia o potenciómetro
4. RS -> Arduino pin 8
5. RW -> Pin 7 de Arduino
6. E -> Pin 6 de Arduino
7. D0 -> Arduino – No conectado
8. D1 -> Arduino – No conectado
9. D2 -> Arduino – No conectado
10. D3 -> Arduino – No conectado
11 . D4 -> Pin 5 de Arduino
12. D5 -> Pin 4 de Arduino
13. D6 -> Pin 3 de Arduino
14. D7 -> Pin 2 de Arduino
15. A -> Pin 13 de Arduino + Resistencia (potencia de luz de fondo)
16. K -> Arduino GND (tierra de luz de fondo)

CÓDIGO ARDUINO:

Para monitor serie:

Serial.print ("VOLTAJE:");
Serial.print (voltaje);

Serial.println ("Volt");
Serial.print ("ACTUAL:");
Serial.print (amperios);
Serial.println ("Amperios");
Serial.print ("POWER:");
Serial.print (vatios);
Serial.println ("Watt");
Serial.print ("ENERGÍA CONSUMIDA:");
Serial.print (energía);
Serial.println ("Watt-Hora");
Serial.println (""); // imprime los siguientes conjuntos de parámetros después de un
retraso de línea en blanco (2000);

Para LCD:

Para la pantalla LCD, primero debe importar la biblioteca “LiquidCrystal” en el código aquí

El siguiente código es un formato para mostrar en LCD todo el cálculo de potencia y energía

#include <LiquidCrystal.h>
lcd (8, 7, 6, 5, 4, 3, 2);
int backLight = 9;configuración vacía ()
{
pinMode (luz de fondo, SALIDA); // establece el pin 9 como salida
analogWrite (backLight, 150); // controla la intensidad de la luz de fondo 0-254
lcd.begin (16,2); // columnas filas. tamaño de la pantalla
lcd.clear (); // limpia la pantalla
}
void loop ()
{
lcd.setCursor (16,1); // coloca el cursor fuera del recuento de la pantalla
lcd.print (""); // imprime un carácter vacío
delay (600);////////////////////////////////////////// Imprime potencia y energía en una pantalla LCD / /////////////////////////////////////////////////
lcd.setCursor (1,0); // coloca el cursor en la 1ª columna y la 1ª filalcd.print (vatios);
lcd.print ("W");
lcd.print (voltaje);
lcd.print ("V");
lcd.setCursor (1,1); // coloca el cursor en la 1ª columna y la 2ª fila
lcd.print (energía);
lcd.print ("WH");
lcd.print (amperios);
lcd.print ("A");
}

Carga de datos a Xively.com

Carga de datos a Xively.com
Carga de datos a Xively.com

Elija un nombre de usuario, contraseña, establezca su dirección Recibirá un correo electrónico de confirmación; luego haga clic en el enlace de activación para activar su cuenta. Después de abrir correctamente la cuenta, será redirigido a la página de dispositivos de desarrollo .Haga clic en el cuadro + Agregar dispositivo .Dé un nombre a su dispositivo y una descripción (por ejemplo,MONITOREO DE ENERGÍA). Elija datos privados o públicos (elijo privados)
Haga clic en Agregar dispositivo-Después de agregar el dispositivo, se le redirige a una nueva página donde hay mucha información importante.
ID de producto,secreto de producto, número de serie, código de activación·


Feed ID, Feed URL, API End Point (Feed ID se usa en el código ARDUINO)


Agregar canales (elijo ENERGÍA y POTENCIA, pero puede elegir según su elección) Proporcione la unidad y el símbolo para el parámetro·Agrega tu ubicación·Claves API (utilizadas en el código ARDUINO, evite compartir este número)·Disparadores (hacer ping a una página web cuando ocurre un evento, como cuando el consumo de energía supera un cierto límite)

Código Xively y ARDUINO

Archivos adjuntos

Registro de datos en una tarjeta SD

Para almacenar datos en una tarjeta SD, debe importar la biblioteca SD.


El código para almacenar datos en una tarjeta SD se escribe por separado, ya que no tengo suficiente memoria en mi ARDUINO UNO después de escribir el código para la pantalla LCD y cargar los datos xively.com. Pero estoy tratando de mejorar el código de la versión beta para que un solo código pueda contener todas las funciones (pantalla LCD, carga de datos Xively y almacenamiento de datos en una tarjeta SD).
El código para el registro de datos se adjunta a continuación.


/*
  SD card datalogger
 
 This example shows how to log data from three analog sensors 
 to an SD card using the SD library.
 	
 The circuit:
 * SD card attached to SPI bus as follows:
 ** UNO:  MOSI - pin 11, MISO - pin 12, CLK - pin 13, CS - pin 4 (CS pin can be changed)
  and pin #10 (SS) must be an output
 ** Mega:  MOSI - pin 51, MISO - pin 50, CLK - pin 52, CS - pin 4 (CS pin can be changed)
  and pin #52 (SS) must be an output
 ** Leonardo: Connect to hardware SPI via the ICSP header
 		Pin 4 used here for consistency with other Arduino examples
 
original code was created on 24 Nov 2010 and  modified 9 Apr 2012 by Tom Igoe
I (Debasish Dutta) was again modified for my energy monitoring requirement on 14/01/14
podermos 
 
 This example code is in the public domain.
 	 
 */

#include <SD.h>

// On the Ethernet Shield, CS is pin 4. Note that even if it's not
// used as the CS pin, the hardware CS pin (10 on most Arduino boards,
// 53 on the Mega) must be left as an output or the SD library
// functions will not work.
const int chipSelect = 4;

File dataFile;


float sample1=0; // for voltage
float sample2=0; // for current
float voltage=0.0;
float val; // current callibration
float actualval; // read the actual current from ACS 712
float amps=0.0;
float totamps=0.0; 
float avgamps=0.0;
float amphr=0.0;
float watt=0.0;
float energy=0.0; 

void setup()
{
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(SS, OUTPUT);
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1) ;
  }
  Serial.println("card initialized.");
  
  // Open up the file we're going to log to!
  dataFile = SD.open("energy.txt", FILE_WRITE);
  if (! dataFile) {
    Serial.println("error opening energy.txt");
    // Wait forever since we cant write data
    while (1) ;
  }
}

void loop()

{
   
 long milisec = millis(); // calculate time in milisec
 long time=milisec/1000; // convert time to sec

 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
                      /// taking 150 samples from sensors with a inerval of 2sec and then average the samples data collected
  for(int i=0;i<150;i++)
  {
    sample1+=analogRead(A2);  //read the voltage from the sensor
    sample2+=analogRead(A3); //read the current from sensor
    delay(2);
  }
   sample1=sample1/150; 
   sample2=sample2/150;
   
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
                                                 /////voltage calculation//////////////////////
  
   voltage=4.669*2*sample1/1000; //  callibration // 3.25 from voltage div is eqv 696 in A0 reading 
                                 // multiply 2 to get actual voltage//  I used two 1k resistor to read 6.36v battery volt
                                 
    //////////////////////////////////////////////// current calculation //////////////////////
 val =(5.0*sample2)/1024.0; 
 actualval =val-2.5; // offset voltage is 2.5v 
 amps =actualval*10;// 10 is multiplied as 100mv/A ( from data sheet )
 totamps=totamps+amps; // total amperes 
 avgamps=totamps/time; // average amperess
 amphr=(avgamps*time);  // ampere hour
 watt =voltage*amps;    // power=voltage*current
 energy=(watt*time)/3600;      // energy = power*timein Watt-sec ///again convert to Watt-Hr by dividing 3600sec
 
  ////////////////////////////////////////////////////////
  // make a string for assembling the data to log:
String dataString = "";
int parameter[4]={voltage,amps,watt,energy}; // here parameters are power,energy,watt-hour and current
  // read 4 parameters and append to the string:
  for (int i = 0; i < 4; i++) 
  {
    int sensor = parameter[i];
    dataString += String(sensor);
    if (i < 4) 
    {
      dataString += ","; 
    }
  }

  dataFile.println(dataString);

  // print to the serial port too:
  Serial.println(dataString);
  
  // The following line will 'save' the file to the SD card after every
  // line of data - this will use more power and slow down how much data
  // you can read but it's safer! 
  // If you want to speed up the system, remove the call to flush() and it
  // will save the file only every 512 bytes - every time a sector on the 
  // SD card is filled with data.
  dataFile.flush();
  
  // Take 1 measurement every 500 milliseconds
  delay(500);
}





Fuente https://www.instructables.com/ARDUINO-ENERGY-METER/