En esta práctica vamos a integrar la práctica del servomotor junto con la del ADC para que mediante un potenciómetro se varíe el voltaje de entrada a Miuva, y esto ocasione que el servomotor se mueva proporcionalmente al giro del potenciómetro.
Definiremos en una función de interrupción por desborde del timer0 el proceso para mandar el pulso deseado al servomotor, recordando que este debe de ser con un periodo de 20ms y el pulso en alto debe de durar entre 1 y 2ms.
Podemos ver las siguientes equivalencias de: Valor_digital -> Voltaje -> Tiempo en microsegundos
valor_digital -> Voltaje -> tiempo_alto
1023 -> 5V -> 1000
La conversión del dato digital a voltaje y a tiempo la podemos realizar de la siguiente forma:
Voltaje = valor_digital * 5.0 / 1023.0
tiempo_alto = voltaje * 1000.0 / 5.0
valor_digital = read_adc(); //Lee el ADC voltaje = 5.0*valor_digital/1024; //Convierte el ADC a voltaje TIEMPO_ALTO = voltaje * 1000.0/5.0; //Convierte el voltaje a un valor entre 0 y 10001
Entonces tendremos los valores en microsegundos para 0 y 1ms, por lo tanto si le sumamos 1000 a cada valor, tendremos el valor en microsegundos para 1 y 2ms que son justo los valores que necesitamos.
TIEMPO_ALTO = TIEMPO_ALTO + 1000; //Convierte a un valor entre 1000 y 2000
Este tiempo en alto se enviará al servomotor en la función de interrupción y posteriormente tendremos que calcular el tiempo que debe de tardar en desbordarse el timer0 para que haya pasado el periodo de 20ms.
Con esto podemos crear el siguiente código.
Código del programa
#include <18f46k22.h> // la librería del PIC #device ADC = 10 //Bits del ADC #fuses HSM,NOWDT,PUT,BROWNOUT, MCLR,NOLVP,NOXINST,NOWRT,PLLEN #use delay (clock=48M) //Seleccionamos la frecuencia de reloj de 48MHz #use standard_io(b) //preconfiguracion del puerto b int16 TIEMPO_ALTO, carga, adc_read; //Variables float v; //Variable flotante #int_TIMER0 //Funcion de interrupcion void TIMER0_isr(void){ output_high(PIN_C1); //PWM ON delay_us(TIEMPO_ALTO); //Tiempo que estará en alto en microsegundos output_low(PIN_C1); //PWM OFF carga = 20 - (TIEMPO_ALTO/1000); //Para calcular el tiempo de carga = carga*48000.0/32.0; //la precarga del timer0 carga = 65535 - carga; set_timer0(carga); //Precargar el timer0 } void main(){ setup_adc_ports(sAN0); //Configura A0 como analógico setup_adc(ADC_CLOCK_INTERNAL); //ADC con oscilador interno setup_timer_0(T0_INTERNAL|T0_DIV_8); //Configura Timer0 enable_interrupts(int_TIMER0); //Habilita interrupciones enable_interrupts(GLOBAL); set_timer0(0x8AD0); //Precarga del timer0 set_adc_channel(0); //Configura para ller A0 delay_us(20); //Retardo de 20us while(true){ adc_read = read_adc(); //Lee el ADC v = 5.0*adc_read/1024; //Convierte el ADC a voltaje TIEMPO_ALTO = v * 1000.0/5.0; //Convierte el voltaje a un valor //entre 0 y 1000 TIEMPO_ALTO = TIEMPO_ALTO + 1000; //Convierte a un valor entre 1000 y 2000 } }