TODOPIC

Microcontroladores PIC => Todo en microcontroladores PIC => Mensaje iniciado por: Keiper en 14 de Marzo de 2006, 12:28:00

Título: el muestreo es asi?
Publicado por: Keiper en 14 de Marzo de 2006, 12:28:00
Hola que tal, tengo un problema en mi programa que hace que no funcione correctamente.
Primero explicare lo que hace el programa: Rebotado
Adquiero una señal de audio "simétrica" que varia en funcion al movimiento de un motor, y hago la conversion.
Voy guardando el valor máximo encontrado durante un tiempo de 10 segundos. Pasado ese tiempo continuo adquiriendo esa señal, pero ahora quiero que cuando se encuentre un valor igual o mayor al máximo guardado el motor se detenga.
El programa funciona, pero creo que no todo lo bien que podría funcionar, y ahi van mis preguntas:
Que frecuencia de muestreo estoy obteniendo? Llorando
Se puede muestrear a mayor velocidad? ,obtener más muestras por periodo?
Gracias a todos.

#include <16F876.H>
#device ADC=10 //Directiva para obtener una resolucion de 10 bits.
#fuses XT, NOPROTECT, NOPUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD, WRT
#use Delay(Clock=4000000) //Reloj
#use RS232(BAUD=9600, BITS=8, PARITY=N, XMIT=PIN_C6, RCV=PIN_C7, RESTART_WDT)
long periodo=0;
float valor;

#INT_TIMER1 //Desbordamiento TMR1
void timer1()
{
set_timer1(64536); //Recarga TMR1 con 1ms como base de tiempo
periodo=periodo+1; //Incremento de la variable periodo
}

void motor() //Rutina para activación de motor
{
output_high(pin_b0); //pin_b0 y pin_b1 habilitan las señales del driver L239B
output_low(pin_b1);
output_high(pin_b2);
}

float conversion()
{
valor=read_adc();
valor=valor/204.8;
return(valor);
}

void main()
{
float maximo;
setup_adc_ports(RA0_ANALOG);
setup_adc(ADC_CLOCK_INTERNAL); //Configuracion del conversor A/D
set_adc_channel(0);
enable_interrupts(INT_TIMER1);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
enable_interrupts(GLOBAL);
set_timer1(64536);
maximo=0;

while(1)
{
while(periodo<10000) // temp=10 segundos
{
conversion();
if(valor>maximo)
{
maximo=valor; //Guarda en max el si es mayor que el anterior
output_high(pin_b5);
delay_ms(100);
output_low(pin_b5);
motor();
printf("VALOR MAXIMO= %f voltios
",maximo );
}
else
{
motor();
printf("Valor no maximo= %f voltios
",valor);
}
}
disable_interrupts(INT_TIMER1);
conversion();
while(valor<maximo)
{
conversion();
output_high(pin_b4);
motor();
printf("Buscando el valor maximo= %f voltios
", maximo);
}
setup_adc (adc_off); //Apaga ADC
output_high(pin_b5);
output_low(pin_b2);
printf("Valor maximo encontrado= %f voltios
", valor);
}
}
Título: RE: el muestreo es asi?
Publicado por: maunix en 14 de Marzo de 2006, 17:54:00
Si veo varias formas de mejorar ese software.

1) En la rutina de conversion,  no hagas esa división float! para que? intenta llevar todo a multiplicaciones o sumas o siquiera comparaciones de numeros enteros! esto lo realiza cientos de veces más rapido un pic que una divsión por coma flotante!

2) Para que hacer el delay de 100mseg y hacer titilar al led? Esto te pone una demora monstruosa cuando la señal va subiendo....  y creo que innecesaria.  
Si quieres velocidad y tambien hacer titilar el LED entonces te sigiero lo siguiente:

a) Inicializa tus variables.
b) Activa un timer cada 10mseg con interrupción.
c) Dispara una conversión A/D.
d) Dedicate tu software main todo el tiempo a leer el A/D.
e) Cuando leas el A/D guarda el valor y dispara la conversión del A/D sin leerla.
f) Compara el valor ese con el máximo (mientras el A/D esta convirtiendo el proximo valor) y activa una variable cuando se supere el máximo.
g) ir a d)


i) En la rutina de interrupción verificas si esa varaible se activó.  Si se activó, enciendes el led comienzas una cuenta hasta 10.  Al lllegar a 10 apagas el led y apagas la variable que indica que se superó el máximo


Saludos
Título: RE: el muestreo es asi?
Publicado por: Keiper en 15 de Marzo de 2006, 04:54:00
Hola maunix en primer lugar agradecer tu colaboracion, y en segundo ser un poco pesado pero es que voy perdidito y no acabo de entender  los pasos que me has citado:

b) Activa un timer cada 10mseg con interrupción.

Y en ese timer que se supone que debo declarar??es el mismo timer que me cuenta los 10 segundos??

c) Dispara una conversión A/D.

La conversion la debo realizar en una rutina, dentro de la interrupcion del timer o en el main??

e) Cuando leas el A/D guarda el valor y dispara la conversión del A/D sin leerla.

Que quiere decir esto??

f) Compara el valor ese con el máximo (mientras el A/D esta convirtiendo el proximo valor) y activa una variable cuando se supere el máximo.
 


i) En la rutina de interrupción verificas si esa varaible se activó. Si se activó, enciendes el led comienzas una cuenta hasta 10. Al lllegar a 10 apagas el led y apagas la variable que indica que se superó el máximo

En mi programa debo realiazar la cuenta de 10 segundos desde que comienza el programa no desde que encuentra un maximo, no entiendo bien esto ultimo

Agradezco todo el apoyo prestado!!!