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

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

Desconectado rarc_357

  • PIC10
  • *
  • Mensajes: 3
Re: Generar Senoidal
« Respuesta #15 en: 05 de Octubre de 2009, 14:49:17 »
ok ok he estado trabajando y desde esa fecha para aca muchas cosas me han quedado claras
Efectivamente estoy utilizando la tabla de look-up para generar la onda senoidal, ya he podido obtener una salida, con un dac0800, q por cierto me quitó algo de tiempo echarlo a andar, (errores tontos) y si, logro dibujar una senoidal, pero a frecuncia muy baja!!!, y pensando, vi q no es necesario o al menos eso pienso, utilizar la interrupción de overflow del rtcc para ir colocando las muestras.

Pienso dejar una sola tabla, y no colocar muchas, pues pretendo hacer un barrido d frecuencias, entonces, mejor modificaré el tiempo entre muestra y muestra con un retraso
asi puedo controlar el tiempo q lleva escribir todas las muestras, q correspondería al periodo.

peeeero al modificar el programa ahora ya no tengo salidas en PORTB, no se específicamente cuál sea el error. este es el código nuevo.

#include <18F452.h>
#fuses HS,NOWDT,NOPROTECT
#use delay(clock=4000000)

BYTE CONST SINE_WAVE[256] = {
128,131,134,137,140,144,147,150,153,156,159,162,165,168,171,174,
177,179,182,185,187,191,193,196,199,201,204,206,209,211,213,216,
218,220,222,224,226,228,230,232,233,235,237,239,240,241,243,244,
245,246,248,249,250,250,251,252,253,253,254,254,254,255,255,255,
255,255,255,255,254,254,254,253,253,252,251,250,250,249,248,246,
245,244,243,241,240,239,237,235,234,232,230,228,226,224,222,220,
218,216,213,211,209,206,203,201,199,196,193,191,188,185,182,179,
177,174,171,168,165,162,159,156,153,150,147,144,140,137,134,131,
128,125,122,119,116,112,109,106,103,100,97,94,91,88,85,82,79,76,
74,71,68,65,63,60,57,54,52,49,47,45,43,40,38,36,34,32,30,28,26,
24,22,21,19,17,16,15,13,12,11,10,8,7,6,6,5,4,3,3,2,1,1,1,1,1,1,
1,1,1,2,2,2,3,3,4,5,6,6,7,8,10,11,12,13,15,16,17,19,21,24,26,28,
30,32,34,36,38,40,43,45,47,50,52,55,57,60,63,65,68,71,74,77,79,
82,85,88,91,94,97,100,103,106,109,112,116,119,122,125,128};

BYTE sine_index;




void main() {

output_B(SINE_WAVE[sine_index]);

delay_ms(10);

   if(++sine_index==256) {
      sine_index=0;
 }
while (true);
}


Despues haré variable el retraso, controlado por un botón externo. Pero en este momento no logro ver salida en portB

Primero pretendo obtenr la máxima frecuencia posible con este pic, y cuento con osciladores XT de hasta 40Mhz

Saludos a todos los q han comentado

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Generar Senoidal
« Respuesta #16 en: 05 de Octubre de 2009, 15:10:43 »
El 452 creo que la máxima velocidad que soporta es de 32MHz con PLL, revisa eso. Ahora ese código que has colocado no va hacer nada, solamente va a mostrar un valor de la tabla y nada mas, debería ser así:

Código: C
  1. while(1){
  2.      output_B(SINE_WAVE[sine_index++]);
  3.      delay_ms(xx); // o delay_us(xx);
  4. }

Igual con una tabla de tantos valores mucha velocidad no vas a lograr, revisa todo lo que hemos comentado  :?


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

Desconectado rarc_357

  • PIC10
  • *
  • Mensajes: 3
Re: Generar Senoidal
« Respuesta #17 en: 13 de Octubre de 2009, 15:28:04 »
OK quiero decirles que todo va bien, gracias por su ayuda.
He podido generar una senoidal de forma exitosa, incluso he podido hacer variar la frecuencia utilizando una rutina de interrupción en B
que lo que hace es hacer variable un delay que coloco entre muestra y muestra de la tabla de look-up.

Lamentablemente, con o sin retrasos, solo he podido llegar hasta 1.2Khz con un clock a 16Mhz (por cierto ¿cuál es el clock maximo q han utilizado con un 18F452?)

La tabla la he disminuido a 200 muestras, se que puedo disminuirla mas, Pero:

Alguien me puede bajar de mi nube y decirme q jamás llegaré a frecuencias de 15-20Khz  :shock:

Saludos desde Veracruz, México.


Pronto compartiré el proyecto, si les viene bien  8)

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
Re: Generar Senoidal
« Respuesta #18 en: 13 de Octubre de 2009, 19:43:34 »
Lamentablemente, con o sin retrasos, solo he podido llegar hasta 1.2Khz con un clock a 16Mhz (por cierto ¿cuál es el clock maximo q han utilizado con un 18F452?)

