Control de 8 servos con PIC
Este proyecto consiste en el control de 8 servos por el puerto c del pic.
Puedes ver un artículo del control de 4 servos en: http://www.pesadillo.com/pesadillo/?p=9309
En la interacción para el control de los servos se emplea un teclado numérico y un lcd, ambos controlados por el puero b del PIC.
En su funcionamiento, el pic pide introducir el número del servo a controlar. Posteriormente solicita el ángulo de orientación deseado para ese servo ( de 0º a 180º). El valor se acepta con la tecla “*” y el programa vuelve a mostrar un mensaje de presentación para un nuevo control. Si el ángulo introducido es superior a 180º, el pic toma por defecto 180º.
Para la generación de las señales moduladas de control de los servos (bit_pwmx), se emplea la subrutina de interrupción por rebose del timer 0. La orientación de cada servo se establece con el valor que se carga en la variable pwmx, donde x es el número de servo correspondiente. Con cada llamada a la subrutina de generación de la señal por mediación de la interrupción del timer 0, se incrementa la variable control_pwm que comparandose con el valor en pwmx, decide si debe o no cortar alguno de los pulsos de modulación de los servos.
control_pwm++;
if (control_pwm==0) bit_pwm0=1;
if (control_pwm==pwm0) bit_pwm0=0;
Cuando la variable control_pwm, incrementandose en cada rebose del timer0, llega a su máximo valor y pasa a ser 0, todas las señales moduladas comienzan un nuevo ciclo.
Para interpretar los valores numéricos de varias cifras a partir de números simples introducidos por teclado, primero espera a que se pulse una tecla
x=kbd_getc();
el valor obtenido está en codificación ASCII por lo que habrá que pasarlo a su valor numérico decimal
tecla=x-48;
si se ha pulsado una tecla se descartan las pulsaciones en # y * puesto que solo se necesitan números
if (x!=0&&x!=’*'&&x!=’#'){
y conforme se van pulsando números el último pulsado será las unidades y los anteriores van pasando a decenas y centenas
centenas=decenas;
decenas=unidades;
unidades=tecla;
conforme se van introduciendo números simples se va mostrando el número completo por pantalla lcd
printf(lcd_putc,”\f Angulo = %ld%d%d\n”, centenas, decenas, unidades);
y finalmente se guarda en una única variable el número completo resultante de todos los números simples
angulo=(centenas*100)+(decenas*10)+unidades;
Codigo fuente:
//////////////////////////////////////////////////////////////////////////////// // // // CONTROL DE 8 SERVOS CON PIC // // // // (c) RobotyPic // // // //////////////////////////////////////////////////////////////////////////////// #include <16f876a.h> //archivo para control del pic 16f876a #fuses XT,NOWDT,NOPROTECT,NOLVP //protecciones #use delay(clock=4000000) //frecuencia de reloj 4 MHz #byte trisb=0x86 #byte portb=0x06 #byte trisc=0x87 #byte portc=0x07 #define use_portb_lcd TRUE //Configuración puerto b control lcd #define use_portb_kbd TRUE //Configuración puerto b control teclado #include <lcd.c> //archivo para control del lcd #include <kbd.c> //archivo para control del teclado #bit Bit_PWM0 = PORTC.0 //Bit 0 puerto C Salida modulación 0 #bit Bit_PWM1 = PORTC.1 //Bit 1 puerto C Salida modulación 1 #bit Bit_PWM2 = PORTC.2 //Bit 2 puerto C Salida modulación 2 #bit Bit_PWM3 = PORTC.3 //Bit 3 puerto C Salida modulación 3 #bit Bit_PWM4 = PORTC.4 //Bit 4 puerto C Salida modulación 4 #bit Bit_PWM5 = PORTC.5 //Bit 5 puerto C Salida modulación 5 #bit Bit_PWM6 = PORTC.6 //Bit 6 puerto C Salida modulación 6 #bit Bit_PWM7 = PORTC.7 //Bit 7 puerto C Salida modulación 7 /********************** Prototipos de las funciones ***************************/ void main (void); //función principal void generacion_pwm (void); //genera señales moduladas para control de servos void presentacion (void); //mensaje de presentación /********************** Variables para generación PWM *************************/ int8 PWM0=0,PWM1=0,PWM2=0,PWM3=0,PWM4=0,PWM5=0,PWM6=0,PWM7=0; //Valores de las señales PWM int8 control_PWM=0; /******************************************************************************/ /******************* FUNCIÓN GENERACIÓN MODULACIONES PWM **********************/ #int_Timer0 void generacion_pwm(){ control_PWM++; //Incremento cada rebose del timer0 if (control_PWM==0){ //inicio del ciclo con todos los pulsos pwm a 1 Bit_PWM0=1; Bit_PWM1=1; Bit_PWM2=1; Bit_PWM3=1; Bit_PWM4=1; Bit_PWM5=1; Bit_PWM6=1; Bit_PWM7=1; } //Finalizará el pulso de modulación según el valor del correspondiente pwm if (control_PWM==PWM0) Bit_PWM0=0; if (control_PWM==PWM1) Bit_PWM1=0; if (control_PWM==PWM2) Bit_PWM2=0; if (control_PWM==PWM3) Bit_PWM3=0; if (control_PWM==PWM4) Bit_PWM4=0; if (control_PWM==PWM5) Bit_PWM5=0; if (control_PWM==PWM6) Bit_PWM6=0; if (control_PWM==PWM7) Bit_PWM7=0; set_timer0(255); //Carga del contador } /******************************************************************************/ /************************* PRESENTACIÓN LCD ***********************************/ void presentacion (){ lcd_putc("\f Introduce \n"); lcd_putc(" num. de servo "); } /******************************************************************************/ /******************** FUNCIÓN PRINCIPAL ***************************************/ void main(){ int x; //Valor ASCII de la tecla pulsada int tecla; //Valor numérico de la tecla pulsada int servo; //Número de servo int16 angulo; //Ángulo del servo int16 centenas; //variable para las centenas del ángulo int decenas,unidades; //Variable para las decenas y unidades del ángulo int pwm; //valor de la modulación por teclado trisc=0x00; //Puerto C como salida de datos pwm0=7; //Impulso de 0,8 msg de pwm0 posición 0º pwm1=7; //Impulso de 0,8 msg de pwm1 posición 0º pwm2=7; //Impulso de 0,8 msg de pwm2 posición 0º pwm3=7; //Impulso de 0,8 msg de pwm3 posición 0º pwm4=7; //Impulso de 0,8 msg de pwm4 posición 0º pwm5=7; //Impulso de 0,8 msg de pwm5 posición 0º pwm6=7; //Impulso de 0,8 msg de pwm6 posición 0º pwm7=7; //Impulso de 0,8 msg de pwm7 posición 0º setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32); //Configuración interrupción generación PWM enable_interrupts(INT_TIMER0); //Habilitación interrupción generación pwm enable_interrupts(GLOBAL); //Habilitación de las interrupciones port_b_pullups(TRUE); //Habilitación resistencias pullups puerto b lcd_init(); //Inicialización del lcd kbd_init(); //Inicialización del teclado presentacion (); //Muestra mensaje de inicio en lcd while (true){ x=kbd_getc(); //En "x" valor ASCII de la tecla pulsada if (x!=0&&x!='9'&&x!='8'&&x!='*'&&x!='#'){ //Si se pulsa tecla numérica 0 a 7 ... servo=x-48; //Valor ASCII se pasa a valor numerico de servo printf(lcd_putc,"\fServo = %d\n", servo); //...muestra el valor pulsado lcd_putc("Introduce angulo"); while (x!='*'){ //Espera a introducir ángulo y aceptar con * x=kbd_getc(); tecla=x-48; if (x!=0&&x!='*'&&x!='#'){ //Solo se toman los valores numéricos //A cada tecla pulsada se desplaza posición decimal y se muestra centenas=decenas; decenas=unidades; unidades=tecla; printf(lcd_putc,"\f Angulo = %ld%d%d\n", centenas, decenas, unidades); lcd_putc(" * para aceptar"); } } angulo=(centenas*100)+(decenas*10)+unidades; if (angulo>180) angulo=180; //No acepta valores >180º pwm=(angulo/13)+7; //Ajuste modulación en función del valor introducido centenas=decenas=unidades=0; //Según número de servo introducido se le aplica el ángulo elegido switch(servo){ case 0: pwm0=pwm; break; case 1: pwm1=pwm; break; case 2: pwm2=pwm; break; case 3: pwm3=pwm; break; case 4: pwm4=pwm; break; case 5: pwm5=pwm; break; case 6: pwm6=pwm; break; case 7: pwm7=pwm; break; } printf(lcd_putc,"\fServo %d\n", servo); printf(lcd_putc," Angulo %ld", angulo); delay_ms(200); presentacion(); } } }
Ficheros: http://dfiles.eu/files/5wb4slfmx
Tuitear 6.819 Veces leído 0 comentarios |
9 septiembre 2013 en Electronica | tags: Circuitos electrónicos, Electronica |