////////////////////////////////////////////////////////////////////////////////
// //
// CONTROL DE SERVOS //
// //
// PIC principal //
// //
// http://robotypic.blogspot.com/ // //
// RobotyPic 2013 (c) //
// //
////////////////////////////////////////////////////////////////////////////////
#include <16F876a.h>
#use delay(clock=4000000)
#fuses XT, NOWDT, BROWNOUT, NOPUT, NOPROTECT, NOLVP, NOCPD, NOWRT, NODEBUG
#use i2c(Master,fast,sda=PIN_C4,scl=PIN_C3,force_sw)
#use fast_io(a)
#use fast_io(B)
#use fast_io(C)
#define use_portb_lcd TRUE //Configuración puerto b control lcd
#include <lcd.c> //archivo para control del lcd
#define servo1 1
#define Servo2 2
#define Servo3 3
#define Servo4 4
#define Servo5 5
#define Servo6 6
#define Servo7 7
#define Servo8 8
#define Servo9 9
#define Servo10 10
#define Servo11 11
#define Servo12 12
#define Servo13 13
#define Servo14 14
#define Servo15 15
#define Servo16 16
#define Servo17 17
#define Servo18 18
#define servo19 19
#define Servo20 20
#define PICServos_ID 0xA0; //Dirección I2C de acceso al PIC controlador de servos
/************************ Variables globales **********************************/
int posicion=0; //Variable para registro de posición del servo
int direccion=0; //Variable para dirección I2C de acceso a los servos
int servo=0; //Variable para registro de número de servo
int velocidad=0; //Variable para registro de velocidad de movimiento
/******************************************************************************/
/************* FUNCIÓN ESCRITURA EN PIC CONTROLADOR DE SERVOS *****************/
void PicServos_I2C(direccion, servo, posicion, velocidad){
i2c_start(); // Comienzo comunicación
i2c_write(direccion); // Dirección del esclavo en el bus I2C
i2c_write(servo); // Servo que se controlará en el esclavo
i2c_write(posicion); // Posición del servo controlado
i2c_write(velocidad); // Velocidad de cambio del servo
i2c_stop(); // Fin comunicación
delay_ms(10);
}
/******************************************************************************/
/************************* FUNCIÓN ESCRITURA LCD ******************************/
void LCD_display () {
float grados;
grados= (4.5 * (posicion-20));
printf(lcd_putc,"\fServo %d Vel. %u", servo, velocidad);
printf(lcd_putc,"\n Angulo = %3.1f\337", grados);
}
/******************************************************************************/
/*************************** FUNCIÓN PRINCIPAL ********************************/
void main(){
port_b_pullups(TRUE); //Habilitación resistencias pullups puerto b
lcd_init(); //Inicialización del lcd
delay_ms(1000);
while(true){
//Control servo 3. Pos.0º Velocidad 60
direccion=PICServos_ID; //Dirección PIC servos
servo=servo3; //nº de servo
posicion=20; //Registro de Posición servo de 20 (0º) a 60 (180º)
velocidad=60; //Registro de velocidad (de 0 a 255)
PicServos_I2C(direccion, servo, posicion, velocidad);
LCD_display (); //Muestra información enviada en LCD
delay_ms(3000); //Retardo hasta movimiento siguiente servo
//Control servo 3. Pos.180º Velocidad 200
direccion=PICServos_ID; //Dirección PIC servos
servo=servo3; //nº de servo
posicion=60; //Registro de Posición servo de 20 (0º) a 60 (180º)
velocidad=200; //Registro de velocidad (de 0 a 255)
PicServos_I2C(direccion, servo, posicion, velocidad);
LCD_display (); //Muestra información enviada en LCD
delay_ms(3000); //Retardo hasta movimiento siguiente servo
//Control servo 3. Pos.0º Velocidad máxima
direccion=PICServos_ID; //Dirección PIC servos
servo=servo3; //nº de servo
posicion=20; //Registro de Posición servo de 20 (0º) a 60 (180º)
velocidad=0; //Registro de velocidad (de 0 a 255)
PicServos_I2C(direccion, servo, posicion, velocidad);
LCD_display (); //Muestra información enviada en LCD
delay_ms(3000); //Retardo hasta movimiento siguiente servo
//Control servo 3. Pos.117º Velocidad máxima
direccion=PICServos_ID; //Dirección PIC servos
servo=servo3; //nº de servo
posicion=46; //Registro de Posición servo de 20 (0º) a 60 (180º)
velocidad=200; //Registro de velocidad (de 0 a 255)
PicServos_I2C(direccion, servo, posicion, velocidad);
LCD_display (); //Muestra información enviada en LCD
delay_ms(3000); //Retardo hasta movimiento siguiente servo
//Control servo 6. Pos.63º Velocidad 60
direccion=PICServos_ID; //Dirección PIC servos
servo=servo6; //nº de servo
posicion=34; //Registro de Posición servo de 20 (0º) a 60 (180º)
velocidad=60; //Registro de velocidad (de 0 a 255)
PicServos_I2C(direccion, servo, posicion, velocidad);
LCD_display (); //Muestra información enviada en LCD
delay_ms(3000);
//Control servo 6. Pos.180º Velocidad 60
direccion=PICServos_ID; //Dirección PIC servos
servo=servo6; //Nº de servo
posicion=60; //Registro de Posición servo de 20 (0º) a 60 (180º)
velocidad=60; //Registro de velocidad (de 0 a 255)
PicServos_I2C(direccion, servo, posicion, velocidad);
LCD_display (); //Muestra información enviada en LCD
delay_ms(3000);
//Control simultáneo de varios servos
//Control servo 3. Pos.180º
direccion=PICServos_ID; //Dirección PIC servos
servo=servo3; //nº de servo
posicion=200; //Registro de Posición servo de 20 (0º) a 60 (180º)
velocidad=255; //Registro de velocidad (de 0 a 255)
PicServos_I2C(direccion, servo, posicion, velocidad);
//Control servo 1. Pos.180º
direccion=PICServos_ID; //Dirección PIC servos
servo=servo1; //nº de servo
posicion=60; //Registro de Posición servo de 20 (0º) a 60 (180º)
velocidad=200; //Registro de velocidad (de 0 a 255)
PicServos_I2C(direccion, servo, posicion, velocidad);
//Control servo 2. Pos.0º
direccion=PICServos_ID; //Dirección PIC servos
servo=servo2; //nº de servo
posicion=20; //Registro de Posición servo de 20 (0º) a 60 (180º)
velocidad=200; //Registro de velocidad (de 0 a 255)
PicServos_I2C(direccion, servo, posicion, velocidad);
LCD_display ();
delay_ms(3000);
//Control simultáneo de varios servos
//Control servo 3. Pos.180º
direccion=PICServos_ID; //Dirección PIC servos
servo=servo3; //nº de servo
posicion=60; //Registro de Posición servo de 20 (0º) a 60 (180º)
velocidad=0; //Registro de velocidad (de 0 a 255)
PicServos_I2C(direccion, servo, posicion, velocidad);
//Control servo 1. Pos.81º
direccion=PICServos_ID; //Dirección PIC servos
servo=servo1; //nº de servo
posicion=38; //Registro de Posición servo de 20 (0º) a 60 (180º)
velocidad=0; //Registro de velocidad (de 0 a 255)
PicServos_I2C(direccion, servo, posicion, velocidad);
//Control servo 2. Pos.90º
direccion=PICServos_ID; //Dirección PIC servos
servo=servo2; //nº de servo
posicion=40; //Registro de Posición servo de 20 (0º) a 60 (180º)
velocidad=0; //Registro de velocidad (de 0 a 255)
PicServos_I2C(direccion, servo, posicion, velocidad);
delay_ms(4000);
}
}
////////////////////////////////////////////////////////////////////////////////
// //
// MÓDULO CONTROLADOR DE 20 SERVOS CON PIC v1.1 //
// //
// //
// http://robotypic.blogspot.com/ //
// (c) RobotyPic 2015 //
// //
////////////////////////////////////////////////////////////////////////////////
#include <16f876a.h> //archivo para control del pic 16f876a
#FUSES NOWDT, HS, NOPUT, NOPROTECT, NOCPD, NOBROWNOUT, NOLVP, NODEBUG, NOWRT
#use delay(clock=20000000) //frecuencia de reloj 20 MHz
#use i2c(SLAVE, fast, SDA=PIN_C4, SCL=PIN_C3, address=0xA0)
#byte trisb=0x86
#byte portb=0x06
#byte trisc=0x87
#byte portc=0x07
#byte trisa=0x85
#byte porta=0x05
#bit Bit_PWM1 = PORTB.0 //Bit 0 puerto B Salida modulación 0
#bit Bit_PWM2 = PORTB.1 //Bit 1 puerto B Salida modulación 1
#bit Bit_PWM3 = PORTB.2 //Bit 2 puerto B Salida modulación 2
#bit Bit_PWM4 = PORTB.3 //Bit 3 puerto B Salida modulación 3
#bit Bit_PWM5 = PORTB.4 //Bit 4 puerto B Salida modulación 4
#bit Bit_PWM6 = PORTB.5 //Bit 5 puerto B Salida modulación 5
#bit Bit_PWM7 = PORTB.6 //Bit 6 puerto B Salida modulación 6
#bit Bit_PWM8 = PORTB.7 //Bit 7 puerto B Salida modulación 7
#bit Bit_PWM9 = PORTC.0 //Bit 0 puerto C Salida modulación 0
#bit Bit_PWM10 = PORTC.1 //Bit 1 puerto C Salida modulación 1
#bit Bit_PWM11 = PORTC.2 //Bit 2 puerto C Salida modulación 2
#bit Bit_PWM12 = PORTC.5 //Bit 5 puerto C Salida modulación 5
#bit Bit_PWM13 = PORTC.6 //Bit 6 puerto C Salida modulación 6
#bit Bit_PWM14 = PORTC.7 //Bit 7 puerto C Salida modulación 7
#bit Bit_PWM15 = PORTA.0 //Bit 0 puerto A Salida modulación 0
#bit Bit_PWM16 = PORTA.1 //Bit 1 puerto A Salida modulación 1
#bit Bit_PWM17 = PORTA.2 //Bit 2 puerto A Salida modulación 2
#bit Bit_PWM18 = PORTA.3 //Bit 3 puerto A Salida modulación 3
#bit Bit_PWM19 = PORTA.4 //Bit 4 puerto A Salida modulación 4
#bit Bit_PWM20 = PORTA.5 //Bit 5 puerto A Salida modulación 5
typedef enum {NOTHING,N_SERVO_READ,POSICION_READ,VELOCIDAD_READ} I2C_STATE;
I2C_STATE fState;
/********************** Prototipos de las funciones ***************************/
void main (void); //función principal
void generacion_pwm (void); //genera señales moduladas para control de servos
/********************** Variables para generación PWM *************************/
int8 PWM[21];
int8 pwm_servo[21];
int8 velocidad[21];
int16 control_PWM=0;
int8 n_servo;
int8 i;
/******************************************************************************/
/******************* FUNCIÓN GENERACIÓN MODULACIONES PWM **********************/
#int_TIMER0
void generacion_pwm(){
control_PWM=control_PWM+1; //Incremento cada rebose del timer0
if (control_PWM==550) control_PWM=0;
if (control_PWM==0){ //inicio del ciclo con todos los pulsos pwm a 1
Bit_PWM1=1;
Bit_PWM2=1;
Bit_PWM3=1;
Bit_PWM4=1;
Bit_PWM5=1;
Bit_PWM6=1;
Bit_PWM7=1;
Bit_PWM8=1;
Bit_PWM9=1;
Bit_PWM10=1;
Bit_PWM11=1;
Bit_PWM12=1;
Bit_PWM13=1;
Bit_PWM14=1;
Bit_PWM15=1;
Bit_PWM16=1;
Bit_PWM17=1;
Bit_PWM18=1;
Bit_PWM19=1;
Bit_PWM20=1;
}
//Finalizará el pulso de modulación según el valor del correspondiente pwm
if (control_PWM==PWM[1]) Bit_PWM1=0;
if (control_PWM==PWM[2]) Bit_PWM2=0;
if (control_PWM==PWM[3]) Bit_PWM3=0;
if (control_PWM==PWM[4]) Bit_PWM4=0;
if (control_PWM==PWM[5]) Bit_PWM5=0;
if (control_PWM==PWM[6]) Bit_PWM6=0;
if (control_PWM==PWM[7]) Bit_PWM7=0;
if (control_PWM==PWM[8]) Bit_PWM8=0;
if (control_PWM==PWM[9]) Bit_PWM9=0;
if (control_PWM==PWM[10]) Bit_PWM10=0;
if (control_PWM==PWM[11]) Bit_PWM11=0;
if (control_PWM==PWM[12]) Bit_PWM12=0;
if (control_PWM==PWM[13]) Bit_PWM13=0;
if (control_PWM==PWM[14]) Bit_PWM14=0;
if (control_PWM==PWM[15]) Bit_PWM15=0;
if (control_PWM==PWM[16]) Bit_PWM16=0;
if (control_PWM==PWM[17]) Bit_PWM17=0;
if (control_PWM==PWM[18]) Bit_PWM18=0;
if (control_PWM==PWM[19]) Bit_PWM19=0;
if (control_PWM==PWM[20]) Bit_PWM20=0;
set_timer0(244); //Carga del contador
}
/******************************************************************************/
/********************* FUNCIÓN TIEMPO DE RETARDO ******************************/
void retardo_servo (){
for (i=1; i<=20; ++i) {
if (PWM[i] != pwm_servo[i]) { //Si el servo no está en su posición...
if (PWM[i] > pwm_servo[i]) --PWM[i]; //...retrocede una posición...
else if (PWM[i] < pwm_servo[i]) ++PWM[i];//...o avanza una posición
delay_us(10*velocidad[i]); //Retardo movimiento de posición
}
}
}
/******************************************************************************/
/***************** FUNCIÓN INTERRUPCIÓN POR RECEPCION I2C *********************/
#INT_SSP
void ssp_interupt (){
byte incoming; //donde se recibe el byte que manda el maestro
fstate = i2c_isr_state(); //estado del bus tras la interrupción
if (fstate == 0x80) { //no hay dato recibido
}
else { //Sino es que hay dato en el bus I2C...
incoming = i2c_read(); //... lo lee
if (fState == NOTHING){ //Información recibida es aviso de que va mandar algo master
fState = N_SERVO_READ; //Siguiente información será nº de servo
}
else if (fState == N_SERVO_READ) { //Información recibida corresponde al nº de servo
n_servo = incoming; //Se guarda nº de servo
fState = POSICION_READ; //Siguiente información recibida será posicion
}
else if (fState == POSICION_READ) { //Información recibida corresponde a la posición
pwm_servo[n_servo] = incoming; //Se guarda posición de servo
fState = VELOCIDAD_READ; //Siguiente información será velocidad
}
else if (fState == VELOCIDAD_READ) { //Información recibida corresponde a velocidad
velocidad[n_servo] = incoming; //Se guarda velocidad
fState = NOTHING; //Siguiente información será aviso de nuevo envío del master
}
}
}
/******************************************************************************/
/******************** FUNCIÓN PRINCIPAL ***************************************/
void main(){
//Configuración I/O puertos
trisc=0b00011000;
trisb=0x00;
trisa=0x00;
//Posiciones iniciales de los servos 90º
for (i=1; i<=20; ++i) PWM[i]=40;
for (i=1; i<=20; ++i) pwm_servo[i]=40;
//Inicialización velocidades a valor máximo
for (i=1; i<=20; ++i) velocidad[i]=0;
//Configuración timer0 e interrupciones
setup_timer_0(RTCC_INTERNAL); //Configuración interrupción generación pwm
enable_interrupts(INT_TIMER0); //Habilitación interrupción generación pwm
enable_interrupts(INT_SSP); //Habilitación interrupción recepción I2C
enable_interrupts(GLOBAL); //Habilitación de las interrupciones
while (true){
retardo_servo ();
}
}
No hay comentarios:
Publicar un comentario