Controlando un Servomotor con un pic16f877, por medio de la interrupción del timer0.
Código que realice para entender el funcionamiento del servomotor, aclaro que no es la única forma de realizarlo, y no conozco cual sea la mejor, esta es la primera aplicación que realizo para controlar uno.Si crees que un poco de teoría no te vendrá mal te recomiendo este link: [Servomotor]. Bueno si ya conoces la teoría, o eres de los que creen que aquí ay que arriesgar, manos a la obra.
Estoy usando el pic16f877a, 3 botones, 1 lcd, y por su puesto un Servo.
Como ya sabemos la forma de controlar el servo es por medio de PWM, osea un tiempo en alto y otro en bajo, a una frecuencia de 50hz -Osea todo el ciclo completo cada 20mS-, mi servo es el de la imagen, usado en aeromodelismo, no cuenta con datasheet, -no tiene marca- y no hace un giro exacto de 180º, Su tiempo de operación ronda de los 0.7mS para 0º y 2.7mS para hacer un giro de -casi- 180º.
[Código]
[Descripción del código]
El objetivo del código es que al presionar un botón conectado al pin_B4 ponga en alto por 0.7mS el pin_B0 del pic y transcurrido ese tiempo mantenga ese pulso en bajo por 17.3mS, y repetir este proceso indefinidamente, asegurando el ciclo de trabajo por 20mS. -De similar forma para 90º y 180º con sus respectivos tiempos-.
La forma en la que logro esto es usando el timer0, el cual usando el oscilador de 20Mhz, iniciando el timer0 con un valor de 150 y con un preescaler de 4 obtengo que cada 100uS -0.1 mS- el timer0 desvordara y atenderá la interrupción llamada #int_timer0, dentro de esta interrupción ay una variable llamada cont, la cual contara las veces que desborda el timer0, dentro de esta misma función ay 3 condiciones, la primera reviza si el contador no a sobrepasado los 200 desvordamientos para no superar los 20mS (200 * 0.1mS = 20mS), una ves que sobrepase el contador se reinicia a 0, la otra condición es para poner el servo en la posición indicada por los botones, (B4, B5, B6). Por ejemplo si queremos ponerlo en 90º presionamos el boton B5, el cual tiene un valor de 15 en la variable pos la cual es checada en la segunda condición, la cual compara el valor cont con el valor pos y si cont es menor a pos pone en alto el pin_B0, y la tercera es cuando los dos valores son idénticos apaga esta señal por los 18.5mS restantes (185 desbordamientos).
[Vídeo]
Aquí la representación visual de todo lo dicho.
#include <16f877a.h> #use delay(clock=20000000) #fuses HS, NOWDT, NOLVP, NOPROTECT #define LCD_E PIN_d0 #define LCD_CK PIN_d1 #define LCD_DAT PIN_d2 #define LCD_LED PIN_d3 #include <3pins.c> #use fast_io(B) int cont=0; int pos=16; #int_timer0 void Pwm() { set_timer0(150); cont++; if(cont>=200) { cont=0; } if(cont<pos) { output_high(PIN_B0); } if(cont=pos) { output_low(PIN_B0); } } void main() { lcd_init(); set_tris_b(0b11111110); // Pin B0 como salida, setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4); // Preescaler de 4 EXT_INT_EDGE(l_TO_H); // se desborda de Alto a bajo enable_interrupts(INT_timer0); // Activar timer0 enable_interrupts(global); // Activar Interrupciones Globales set_timer0(150); while(1) { lcd_gotoxy(1,1); printf(lcd_putc,"Posicion: "); if(Input(Pin_b4)) delay_ms(100); if(Input(Pin_b4)) { pos=7; lcd_gotoxy(1,2); printf(lcd_putc," 0 Grados "); } if(Input(Pin_b5)) delay_ms(100); if(Input(Pin_b5)) { pos=15; lcd_gotoxy(1,2); printf(lcd_putc," 90 Grados "); } if(input(pin_b6)) delay_ms(100); if(Input(Pin_b6)) { pos=27; lcd_gotoxy(1,2); printf(lcd_putc," 180 Grados "); } } }
[Descripción del código]
El objetivo del código es que al presionar un botón conectado al pin_B4 ponga en alto por 0.7mS el pin_B0 del pic y transcurrido ese tiempo mantenga ese pulso en bajo por 17.3mS, y repetir este proceso indefinidamente, asegurando el ciclo de trabajo por 20mS. -De similar forma para 90º y 180º con sus respectivos tiempos-.
La forma en la que logro esto es usando el timer0, el cual usando el oscilador de 20Mhz, iniciando el timer0 con un valor de 150 y con un preescaler de 4 obtengo que cada 100uS -0.1 mS- el timer0 desvordara y atenderá la interrupción llamada #int_timer0, dentro de esta interrupción ay una variable llamada cont, la cual contara las veces que desborda el timer0, dentro de esta misma función ay 3 condiciones, la primera reviza si el contador no a sobrepasado los 200 desvordamientos para no superar los 20mS (200 * 0.1mS = 20mS), una ves que sobrepase el contador se reinicia a 0, la otra condición es para poner el servo en la posición indicada por los botones, (B4, B5, B6). Por ejemplo si queremos ponerlo en 90º presionamos el boton B5, el cual tiene un valor de 15 en la variable pos la cual es checada en la segunda condición, la cual compara el valor cont con el valor pos y si cont es menor a pos pone en alto el pin_B0, y la tercera es cuando los dos valores son idénticos apaga esta señal por los 18.5mS restantes (185 desbordamientos).
[Vídeo]