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
|
|
![]() | 9 septiembre 2013 en Electronica | tags: Circuitos electrónicos, Electronica |









![Esquema+control+8+servos+con+pic[1]](http://www.pesadillo.com/pesadillo/wp-content/uploads/2013/09/Esquema+control+8+servos+con+pic1.png)












