TODOPIC

FORO TÉCNICO => Foro Técnico => Mensaje iniciado por: migsantiago en 15 de Diciembre de 2008, 16:08:11

Título: Tutorial para calcular valores RMS
Publicado por: migsantiago en 15 de Diciembre de 2008, 16:08:11
Hola

Estoy investigando aquí en el foro cómo se calcula el valor RMS de una onda no periódica muestreada digitalmente. Encontré unos cuantos temas en los que se menciona que es muy difícil de hacer y que es necesario hacer integración.

Quisiera saber si alguien tiene un tutorial para realizar este cálculo.

Gracias.

 :mrgreen:
Título: Re: Tutorial para calcular valores RMS
Publicado por: Modulay en 15 de Diciembre de 2008, 16:34:33
Desde la perspectiva discreta no es neceaario aplicar calculos integrales,simplemente habría que busca la manera de sustituir la integral de la fórmula de la imagen por el valor numérico del área bajo la curva representada por los valores digitales (cada uno multiplicado por sí mismo) comprendidos en un periodo de la señal. Ahora mismo no se me ocurre una forma directa de usar dichos valores para hacer el cálculo numérico de dicha integral, pero sí te digo que hay mil maneras de hacerlo. Una vez tengas hecho ese cálculo, el resto es sencillo

