Medición de señales simétricas con ADC

A menudo encontramos algún proyecto o la necesidad de medir una señal simétrica, como podría ser una señal senoidal o simplemente la corriente o tensión alterna en un circuito.
Después de haber realizado en otros post el método para rectificar de forma precisa una señal con corrección de cuadratura y demás, estoy analizando una manera diferente pero mas sencilla.
Esto no es nada nuevo, simplemente sabemos que el ADC de un microcontrolador no tiene la posibilidad de tomar muestras negativas de una señal, entonces una manera sencilla seria montar la señal simétrica en una continua, es decir, si tenemos una señal senoidal simétrica de 2Vpp (+/-1Vp) podríamos montarla en una continua de 2.5V y ahora esta señal tendría un máximo de 3.5Vp y un mínimo de 1.5Vp, de esta forma ya no tenemos valores negativos.



Como podremos ver en el siguiente oscilosgrama tenemos dos señales, la primera (amarilla) es la señal sin tratar, donde su gnd se encuentra en el punto medio, esta señal es de 10Vp, es decir 20Vpp, y con GND en el centro tendremos -10Vp GND +10Vp, esto no nos sirve para nuestro ADC, pero en la señal de abajo (azul) tenemos la señal senoidal simétrica que ha sido montada en una continua de 2.5V (la linea azul es GND, podemos ver como se ha elevado del GND), esta señal es de menor valor de amplitud porque se ha atenuado con un circuito resistivo para el ejemplo.

La fuente de señal V1, es nuestro generador senoidal que nos proporciona 10Vp y 50Hz.
Luego tendremos el divisor resistivo conformado con R1 y R2, en este caso divide por 11 veces, las resistencias R3 y R4 se utilizan para dividir la tensión de 5V en dos partes iguales, es decir tendremos 2.5V en su punto central, esta tensión sera la que sumaremos a la alterna de entrada, aquí montamos la alterna en los 2.5V.
El capacitor C1 proporciona una rama de baja impedancia para la señal alterna a GND.
El valor puede oscilar entre 1uF y 10uF.

En el caso de medir la tensión de linea (220Vac, 120Vac, 110Vac, etc...) lo ideal es aislar el sistema, pero en este caso no quedan muchas opciones, ya que la alterna que montaremos en la continua no puede tener la misma masa que la continua ya que sino no podría montarse, si miramos el siguiente circuito, se ha utilizado un transformador como aislación galvánica y también como reductor, podríamos usar un transformador de 220Vac a 9Vac por ejemplo, y luego atenuar el valor con resistencias, hay que tener en cuenta que el valor pico no debe pasar los 2V porque esto sumado a los 2.5V daría 4.5V y el máximo es 5V (aunque podemos poner protección en el ADC).


Bueno hasta ahora todo esta bien pero debemos modificar el programa en el microcontrolador, ya que como recordamos anteriormente, he mostrado como medir una señal TrueRMS en base a una formula de la raíz del promedio cuadrado de las muestras. 


Recordando esta formula, lo que hacemos es tomar medir con el ADC cada un determinado tiempo, cada valor del ADC lo elevamos al cuadrado y lo sumamos con el siguiente, una vez que tenemos todos los valores sumados, dividimos esa suma por la cantidad de valores o muestras tomadas, y a ese valor le aplicamos la raíz cuadrada.

En este circuito tenemos que tener en cuenta los 2.5V donde montamos la alterna, para ello vamos a sumar este valor a cada uno de los valores medidos y luego seguiremos calculando el valor eficaz de la misma forma.


El valor Vdc sera los 2.5V, que podríamos ponerlo como variable en el programa y podría ser otro canal ADC midiendo la referencia de forma dinámica para que se auto ajuste y siempre nos de un valor preciso.

Antes de entrar en un ejemplo de programación, he realizado algunos cálculos en la hoja de cálculos:

En este primer gráfico podremos ver el la forma de onda que responde a las columnas de datos para un ciclo completo.


La formula en la planilla será: =RAIZ((C5^2+C6^2+C7^2+C8^2+C9^2+C10^2+C11^2+C12^2+C13^2+C14^2+C15^2+C16^2+C17^2)/13)

Como podremos ver, en esta formula estamos tomando cada valor, elevándolo al cuadrado, sumándolo con el siguiente y a toda esa formula la dividimos por la cantidad de muestras que en este caso son 13, luego aplicamos la raíz cuadrada y nos da como resultado una Vrms de 0.733, claramente debería dar 0.707, pero sucede que son pocas muestras y esto mejora con la cantidad de muestras.

En cambio si implementamos la nueva formula con el offset de 2.5V quedara:


La formula en la planilla será: =RAIZ((((C22-2,5)^2)+((C23-2,5)^2)+((C24-2,5)^2)+((C25-2,5)^2)+((C26-2,5)^2)+((C27-2,5)^2)+((C28-2,5)^2)+((C29-2,5)^2)+((C30-2,5)^2)+((C31-2,5)^2)+((C32-2,5)^2)+((C33-2,5)^2)+((C34-2,5)^2))/13)

