Autor Tema: Proyecto para medir el valor eficaz verdadero (True RMS)  (Leído 8190 veces)

0 Usuarios y 4 Visitantes están viendo este tema.

Desconectado Picuino

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 5883
    • Picuino
Re:Proyecto para medir el valor eficaz verdadero (True RMS)
« Respuesta #75 en: 24 de Noviembre de 2023, 14:51:39 »
Para conseguir un valor más exacto deberías calcular el valor RMS de un número par de periodos exactos.
Por ejemplo comenzando la primera conversión con el cruce por cero y terminando la última conversión lo más cerca del siguiente cruce por cero que sea par.

Puedes simular en una hoja excel o con un programa el resultado de hacer los cálculos con una onda sinusoidal perfecta.

Desconectado Picuino

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 5883
    • Picuino
Re:Proyecto para medir el valor eficaz verdadero (True RMS)
« Respuesta #76 en: 24 de Noviembre de 2023, 15:18:20 »
Adjunto hoja excel de ejemplo con cálculo de RMS en 4 semiciclos y un error del 0.1% en los cálculos debido al error de muestreo, que no está sincronizado perfectamente con la frecuencia de la onda sinusoidal.

Desconectado Picuino

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 5883
    • Picuino
Re:Proyecto para medir el valor eficaz verdadero (True RMS)
« Respuesta #77 en: 24 de Noviembre de 2023, 15:29:53 »
Lo de medir un número par de semiciclos es importante, porque la onda no suele ser simétrica. En una ocasión estuve midiendo la frecuencia de red para observar las desviaciones y era imperativo tomar un número par de semiciclos para que la medida no tuviese error.

Desconectado DominusDRR

  • PIC24H
  • ******
  • Mensajes: 1937
    • Sicoy
Re:Proyecto para medir el valor eficaz verdadero (True RMS)
« Respuesta #78 en: 24 de Noviembre de 2023, 16:10:10 »
Para conseguir un valor más exacto deberías calcular el valor RMS de un número par de periodos exactos.
Por ejemplo comenzando la primera conversión con el cruce por cero y terminando la última conversión lo más cerca del siguiente cruce por cero que sea par.

Hola, si esa es la idea, anteriormente expliqué como se va hacer. Tengo dos buffers o arreglos, en un periodo dado, el buffer 1 se utiliza para almacenar la información, mientras que el otro es utilizado por la tarea RMS para realizar el cálculo.

Luego en el siguiente periodo, se intercambian los buffers, es decir el número 2 se utiliza para almacenar las muestras y el 1 para calcular el RMS.

Puedes simular en una hoja excel o con un programa el resultado de hacer los cálculos con una onda sinusoidal perfecta.

eh... si, gracias, puedes ver en anteriores publicaciones que hice eso.

Aqui:

http://www.todopic.com.ar/foros/index.php?topic=51537.30
« Última modificación: 24 de Noviembre de 2023, 16:21:23 por DominusDRR »
Tengo una idea algo difusa sobre MPLAB Harmony, XC32 con PIC32

Desconectado DominusDRR

  • PIC24H
  • ******
  • Mensajes: 1937
    • Sicoy
Re:Proyecto para medir el valor eficaz verdadero (True RMS)
« Respuesta #79 en: 28 de Noviembre de 2023, 18:09:17 »
Hola.

He escrito la tarea que realiza el cálculo del RMS según las siguientes ecuaciones que se dedujeron tiempo atrás, está dividida en varias partes, de tal manera que se intenta que no sea un proceso apropiativo del CPU, o por lo menos reducir esa desventaja de alguna manera.



En la tarea que se realiza el muestreo, pongo en verdadero una bandera booleana para indicar el fin de un periodo de muestreo:

.

En la tarea que calcula el RMS, en el primer estado, espero que dicha bandera pase a verdadero, para realizar los cálculos.

Código: C
  1. case APPRMS_ESTADO_INICIAL:
  2. {
  3.     if (appsamplingData.periodoCompleto)
  4.     {
  5.           apprmsData.indice = 0x00;
  6.           apprmsData.sumatorio1 = 0.0;
  7.           apprmsData.sumatorio2 = 0.0;
  8.           apprmsData.puntero = (appsamplingData.punteroABuffer == 0x01)? 0 : 1;
  9.           appsamplingData.periodoCompleto = false;
  10.           apprmsData.state = APPRMS_ESTADO_SUMATORIO_1;
  11.     }
  12.     break;
  13. }