Hola, yo he usado el PIC18F452 con un cristal de 10MHz y un PLL que lo eleva a 40MHz.

Edito en fuses para usar un xtal de 10MHz y elevarlo a 4MHz debes usar:

Código: [Seleccionar]
#fuses h4
« Última modificación: 13 de Octubre de 2009, 19:48:32 por migsantiago »

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: Generar Senoidal
« Respuesta #19 en: 13 de Octubre de 2009, 21:00:49 »
Utilizando PLL, llegas a 40MHz, osea un ciclo de trabajo de 100ns. La rutina para cargar el valor podría ser la siguiente:

Código: C
  1. while(Signal==1){
  2.     output_b(Tabla[i++]);
  3. }

con Tabla de 256 valores, configurando #use fast_io(b) vemos que el asm generado es:

Código: ASM
  1. ....................    while(Signal==1){
  2. 0170:  MOVLB  1
  3. 0172:  BTFSS  x1C.0
  4. 0174:  BRA    0190
  5. ....................       output_b(Tabla[i++]);    
  6. 0176:  MOVF   x1E,W
  7. 0178:  INCF   x1E,F
  8. 017A:  CLRF   03
  9. 017C:  ADDLW  1B
  10. 017E:  MOVWF  FE9
  11. 0180:  MOVLW  00
  12. 0182:  ADDWFC 03,W
  13. 0184:  MOVWF  FEA
  14. 0186:  MOVFF  FEF,125
  15. 018A:  MOVFF  125,F8A
  16. ....................    }
  17. 018E:  BRA    0172

Así que sin ningún tipo de demora el ciclo ocurrirá cada 14 instrucciones. Si nuestra tabla contiene 16 ciclos de la señal con 16 valores por ciclo, la frecuencia de la señal generada será:

14x100nsx16=22.4us-> 44.6kHz.- Así que se puede llegar a generar lo que necesitas ;-)


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

Desconectado jgpeiro06

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 276
Re: Generar Senoidal
« Respuesta #20 en: 15 de Octubre de 2009, 06:49:42 »
Conozco otras dos maneras de generar una onda senoidal que no son tan rapidas como la busqueda en una tabla, pero que pueden ser suficientes para.
    -El metodo de CORDIC, que calcula el sin(x) utilizando la busqueda binaria sobre una tabla de arctg. http://es.wikipedia.org/wiki/CORDIC
    -La transformada Z inversa de la transformada Z de la funcion sin(t) es una ecuacion recursiva. Pârtiendo de la transformada Z de la funcion sin(w0n)u(n) que aparece en http://es.wikipedia.org/wiki/Transformada_Z y operando obtenemos y[n] = x[n-1]*sin(w0) + y[n-1]*2*cos(w0) - y[n-2]. Si x[n] es una delta de dirac, y[n] será sin(w0*n). La funcion delta de dirac en tiempo discreto esta definida d[n] = 1 si n == 0 o 0 si n != 0.

Desconectado fuente

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 571
Re: Generar Senoidal
« Respuesta #21 en: 15 de Octubre de 2009, 08:33:41 »
En www.bitscope.com, en la seccion de Downloads, hay un archivo que se llama wavePOD.zip.
Ahí tienen un generador de funciones con un 16F84, con el código asm bastante bien explicado, así como el esquema.

Por cierto y por si le interesa a alguien, hace como unos 7 años compré un osciloscopio de estos, cuando todavía te los mandaban en kit y te los tenías que montar y ajustar, y la verdad es que va bastante bien para el uso que le doy en casa. El mío va por puerto serie, así que los que tienen ahora por USB o ethernet tienen que ir de perlas.

Saludos.

Desconectado matyvico

  • PIC10
  • *
  • Mensajes: 20
Re: Generar Senoidal
« Respuesta #22 en: 02 de Febrero de 2013, 15:38:00 »
Disculpen por revivir este post, pero estuve buscando por todo el foro sobre la generación de una función senoidal y este fué el post más completo (y cercano a lo que yo busco).
Yo estoy (en este post) tratando de que entre todos armemos un generador de señales, hasta ahora funciona todo bastante bien, el inconveniente es generar una función senoidal (o cualquier otra en sí) de frecuencia y amplitud variables (así como ciclo de trabajo en la cuadrada, ect).

No discuto que la forma mas rapida de mostrar valores es leyendo la tabla y poniendo ese valor en el puerto (usando fast_io también), pero lo que simpre vi fueron discusiones sobre tablas CONSTANTES, no vi en ningún lugar que nadie planteara la idea de primero (en base a parámetros elegidos por el usuario como amplitud, y frecuencia) generar una tabla haciendo uso por ejemplo de la función sin(); de math.h y luego en otro loop hacer la muestra común y corriente leyendo rapidísimo desde esta tabla recién generada y no de una tabla constante. He tratado de implementar esto que digo pero no logro resultados, aunque estoy seguro que el problema es con el tipo de datos usado en alguna variable, un casting o algo por el estilo, mi idea es así:

Código: [Seleccionar]
#INCLUDE <math.h>

    static int salida[200]={};
    float temp;
    float incremento=((2*pi)/199);
    float fase;
    i=199;
    x=0;

    //SEÑAL SENOIDAL
        case 3:
        {
            for(fase=0;fase<=(2*pi);fase+=incremento)
            {
                 temp=ceil((0.5*sin(fase)+0.5)*255.0);
                 strcpy(salida[x],(int)temp);
                 x++;
            }
            while(salir)
            {
                delay_ms(1);
                output_d(salida[i]);
                i--;
                if(i==0){i=199;}
            }
            break;
        }

Eso es parte de un programa que actualmente estoy desarrollando para el generador del post que les puse mas arriba, estoy probando con eso para generar la tabla del seno desde calculos hechos por el mismo pic, luego si hago funcionar eso, implementar una modificación de la amplitud sería tan simple (supongo) como modificar el multiplicador en frente a la función sin(), y su frecuencia en función de incrementar o disminuir el argumento de un delay... Pero como dije, si hago lo que puse arriba, solo obtengo que el array salida[] se llene de vez en cuando en alguna de las 200 posiciones con algún valor, y en el resto solo tengo caracteres nulos...

Si me pudieran tirar alguna pista estaría muy agradecido! Muchas gracias por adelantado!

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: Generar Senoidal
« Respuesta #23 en: 03 de Febrero de 2013, 14:46:16 »
  Hice el siguiente ejemplo en XC8, en el cual almaceno valores en una tabla. Cuando el pin B0 está en estado bajo, la tabla se llena con valores correspondientes a la función seno. Si está en estado alto, se llena con valores correspondientes a función triangular.

  Variando el delay dentro del ciclo for se puede cambiar la frecuencia. Me encuentro con un inconvenientes y es que según la frecuencia o la forma de onda, debo cambiar el filtro pasabajos colocado al final del dar R-2R. El filtro está colocado directamente sobre la salida del pic y tal vez sería mejor colocar un operacional y luego el filtro.

  El programa está hecho para un PIC16F886 corriendo a 20MHz. Si saco el delay del ciclo for obtengo una máxima frecuencia de aproximadamente 16KHz. Me imagino que con un 18F2550 corriendo a 48MHz se podrá lograr mucha mayor frecuencia de salida. Incluso quizá se pueda lograr aumentar el número de valores de la tabla.

Programa:

Código: C
  1. #include <xc.h>
  2.  
  3. #pragma config FOSC = HS, MCLRE = OFF, WDTE = OFF
  4. #pragma config BOREN = OFF, IESO = OFF, FCMEN = OFF
  5.  
  6. #define _XTAL_FREQ 20000000
  7.  
  8. unsigned char tabla[16];
  9. unsigned char indice;
  10.  
  11. void main(void)
  12. {
  13.     ANSEL = 0;
  14.     ANSELH = 0;
  15.     TRISB = 255;
  16.     TRISC = 0;
  17.     PORTC = 0;
  18.  
  19.     if (PORTBbits.RB0 == 0)
  20.     {
  21.       tabla[0] = 100;
  22.       tabla[1] = 138;
  23.       tabla[2] = 170;
  24.       tabla[3] = 192;
  25.       tabla[4] = 200;
  26.       tabla[5] = 192;
  27.       tabla[6] = 170;
  28.       tabla[7] = 138;
  29.       tabla[8] = 100;
  30.       tabla[9] = 62;
  31.       tabla[10] = 30;
  32.       tabla[11] = 8;
  33.       tabla [12] = 0;
  34.       tabla[13] = 8;
  35.       tabla[14] = 30;
  36.       tabla[15] = 62;
  37.     }
  38.     else
  39.     {
  40.       tabla[0] = 100;
  41.       tabla[1] = 125;
  42.       tabla[2] = 150;
  43.       tabla[3] = 175;
  44.       tabla[4] = 200;
  45.       tabla[5] = 175;
  46.       tabla[6] = 150;
  47.       tabla[7] = 125;
  48.       tabla[8] = 100;
  49.       tabla[9] = 75;
  50.       tabla[10] = 50;
  51.       tabla[11] = 25;
  52.       tabla [12] = 0;
  53.       tabla[13] = 25;
  54.       tabla[14] = 50;
  55.       tabla[15] = 75;
  56.     }
  57.  
  58.     while(1)
  59.     {
  60.         for (indice = 0; indice < 16; indice++)
  61.         {
  62.             __delay_us (100);
  63.             PORTC = tabla[indice];
  64.         }
  65.     }
  66. }

Dejo la captura del osciloscopio de proteus.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas


 

anything