Buenas, soy nuevo en esto y supongo que mis dudas seran bastante básicas pero llevo tiempo dándole vueltas y no encuentro solución. Explico primero mi programa y de que va para que se entienda bien y luego especifico mis dudas.
Estoy haciendo un proyecto sobre un seguidor solar que se autoposiciona y primero estoy probando con programas para simular lo que hará el seguidor. El seguidor solar para autoposicionarse se ayuda de 2 sensores colocados perpendicularmente entre si para saber si el seguidor, por ejemplo, tiene que girar hacia la izquierda o hacia la derecha (dependiendo donde tengamos menos luz); la comparación se hace mediante una tensión de referencia 2.5V y si el sol esta más a la derecha o más a la izquierda pues al puerto analógico le llegará un valor menor de 2.5V o mayor de 2.5V y entonces tendrá que encender un LED y sacará un PWM con un duty cycle u otro para mover el motor hacia al derecha o hacia la izquierda. El seguidor consta de Finales de Carrera para que no se exceda en posición; cuando un final de carrera se pone a estado alto se paran el motor (los dos LED's).
No detallo el control del motor o la obtención de la señal analógica a comparar porque como he dicho, este es un programa de prueba y no el programa real y la información esta es irrelevante a mi parecer.
Detallo los pines:
B7 y B6: Finales de Carrera
B1 y B3: motor a izquierda y motor a derecha
AN0: entrada analógica de 0 a 5 V
Programa:
#include <16F877.h>
#device adc=10 // resolución 1024 bits del ADC, 512=2.5V
#FUSES HS // configuración fusibles
#FUSES NOWDT
#FUSES NOBROWNOUT
#FUSES NOPROTECT
#FUSES NOPUT
#FUSES NOLVP
#FUSES NOCPD
#FUSES NOWRT
#FUSES NODEBUG
#use delay(clock=16000000) // reloj externo utilizado
#use fast_io(A)
#use fast_io(B)
#byte port_a=5
#byte port_b=6
#org 0x1F00,0x1FFF{} // para proteger el código
// inicializacion variables
float value1=0x00;
int i=0;
// subrutina de lectura del ADC
void lectura_adc(){ //función de lectura del ADC y su respectiva configuración
setup_adc(ADC_CLOCK_INTERNAL);
delay_ms(1);
setup_adc_ports(AN0);
delay_ms(1);
set_adc_channel(0);
delay_ms(1);
value1=(float)read_adc();
delay_ms(1);
setup_adc(ADC_OFF);
}
//main
void main(){ //configuración PORTA y PORTB, timer2 (para el periodo del PWM) y el módulo CCP como PWM
set_tris_a(0xFF);
set_tris_b(0xF0);
setup_timer_2(T2_DIV_BY_16,255,16);
setup_ccp1(CCP_PWM);
inicio:
while(i!=20){ //parpadeo de 2 LED's cada 250ms, durante un total de 10S ((250ms+250ms)*20)
bit_set(port_b,1)
delay_ms(250);
bit_clear(port_b,1);
bit_set(port_b,3);
delay_ms(250);
bit_clear(port_b,3);
i++;
}
i=0;
do{
while((!input(PIN_B6))&&(!input(PIN_B7))){ // mientras no se produzca las "interrupciones" a estado alto del PIN B6 o el B7 haz:
lectura_adc();
if(value1<(512)){ // si el valor del ADC está por debajo de 2.5V haz:
bit_clear(port_b,3);
delay_ms(1);
bit_set(port_b,1);
delay_ms(1);
set_pwm1_duty(51); // duty cycle del PWM del 20%
}
if(value1>=(512)){ // si el valor del ADC está por encima o igual a 2.5V haz:
bit_clear(port_b,1);
delay_ms(1);
bit_set(port_b,3);
delay_ms(1);
set_pwm1_duty(204); // duty cycle del PWM del 80%
}
delay_ms(5000); // delay 5s
}
// si se produce la "interrupción" de B6 o de B7 haz esto:
bit_clear(port_b,1);
bit_clear(port_b,3);
delay_ms(5000); // delay 5s
goto inicio;
}while(TRUE);
}
Las dudas:
1. Este programa ha sido compilado y cargado al PIC y funciona salvo que cuando ha hecho la comparación los delays no son de 5s como yo he puesto sino que si se da una condicion me tarda cosa de unos 10s u 11s y si se da la otra me tarda menos de 5s. También cuando el pin B6 o B7 se ponen a estado alto el tiempo que tarda para volver a inicio: es menor a 5s.
Alguien me puede decir a que se deben esas variaciones de tiempo? Existe alguna manera de saber el tiempo real que tardará en frente al valor que le de al delay_ms(X)?
2. El periodo del PWM que tengo segun la configuracion del timer2 (no lo he calculado, sino que me lo han dicho) es de 1 ms visto en un osciloscopio, ahora bien, he buscado como calcular el periodo del PWM para variarlo. Se que mi preescaler y postscaler son 16 pero no m salen los cálculos.
La fórmula es esta verdad? --> Tpwm=[(PR2)+1]*4*Tosc*(PMR2 valor preescalado)
Que cojo como Tosc? Y como PR2 y PMR2?
3. Se que la lecutra de cada instrucción del PIC dura 200ns pero he estado buscando en el datasheet y nose cuanto puede durar por ejemplo activar el ADC o leer el ADC (read_adc()). Como puedo saber cuanto dura cierta instrucción para poner posteriormente un delay tal que de tiempo a acabarse la instrucción anterior y que empiece la siguiente sin problema?
Espero no haber sido muy pesado y que mis dudas sean de ayuda para alguien más. También decir que he utilizado el buscador y no he visto alguna duda como la mía. Como ya he dicho soy princpipiante en esto de la programación de PIC's y espero que alguien me pueda dedicar unos minutillos para aclararme.
Muchas gracias de antemano. Hasta pronto.