Generador de onda senoidal de frecuencia variable con pic

Estado
Cerrado para nuevas respuestas.
Hola , quisiera saber si alguien sabe o tiene como generar una onda seno con un pic , y que sea de frecuencia variable (de 50hz a 200khz).
Cualquier ayuda seria bien recibida...
Gracias .
 
saludos colegas... me quiero embarcarme en un proyecto ... para que con un pic general un onda sinusoidal... para la aplicación que las personas que entren al foro les quieran dar...... así que soporto sugerencias por que... es un buen proyecto discutir
 
Divides el período de la señal en (Por ejemplo) 200 pasos
Calculas el seno para el punto 0 [X = Sen(P) siendo "P" = Nº Punto * (360º /200)]
Calculas el seno para el punto 1
Calculas el seno para el punto 2
Etc.
Etc.
Hasta llegar al valor 200, alli vuelves a comenzar desde 0

Los valores [X] que calculaste los conviertes a dato y los mandas a un conversor DA, a la salida del conversor tiene la señal senoidal.
 
mediante una rutina puedes hacer que el siguiente punto de la onda no se genere hasta que llegue una señal de reloj externa, con lo que puedes rgular la frecuencia

Creo que voy a intentarlo :D

saludos
 
Ortega: Solo adiciono que, en general, en programacion se usa mucho crear inicialmente una tabla con los valores del seno de distintos angulos. La tabla se carga en memoria y se la emplea posteriormente para lo que necesites (mas calculos, graficas o enviarlos al conversor DA, etc). Esto reduce la gran cantidad de tiempo que emplea el micro haciendo calculos... pero el costo a pagar es que necesitas algo mas de memoria para cargar la tabla. Salu2.
 
>>> conseguí algo bueno, que opinan <<<


antes de pasar a los diagramas y codigos, es necesario conocer como funciona... lo que se pretende con esta tecnica es tratar de generar una señal se salida que tenga una similitud a una señal senoidal alterna con determinada magnitud (Amplitud) y frecuencia. Yo parti del analisis de la onda senoidal pura; la cual tiene una area determinada en cualquiera de sus semiciclos, si, se mantiene a una amplitud y frecuencias constantes. La idea es dividir ese semiciclo en intervalor de tiempo iguales y en un numero par ( Mas adelante veremos porque ) para que en cada intervalo de tiempo se genere un pulso PWM con una Area equivalente a el area de la señal senoidal en ese mismo periodo de tiempo.

Como se observa en la figura lo que se tiene que calcular son los Anchos de Pulso o Duty Cicle para cada pulso de PWM a fin de que el area en ese pulso sea la misma area en el mismo instante en la señal senoidal.


La velocidad del cristal a usar se elige en base a el tiempo que duren los pulsos PWM ya que si el tiempo es muy grande no nos alcanzara el TMR2 y PR2 para temporizar ese pulso sin complicarnos mucho. En este caso estoy dividiendo una señal senoidal a 60 Hz y con proximadamente 180 Volts pico lo que me da un periodo de señal aproximado de 16 ms. y estoy dividiendo el ciclo senoidal en 20 pulsos de PWM con lo que el periodo del PWM viene siendo 16ms/20 = 0.8 ms.
Utilizo un cristal a 20 Mhz considerando la formula para el periodo PWM y tengo que:


PWM Period = [(PR2) + 1] • 4 • T
OSC • (TMR2 Prescale Value)
[/size]​

Como se que PR2 es un registro de 8 bits puede valer como maximo 255 y calculo el valor de PR2 para el PWM period deseado y con el Tosc definido y con un Preescale value para TMR2 de 1:16:


PR2 = PWM Period / [ 4 • TOSC • (TMR2 Prescale Value) ] - 1

PR2 = 0.8ms / [ 4 • (1/20Mhz) • ( 16 ) ] - 1
PR2 = 249