Nótese que en esta tarea tengo una variable denominada puntero, la cual es inicializada en 0, si el buffer 1 está siendo usado para almacenar muestras, o es inicializado en 1, si el buffer 0 está siendo usado para almacenar muestras.

Código: C
  1. apprmsData.puntero = (appsamplingData.punteroABuffer == 0x01)? 0 : 1;

En el segundo estado se realiza el primer sumatorio, que es elevar al cuadrado cada elemento de la muestra.

Código: C
  1. case APPRMS_ESTADO_SUMATORIO_1: // sumatorio(x^2)
  2.         {
  3.             if (apprmsData.indice < appsamplingData.estructuraADC[apprmsData.puntero].muestra)
  4.             {
  5.                 apprmsData.sumatorio1 += (float)(appsamplingData.estructuraADC[apprmsData.puntero].bufferADC[apprmsData.indice])*(float)(appsamplingData.estructuraADC[apprmsData.puntero].bufferADC[apprmsData.indice]);
  6.                 apprmsData.indice++;
  7.             }
  8.             else
  9.             {
  10.                 apprmsData.indice = 0x00;
  11.                 apprmsData.sumatorio1 = 0.34399*apprmsData.sumatorio1; // m^2* sumatorio1
  12.                 apprmsData.state = APPRMS_ESTADO_SUMATORIO_2;
  13.             }
  14.             break;
  15.         }

Nótese que cada elemento del arreglo es convertido a float, antes de multiplicarse con sigo mismo, esto no lo noté antes, cuando hice pruebas, era la causa del error en la imprecisión de la prueba que se realizó hace tiempo atrás.

Código: C
  1. for (i = 0; i< 100; i++)
  2. {
  3.    // el error consiste en primero multiplicar cada elemento del arreglo y luego convertirlo en float
  4.    sumatorio1 +=(float)(apprmsData.arreglo[i]*apprmsData.arreglo[i]); // sumatorio(x^2)
  5.  }

El valor en appsamplingData.estructuraADC[apprmsData.puntero].muestra, tiene el número de muestras.

Recuerde que el valor del ADC varía de 0 a 1023.

Estos cálculos ya se hicieron anteriormente, pero los pondré aquí para recordarlo.

Si el valor del ADC es 1023, significa que el valor medido es 300 V.

Si el valor del ADC es 0, significa que el valor medido es -300V

Por lo tanto,

1023*m + c = 300
0*m + c = -300

Donde m sería igual a m = 200/341 y c = -300.

m al cuadrado sería 0.34399 y por eso se hace esto:

Código: C
  1. apprmsData.sumatorio1 = 0.34399*apprmsData.sumatorio1;

En otro post, voy a continuar explicando que se hace en el estado APPRMS_ESTADO_SUMATORIO_2
Tengo una idea algo difusa sobre MPLAB Harmony, XC32 con PIC32

Desconectado DominusDRR

  • PIC24H
  • ******
  • Mensajes: 1937
    • Sicoy
Re:Proyecto para medir el valor eficaz verdadero (True RMS)
« Respuesta #80 en: 28 de Noviembre de 2023, 19:01:03 »
En el estado APPRMS_ESTADO_SUMATORIO_2 se realiza el siguiente sumatorio, pero esta vez cada muestra ya no se debe elevar al cuadrado y al final se debe multiplicar por 2mc, es decir 2* (200/341)*(-300) = -351.9062.
Código: C
  1. case APPRMS_ESTADO_SUMATORIO_2:
  2. {
  3.     if (apprmsData.indice < appsamplingData.estructuraADC[apprmsData.puntero].muestra)
  4.     {
  5.             apprmsData.sumatorio2 += (float)(appsamplingData.estructuraADC[apprmsData.puntero].bufferADC[apprmsData.indice]);
  6.             apprmsData.indice++;
  7.     }
  8.     else
  9.     {
  10.             apprmsData.sumatorio2 = -351.9062*apprmsData.sumatorio2; //2mc* sumatorio2(x)
  11.             apprmsData.sumatorio1 = apprmsData.sumatorio1 + apprmsData.sumatorio2 + 90000*(float)(appsamplingData.estructuraADC[apprmsData.puntero].muestra) - 90000;  // (N-1)*C^2
  12.             apprmsData.sumatorio1 = apprmsData.sumatorio1/(appsamplingData.estructuraADC[apprmsData.puntero].muestra - 1);
  13.             apprmsData.state = APPRMS_ESTADO_EXTRAER_RAIZ_CUADRADA;
  14.     }
  15.     break;
  16. }