(http://img81.imageshack.us/img81/5484/rmshe5.jpg)
Título: Re: Tutorial para calcular valores RMS
Publicado por: Modulay en 15 de Diciembre de 2008, 16:40:09
ahm que dijiste onda no periódica....
Pues...imagino que deberás tomar un intervalo si es que quieres obtener un valor eficaz (dicho intervalo vendría a ser el período en ondas periódicas)
Título: Re: Tutorial para calcular valores RMS
Publicado por: migsantiago en 15 de Diciembre de 2008, 16:42:38
El calcular la integral con muestras discretas va a ser fácil, necesito buscar mis apuntes de métodos numéricos en los que se usaban los métodos del trapecio y simpson para calcularla.

Si tengo 10 muestras, una cada segundo, entonces calculo el área bajo la curva que generan esas 10 muestras y la sustituyo en la ecuación, luego divido entre 10s y saco raíz cuadrada, ¿es así?

En cuanto tenga los datos te aviso cómo resultó el asunto  :D

Gracias por la ecuación Modu  :mrgreen:
Título: Re: Tutorial para calcular valores RMS
Publicado por: Modulay en 15 de Diciembre de 2008, 16:48:07
Si tengo 10 muestras, una cada segundo, entonces calculo el área bajo la curva que generan esas 10 muestras y la sustituyo en la ecuación, luego divido entre 10s y saco raíz cuadrada, ¿es así?

Efectivamente, pero lo primero que debes hacer es multiplicar cada muestra por sí misma y sobreescribir su valor
Título: Re: Tutorial para calcular valores RMS
Publicado por: migsantiago en 15 de Diciembre de 2008, 16:57:20
Cierto, ya que si no lo hiciera, entonces tendría áreas bajo la curva positivas y negativas y para el caso de ondas senoidales, las áreas se cancelarían.

¿De casualidad tienes una referencia de dónde sacaste la ecuación?
Título: Re: Tutorial para calcular valores RMS
Publicado por: Modulay en 15 de Diciembre de 2008, 17:11:19
yes, my friend

http://es.wikipedia.org/wiki/Corriente_alterna (http://es.wikipedia.org/wiki/Corriente_alterna)
Título: Re: Tutorial para calcular valores RMS
Publicado por: jfh900 en 15 de Diciembre de 2008, 21:18:34
Mira este hilo donde tengo un aporte para un voltímetro de verdadero valor eficaz:

http://www.todopic.com.ar/foros/index.php?topic=11720.msg113837#msg113837

Un saludo
Título: Re: Tutorial para calcular valores RMS
Publicado por: migsantiago en 16 de Diciembre de 2008, 16:32:54
Ya lo descargué JFH900, gracias.
Título: Re: Tutorial para calcular valores RMS
Publicado por: migsantiago en 17 de Diciembre de 2008, 19:54:54
Bueno, ya creé mi subfunción para calcular el valor rms de cualquier arreglo de números flotantes. La integral la hice con el método de los trapecios múltiples.

Su prototipo es:

float ValorRMS(float *arreglo, int samples);

Se le entrega un apuntador al arreglo de flotantes y en samples el número de elementos del arreglo y listo, entrega el valor en flotante a la salida.  :mrgreen:

La subfunción se declara así:

Código: [Seleccionar]
//Subfunción Calcula Valor RMS de un arreglo flotante de n muestras
float ValorRMS(float *arreglo, int samples)
{
int i;
float suma=0;

for(i=0;i<samples;i++)
arreglo[i]*=arreglo[i];

for(i=1;i<samples-1;i++)
suma+=arreglo[i];

suma+=(arreglo[0]+arreglo[samples-1])/2.0;

return sqrt(suma/samples);
}

Si alguien la llega a implementar en un PIC16, no olvidar que int samples deberá ser capaz de apuntar a todas las muestras de arreglo.

Ah y los valores en arreglo son modificados (elevados al cuadrado). Si es necesario dejarlos intactos entonces hay que clonar el arreglo con un realloc o algo por el estilo.

La probé con una onda senoidal a 60Hz y Vpico de 180V. El programa de prueba es éste:

Código: [Seleccionar]
//Programa para calcular el valor RMS de una señal discreta

#include "stdafx.h"
#include "math.h"
#include "malloc.h"
#include "conio.h"

//Constantes
#define dospi 6.283185

//Variables
float vpico=180.0;
int muestras=22050; //muestras totales del arreglo
float frec=60.0;
int fsample=22050;
float *seno;
int i,j;
float vrms;

///////////////////////////////////////////////////////////////////////////////////////////////////////////
//Subfunción Calcula Valor RMS de un arreglo flotante de n muestras
float ValorRMS(float *arreglo, int samples)
{
int i;
float suma=0;

for(i=0;i<samples;i++)
arreglo[i]*=arreglo[i];

for(i=1;i<samples-1;i++)
suma+=arreglo[i];

suma+=(arreglo[0]+arreglo[samples-1])/2.0;

return sqrt(suma/samples);
}


///////////////////////////////////////////////////////////////////////////////////////////////////////////
//Función principal
int main(int argc, char* argv[])
{
printf("Programa para calcular el valor RMS de una señal discreta");
printf("\nVoltaje pico = %f",vpico);

printf("\nGenerando onda senoidal %fHz @ %dsps",frec,fsample);

//Genera el arreglo senoidal
seno=(float *)malloc(sizeof(float)*muestras);
for(i=0;i<muestras;i++)
seno[i]=vpico*sin((float)dospi*frec*i/fsample);

//Sobre el arreglo senoidal se calcula el valor rms usando el método del trapecio múltiple
vrms=ValorRMS(seno,muestras);
printf("\nValor RMS %f",vrms);

printf("\nPresione enter");
getch();

return 0;
}
Título: Re: Tutorial para calcular valores RMS
Publicado por: Modulay en 17 de Diciembre de 2008, 21:56:12
¿Qué cotas de error estás manejando?

¿La aplicación vale para trabajar sobre archivos de audio o simplemente lo implementaste para un arreglo sencillo basado en array?
Título: Re: Tutorial para calcular valores RMS
Publicado por: migsantiago en 18 de Diciembre de 2008, 18:50:29
¿Cotas de error? mmhh no sé  :D

El método del trapecio tiene errores pero dependen de la distancia entre muestras y del área bajo la curva que no se llega a calcular. También puedo implementar el método de Simpson que es más preciso, pero es más pesado para el microcontrolador.

La subfunción ValorRMS sirve para cualquier arreglo de números flotantes con n muestras en ese arreglo, puede ser cualquier unidad lineal de ingeniería (Volts, Pascales, aceleración, etc.).

La aplicación que escribí sólo fue para poner a prueba la función. Sería interesante generar una señal aleatoria y calcularle el valor RMS con mi subfunción y con un método de Matlab para ver si realmente entregan algo similar.
Título: Re: Tutorial para calcular valores RMS
Publicado por: Modulay en 19 de Diciembre de 2008, 11:03:41
El valor de las cotas de error evidentemente depende del método que uses para el cálculo de la integral, de los datos con los que lo apliques, etc...
Sólo lo menciono como sugerencia para afinar tu aplicación, o al menos, tener controlado el error que cometes en las mediciones.
De seguro que matlab cuenta con alguna función de uso sencillo para hacer cálculos de valores rms
Título: Re: Tutorial para calcular valores RMS
Publicado por: migsantiago en 20 de Diciembre de 2009, 15:26:21
Una pequeña corrección a la función RMS, al final se debe dividir la suma entre el número de trapecios del cálculo. El número de trapecios es igual al número de muestras menos uno.

Código: [Seleccionar]
//Subfunción Calcula Valor RMS de un arreglo flotante de n muestras
float ValorRMS(float *arreglo, int samples)
{
int i;
float suma=0;

for(i=0;i<samples;i++)
arreglo[i]*=arreglo[i];

for(i=1;i<samples-1;i++)
suma+=arreglo[i];

suma+=(arreglo[0]+arreglo[samples-1])/2.0;

return sqrt(suma/(samples-1)); //Corregido :D
}

Se asume el que número de muestras es la unidad t y es adimensional, no se maneja en segundos. El valor de t0 = 0. El valor de T = samples-1.
Título: Re: Tutorial para calcular valores RMS
Publicado por: jorgeaf_59 en 21 de Diciembre de 2009, 21:01:47
Hola migsantiago;

Permitime dos observaciones/preguntas:
1- Creo que se pueden reemplazar los 2 ciclos for por uno solo
Código: C
  1. for(i = 0; i < samples; i++)
  2.                suma = suma + arreglo[i] * arreglo[i];

2- La expresión suma+=(arreglo[0]+arreglo[samples-1])/2.0;
no sería necesaria (aparte no tengo claro porque hay que dividir por 2).

Mis comentarios están motivados en las ganas de aprender y no de criticar: un mal alumno NO puede hacerle objeciones a un gran maestro como vos.

Saludos,

Jorge
Título: Re: Tutorial para calcular valores RMS
Publicado por: migsantiago en 21 de Diciembre de 2009, 21:24:05
Hola Jorge

Nada de maestro, solo otra persona que gusta de programar mucho  :D

1.- No puedo anexar ambas operaciones en el mismo for. El primer for se encarga de elevar al cuadrado todas las muestras. El segundo for solo se encarga de sumar todas las muestras intermedias. La primera y la última muestras son divididas entre dos a diferencia de las demás. Los for tienen intervalos diferentes.

2.- La división entre 2 se debe a la ecuación de los trapecios múltiples.

Código: [Seleccionar]
Area = (h / 2) (v[0] + 2 ∑ v[i] + x[n])
La sumatoria va de 1 a n-1

donde:

h = (b-a)/n
b = límite superior en eje x
a = límite inferior en eje x
n = número de trapecios (muestras - 1)

Para el caso de mi cálculo...

b = muestras - 1
a = 0
n = muestras - 1
h = 1

Por lo que todo se reduce a solo sumar las muestras intermedias y agregar las primera y última pero divididas en 2.

Ya después de haber resuelto la integral discreta solo se divide entre muestras - 1 de acuerdo a la fórmula RMS.

(http://img81.imageshack.us/img81/5484/rmshe5.jpg)
Título: Re: Tutorial para calcular valores RMS
Publicado por: jorgeaf_59 en 21 de Diciembre de 2009, 22:11:35
Mis errores fueron dos (como mínimo):
1- Pensar que podía corregirte algo en lo que evidentemente invertiste mucho tiempo.
2- Confundí trapecios con paralelogramos.
Gracias por tu paciencia,

Jorge
Título: Re: Tutorial para calcular valores RMS
Publicado por: Chenao en 29 de Diciembre de 2009, 14:40:08
Saludos

Santiago no se podria crear una estructura para que el usuario entre la función, de forma más general ya sea un polinomio, una función trigonométrica, irracional exponencial que se yo, seria muy interesante si se pudiera realizar todo este cálculo utilizando la regla del trapecio o otro método para cualquier función.

Se que es antioperativo tener una funcion exponecial pero seria muy vacano realizar este tipo de proyecto saludos. 
Título: Re: Tutorial para calcular valores RMS
Publicado por: Chenao en 29 de Diciembre de 2009, 14:45:23

Casi se me olvida, hay un libro llamado métodos numéricos de burdel explican todos lo métodos para calcular la áreas bajo la curva de un función definida, ahy podrias encontrar varios conceptos y ayuda teóricas.

Saludos.
Título: Re: Tutorial para calcular valores RMS
Publicado por: migsantiago en 29 de Diciembre de 2009, 16:11:21
Hola Chenao, mi objetivo no es integrar cualquier función, el objetivo era calcular el valor RMS.

Actualmente ya escribí otras funciones para integrar dos veces la señal de aceleración y funcionan bien con el método del trapecio.

Ya tengo mucha teoría sobre métodos numéricos, pero gracias por el tip.
Título: Re: Tutorial para calcular valores RMS
Publicado por: migsantiago en 11 de Enero de 2010, 21:45:47
Aquí un uso práctico que le di a la función RMS...

Vúmetro RMS con PIC24



Y el programa que funciona para cualquier PIC...

Código: [Seleccionar]
//Autor: MigSantiago
//Enero 2010

/*
Orden de la barra de 10 leds
1 - a0
2 - a1
3 - b0
4 - b1
5 - b2
6 - b3
7 - a2
8 - a3
9 - b4
10 - a4
*/

#define L10 pin_a0
#define L20 pin_a1
#define L30 pin_b0
#define L40 pin_b1
#define L50 pin_b2
#define L60 pin_b3
#define L70 pin_a2
#define L80 pin_a3
#define L90 pin_b4
#define L100 pin_a4

float ValorRMS(float* var, int16 muestras);

////////////////////////////////////////////////////////////////////////////////
#define MUESTRASRMS 48     //muestras para valor rms
#define TMUESTREO   200    //us
//Rango de comparación
//const float MAX=362.0; //máximo puede ser 512 por raíz de 2 (RMS)
const float MAX=250.0;
float c[10];
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
//Función para reordenar los 10 bits de un int10 en la barra de leds por ciento
void ordena_vumetro(float v)
{
int8 i=0;

if(v>=c[i++]) output_high(L10); else output_low(L10);
if(v>=c[i++]) output_high(L20); else output_low(L20);
if(v>=c[i++]) output_high(L30); else output_low(L30);
if(v>=c[i++]) output_high(L40); else output_low(L40);
if(v>=c[i++]) output_high(L50); else output_low(L50);
if(v>=c[i++]) output_high(L60); else output_low(L60);
if(v>=c[i++]) output_high(L70); else output_low(L70);
if(v>=c[i++]) output_high(L80); else output_low(L80);
if(v>=c[i++]) output_high(L90); else output_low(L90);
if(v>=c[i++]) output_high(L100); else output_low(L100);
}
////////////////////////////////////////////////////////////////////////////////

...

void main(void)
{
float binario[MUESTRASRMS];

...

//Calcula los límites de cada led
for(i=3; i<14;++i) //empiezo en 3 para eliminar ruido de fondo
   c[i-3]=(MAX*(float)i)/10;

while(1)
   {
   for(i=0; i<MUESTRASRMS; ++i)
      {
      binario[i]=(float)read_adc()-512.0;
      delay_us(TMUESTREO);
      }
   ordena_vumetro(ValorRMS(binario, MUESTRASRMS));
   }
}

Está hecho con un PIC24FJ64GB002 y un electret amplificado con este circuito (gracias JFMateos  :mrgreen: )...
http://www.todopic.com.ar/foros/index.php?topic=19699.msg240561#msg240561

http://img709.imageshack.us/img709/2004/abcd0002mh.jpg
(http://img709.imageshack.us/img709/2004/abcd0002mh.th.jpg) (http://img709.imageshack.us/img709/2004/abcd0002mh.jpg)
Título: Re: Tutorial para calcular valores RMS
Publicado por: JCCC en 12 de Enero de 2010, 12:26:12
mmmm
En tu código
#define MUESTRASRMS 48     //muestras para valor rms
#define TMUESTREO   200    //us

Numero de muestras 48? Tiempo de muestreo 200 us?
si es así....
la Frecuencia de muestreo es 5 KHz el oído humano percibe de 20 Hz a 20 KHz y los 5 KHz no esta ni cerca de los 40 KHz de frecuencia de muestreo que debería tener, el tiempo que tomas tus muestras es 48*200us = 9600us  cuya frecuencia es 104.1 Hz (frecuencia de toma de datos)
para las frecuencias de 20 Hz el tiempo que deberias tomar muestras es 50000 us

Usualmente en amplificadores se desprecia los 20 Hz por una frecuencia de 100 Hz pero los 5 KHz por 40 KHz de frecuencia de muestro.....
Saludos.......
Título: Re: Tutorial para calcular valores RMS
Publicado por: migsantiago en 12 de Enero de 2010, 14:02:45
Es una buena observación JCCC, usando la respuesta de frecuencia del oído humano debería ser una f de muestreo de 40kSps.

Pero dudo seriamente que el electret tenga tal respuesta de frecuencia, yo creo que ha de llegar a 8kHz como máximo.

Se puede modificar el periodo de muestreo a lo que gusten mientras el PIC lo soporte. Este PIC24 en específico tolera hasta 500kSps (2us).
Título: Re: Tutorial para calcular valores RMS
Publicado por: JCCC en 12 de Enero de 2010, 14:33:01
mmmm......
Disculpa si no observe el circuito, como leí que era un Vúmetro me dedique a observar solo la teoría de este....
Título: Re: Tutorial para calcular valores RMS
Publicado por: migsantiago en 12 de Enero de 2010, 14:42:18
No te preocupes, es muy atinado tu comentario, pero se me fue lo de la respuesta de frecuencia por andar preocupándome porque el ADC no me servía.

Gracias.
Título: Re: Tutorial para calcular valores RMS
Publicado por: ricardoesime en 06 de Octubre de 2011, 17:27:56
Hola buenas tardes migsantiago me ha interesado tu tema y soy nuevos en esto de los pic,
mi pregunta es del codigo que pones para calcular el valor rms de ahi puede salir el codigo para calcular
la pura regla del trapecio.

Agradezco tu atencion y espero me puedas contestar.