Autor Tema: Generar Senoidal  (Leído 11390 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado rarc_357

  • PIC10
  • *
  • Mensajes: 3
Generar Senoidal
« en: 04 de Septiembre de 2009, 11:18:36 »
Necesito generar ondas senoidales de diferentes frecuencias, (10-15Khz) para lo cual utilizaré tablas lookup y un DAC para obtener la salida analógica de la señal. En CCS existe este ejemplo:


BYTE CONST SINE_WAVE[200] = {
128,132,136,139,143,147,150,154,158,161,165,169,172,176,179,
182,186,189,192,195,199,202,204,207,210,213,215,218,220,223,
225,227,229,231,233,235,237,238,240,241,242,243,244,245,246,
247,247,247,248,248,248,248,248,247,247,247,246,245,244,243,
242,241,240,238,237,235,233,231,229,227,225,223,220,218,215,
213,210,207,204,202,199,195,192,189,186,182,179,176,172,169,
165,161,158,154,150,147,143,139,136,132,128,124,120,117,113,
109,106,102,98,95,91,87,84,80,77,74,70,67,64,61,57,54,52,49,
46,43,41,38,36,33,31,29,27,25,23,21,19,18,16,15,14,13,12,11,
10,9,9,9,8,8,8,8,8,9,9,9,10,11,12,13,14,15,16,18,19,21,23,
25,27,29,31,33,36,38,41,43,46,49,52,54,57,61,64,67,70,74,77,
80,84,87,91,95,98,102,106,109,113,117,120,124};

BYTE sine_index;

#int_rtcc
void isr() {

   set_rtcc(102);         // frequency of interrrupt = (clock/(4*divisor))/(256-reload)
                          //                 2029 hz = (20000000/(4*16))/(256-102)

   write_dac(SINE_WAVE[sine_index]);

   if(++sine_index==200) {
      sine_index=0;
   }
}


void main() {

  setup_counters( RTCC_INTERNAL, RTCC_DIV_16);
  enable_interrupts(INT_RTCC);
  enable_interrupts(GLOBAL);

  while (TRUE) ;
}

La tabla ya está calculada y tiene 200 muestras, mi duda es como generar esa tabla, y creo q a mayor frecuencias quizá necesite menos muestras, tampoco me queda claro como puedo hacer variar la frecuencia (este ejemplo es a 10Hz)

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Generar Senoidal
« Respuesta #1 en: 04 de Septiembre de 2009, 11:46:25 »
Para generar la tabla en muy sencillo, una calculadora y listo  :mrgreen: Y=127.5+ 127.5*sen(2*Pi*f*t) donde t dependerá de la velocidad de muestreo. Igual lo que puedes hacer es hacer una sola tabla de cierta cantidad de pasos, y por la frecuencia que quieres generar mas de 20 no creo que puedas usar. Y después para reproducir las distintas frecuencias lo único que haces es variar el tiempo entre envío de muestras.



Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado gera

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2188
Re: Generar Senoidal
« Respuesta #2 en: 04 de Septiembre de 2009, 12:04:57 »
Y por q no usas la funcion sin() de la libreria math.h?
Yo una vez haciendo un filtro digital hice un oscilador sin querer jeje, pero no guarde el codigo :(
saludos!

"conozco dos cosas infinitas: el universo y la estupidez humana. Y no estoy muy seguro del primero." A.Einstein

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Generar Senoidal
« Respuesta #3 en: 04 de Septiembre de 2009, 12:24:25 »
Y por q no usas la funcion sin() de la libreria math.h?
Yo una vez haciendo un filtro digital hice un oscilador sin querer jeje, pero no guarde el codigo :(
saludos!
Noooo! ocupa muchas instrucciones, es imposible hacer algo 10kHz con eso  :?
No contesto mensajes privados, las consultas en el foro

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: Generar Senoidal
« Respuesta #4 en: 04 de Septiembre de 2009, 12:53:59 »
Acabo de probar la generación de una senoidal con puras funciones flotantes y Suky tiene razón, un PIC18 corriendo a 40MHz (10MIPS) no puede ser tan rápido...

Código: [Seleccionar]
#include <18f452.h>
#use delay(clock=40000000)

#include <math.h>

void main(void)
{
float t;
const float p = 0.00005; //muestreo requerido de 20kHz
float f = 10000.0; //frecuencia senoidal
const float dos_pi = 6.2831;
int8 salf;
int8 salida;

while(1)
   {
   salf = 255.0 * sin(dos_pi * f * t);
   salida = (int8)salf; //aquí falta desplazar la muestra a polaridad positiva pero bueno XD
   t += p;
   if(t>1.0)
      t=0;
   }
  
}

El bloque del while(1) consume 653us aproximadamente en calcular el seno, multiplicar por la amplitud de 255, hacer el casting a entero e incrementar el tiempo.

Si cada 0.65ms se puede conocer una muestra senoidal, la frecuencia en tiempo real sería de 1,538Hz aproximadamente... muy por debajo de los 15kHz que necesita rarc.

Para hacer la tabla de constantes que está arriba se puede usar excel o cualquier otra cosa siguiendo la fórmula de mi ejemplo, pero al modificar la frecuencia de la senoidal o el valor de t la tabla resulta inútil porque todos sus valores cambian.

Lo bueno es que los PIC18 tienen mucha memoria de programa y puedes llenarlas con cuantas tablas de frecuencias necesites.
« Última modificación: 04 de Septiembre de 2009, 12:56:02 por migsantiago »

Desconectado gera

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2188
Re: Generar Senoidal
« Respuesta #5 en: 04 de Septiembre de 2009, 13:11:58 »
hmm, es cierto.. entonces con tabla sera. Aunq pienso q tiene q haber una forma mas eficaz.
saludos!!

"conozco dos cosas infinitas: el universo y la estupidez humana. Y no estoy muy seguro del primero." A.Einstein

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Generar Senoidal
« Respuesta #6 en: 04 de Septiembre de 2009, 13:19:35 »
Con un PIC a esa frecuencia te ves muy limitado  :tongue:
No contesto mensajes privados, las consultas en el foro

Desconectado RICHI777

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1498
Re: Generar Senoidal
« Respuesta #7 en: 04 de Septiembre de 2009, 13:20:21 »
Hola, los metodos de tabla con valores precalculados son los metodos mas eficaces que existen, nada es mas rapido que indexar y tomar el valor de una posicion de memoria.

Saludos !

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Generar Senoidal
« Respuesta #8 en: 04 de Septiembre de 2009, 13:26:38 »
Exacto, y yo crearía una única tabla de 256 valores, para usar un "puntero" de 8 bits para no usar esta rutina:

Código: C
  1. if(++sine_index==200) {
  2.       sine_index=0;
  3.    }

por ejemplo que le quita rendimiento, aparte de no usar interrupción  :undecided:

Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado PalitroqueZ

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5474
    • Electrónica Didacta
Re: Generar Senoidal
« Respuesta #9 en: 04 de Septiembre de 2009, 13:27:45 »
Con tablas es una forma muy rapida, los chips de analog Devices usan tablas ROM super rapidas



fuente: 450968421DDS_Tutorial_rev12-2-99.pdf

La propiedad privada es la mayor garantía de libertad.
Friedrich August von Hayek

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: Generar Senoidal
« Respuesta #10 en: 04 de Septiembre de 2009, 13:33:03 »
Exacto, y yo crearía una única tabla de 256 valores, para usar un "puntero" de 8 bits para no usar esta rutina:

Suky, ¿pero cómo modificarías la frecuencia y el periodo de muestreo si la tabla se calcula con f y t constantes? Según entiendo esa tabla de 256 valores sería a partir de una f y una t, pero al cambiarlas la tabla dejaría de servir.

Tendría que tener muchas tablas, cada una con un par de f y t.  :?:

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Generar Senoidal
« Respuesta #11 en: 04 de Septiembre de 2009, 13:37:53 »
Exacto, y yo crearía una única tabla de 256 valores, para usar un "puntero" de 8 bits para no usar esta rutina:

Suky, ¿pero cómo modificarías la frecuencia y el periodo de muestreo si la tabla se calcula con f y t constantes? Según entiendo esa tabla de 256 valores sería a partir de una f y una t, pero al cambiarlas la tabla dejaría de servir.

Tendría que tener muchas tablas, cada una con un par de f y t.  :?:
Los niveles de tensión son exactamente los mismos, si siempre muestreo por ejemplo con 16 muestras por periodo de la señal, claro esta que la frecuencia de muestreo va a variar en cada caso, pero es una solución rápida dentro de un pequeño rango de frecuencias. Después para la generación lo único que se varia es el tiempo en presentar las muestras.
No contesto mensajes privados, las consultas en el foro

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: Generar Senoidal
« Respuesta #12 en: 04 de Septiembre de 2009, 13:39:50 »
Me has convencido, tienes razón. Es solo cuestión de estirar o comprimir la senoidal... incluso se podría generar solo el semiciclo positivo y negar el otro.  :mrgreen:

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Generar Senoidal
« Respuesta #13 en: 04 de Septiembre de 2009, 13:43:24 »
Me has convencido, tienes razón. Es solo cuestión de estirar o comprimir la senoidal... incluso se podría generar solo el semiciclo positivo y negar el otro.  :mrgreen:
Claro a eso me refería, estirar o comprimir la señal. Eso para un determinado rango de frecuencias, porque para generar 50 Hz con 16 muestras creo que tiene muy poca resolución  :undecided:
No contesto mensajes privados, las consultas en el foro

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: Generar Senoidal
« Respuesta #14 en: 04 de Septiembre de 2009, 13:48:25 »
Sí, por ejemplo generas una tabla de 16 muestras para una señal rápida como de 1kHz pero luego generas una tabla de 128 muestras para una de 50Hz.  :mrgreen:


 

anything