• Autor de la entrada:
  • Tiempo de lectura:18 minutos de lectura

Implementación real de un SRF-PLL SOGI discreto para medir fase de red, RMS y frecuencia con Arduino. Se pondrá a prueba sobre una tensión monofásica de una red de distribución real.

El SRF-PLL SOGI para medir fase de red

Como se vió en sincronización con redes monofásicas, existen varios métodos para extraer información de una señal. Utilizar un método u otro dependerá de la naturaleza de esta y de la información que se considere relevante.

De los métodos analizados en dicho post, el SRF-PLL SOGI ganó una entrada propia por reunir sencillez y potencia. Ahora falta ponerlo a prueba en una situación reale.

Solo se verá la implementación del PLL, para detalles del mismo acudir al anterior enlace.

Esquema SRF-PLL
Esquema SRF-PLL

Implementación en Arduino

Diagrama de funcionamiento

La entrada del PLL se alimenta con las lecturas del ADC, que tendrán lugar en intervalos fijos de tiempo para simplificar la discretización y, en consecuencia, los cálculos.

Para ello, una interrupción temporal marcará el ritmo de lectura analógica y ejecución del PLL a intervalos fijos.

Diagrama concepto de firmware para medir RMS y frecuencia con Arduino
Diagrama concepto de firmware para medir RMS y frecuencia con Arduino

Será fundamental conocer cuanto tiempo tarda Arduino en ejecutar todo este proceso, pues esto repercutirá en la frecuencia máxima de muestreo. Si el PLL debe coexistir con otros procesos, también deben tenerse en cuenta.

Adaptar la tensión de red a Arduino

ZMPT101B para adaptar tensión de red a Arduino
ZMPT101B para adaptar tensión de red a Arduino

Para la prueba con red monofásica real se utiliza una placa de adaptación simple que puede conseguirse fácilmente. Pueden encontrarse buscando «ac voltage lm358» o «ZMPT101B». Esta placa se alimenta entre 3V y 5V, cuando no hay tensión la salida es 1/2 la tensión de alimentación (en teoría). Dispone de un potenciómetro para regular la ganancia de esta salida.

Esquema para adaptar tensión de red basada en el transformador ZMPT101B
Esquema para adaptar tensión de red basada en el transformador ZMPT101B

El esquema es muy sencillo y puede obtenerse mediante inspección visual, los valores de los componentes se extraen buscando en internet. El archivo de simulación para LTSpice puede descargarse aquí:

El problema de Arduino y las entradas analógicas

Antes de seguir es importante dejar algunas cosas claras. Arduino es un ecosistema al que se debe agradecer uno de los mayores auges de la electrónica, acercando esta tecnología de forma sencilla a profanos. Pero este éxito no está exento de sacrificios e inconvenientes, la simplicidad que percibe el usuario final viene de simplificaciones y abstracciones más o menos ingeniosas.

Una de esas simplificaciones se encuentra en las entradas analógicas. Con un simple analogRead() se obtiene el valor de tensión en un pin, y aunque funciona, pasa por alto fundamentos muy importantes de la conversión analógico-digital.

Medir significa (de forma simple) comparar. Esta comparación debe hacerse respecto a algo estable, que se mantenga inmutable en el tiempo y en el espacio. Sería muy difícil medir un mueble si el metro usado cambia la longitud de los centímetros dependiendo de la hora o la estancia donde se encuentre. Curiosamente, esto es lo que pasa en Arduino al utilizar las tensiones de alimentación como tensiones de referencia.

Las imágenes anteriores muestran que tanto la tensión de 5V como la de 3,3V no son tal. Dichas tensiones son las que usa Arduino para comparar, e introducen un error muy importante en las medidas analógicas. Es habitual ver proyectos donde se usa el clásico «(5/1024) * analogRead()«, dependiendo de la aplicación, este error será más o menos grave.

Para mantener la simplicidad sin renunciar a la mayor precisión posible se introducirá un sencillo ajuste en el código. Para ello se miden los valores reales de tensión y de offset antes de introducir la tensión de red. Si bien no es una solución práctica, tampoco es el objetivo de esta entrada solucionar este problema.

Medir fase de red con Arduino DUE y SRF-PLL SOGI

Arduino DUE ofrece una opción de depuración para control en tiempo real muy potente: 2 salidas analógicas. Utilizando estas y un osciloscopio es posible conocer el comportamiento de una magnitud en un lazo de control sin tener que lidiar con las limitaciones de buffers y canales de comunicación. Se utilizarán ambas salidas para conocer la lectura de la entrada analógica y la medida de fase que hace el PLL de la misma.

Conexiones medida RMS y Frecuencia con Arduino Due
Conexiones medida RMS y Frecuencia con Arduino Due

El siguiente repositorio de GitHub contiene el código que se utilizará a continuación:

https://github.com/abrahanlp/SRF-PLL-SOGI-ArduinoDUE

Tiempo de ejecución del SRF-PLL SOGI en Arduino DUE

Como ya se dijo, es necesario conocer el tiempo de ejecución para establecer una frecuencia máxima de muestreo. El código creado mide este tiempo de ejecución en microsegundos y lo emite por el puerto serie junto a la RMS y la frecuencia. En este punto no es importante la configuración del PLL, simplemente se ejecuta el programa sin observar los valores de RMS y frecuencia calculados, incluso puede hacerse con la entrada anlógica al aire.

El tiempo de ejecución en Arduino DUE resulta ser 143µs.

Para garantizar la estabilidad del bucle se configura la interrupción para 200µs (5kHz), en Arduino DUE esto se consigue mediante el siguiente código:

//Llamar esta función en setup()
void config_timer2(void){
  pmc_set_writeprotect(false);
  pmc_enable_periph_clk((uint32_t) TC5_IRQn);
  TC_Configure(TC1, 2, TC_CMR_TCCLKS_TIMER_CLOCK1 | TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC);
  TC_SetRC(TC1, 2, 8400); // 1":84000000/2; 1ms:84000/2; 100us: 8400/2;
  TC_Start(TC1, 2);
  TC1->TC_CHANNEL[2].TC_IER=TC_IER_CPCS;
  TC1->TC_CHANNEL[2].TC_IDR=~TC_IER_CPCS;
  NVIC_EnableIRQ(TC5_IRQn);
}

//Función que se ejecuta al activarse la interrupción
void TC5_Handler() {
  i0 = micros();
  u_in_0 = analogRead(A0);
  timerFlag = true;
  timerCount++;
  TC_GetStatus(TC1, 2); //Clear flag interruption
}

Medir la fase de un generador de señal

Antes de probar con una red monofásica real, se evalúa el comportamiento con un generador de señal y un osciloscopio. Se utiliza un Hantek 6254BD (no patrocinan este sitio), que aúna ambos instrumentos, y se realiza el siguiente procedimiento:

  1. Medir tensión de alimentación real (ADC_Vref)
  2. Medir señal generada (ADC_offset, RMS y frecuencia reales)
  3. Cargar firmware con datos anteriores.
  4. Evaluar medidas de fase, RMS y frecuencia.
Generador de señal para probar medida RMS y frecuencia en Arduino DUE
Generador de señal para probar medida RMS y frecuencia en Arduino DUE

La señal de entrada será una senoidal de 2Vpp@50Hz y offset de 1VDC, por tanto la medida RMS debería ser 1/sqrt(2)=0,71V.

En la siguiente imagen se muestran los resultados. Las medidas resultan ser muy precisas en relación a las limitaciones de los recursos utilizados.

Tiempo máximo de ejecución, medida RMS y frecuencia en Arduino DUE
Tiempo máximo de ejecución, medida RMS y frecuencia en Arduino DUE

Con un osciloscopio se mide en la salida analógica la fase obtenida mediante este método (el rango de esta salida en Arduino DUE es 0,55-2,75V).

Medida de fase de una señal senoidal con Arduino DUE. Amarillo: Señal de entrada. Azul: Fase medida
Medida de fase de una señal senoidal con Arduino DUE. Amarillo: Señal de entrada. Azul: Fase medida

A continuación se prueba la reacción del sistema a cambios bruscos en frecuencia, pasando de 50Hz a 48Hz para posteriormente pasar de 48Hz a 52Hz.

Medir fase, RMS y frecuencia de tensión de red

Se conecta la tarjeta con el ZMPT101B al Arduino DUE como en la siguiente imagen, alimentación de 5V desde el USB y la entrada analógica A0.

Conexión de ZMPT101B y Arduino DUE
Conexión de ZMPT101B y Arduino DUE

En la siguiente imagen se muestran la señal dada por el ZMPT101B (amarillo) y la fase medida (azul). Aparece distorsión en la señal adaptada de la tensión de red, nada sorprendente teniendo en cuenta la calidad de la tarjeta de adaptación. A pesar de ello la fase medida resulta ser muy precisa.

Medida fase de red con Arduino DUE y SRF-PLL SOGI
Medida fase de red con Arduino DUE y SRF-PLL SOGI

Las medidas de RMS y frecuencia son relativamente precisas, pero presentan un «molesto» rizado de baja frecuencia. Dicho rizado es fruto del ruido introducido por la tarjeta de adaptación, la conversión A/D y por supuesto, la propia red eléctrica.

Se utiliza el BetterSerialPlotter para la siguiente visualización.

Medida de RMS y frecuencia con Arduino DUE en una red monofásica real
Medida de RMS y frecuencia con Arduino DUE en una red monofásica real

Medir RMS y frecuencia con Arduino UNO y SRF-PLL SOGI

Conexión de ZMPT101B y Arduino UNO
Conexión de ZMPT101B y Arduino UNO

Repitiendo los mismos pasos que para Arduino DUE se conecta la tarjeta de adaptación a un Arduino UNO. El código se encuentra en el siguiente repositorio:

https://github.com/abrahanlp/SRF-PLL-SOGI-ArduinoUNO

Se tienen 364us de tiempo de ejecución, lo cual no es muy sorprendente en comparación a Arduino DUE. La frecuencia de muestreo podría ser 2kHz, pero será 1kHz para evaluar el comportamiento.

Arduino UNO no posee una salida analógica como tal, aunque podría utilizarse una salida PWM y un filtro paso bajo para obtener la fase medida.

La RMS y frecuencia resultan algo sorprendentes, mientras que la RMS oscila en torno al valor real, la frecuencia presenta un offset de 1Hz.

Medida de RMS y frecuencia con Arduino UNO en una red monofásica real
Medida de RMS y frecuencia con Arduino UNO en una red monofásica real

Conclusiones o comentarios

La utilización de coma flotante para cálculos es un serio lastre para las arquitecturas que utiliza Arduino. Para realizar operaciones como estas en arquitecturas sin unidad de coma flotante (FPU), se hace prácticamente obligatorio utilizar un sistema numérico de coma fija.

De haber utilizado coma fija, una arquitectura de 8 bits como la del Arduino UNO se queda igualmente corta si no se realizan importantes simplificaciones y aproximaciones en el PLL.

A pesar de todo, aún sería necesario salvar el escollo de las operaciones trigonométricas, no siempre implementadas en arquitecturas con FPU.

Arduino no resulta conveniente para este tipo de implementaciones en el mundo real, pero su valor educacional es lo suficientemente importante como para invertir tiempo en experimentar con ello.