Luego de realizar, este sumatorio, se debe sumar la constante (N-1)*c^2, es decir 90000*(N-1), de ahí el porqué se hace esto:

Código: C
  1. + 90000*(float)(appsamplingData.estructuraADC[apprmsData.puntero].muestra) - 90000;

Finalmente, hay que dividir la suma total, para el periodo, que es el número de muestras:

Código: C
  1. apprmsData.sumatorio1 = apprmsData.sumatorio1/(appsamplingData.estructuraADC[apprmsData.puntero].muestra - 1);

En el último estado, se obtiene la raíz cuadrada del sumatorio total y en teoría debería obtener 24VAC,

Código: C
  1. case APPRMS_ESTADO_EXTRAER_RAIZ_CUADRADA:
  2. {
  3.       apprmsData.sumatorio1 =  sqrtf(apprmsData.sumatorio1); //raiz cuadrada del sumatorio
  4.       apprmsData.state = APPRMS_ESTADO_INICIAL;
  5.       break;
  6. }

En los próximos días verificaré si esto funciona.
Tengo una idea algo difusa sobre MPLAB Harmony, XC32 con PIC32

Desconectado DominusDRR

  • PIC24H
  • ******
  • Mensajes: 1937
    • Sicoy
Re:Proyecto para medir el valor eficaz verdadero (True RMS)
« Respuesta #81 en: 30 de Noviembre de 2023, 12:07:09 »
Hola, ya realicé algunas pruebas, a continuación explico algunos detalles.

En primer lugar, como se analizó hace mucho, la interrupción por conversión ADC, era la que debía tener mayor prioridad, luego la interrupción externa y finalmente la interrupción del temporizador 4, así es lo que hice:




Estaba haciendo algunas pruebas, y de repente, el sumatorio total dividido para el número de muestras era negativo, y al obtener la raíz cuadrada, obviamente se generaba un error.



Lamentablemente, detuve la depuración con el hardware, pero repetí el proceso hasta nuevamente conseguir un valor negativo.

En ese momento, exporté a un archivo CVS todo lo que contenía el arreglo, para con ayuda de excel realizar los cálculos y determinar en que parte de mi código estaba mal.



Y efectivamente, la suma total puede dar un número negativo.

Por un momento, pensé que estaba mal algo en la ecuación de los sumatorios, la razón del valor negativo, es que la contante c es -300 y también existe un - 300 x C^2.

Luego de pensarlo un poco me doy cuenta que el sumatorio debe ser un valor absoluto, ya que de donde se parte, está elevado al cuadrado, así que esa suma nunca debe ser negativa:



Entonces, coloqué la función que extrae el valor absoluto de un flotante en el sumatorio total.

Código: C
  1. case APPRMS_ESTADO_SUMATORIO_2:
  2.         {
  3.             if (apprmsData.indice < appsamplingData.estructuraADC[apprmsData.puntero].muestra)
  4.             {
  5.                 apprmsData.sumatorio2 += (float)(appsamplingData.estructuraADC[apprmsData.puntero].bufferADC[apprmsData.indice]);
  6.                 apprmsData.indice++;
  7.             }
  8.             else
  9.             {
  10.                 apprmsData.sumatorio2 = -351.9062*apprmsData.sumatorio2; //2mc* sumatorio2(x)
  11.                 apprmsData.sumatorio1 = apprmsData.sumatorio1 + apprmsData.sumatorio2 + 90000*(float)(appsamplingData.estructuraADC[apprmsData.puntero].muestra) - 90000;  // (N-1)*C^2
  12.                 apprmsData.sumatorio1 = fabs(apprmsData.sumatorio1/(appsamplingData.estructuraADC[apprmsData.puntero].muestra)); //valor absoluto
  13.                 apprmsData.state = APPRMS_ESTADO_EXTRAER_RAIZ_CUADRADA;
  14.             }
  15.             break;
  16.         }

