TODOPIC
FORO TÉCNICO => Foro Técnico => Mensaje iniciado por: japifer_22 en 27 de Octubre de 2011, 10:11:03
-
Hola, como dice el titulo estoy realizando una señal sinusoidal de frecuencia variable de 50 a 250 Hz entre un rango de 1Hz si es que lo puedo lograr y todo lo demás fijo. Esto lo estoy generando por un pic 18f y un DAC. Pero en este punto tengo una duda y es que frecuencia de muestreo me sirve ¿?, para generar lo mejor posible la sinusoidal ¿?. Sé que no me puedo escapar del teorema del señor Nyquist-Shannon (fsampling=2*fseñal).
Espero que me puedan responder esta pregunta.
Saludos
-
Y bueno, siguiendo el teorema de Nyquist necesitas por lo menos 2 muestras por periodo de la señal para reproducirla, aunque no es lo más adecuado. Eso tienes que evaluarlo tu, prueba si con 10 muestras por ciclo te sirve. A la salida podes colocarle un filtro pasa-bajos con Fc en 300Hz, y vas a tener una señal más suave.
Saludos!
-
hola suky, perdon la tardanza :lol: alfinal genere 100 puntos para la senoidal. pero ahora tengo el problemas que como genero mi entrada digital a partir del voltaje que tiene que generar el DAC para formar esta señal.
alguna idea ?
saludos
-
No entendí :z) :mrgreen:
-
:mrgreen: todo de nuevo:
quiero generar una señal senoidal de 65 a 250 Hz con un PIC 18f y un ADC de 8. ahora mi idea es generar una tabla la cual tenga las convinaciones nesesaria digitales, para mandarle al DAC desde el PIC, para sí dar forma a la señal senoidal. en este punto mi tabla tiene 100 valores pero son el voltaje que tiene que entregar mi DAC, pero ahora yo nesesito mis entradas digitales para formar estos voltajes. mi pregunta es como puedo obtener mi entrada digital del DAC, si yo tengo los voltajes de salida de este, que es el o los voltajes que forman mi senoidal. me expreso mejor ??????
-
A! Fácil! Seguramente tu tienes una tabla con valores que van desde 0 V hasta 5 V, no es así? Bueno, si el DAC es de 8-bits, significa que le debes enviar 255 para que a la salida obtengas 5.0 V. Lo que queda es realizar una regla de tres y listo ;-)
-
cuack... jajaj oka no se me avia ocurrido
-
tengo otra duda...... :?
supongamos que quiero generar una señal senoidal de 100Hz, por lo cual el periodo de esta señal seria de 10ms. ahora para formar este periodo de la señal senoidal, el PIC tiene que entregarle al DAC 100 combinaciones para poder generar la senoidal. esto quiere desir que cada 100us tengo que enviar una combinacion desde el PIC al DAC, (claro si es que estoy bien ??)
ahora el problema que tengo es que supuestamente genere el codigo para esto pero no me da la frecuencia que quiero la de 100Hz, en que estare mal.... me pueden orientar por favor.
#include <18f4550.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT
#use delay (clock = 4000000)
#use standard_io(B)
#use standard_io(C)
#use standard_io(D)
int8 desbordes=0;
BYTE CONST 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(){
output_B(seno[desbordes]);
set_rtcc(231);
desbordes++;
if(desbordes>=100)
{
desbordes = 0;
}
}
void main()
{
set_tris_b(0x00); // Puerto B como salidas digitales
setup_counters(rtcc_internal, rtcc_div_4 | rtcc_8_bit); // Se configura con un predivisor de frecuencias 1:4
enable_interrupts(int_rtcc); // Se habilita interrupciòn por desborde Timer 0 y se activa la interrupciòn global
enable_interrupts(global);
set_rtcc(240);
desbordes = 0;
while(true)
{
}
}
-
Si quieres tantos puntos, lo más adecuado es que lleves al microcontrolador a 48MHz, así tienes suficientes ciclos de reloj para trabajar entre interrupción e interrupción.
Con esas pruebas te darás cuenta si 100 puntos es necesario, o mejor disminuirlo ;-)
Saludos!
-
suky, lo he probado igual con menos puntos. pero el punto es que no se bin como generar la frecuencia del sampling v/s la frecuencia de mi senoidal que es de 100Hz. me puedes orientar por favor.
saludos
-
hola bueno despues de una larga noche he investigando con esto, creo entender como generar esta señal y como cargar el TMR0, lo dejo para ver si me pueden recovorar lo que digo:
Para generar la frecuencia senoidal con un PIC y un DAC, de por ejemplo 100Hz, tenemos que ver cuantos escalones queremos para generar un periodo de ésta frecuencia, en mi caso voy a probar con 50 puntos o escalones. Donde esto quiere decir que el pic generara 50 combinaciones en el puerto B que saldrá a la entrada digital del DAC, para formar el periodo de la frecuencia que queremos (100Hz). Ahora tenemos que calcular cuánto se tiene que demorar el pic en generar estos 50 puntos para un periodo de la frecuencia a sacar de 100Hz.
El periodo de la frecuencia de 100Hz es:
Tfout=1/100 = 0.01seg o 10ms.
Ahora tenemos que dividir este periodo en los escalones que generara el pic para un periodo, para así generar el periodo del sampling, o frecuencia de muestreo:
Tsampling= Tfout/escalones = 0.01/50= 0.0002 o 200us
Esos 200uS es cada cuanto debes entregar un solo dato al DAC. 200uS*50=10mS y este si es el periodo de tu señal
Los 200us son lo que se tiene que demorar el pic en entregarle al DAC las 50 combinaciones para formar un periodo de la frecuencia senoidal de salida del DAC.
Por lo cual la frecuencia del sampling queda expresada como:
Fsampling =1/Tsampling = 1/0.0002 = 5000Hz o 5KHz.
Una vez obtenida esta frecuencia tenemos que saber a cuanto tenemos que cargar el TMR0 para formar la frecuencia sampling.
Primero tenemos que saber cuál es la frecuencia interna del PIC, para un Cristal de 4MHz, la cual está dada por:
Fint= Fcristal / 4 = 4,000,000.0/4 = 1,000,000.0 o 1MHz
Ahora esta frecuencia fint la tenemos que dividir por el pre-escaler a utilizar, que en mi caso utilizare el pre-escaler=2
Fout pre-escaler= fint/ pre-escaler = 1,000,000.0/2 = 500,000.0 o 500KHz
Ahora esta frecuencia Fout pre-escaler la dividimos por la frecuencia del sampling y obtenemos a cuanto tenemos que cargar el TMR0, esto es:
TMR0= Fout pre-escaler/ Fsampling =500,000.0/5,000.0 = 100
Por ultimo 256-100= 156 por el cual está dentro del rango a cargar el TMR0, por el cual es el valor a cargar (156).
Bueno espero que me puedan corregir si es que en esto estoy mal, por favor.
Ahora tengo otra duda y es con respecto a por ejemplo tengo una frecuencia de 67Hz, el cual me da TMR0 = a 149.25, esto quiere decir que no voy a tener la frecuencia de salida perfecta, ahora ¿Cómo puedo compensar este delta de frecuencia, para obtener los 67.0Hz?
Espero que me puedan ayudar y recobrar lo que mencione aquí
-
Los 200us son lo que se tiene que demorar el pic en entregarle al DAC las 50 combinaciones para formar un periodo de la frecuencia senoidal de salida del DAC.
Decir esto es equivalente a decir que el periodo de tu señal es T=1/200uS. y no es asi. Esos 200uS es cada cuanto debes entregar un solo dato al DAC. 200uS*50=10mS y este si es el periodo de tu señal
-
:mrgreen: see tienes razón......
modifico para que no se preste para confusiones entonces......
-
no entré en calculos, pero usando este (http://www.todopic.com.ar/foros/index.php?topic=19454.0) programa, si se puede hacer una interrupcion exactamente a 200uS
pd. :D habia leido mal. la precarga que calculaste es correcta
-
pero es raro, a pesar que me he desligado del simulador proteus, ahora lo tengo que usar devido a que en este momento no tengo las fuente de -Vcc para configurar el op-amp con el DAC, y en este me da otra frecuencia al cargar el TMR0 con el valor que digo.
proteus o yo ??
-
De alguna manera se podria generar los valores de seno ahi mismo en el pic y no generarla externamente?
me refiero a que por ejemplo evaluar la funcion seno para determinado numero de valores y que se guarden en una arreglo de datos.
-
Hay una manera de calcular los valores seno con poca precisión y mucha rapidez. Se puede hacer con un polinomio:
sen(x) = 0.985270841034*x -0.142426981992*x^3
Error absoluto = 0.0046 Error relativo = 1.4%
O con este otro polinomio:
sen(x) = 0.99401986481*x -0.147131487165*x^3
Error absoluto = 0.0088 Error relativo = 0.88%
Este es aún mejor:
sen(x) = 0.999693019613*x -0.165666997546*x^3 +0.0075124058164*x^5
Error absoluto = 0.000069 Error relativo = 0.031% (1/3257)
El valor de x debe estar en radianes.
Saludos.
-
Aún hay una forma más exacta de calcular el seno y el coseno y es calculando sólo los primeros 45º
si (x < 45º) sen(x) = sen(x)
si (x > 45º) sen(x) = cos(90 - x)
Los polinomios aproximadores de sen(x) y cos(x) en el intervalo de 0 a pi/4 (45º) son los siguientes:
sin(x) = 0.999027139959*x -0.160334759967*x^3
Error absoluto = 0.00015 Error relativo = 0.097%
cos(x) = 0.998058565503 -0.474755983075*x^2
Error absoluto = 0.0019 Error relativo = 0.27%
Para x en radianes.
Saludos.
-
Se pueden calcular los polinomios con rapidez de la siguiente manera:
partiendo de este polinomio:
sin(x) = 0.999027139959*x -0.160334759967*x^3
se puede calcular:
xx = x*x
sin(x) = x*(0.999027139959 - xx*0.160334759967)
Sólo hacen falta tres multiplicaciones y una resta en coma flotante. Se puede realizar con coma flotante de 24bits para mayor rapidez.
Saludos.
-
Buena informacion Picuino, se agradece.
-
Excelente.
Bueno como ando en esto de que quiero hacer un sistema time interleaved con DAC ( es mas comun con ADC ).
time interleaved (http://userver.ftw.at/~vogel/TIADC.html)
entonces necesito hacer lo siguiente , sacar valores o partes del valor de seno por las DACs cumpliendo esta ecuacion Y= DAC1 + DAC2.
pongo un ejemplo espero ser claro y me entiendan.
Y= 10 *sen (2Pi*F*T)
con una frecuencia deseada por ejemplo F=100.
por ejemplo con un T = [0..8 nano segundos ]
ahora tengo T=0 Y=0 DAC1 = 0 DAC2= 0 . aquí inicio en tiempo=0, mantengo DAC1=0.
T=1 Y=5.87 DAC1= 0 DAC2= 5.87 aqui hago DAC2= Y (5.87) -DAC1 (0) = 5.87.
T=2 Y=9.51 DAC1= 3.64 DAC2= 5.87 se matiene 5.87 Y hago DAC1=Y-DAC2.
T=3 Y=9.51 DAC1= 3.64 DAC2= 5.87 se mantiene 3.64 y hago DAC2=Y-DAC1.
T=4 Y=5.87 DAC1= 0 DAC2=5.87 se mantiene 5.87 y hago DAC1=Y-DAC2
Y asi sucesivamente.
estoy trabajando sobre un PIC18f4550.
no encuentro la manera o bueno estoy bloqueado , no quiero q me hagan mi código ni nada por el estilo solo una ayudadita para poder empezar , habia pensado algo como esto:
For (y=0;y<=T,y++)
{
Y= sin (2*Pi*F*T)
If Y=PAR then
Y= DAC1
DAC2= Y-DAC1
if Y=Impar then
Y=DAC2
DAC1=Y-DAC2
salida_puertob(DAC1)
salida_puertod(DAC2)
}
Obvio este Pseudo-pseudo codigo no cumple con el algoritmo que mencione anteriormente , como podria hacer para ir sabiendo como voy a ir intercalando cada DAC con su valor correcto... una pista?
-
Hola , genere dicho codigo del problema que habia mencionado . en matlab sale pero no puedo pasar de matlab a pic cc no se por que razon
adjunto mi codigo en PICC
#include <18f4550.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT
#use delay (clock = 48000000)
#use fast_io (B)
#use fast_io (D)
#define PI
#include <C:\Program Files (x86)\PICC\Drivers\MATH.h>
#define mili 0.001
float f =100;
float amplitud =10;
float periodo=100;
float y;
int t;
int x;
float DAC1;
float DAC2;
void main ()
{
set_tris_b(0x00);
set_tris_d(0x00);
setup_adc( ADC_CLOCK_INTERNAL );
set_adc_channel( 0 );
setup_adc_ports( ALL_ANALOG );
delay_us (50);
periodo = read_adc ();
DAC1=0;
DAC2=0;
t=0;
while (1)
{
t=++
x = t*mili;
y = amplitud*(sin (2*PI*f*x));
if (t%2==0)
{
DAC2 = y - (DAC1);
output_B(DAC2);
}
if (t%2!=0)
{
DAC1 = y - (DAC2);
output_d(DAC1);
}
}
}
-
Estimados, yo tengo una duda de como generar una tabla para lo siguiente:
Tengo un dac de 7 bit hecho con una red r2r por lo que mi dac va a variar entre 0 y 127 cierto? yo quería hacer una seno de 50Hz con 128 valores. para ello tengo un timer que me interrumpe cada 156 uSeg. Entonces cada 156 uSeg mando un dato al dac. Ahora me imagine que si usamos excel se puede simplificar la cosa y pensé en lo siguiente :
"[127xSen(wt) + 127]/2"
w = 2pif
t = tiempo
f = 50Hz
w = 314
Ahora como debería hacer variar a t? voy bien por éste camino?. Espero me ayuden.
Saludos!!