Con lo que los valores elegidos quedan bien.
Finalmente se obtienen unas ecuaciones para poder obtener el valor de cada Duty Cicle dependiendo del pulso que se trate. Se menciono que era preferible elegir una cantidad par para el numero de pulsos en los que dividiriamos a la señal, es porque analizando la primer grafica nos damos cuenta de que las areas A1 - A5 son diferentes pero despues se vuelven a repetir, por lo tanto solo hay que tener los primeros 5 Duty Cicles y los demas son repeticiones de ellos.
Para actualizar el valor de los Duty Cucle utilizamos la interrupcion de coincidencia de PR2 con TMR2, con lo que en cada interrupcion se carga el nuevo valor de Duty Cicle, los 5 valorez necesarios para el Duty Cicle se calculan dependiendo de la lectura del Pote obteniendo resutados como estos:

El Diagrama del circuito queda asi:
http://micros.mforos.com/visit/?http://img338.imageshack.us/my.php?image=diagrampwmrp2.jpg


Se utilizan en total 3 fuentes de bajo voltaje y una bipolar de potencia, son necesarias porque debido a la conexion en medio puente es necesario aislar el circuito de conmutacion de cada transistor (MOSFET) puesto qeu si utilizamos una sola fuente estaria existiendo un corto entre los "Source" de cada transistor. La fuente bipolar de 180 V. se arma en un rectificador de media onda, tal y como se muestra en el siguiente diagrama.



Despues podria hacerse una modificacion para poder controlar tambien la frecuencia en vez de solo controlar la amplitud equivalente, y obtener resultados como estos; que son mas utiles en los motores sincronos.

 
Hola, eso es relativamente facil. Es correcto lo q se ha dicho, yo mismo lo he hecho. Debes calcular el valor (por medio de un muestreo) de la señal en ciertos intervalos de tiempo como lo comenta ortega. Una vez realizado esto la opcion mas recomendable es almacenarlos permanettemente en la memoria del PIC (EEPROM). XQ en la EEPROM??

Bueno, de esta manera te evitas que el PIC este calculando a cada instante los valores, despues de todo es una señal senoidal y es un ciclo, los valores simplemente se repiten. Posteriormente dependiendo como configures tu programa, podras llamar una subrutina que lea y envie al puerto de salida los valores almacenadoe en la EEPROM y de esta manera tu seras capaz de conectar la salida del PIC a un OSC y observar tu señal senoidal. Obviamete deberas contemplar q la resolucion de tu señal varia directamente proporcional muestreo realizado (los valores en los cuales dividiste tu onda y guardaste en EEPROM) Spero haberme explicado
 
La mejor forma, y la mas facil es la del PWm como explicaron anteriormente...y porqué lo digo...simplemente porque hay un muchacho que ha diseñado varios videojuegos con un PIC16F84A y saca el sonido por 1 solo puerto (obviamente es analogico) y en el programa utilizo PWM.
 

Adjuntos

  • tetris_schematic.png
    tetris_schematic.png
    4.2 KB · Visitas: 251
La mejor solución ya se ha propuesto, pero otra forma que se me ocurre es simplemente generar una onda cuadrada y pasarla por un filtro pasabanda :D claro, si lo que se quiere es simplemente obtener "una onda sinusoidal"
 
este es un generador de la onda seno con el pic16f877. espero les sirva.
ah incluye simulacion en proteus:aplauso:
 

Adjuntos

  • generador onda seno.zip
    42.6 KB · Visitas: 4,482
este es un generador de la onda seno con el pic16f877. espero les sirva.
ah incluye simulacion en proteus:aplauso:

este es un generador de la onda seno con el pic16f877. espero les sirva.
ah incluye simulacion en proteus:aplauso:


Jimmy muy bueno el ejemplo tuyo. Hay algunas cosas que no entendi bien de la programacion.
Cuando vos utilizas int seno[67]={...} pones los valores que va a tomar la funcion. Pero no termino de entender como haces para determinar la frecuencia.

puerto_b = seno[desbordes];
set_rtcc(15);

Lo unico que pude notar es que si aumentas el valor dentro de set_rtcc() la frecuencia aumenta.

Lo otro que no pude entender fue lo que se encuentra dentro de void main, las siguientes instrucciones:

enable_interrupts(global);
enable_interrupts(int_rtcc);
setup_counters(rtcc_internal, rtcc_div_64);
set_rtcc(240);