Al hacer esto, parece que realiza un cálculo bastante aproximado del RMS, me faltaría hacer pruebas con un multímetro al mismo tiempo.



También utilicé la función powf para elevar al cuadrado cada elemento del arreglo, en el segundo estado de la tarea:

Código: C
  1. case APPRMS_ESTADO_SUMATORIO_1: // sumatorio(x^2)
  2.         {
  3.             if (apprmsData.indice < appsamplingData.estructuraADC[apprmsData.puntero].muestra)
  4.             {
  5.                 apprmsData.sumatorio1 += powf((float)(appsamplingData.estructuraADC[apprmsData.puntero].bufferADC[apprmsData.indice]),2);
  6.                 apprmsData.indice++;
  7.             }
  8.             else
  9.             {
  10.                 apprmsData.indice = 0x00;
  11.                 apprmsData.sumatorio1 = 0.34399*apprmsData.sumatorio1; // m^2* sumatorio1
  12.                 apprmsData.state = APPRMS_ESTADO_SUMATORIO_2;
  13.             }
  14.             break;
  15.         }

Ahora debo pensar como tomar ese resultado (el rms) y descomponerlo para colocarlo en el display




Tengo una idea algo difusa sobre MPLAB Harmony, XC32 con PIC32

Desconectado DominusDRR

  • PIC24H
  • ******
  • Mensajes: 1937
    • Sicoy
Re:Proyecto para medir el valor eficaz verdadero (True RMS)
« Respuesta #82 en: 02 de Diciembre de 2023, 15:09:28 »
Hola, la función que descompone al valor RMS para mostrarlo en el display, la voy a colocar en la tarea que administra al display y será de la siguiente manera.
Código: C
  1. void rmsDisplay(float valorRMS)
  2. {
  3.  
  4. }

En esta función, lo primero que hago es separar la parte entera y la parte decimal de la siguiente manera:
Código: C
  1. int parteEntera = (int)floorf(valorRMS);
  2. float parteDecimal = (float)(valorRMS - parteEntera);

Supuestamente, la función floorf retorna la parte entera como flotante,

Si por ejemplo el valor rms es 123.4567, floorf sería 123.000, parteEntera será igual a 123 y parteDecimal será igual a 0.4567

Luego tengo que verificar si la parte entera es de 3, 2 o 1 dígito, es decir, si es mayor a 99 (de 100 en adelante) hago lo siguiente:

Código: C
  1. if (parteEntera > 99)
  2. {
  3.      appdisplayData.arregloDisplay[0x00] = (unsigned char)floorf(parteDecimal *10); // obtengo el primer decimal
  4.      appdisplayData.arregloDisplay[0x01] = (unsigned char)(parteEntera%10); // obtengo unidad
  5.      appdisplayData.arregloDisplay[0x02] = (unsigned char)((parteEntera/10)%10); //obtengo unidadDeDecena
  6.      appdisplayData.arregloDisplay[0x03] = (unsigned char)(parteEntera/100);
  7. }

Para el dígito 0, la parteDecinal se multiplica por 10, es decir para el ejemplo, sería 4.567, al aplicar floorf, sería 4.000, y al pasarlo al display tendría 4.
Para el dígito 1, la parte entera al realizar el módulo con diez, obtengo 7.
Para el dígito 2, la parte entera al realizar la división para diez, tendría 12, y ese resultado al obtener el módulo con diez, tendría 2.
Para el dígito 3, la parte entera al realizar la división para cien, obtengo 1.

Lo que me acabo de dar cuenta, en este momento, es que para esta opción, el dígito 0 también debe activar su punto decimal.

Debo pensar como hacer esto.
« Última modificación: 02 de Diciembre de 2023, 16:39:22 por DominusDRR »
Tengo una idea algo difusa sobre MPLAB Harmony, XC32 con PIC32

Desconectado DominusDRR

  • PIC24H
  • ******
  • Mensajes: 1937
    • Sicoy