Como podremos ver, en esta formula estamos tomando cada valor restando el offset de 2.5V, elevándolo al cuadrado, sumándolo con el siguiente y a toda esa formula la dividimos por la cantidad de muestras que en este caso son 13, luego aplicamos la raíz cuadrada y nos da como resultado una Vrms de 0.733, al igual que la formula original nos da el mismo valor, por ende sera la que vamos a utilizar en nuestro algoritmo en el MCU.

En el programa realizaremos el mismo algoritmo de siempre pero agregaremos los 2.5V en las lineas 23 y 27, directamente en el valor de lectura del ADC, simplemente es ese el cambio.

  1. #include <16F883.h>
  2. #device adc=10
  3. #use delay(int=4000000)
  4. #define LCD_ENABLE_PIN  PIN_B2
  5. #define LCD_RS_PIN      PIN_B0
  6. #define LCD_RW_PIN      PIN_B1
  7. #define LCD_DATA4       PIN_B4
  8. #define LCD_DATA5       PIN_B5
  9. #define LCD_DATA6       PIN_B6
  10. #define LCD_DATA7       PIN_B7
  11. #include <LCD.C>
  12. #include <math.h>
  13. void main(){
  14.    setup_adc_ports(sAN0|sAN1|VSS_VDD);
  15.    setup_adc(ADC_CLOCK_DIV_2);
  16.    int16 i, adcZ=0;
  17.    float adc1=0, valorMax1=0, adc2=0, valorMax2=0;
  18.    float tension, corriente, potencia;
  19.    lcd_init();
  20.    while(true){
  21.       do{
  22.          set_adc_channel(0);
  23.          adcZ=read_adc()-512;
  24.          delay_us(20);
  25.       }while(adcZ<10);
  26.       for(i=0;i<300;i++){
  27.          set_adc_channel(0);
  28.          adc1=(read_adc()*5.0/1023.0)-2.5;
  29.          delay_us(33);
  30.          valorMax1=adc1*adc1+valorMax1;
  31.          set_adc_channel(1);
  32.          adc2=(read_adc()*5.0/1023.0)-2.5;
  33.          delay_us(33);
  34.          valorMax2=adc2*adc2+valorMax2;
  35.       }  
  36.       tension=sqrt(valorMax1/300);
  37.       corriente=sqrt(valorMax2/300);
  38.       potencia=tension*corriente;
  39.       lcd_gotoxy(1,1);
  40.       printf(lcd_putc,"RMS     W:%1.3f ",potencia);
  41.       lcd_gotoxy(1,2);
  42.       printf(lcd_putc,"V:%1.3f A:%1.3f ",tension, corriente);
  43.       valorMax1=0;
  44.       valorMax2=0;
  45.    }
  46. }

Podemos ver que se ha ingresado dos señales iguales midiendo 1Vp y haciendo una fuente de señal capacitiva, se hace evidente la variación de fase de corriente en función a la tensión.
En el circuito podemos ver el capacitor de 50nF y en el oscilograma podemos ver la fase de ambas señales.






11 comentarios:

  1. Muy interesante proyecto, saludos desde México.

    ResponderBorrar
  2. hola,supongamos que en vez de un transformador de tensión en la entrada tengo un transformador de intensidad, seria igual la analogía?(uno con 70mA pp

    ResponderBorrar
    Respuestas
    1. Hola, fíjate que acá hablo sobre el sensado de la corriente y lo dejo listo para ingresar al microcontrolador.
      http://electgpl.blogspot.com.ar/2017/01/sensado-de-corriente-alterna.html
      Saludos.

      Borrar
  3. Justo lo que buscaba, Muchas Gracias

    ResponderBorrar
  4. de donde sale el 512? adcZ=read_adc()-512;

    ResponderBorrar
    Respuestas
    1. Hola, se resta 512, ya que el valor medio de la señal senoidal esta en 2.5V, es decir, el ADC función entre 0 y 5V o entre 0 y 1023 cuentas. Entonces si el "cero" de la señal senoidal esta en el punto medio (2.5V) entonces sera equivalente a 512 cuentas. Entonces la señal senoidal alterna entre +/-2.5V o entre -/+512 cuentas. De ahi que el valor del ADC lo resta a 512, ya que se encuentra montado en una continua de 2.5V como cero.
      Saludos.

      Borrar
  5. HOLA, ME PODRIAS EXPLICAR COMO SACAS ESAS CONSTANTE #define CONST_CORRIENTE 5
    #define CONST_TENSION 310 LOS VALORES 5 Y 310

    ResponderBorrar
    Respuestas
    1. Hola, esos valores salen de calcular el divisor resistivo externo al microcontrolador, es decir para medir la tensión de linea tenes los 220Vp que son atenuados mediante resistencias con un factor de división dado por ese divisor resistivo, ese factor de división luego hay que compensarlo en el software para que puedas leer lo mismo que en realidad hay, ya que si no multiplicas en el software por ejemplo con 310, vas a leer un valor muy bajo de tensión que es el que entra al ADC atenuado por las resistencias. Entonces si el ADC lee 0.7V entonces al multiplicarlo por 310, va a mostrar 217V.
      Lo mismo sucede con la corriente.
      Saludos.

      Borrar
  6. Muy buen proyecto, me interesa saber como ver a través de un servidor iot local y acceder desde internet para verlo en un celular.

    ResponderBorrar