¿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/

Deja una respuesta