Re:Proyecto para medir el valor eficaz verdadero (True RMS)
« Respuesta #83 en: 02 de Diciembre de 2023, 16:38:50 »
Se me ha ocurrido una idea de como añadir el punto decimal a cualquier número.

Actualmente tengo un arreglo que cambia el numero de cada dígito al valor adecuado para activar el número correcto en el display:

Código: C
  1. //                                          0     1    2    3    4    5   6    7     8   9
  2. const unsigned char digitoDisplay[0x0A] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x98};

Por ejemplo, si un display tiene el número cero, el arreglo retorna 0xC0, que es el valor que visualiza  cero en el display.

El bit más alto de este número corresponde al segmento PD del display, si deseara que el número cero tenga su punto decimal activo, el valor a retornar sería 0x40.

Para el número 1, es 0xF9, para 1 con punto decimal, sería 0x79, es decir el bit 7 de cualquiera de los valores del arreglo, deben estar en cero.

Estos 10 nuevos valores, los añadiría al arreglo así:

Código: C
  1. //                                          0     1    2    3    4    5   6    7    8   9    0.   1.   2.    3.   4.   5.   6.   7.   8.   9.
  2. const unsigned char digitoDisplay[0x14] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x98,0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x38,0x00,0x18};


Es decir, por ejemplo, que si deseo que un display active su punto decimal, simplemente debo sumar 10.

Por ejemplo, si el display tiene un valor de 7, al sumarle 10, será 17, que corresponde a 0x38, que es el número 7 con punto decimal, por lo tanto mi código donde el valor RMS es mayor a 99 sería ahora así:

Código: C
  1. if (parteEntera > 99)
  2.     {
  3.         appdisplayData.arregloDisplay[0x00] = (unsigned char)floorf(parteDecimal *10);
  4.         appdisplayData.arregloDisplay[0x01] = 10 + (unsigned char)(parteEntera%10); // sumo diez para activar el punto decimal
  5.         appdisplayData.arregloDisplay[0x02] = (unsigned char)((parteEntera/10)%10);
  6.         appdisplayData.arregloDisplay[0x03] = (unsigned char)(parteEntera/100);
  7.     }

Luego tendría un else if, para valores mayores que 10, así:

Código: C
  1. else if (parteEntera > 9)
  2.     {
  3.         int decimalDosDigitos = (int)floorf(parteDecimal *100);
  4.        
  5.         appdisplayData.arregloDisplay[0x00] = (unsigned char)(decimalDosDigitos%10);
  6.         appdisplayData.arregloDisplay[0x01] = (unsigned char)(decimalDosDigitos/10);
  7.        
  8.         appdisplayData.arregloDisplay[0x02] = 10 + (unsigned char)(parteEntera%10); //sumo diez para el punto decimal
  9.         appdisplayData.arregloDisplay[0x03] = (unsigned char)(parteEntera/10);
  10.     }

En este caso, supongamos que el valor RMS es 78.953.

En la variable auxiliar decimalDigitos al multiplicar la parte decimal por 100, se tendría 95.3, por lo tanto tendría 95.

En el display 0, se tendría el módulo de 95 para 10, que sería 5.
En el display 1, se tendría el residuo de 95 para 10, que sería 9.

En el display 2, se tendría el módulo de 78 para 10, que sería 8, y más 10, para que el 8 tenga punto decimal
En el display 3, se tendría el residuo de 78 para 10, que sería  7.

Por lo tanto en el display se vería 78.95

Y finalmente tendrá un caso else, que sería para valores enteros del RMS de 0 a 9, y sería así:

Código: C
  1. else
  2.     {
  3.         int decimalTresDigitos = (int)floorf(parteDecimal *1000);
  4.        
  5.         appdisplayData.arregloDisplay[0x00] = (unsigned char)(decimalTresDigitos%10);
  6.         appdisplayData.arregloDisplay[0x01] = (unsigned char)((decimalTresDigitos/10)%10);
  7.         appdisplayData.arregloDisplay[0x02] = (unsigned char)(decimalTresDigitos/100); // obtengo centena
  8.        
  9.         appdisplayData.arregloDisplay[0x03] = 10 + (unsigned char)(parteEntera);
  10.     }

Supongamos que el valor rms es 5.347.

La parte decimal al multiplicarse por 1000 sería 347, que sería el valor de la variable auxiliar decimalTresDigitos.