Muchas Gracias!!
Nico
 
Hola una ves en la escuela nos pidieron generar una señal senoidal con un pic, y lo logramos, usamos un pic 18f2550 y un dac I2C (PCF8591), Aqui les comparto el programa (en PICC) y la simulacion (en isis de proteus v7). el pic esta a 48 MHZ con el PLL con un cristal de 12 mhz. espero que a alguien le sea util
 

Adjuntos

  • AD_DA_I2C_2550.rar
    61.2 KB · Visitas: 1,203
Jimmy muy bueno el ejemplo tuyo. Hay algunas cosas que no entendi bien de la programacion.
Cuando vos utilizas int seno[67]={...} pones los valores que va a tomar la funcion. Pero no termino de entender como haces para determinar la frecuencia.

puerto_b = seno[desbordes];
set_rtcc(15);

Lo unico que pude notar es que si aumentas el valor dentro de set_rtcc() la frecuencia aumenta.

Lo otro que no pude entender fue lo que se encuentra dentro de void main, las siguientes instrucciones:

enable_interrupts(global);
enable_interrupts(int_rtcc);
setup_counters(rtcc_internal, rtcc_div_64);
set_rtcc(240);

Muchas Gracias!!
Nico

Veo que no te contestaron , mi duda es : ese arreglo de Intseno[67]= ( ... ) , esos valores yo los meto manual o como es lo que no entiendo.
 
Hola , estoy haciendo un proyecto en el cual la primera fase es sacar dos ondas seno a traves de los puertos del microcontrolador PIC18 , estas ondas la genero con una tabla de valores de seno que hago en matlab y lo que hago sacarlas por los puertos y estos datos va hacia un DAC, este a su salida me estará generando la onda seno.

ADJUNTO el código de lo antes dicho. :

Código:
#include <18f4550.h>
#fuses hspll,mclr,nowdt,noprotect,nolvp,nodebug,usbdiv,pll3,cpudiv1,novregen,nopbaden
#use delay (clock=48000000)
#use standard_io(B)
#use standard_io(C)
#use standard_io(D)


int16 frecuencia=0;
int8 desbordes=0;
int seno[100]={77,82,86,91,96,101,105,109,114,118,122,126,129,133,136,
139,142,144,146,148,150,151,152,153,153,154,153,153,152,151,150,148,146,144,142,
139,136,133,129,126,122,118,114,109,105,101,96,91,86,82,77,72,67,62,58,53,49,44,
40,36,32,28,24,21,18,15,12,9,7,5,4,2,1,1,0,0,1,1,2,4,5,7,9,12,15,18,21,24,28,32,36,
40,44,49,53,58,62,67,72,77};

#int_rtcc
void rtcc_isr(){
        
        frecuencia=read_adc();        
        output_B(seno[desbordes]);
        output_d(seno[desbordes]);
        set_rtcc(frecuencia); 
        desbordes++;
        if(desbordes>=100)
        
        
                     {
                          desbordes = 0;
                        }   
  }

void main()
  {
     setup_adc_ports(all_analog);
     setup_adc(adc_clock_internal);
     set_adc_channel(0);  
     set_tris_b(0x00);
     set_tris_d(0x00);
     setup_counters(rtcc_internal, rtcc_div_4 | rtcc_8_bit);      
     enable_interrupts(int_rtcc);       
     enable_interrupts(global);
     set_rtcc(231);
     desbordes = 0;

   while(true)
   {
   
   }
   }
PREGUNTAS:

los valores de seno en lugar de generarlos por matlab , es posible generar una tabla o Lookup table dentro del mismo y de ahi separarlos en en valores impares y pares. para sacar posteriormente cada arreglo por cada DAC.

Con el esquema que pongo es posible modificar su frecuencia de cierto valor a cierto valor , como configuraria el pic para que este diera su maxima frecuencia posible de salida. tomando en cuenta que la frecuencia maxima de oscilacion del CPU segun microchip es de 48 mhz!
 

Adjuntos

  • Gnerador3.rar
    66 KB · Visitas: 482
Última edición por un moderador:
Estado
Cerrado para nuevas respuestas.
Atrás
Arriba