Control de 8 servos con PIC

Este proyecto consiste en el control de 8 servos por el puerto c del pic. 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.
Esquema control 8 servos con 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.

Gráficas control servos con pic

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;


////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                    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();
      }
   }
}

En la simulación bajo proteus se comprueba el cambio en el tiempo de las señales de control de los servos individualmente en función del valor del ángulo introducido.







Titulo del aviso

Escribe tu mensaje

Recargar página