El display 0 tendría el residuo del 347 para 10, es decir 7.
El display 1 tendría el residuo de la división de 347/10, con 10, es decir 4.
El display 2 tendría el residuo de la división de 347 para 100, es decir 3.

El display 3, tendría la parte entera, que sería 5, que al sumarle 10, sería 5 con punto decimal.

Eso creo que sería todo, falta probarlo con el hardware.
Tengo una idea algo difusa sobre MPLAB Harmony, XC32 con PIC32

Desconectado DominusDRR

  • PIC24H
  • ******
  • Mensajes: 1937
    • Sicoy
Re:Proyecto para medir el valor eficaz verdadero (True RMS)
« Respuesta #84 en: 03 de Diciembre de 2023, 12:46:49 »
Hola.

He realizado las pruebas, para determinar el valor medido.

Primero quería conocer cuanto duraba la tarea en realizar el cálculo del RMS de un periodo.

Utilizo una variable tipo entero, que utilizo para capturar el valor del Core Timer cuando inicia ese proceso:

Código: C
  1. case APPRMS_ESTADO_INICIAL:
  2.         {
  3.             if (appsamplingData.periodoCompleto)
  4.             {
  5.                 apprmsData.retardo = CORETIMER_CounterGet(); // capturo el valor instantáneo del Core Timer
  6.                 apprmsData.indice = 0x00;
  7.                 apprmsData.sumatorio1 = 0.0;
  8.                 apprmsData.sumatorio2 = 0.0;
  9.                 apprmsData.puntero = (appsamplingData.punteroABuffer == 0x01)? 0 : 1;
  10.                 appsamplingData.periodoCompleto = false;
  11.                 apprmsData.state = APPRMS_ESTADO_SUMATORIO_1;
  12.             }
  13.             break;
  14.         }

Luego, al finalizar el cálculo,  hago una diferencia o resta entre el valor del Core Timer y el valor inicial capturado, de esa manera mido cuanto tiempo duró ese proceso:

Código: C
  1. case APPRMS_ESTADO_EXTRAER_RAIZ_CUADRADA:
  2.         {
  3.             rmsDisplay(sqrtf(apprmsData.sumatorio1)); //la raiz cuadrada de todo lo envío a la función rmsDisplay
  4.             apprmsData.retardo = CORETIMER_CounterGet() - apprmsData.retardo;
  5.             apprmsData.state = APPRMS_ESTADO_INICIAL;
  6.             Nop(); //aquí pondo un punto de ruptura.
  7.             break;
  8.         }

Con esto, el valor de retardo es 37329.



Si la frecuencia de ese reloj o temporizador es de 24MHz, el tiempo medido sería:

37329/24MHz = 1.555 ms, que es menor que el periodo de la señal medida (16.667 ms)

También se debe considerar que no esta el código, con el nivel de optimización máximo, está con el nivel gratuito, creo que mejoraría ese tiempo en algo en ese modo.

A continuación, tengo un video del RMS medido con los 24VAC:



Se puede ver que el valor medido, no es exacto, hay un error de 2 voltios aproximadamente, también se puede apreciar que por un instante, parece que se muestra un valor mayor a 99 voltios, pero es muy rápido.

También la transición de los valores decimales, es muy rápida, debo colocar algún tipo de retardo, para evitar eso.

Tenía la esperanza que al utilizar 24VAC, el acondicionamiento de la señal de un voltaje pequeño, generaba ese error, así que lo conecté a 120VAC, he igual manera, hay un error:

.

Pero en un instante dado, se puede ver 122 VAC:



Debo determinar si es un error del código, o el acondicionamiento de la señal, está introduciendo un error.

Tengo una idea algo difusa sobre MPLAB Harmony, XC32 con PIC32

Desconectado DominusDRR

  • PIC24H
  • ******
  • Mensajes: 1937
    • Sicoy
Re:Proyecto para medir el valor eficaz verdadero (True RMS)
« Respuesta #85 en: 03 de Diciembre de 2023, 14:49:31 »
Hola, estaba realizando unas pruebas, y he descubierto que a veces, el número de muestras es menor al que debería ser por el periodo.

