/* MarkGuiver 1.0 - Mark-III implementation Copyright (C) 2008 Kabute & Kaderno & Rodland This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #define PIC_XTAL 20MHz #include __CONFIG(HS&UNPROTECT&PWRTEN&LVPDIS&WDTDIS&BOREN); //************************************************************************** // Definición de constantes //************************************************************************** #define Delay_us(x) { unsigned char _dcnt; \ _dcnt = (x)*((20)/(12)); \ while(--_dcnt != 0) continue; } #define FALSE 0 #define TRUE 1 #define EYE_R 0b010000 #define EYE_L 0b011000 #define LINE_R 0b00101000 // 101000 #define LINE_C 0b00110000 // 110000 #define LINE_L 0b00111000 // 111000 #define OFFSETR 0 #define OFFSETL 0 //************************************************************************** // Definición de variables //************************************************************************** union INTVAL { int i; char b[2]; }; //************************************************************************** // Variables //************************************************************************** bit segundo; unsigned char Reset; unsigned char i, cont; unsigned int lineL, lineC, lineR, media; int speedL, speedR; int eyeL, eyeR, k, j; unsigned long lineAvg; union INTVAL Temp, Total; const char *Mensaje="\r\nMARK III.\r\n"; //************************************************************************** // Gestion de interrupciones //************************************************************************** static void interrupt isr(void) //Aqui estan las funciones de interrupcion { if(TMR1IF) { if(RB2) { RB2=0; RB1=1; Temp.i=speedR; Total.i +=Temp.i; } else if(RB1) { RB2=0; RB1=0; Total.i=0x30D4 -Total.i; //20ms=12500(0x20D4) pulsos Temp.i=Total.i; } else if(!RB1 & !RB2) { RB2=1; Temp.i=speedL; Total.i =Temp.i; } else; Temp.i = 0xFFFF - Temp.i; //Hacemos el complementario. TMR1L=Temp.b[0]; TMR1H=Temp.b[1]; TMR1IF=0; if(cont++==5) { segundo=1; cont=0; } else; } else; } //*************************************************************************** // Funciones //*************************************************************************** void Delay_ms(unsigned char milliseg) { while(milliseg--) { Delay_us(250);Delay_us(250); Delay_us(250);Delay_us(250); } } void Delay_seg(unsigned char segundos) { while(!segundo); segundo=0; while(segundos--) { while(!segundo); segundo=0; } } //Envia un byte por el puerto serie void putchar(unsigned char c) { while(TXIF==0); TXREG=c; } // Lee un caracter por el puerto serie unsigned char getchar(void) { unsigned char c; while(RCIF==0); c=RCREG; return c; } //Envia una cadena de texto por el puerto serie void putstring(const char *s) { unsigned char i=0; if(TXEN==0) TXEN=1; while(s[i]!=0) { while(TXIF==0); TXREG=s[i]; i++; } } //Convierte un numero en una cadena de texto y envia por el puerto serie void putnum(unsigned int num ) { unsigned char buf[5]; int i = 0; unsigned char c; c=(unsigned char)(num % 10); c+='0'; buf[i] = c; i++; num /= 10; while (num != 0) { c=(unsigned char)(num % 10); c+='0'; buf[ i ] = c; i++; num /= 10; } while ( i > 0 ) { i--; putchar(buf[i]); } } // Escribe un dato en la memoria EEPROM en las direccion address void write_EE(unsigned char address, int data) { while(WR); // espera hasta que termina de escribir EEADR = address; // guardo la direccion EEDATA = data; // Cargo el dato que se va a escribir EEPGD = 0; // WREN = 1; // Activo escritura GIE = 0; // Desactivo interrupciones EECON2 = 0x55; // Requiere un ciclo de escritura EECON2 = 0xaa; // " WR = 1; // Escribo while(WR); // Espera hasta que termina de escribir GIE = 1; // Reactivo interrupciones WREN = 0; // Desactivo escritura } // Lee un valor integer como dos bytes de la EEPROM en la direccion address unsigned char read_EE(unsigned char address) { unsigned char data; EEADR = address; // Guardo la direccion EEPGD = 0; // RD = 1; // Leo data = EEDATA; // Guardo el dato leido return data; //Devuelvo el dato } void InitReset(void) { Reset=0x01; write_EE(0xFF, Reset); } //Lectura de puerto analógico (cambiamos de char a int HOYGAN!) unsigned int a2d(unsigned char pin) { // seleccionar pin ADCON0 = 0b10000001 | pin; //espera Delay_us(100); // inicio de conversion ADCON0 |= 0x04; // espera hasta completar while (ADCON0 & 0x04); return(ADRESH*256+ADRESL); } //Control del MotorR (direccion <0 avance,1 retroceso>, velocidad ) void MotorR(unsigned char dirR, int velR ) { if(dirR) speedR = 860 - (velR*2); else speedR = 860 + (velR*2); } //Control del MotorL (direccion <0 avance,1 retroceso>, velocidad ) void MotorL(unsigned char dirL, int velL ) { if(dirL) speedL = 845 + (velL*2); else speedL = 845 - (velL*2); } void test_motores(void) { unsigned char iter=0; for (iter = 0; iter <= 100; iter+=10) /* Avanza aumentando la velocidad */ { MotorR(0,iter); MotorL(0,iter); Delay_seg(3);} /* Ambos motores avanzan */ for (iter = 0; iter <= 2; iter++) { MotorR(0,100); MotorL(0,100); Delay_seg(3); } /* +Max */ for (iter = 0; iter <= 2; iter++) { MotorR(0,0); MotorL(0,0); Delay_seg(3); } /* Stop */ for (iter = 0; iter <= 100; iter+=10) /* Retrocede aumentando la velocidad */ { MotorR(1,iter); MotorL(1,iter); Delay_seg(3); } for (iter = 0; iter <= 2; iter++) { MotorR(1,100); MotorL(1,100); Delay_seg(3); } /* -Max */ for (iter = 0; iter <= 2; iter++) { MotorR(0,0); MotorL(0,0); Delay_seg(3); } /* Stop */ for (iter = 0; iter <= 100; iter+=10) /* gira sobre si mismo aumentando la velocidad */ { MotorR(0,iter); MotorL(1,iter); Delay_seg(3); } /* Motor izq avanza, motor dcho retrocede */ for (iter = 0; iter <= 2; iter++) { MotorR(0,100); MotorL(1,100); Delay_seg(3); } /* +-Max */ for (iter = 0; iter <= 100; iter+=10) /* Cambio de direcciones mientras gira */ { MotorR(1,iter); MotorL(0,iter); Delay_seg(3); } for (iter = 0; iter <= 2; iter++) { MotorR(1,100); MotorL(0,100); Delay_seg(3); } /* -+Max */ for (iter = 0; iter <= 2; iter++) { MotorR(0,0); MotorL(0,0); Delay_seg(3); } /* Stop */ } void test_infrarrojos(void) { putstring("Right:"); putnum(lineR); putchar(';'); putstring("Center:"); putnum(lineC);putchar(';'); putstring("Left:"); putnum(lineL); putchar(';'); putchar('\r'); lineR = a2d(LINE_R);//Lectura sensor optico derecho <0 luz, 255 oscuridad> lineC = a2d(LINE_C);//Lectura sensor optico central <0 luz, 255 oscuridad> lineL = a2d(LINE_L);//Lectura sensor optico izquierdo <0 luz, 255 oscuridad> if (lineC>media) { if(lineL>media) { // MotorL(0,0);MotorR(0,30); Delay_seg(2); } else { if(lineR>media) { // MotorL(0,30);MotorR(0,0); Delay_seg(2); } else { // MotorL(0,20);MotorR(0,20); Delay_seg(1); } } } else { if(lineL>media) { // MotorL(0,0);MotorR(0,30); Delay_seg(2); } else { if(lineR>media) { // MotorL(0,30);MotorR(0,0); Delay_seg(2); } else; } } } void poltergeist(void) { int CERCA=350; int MUYCERCA=450; int MUYLEJOS=10; int luz = 700; // 200 si hay luz ambiente y sobre 750 en la oscuridad //lectura sensores lineR = a2d(LINE_R); lineL = a2d(LINE_L); if ((lineR>luz) && (lineL>luz)){ // mientras no ve la luz giramos sobre si mismo MotorL(0,30); MotorR(1,30); //Delay_seg(10); } // aquí estamos mirando hacia la luz else { /* //Corregimos la trayectoria if ((lineR>lineL)) { if((lineR-lineL)>70) { MotorR(0,30); MotorL(1,30); } } else { if((lineL-lineR)>70) { MotorR(1,30); MotorL(0,30); } } */ //Hacia delante hasta encontrar algo while(a2d(EYE_R)luz) || (lineL>luz)) break; } // Encontramos un obstáculo e xiramos hacia o lado que hai máis luz if (lineR>=lineL) { MotorR(1,100); MotorL(0,100); Delay_seg(10); if(a2d(EYE_R)>=CERCA && a2d(EYE_L)>=CERCA){ MotorR(1,100); MotorL(1,100); Delay_seg(10); MotorR(0,100); MotorL(1,100); Delay_seg(10); } else { MotorR(1,100); MotorL(0,100); Delay_seg(20); } } else { MotorR(0,100); MotorL(1,100); Delay_seg(10); if(a2d(EYE_R)>=CERCA && a2d(EYE_L)>=CERCA){ MotorR(1,100); MotorL(1,100); Delay_seg(10); MotorR(1,100); MotorL(0,100); Delay_seg(10); } else { MotorR(1,100); MotorL(0,100); Delay_seg(20); } } } } void testeyes(void) { eyeR = a2d(EYE_R); eyeL = a2d(EYE_L); putstring("Right eye:"); putnum(eyeR); putchar(';'); putstring(" Left eye:"); putnum(eyeL);putchar(';'); putchar('\r'); } void followTheLeader(void){ int center = 0,ncenter=0; while(1){ lineR = a2d(LINE_R);//Lectura sensor optico derecho <0 luz, 255 oscuridad> lineC = a2d(LINE_C);//Lectura sensor optico central <0 luz, 255 oscuridad> lineL = a2d(LINE_L);//Lectura sensor optico izquierdo <0 luz, 255 oscuridad> putstring("Right:"); putnum(lineR); putchar(';'); putstring("Center:"); putnum(lineC);putchar(';'); putstring("Left:"); putnum(lineL); putchar(';'); putchar('\r'); if (lineC > 250 || ncenter > 10 || ncenter<-10){ ncenter =0; } if(lineR > 250 && lineL > 250){ MotorR(1,100); MotorL(1,100); }else if(lineR > 250 || ncenter > 0){ ncenter++; MotorR(0,40); MotorL(1,100); }else if(lineL > 250 || ncenter < 0 ){ ncenter--; MotorR(1,100); MotorL(0,40); }else{ MotorR(1,100); MotorL(1,100); } } } int abs(int x){ if(x<0){ return x*-1; } return x; } void getmeout(){ int disti,distd,cont=0,temp; int CERCA=350; int MUYCERCA=450; int MUYLEJOS=10; int CHOQUE=200; int NAPROX=10; int REFRESH=50; int codd=0,codi=0,odisti,odistd; //Hacia delante hasta encontrar algo while(a2d(EYE_R)100 && distd>100) && (distidisti || odistd>distd) /*&& (abs(disti-distd)<100)*/ ){ codd++; } //Si el sensor izq está a una distancia de choque y la distancia actual es menor que la anterior... /*if(odistidisti){ codi++; }else{ codi=0; } //Si el sensor derecho está a una distancia de choque y la distancia actual es menor que la anterior... if(odistddistd){ codd++; }else{ codd=0; }*/ putstring("Right eye:"); putnum(distd); putchar(';'); putstring(" Left eye:"); putnum(disti);putchar(';'); putchar('\r'); //Estamos inclinados mirando la izquierda y el sensor izquierdo está muy cerca, giramos a la derecha if( (disti-distd)>100 && disti > MUYCERCA){ MotorR(0,40); MotorL(1,40); }else if( (disti-distd)>100 && distd > MUYCERCA){ //Estamos inclinados mirando la derecha y el sensor derecha está muy cerca, giramos a la izq MotorR(1,40); MotorL(0,40); }else if(codd>NAPROX || codi>NAPROX){ /* Si nos hemos estado aproximando durante NAPROX turnos, giramos a la derecha */ //for(temp=0;temp<3;temp++){ MotorR(0,40); MotorL(1,40); Delay_ms(200); //} codd=0;codi=0; }else{ /* Sino seguimos hacia delante girando levemente a la izquierda */ MotorR(1,70); MotorL(1,40); } } } } void goautse(void) { int cont=0; int distancia_minima=450; int obstaculo=0; //Miramos inicialmente putstring("Right eye:"); putnum(eyeR); putchar(';'); putstring(" Left eye:"); putnum(eyeL);putchar(';'); putchar('\r'); //Esto va hacia delante hasta que encuentre un obstaculo while ( (a2d(EYE_R)<=distancia_minima) && (a2d(EYE_L)<=distancia_minima)) { MotorR(1,100); MotorL(1,100); } //Giramos a la derecha 45º la primera vez para seguir la pared MotorR(1,40); MotorL(0,40); Delay_seg(2); //Entramos en el bucle principal, miramos izquierda y andamos... while(1){ MotorR(0,10); MotorL(1,10); Delay_seg(1); if ((a2d(EYE_R)<=distancia_minima) && (a2d(EYE_L)>=distancia_minima)) { //Estamos cerca de la pared por la parte izquierda: giramos a la derecha 30º MotorR(1,10); MotorL(0,10); Delay_seg(1); if ((a2d(EYE_R)>=distancia_minima) || (a2d(EYE_L)>=distancia_minima)) { //Hay un obstaculo: giramos a la derecha 180º MotorR(1,80); MotorL(0,80); Delay_seg(2); //Con el doble de tiempo giramos los 180º } } //Avanzamos un rato while ( (a2d(EYE_R)<=distancia_minima) && (a2d(EYE_L)<=distancia_minima) && cont <=10) { MotorR(1,100); MotorL(1,100); cont++; Delay_ms(100); } //Giramos a la derecha MotorR(0,40); MotorL(1,40); Delay_ms(1000); //Si no hay obstáculo if ((a2d(EYE_R)<=distancia_minima) && (a2d(EYE_L)<=distancia_minima)) { //Avanzamos un rato int cont=0; while ( (a2d(EYE_R)<=distancia_minima) && (a2d(EYE_L)<=distancia_minima) && cont <=10) { MotorR(1,100); MotorL(1,100); cont++; Delay_ms(100); } } } } //**************************************************************************** // Funcion principal //**************************************************************************** void main(void) { PORTA=0x00; PORTB=0x00; PORTC=0x00; PORTD=0x00; PORTE=0x00; ADCON1=0x80; TRISA=0x3F; TRISB=0xE1; TRISC=0x80; TRISD=0x00; TRISE=0x07; TMR1IE=1; //Activo interrupcion del TIMER_1 OPTION=0x00; //Prescaler 1:1 asignado al Timer0 /*Configuramos puerto serie*/ SPBRG=0x20; //Baudios:38400 TXSTA=0b00100100; RCSTA=0b10010000; cont=0; segundo=0; MotorR(0,0); // Inicialmente MotorR (dir <0 avance,1 retroceso>, vel ) MotorL(0,0); // Inicialmente MotorL (dir <0 avance,1 retroceso>, vel ) //Incremento variable al pulsar Reset Reset=read_EE(0xFF); Reset++; write_EE(0xFF, Reset); T1CON=0x31; //Prescaler de Timer1 a (Fosc/4)/8, Activo Timer1 PEIE=1; //Activo interrupcion externa GIE=1; //Activo interrupciones lineR = a2d(LINE_R);//Lectura sensor optico derecho <0 luz, 255 oscuridad> lineC = a2d(LINE_C);//Lectura sensor optico central <0 luz, 255 oscuridad> lineL = a2d(LINE_L);//Lectura sensor optico izquierdo <0 luz, 255 oscuridad> lineAvg=lineR; lineAvg+=lineC; lineAvg+=lineL; lineAvg/=3; media=(unsigned char)lineAvg; putstring(Mensaje); //MAIN while(1) { switch(Reset) { // case 1: //followTheLeader(); // goautse(); //test_motores(); // break; // case 3: // test_infrarrojos(); // break; case 1: //getmeout(); //testeyes(); //goautse(); poltergeist(); /* for(i=0;i<=10;i++){ MotorR(1,100); MotorL(1,100); Delay_ms(100); } for(i=0;i<=3;i++){ MotorR(1,100); MotorL(0,100); Delay_ms(100); } for(i=0;i<=10;i++){ MotorR(0,100); MotorL(0,100); Delay_ms(100); } */ break; case 2: test_infrarrojos(); break; /* case 4: case 6: //Pause //MotorR(0,0); //MotorL(0,0); break;*/ default: //MotorR(0,0); //MotorL(0,0); InitReset(); } } }