#include <16F876A.h>
#FUSES NOWDT
#fuses XT //Oscilador por cristal entre 4Mhz y 10Mhz
#fuses NOPROTECT
#use delay(clock=4000000) //Frecuencia del cristal oscilador 4MHz
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#priority rtcc
#byte PIR1=0x0C
#byte trisa=0x85
#byte porta=0x05
#byte trisb=0x86
#byte portb=0x06
#byte trisc=0x87
#byte portc=0x07
#define BIT_TEST_ON output_high(PIN_C0)
#define BIT_TEST_OFF output_low(PIN_C0)
#define AVANCE output_high(PIN_C2),output_high(PIN_C4),output_low(PIN_C3),output_low(PIN_C5)
#define RETROCESO output_low(PIN_C2),output_low(PIN_C4),output_high(PIN_C3),output_high(PIN_C5)
#define PARO output_low(PIN_C2),output_low(PIN_C4),output_low(PIN_C3),output_low(PIN_C5)
#define GIRO_DERECHA output_high(PIN_C2),output_low(PIN_C4),output_low(PIN_C3),output_high(PIN_C5)
#define GIRO_IZQUIERDA output_low(PIN_C2),output_high(PIN_C4),output_high(PIN_C3),output_low(PIN_C5)
#bit Bit_PWM = PORTB.7 //Bit 7 puerto B Salida modulación 1
/********************** Prototipos de las funciones ***************************/
void main (void); //función principal
void Generacion_pwm (void); //genera señales moduladas para control de servos
void pulso_test (void); //da pulso y calcula distancia al obstáculo
void ccp2_int (void); //mide pulso de eco ultrasonidos
void navegacion (void); //avance sorteando obstáculos
/********************** Variables para generación PWM *************************/
int8 PWM=0; //Guardará los valores de la señal PWM
int8 Pulso_pwm=0; //Ancho del pulso de control del servo
/******************** Variables para lectura obstáculo ************************/
int1 nuevopulso=0; //Entra otro pulso de lectura
int16 TFB=0,TFS=0,TF=0; //Tiempo flancos
float AP=0.0; //Valor del pulso del obstáculo en microsegundos
int16 distancia=0; //Valor distancia al obstáculo
int16 distancia_derecha=0;
int16 distancia_izquierda=0;
int1 cambio=0; //Control flanco subida o bajada del impulso leido
/******************************************************************************/
/******************* FUNCIÓN GENERACIÓN MODULACIONES PWM **********************/
#int_Timer0
void Generacion_pwm() {
Pulso_pwm++; //Incremento cada rebose del timer0
if (Pulso_pwm==0) {
Bit_PWM=1;
}
if (Pulso_pwm==PWM){
Bit_PWM=0;
}
delay_us(5);
set_timer0(255);
}
/******************************************************************************/
/*********************** FUNCIÓN PULSO DE TEST ********************************/
void pulso_test() {
enable_interrupts(INT_CCP2); //Habilitación interrupción para medida de pulso eco
BIT_TEST_ON; //salida de pulso test durante 10us por Bit 0 puerto C
delay_us(10);
BIT_TEST_OFF;
while(nuevopulso==0) //Espera a finalizar el pulso eco
{}
if(nuevopulso==1) { //Finalizado el pulso eco se calcula su valor.
TF=(TFB-TFS); //Valor entre pulso de subida y bajada.
AP=TF*1.0; //Valor pulso leido en us(obstáculo) de 100u a 25ms
AP = AP/58; //Distancia del obstáculo en cm
distancia =(int16)AP; //paso de flotante a entero largo
nuevopulso=0; //Listo para recibir nuevo pulso
}
disable_interrupts(INT_CCP2);
}
/******************************************************************************/
/************************ FUNCIÓN LECTURA OBSTÁCULO ***************************/
#int_ccp2 //LLamada por interrupción flanco en RC2
void ccp2_int() {
if(cambio==0) //Si es flanco de subida...
{
TFS=CCP_2; //Carga en valor flanco subida valor registro ccpr1
setup_ccp2(CCP_CAPTURE_FE); //Configuración modo captura en flanco de bajada
cambio=1; //Próximo flanco debe ser de bajada
}
else { //Si es flanco de bajada...
TFB=CCP_2; //Carga en valor flanco bajada valor registro ccpr1
setup_ccp2(CCP_CAPTURE_RE); //Configuración modo captura en flanco de subida
cambio=0; //Próximo flanco debe ser de subida
if(nuevopulso==0) //Fin de pulso...
nuevopulso=1; //Pulso finalizado.
}
}
/******************************************************************************/
/********************* FUNCIÓN AVANCE - DETECCIÓN OBSTÁCULO *******************/
void navegacion() {
pulso_test();
if (distancia>30) { //Si distancia >30cm avanza
AVANCE;
}
else {
PARO;
pwm=8;
delay_ms(700);
pulso_test();
distancia_derecha=distancia;
pwm=25;
delay_ms(700);
pulso_test();
distancia_izquierda=distancia;
pwm=16;
if (distancia_derecha>distancia_izquierda) {
GIRO_DERECHA;
delay_ms(500);
}
else {
GIRO_IZQUIERDA;
delay_ms(500);
}
}
}
/******************************************************************************/
/*************************** FUNCIÓN PRINCIPAL ********************************/
void main() {
trisb=0x00; //Puerto B todo salidas
trisc=0b00000010; //Puerto C definición de entradas y salidas
pwm=16; //Impulso de 1,5 msg de pwm posición 0º
PARO;
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32); //Configuración interrupción generación PWM
setup_timer_1(T1_INTERNAL); //Configuración timer1 para lectura obstáculo
setup_ccp2(CCP_CAPTURE_RE); //Configuración modo captura en flanco de subida
enable_interrupts(INT_TIMER0); //Habilitación interrupción generación pwm
disable_interrupts(INT_TIMER1);
disable_interrupts(INT_CCP2); //Deshabilitación interrupción modo comparación
enable_interrupts (GLOBAL);
delay_ms(500); //Estabilización en el arranque del sistema
while (1) {
delay_ms(500); //Tiempo entre impulsos test
navegacion(); //Salto a la función navegacion
}
}