Como dije antes, si el periodo es de aproximadamente 16.667 ms, al tomar muestras en intervalos de 100 us, debería tener unas 167 muestras aproximadamente, pero a veces, tengo entre 40 a 80 muestras.

Es como si la interrupción externa, ocurriera antes de completar un periodo.

Investigando, un poco, hay un problema al utilizar un amplificador operacional como comparador, en lugar de un comparador de voltaje en si.

Esto es, cuando las dos señales a comparar tienen un nivel de voltaje casi iguales, la salida del operacional oscila, ya que no puede definir cual es alta respecto a la otra.





Está oscilación se la ha sabido conocer como  "ruido de ida y vuelta" o "chattering".



Lo que podría ser la causa del posible problema inicialmente explicado.

Es algo similar al rebote de un pulsador al ser presionado.

Posiblemente la solución es un retardo (obviamente asincrónico) y/o un capacitor.

En estos días voy a analizar con el osciloscopio esa señal para determinar si existe tal ruido.



« Última modificación: 03 de Diciembre de 2023, 19:52:08 por DominusDRR »
Tengo una idea algo difusa sobre MPLAB Harmony, XC32 con PIC32

Desconectado Picuino

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 5883
    • Picuino
Re:Proyecto para medir el valor eficaz verdadero (True RMS)
« Respuesta #86 en: 04 de Diciembre de 2023, 06:59:14 »
Otra solución mejor que el retardo es añadir histéresis con realimentación positiva.
https://es.wikipedia.org/wiki/Disparador_Schmitt

Desconectado DominusDRR

  • PIC24H
  • ******
  • Mensajes: 1937
    • Sicoy
Re:Proyecto para medir el valor eficaz verdadero (True RMS)
« Respuesta #87 en: 04 de Diciembre de 2023, 10:04:43 »
Otra solución mejor que el retardo es añadir histéresis con realimentación positiva.
https://es.wikipedia.org/wiki/Disparador_Schmitt

Si, es una buena idea, pero el PCB ya está construido, sería tal vez para una nueva versión del hardware.

Sin embargo debo determinar si dicho ruido se está produciendo (en las simulaciones de MPLAB Mindi no sucede), y si es así, realizar una solución engorrosa tratando de colocar un capacitor y/o una solución a nivel de software.

Por cierto, la simulación (la línea roja es la salida del OP)


Tengo una idea algo difusa sobre MPLAB Harmony, XC32 con PIC32

Desconectado DominusDRR

  • PIC24H
  • ******
  • Mensajes: 1937
    • Sicoy
Re:Proyecto para medir el valor eficaz verdadero (True RMS)
« Respuesta #88 en: 04 de Diciembre de 2023, 11:00:22 »
Pues no parece algún ruido en la salida del operacional utilizado como comparador:



Estuve verificado por algún tiempo, pero parece funcionar bien.

Sospecho acerca de la configuración del ADC, voy a intentar analizar eso cuando tengo un poco de tiempo libre.

Tengo una idea algo difusa sobre MPLAB Harmony, XC32 con PIC32

Desconectado AnitaMalhereux

  • PIC10
  • *
  • Mensajes: 42
Re:Proyecto para medir el valor eficaz verdadero (True RMS)
« Respuesta #89 en: 05 de Diciembre de 2023, 09:27:17 »
Hola, estoy siguiendo tu proyecto.

Creo que para descartar un problema de la interrupción externa, deberías realizar la parte que mencionaste que también medirías la frecuencia.

Al hacer eso, ya no dependes del temporizador 4 que genera interrupciones cada 100 us, ni del ADC.

Es decir, tal vez no necesitas el modulo de captura que estás pensando usar para medir la frecuencia, me refiero a que mediante el flanco positivo de la interrupción externa, hagas algo similar que utilizaste para medir cuanto tiempo te tomaba en realizar el cálculo del RMS de un periodo.

Es decir cuando sucede dicha int externa, capturas el valor del temporizador central o Core Timer, y en la siguiente interrupción, nuevamente capturas ese valor para realizar la diferencia y tienes el valor del periodo de la señal,

Luego con un poco de matemáticas obtienes el valor de la frecuencia y usas la misma función para mostrar ese valor en el display.

Con ese valor y visualizando si pasa algo similar como en los videos que has compartido, podrías afirmar que es un problema de la interrupción.