09 Nov

Robot Mobile

Robot Mobile is a project I realised for my high school graduation exam year 2009/10.

The robot has 3 wheels (2 wheel-drive and one rotating in the front), and can move on a plane area avoiding obstacles. It has also a switch in the front which helps the robot to intercept a step o any other situation that might make it fall down on its track.

The project was realised by Lorenzo Frangella, Luca Simeone and Matteo Raffaeli.

 

This document includes functional specifications, the initial analysis phase results, the software, the realisation, and shows detailed pictures of the project.

Documentazione robot mobile

/* firmware V1.0 Controllo robot mobile */
/* Frangella Lorenzo - Simeone Luca - Raffaeli Matteo */
/* per maggiori informazioni : frangella@email.it */

#include <p18cxxx.h>
//#include <p18f452.h>
//#include <stdio.h>
//#include <ancomp.h>
//#include <usart.h>
#pragma config OSC = HS//10 Mhz
#pragma config WDT = OFF
#pragma config PWRT = ON
#pragma config LVP = OFF

#pragma config PBADEN = OFF // altrimenti porta B partirebbe come ingresso analogico

//funzioni di controllo
int input_radio(int);
int input_sensori(void);
int muovi(int, int, int);

//funzioni di movimento
void azioneA(void);
void azioneB(void);
void azioneC(void);
void azioneD(void);
void azioneE(void);
void azioneF(void);
void azioneG(void);
void azioneH(void);
void azioneI(void);

#define A 0
#define B 1
#define C 2
#define D 3
#define E 4
#define F 5
#define G 6
#define H 7
#define I 8

//funzioni di ritardo
void ritardo(void);
void ritardobreve(void);
void ritardolungo(void);

//funzione di impostazione delle porte di input e output del pic
void imposta_input_output(void);

//INIZIO VARIABILI GLOBALI
// comportamenti da tenere in ogni cambio di stato
int IN1[] =  {E,E,E,E,E,H,E,E,E};
int IN2[] =  {A,B,A,B,F,F,F,F,F};
int IN3[] =  {A,B,A,B,A,F,I,F,F};
int IN4[] =  {A,B,A,D,D,B,D,B,B};
int IN5[] =  {A,B,C,B,C,A,C,A,A};
int IN6[] =  {A,B,A,B,B,B,B,B,B};
int IN7[] =  {A,B,A,B,A,A,A,A,A};


int stato=E;//variabile per tenere traccia della stato precedente

//int interruttore = 0;
//FINE VARIABILI GLOBALI

//INIZIO funzione MAIN - funzione principale
void main (void){
int sensori=1;//controlla cosa vogliono fare i sensori
/* significato valori possibili:
    1 -> IN1 -> via libera
    2 -> IN2 -> ostacolo da tutti i sensori
    3 -> IN3 -> ostacolo centrale
    4 -> IN4 -> ostacolo a destra
    5 -> IN5 -> ostacolo a sinistra
    6 -> IN6 -> ostacolo avanti e a destra
    7 -> IN7 -> ostacolo avanti e a sinistra
*/

int radio=0;//controlla cosa vuole fare il telecomando
/* significato valori possibili:
    0 -> deufalt -> lascia il controllo ai sensori
    1 -> parti
    2 -> ruota sinistra
    3 -> ruota detra
    4 -> fermo
*/

    imposta_input_output();
    
    //abilitiamo circuito di controllo motori
    PORTCbits.RC1=1;//enable 16
    PORTCbits.RC5=1;//enable 24
    
    
    //avviamo robot avanti
    azioneE();
        //ciclo principale
        while(1) {    
            radio = input_radio(radio);
            //sensori = input_sensori();
            stato = muovi(radio, sensori, stato);
            ritardo();    
            //radio = 0;        
        }
}
//FINE funzione MAIN
        
void ritardo(void){
    unsigned long int i;
    for(i=0; i< 5000; i++);
}

void ritardobreve(void){
    unsigned long int i;
    for(i=0; i< 100; i++);
}

void ritardolungo(void){
    unsigned long int i;
    for(i=0; i< 30000; i++);
}

//funzione di controllo input dal radiocomando
int input_radio(int radio){
/*sensori:
PORTDbits.RB2 -> radio C1 - parti
PORTDbits.RB3 -> radio C2 - sx
PORTDbits.RB4 -> radio C3 - dx
PORTDbits.RB5 -> radio C4 - fermo
*/
    if(PORTBbits.RB2==1){
        ritardobreve();
        if(PORTBbits.RB2==1){
            return 1;//parti
        }
    }
    if(PORTBbits.RB3==1){
        ritardobreve();
        if(PORTBbits.RB3==1){
        return 2;//sx
        }
    }
    if(PORTBbits.RB4==1){
        ritardobreve();
        if(PORTBbits.RB4==1){
        return 3;//dx
        }
    }
    if(PORTBbits.RB5==1){
        ritardobreve();
        if(PORTBbits.RB5==1){
        return 4;//fermo
        }
    }
    return radio;
}

//funzione di controllo input dai sensori
int input_sensori(void){
/*sensori:
PORTDbits.RD7 -> sens sx
PORTDbits.RD6 -> sens c
PORTDbits.RD5 -> sens dx
*/
    if(PORTDbits.RD7==0&&PORTDbits.RD6==0&&PORTDbits.RD5==0){
        return 1;//via libera
    }
    if(PORTDbits.RD7==1&&PORTDbits.RD6==1&&PORTDbits.RD5==1){
        return 2;//ostacolo da tt i sens
    }
    if(PORTDbits.RD7==0&&PORTDbits.RD6==1&&PORTDbits.RD5==0){
        return 3;//ostacolo centrale
    }
    if(PORTDbits.RD7==0&&PORTDbits.RD6==0&&PORTDbits.RD5==1){
        return 4;//ostacolo dx
    }
    if(PORTDbits.RD7==1&&PORTDbits.RD6==0&&PORTDbits.RD5==0){
        return 5;//ostacolo sx
    }
    if(PORTDbits.RD7==0&&PORTDbits.RD6==1&&PORTDbits.RD5==1){
        return 6;//ostacolo avanti dx
    }
    if(PORTDbits.RD7==1&&PORTDbits.RD6==1&&PORTDbits.RD5==0){
        return 7;//ostacolo avanti sx
    }
    return 1;
}

//funzione che decide il prossimo stato del robot
int muovi(int radi, int sens, int stat){

int old_stato = stat; // serve per ricordare lo stato al tempo precedente
/* solamente se da una rilevazione alla successiva lo stato cambia, allora
si prende una nuova decisione di movimento, altrimenti si continua il comportamento
scelto nel giro precedente
*/

// parte 1) determinare il nuovo stato

    if(radi != 0){
        switch(radi){
            case 1:
                stat = E;
                //interruttore = 0;
                break;
            case 2:
                stat = H;
                break;
            case 3:
                stat = I;
                break;
            case 4:
                stat = G;
                //interruttore = 1;
                break;
        }
        
    } else {
        switch(sens){
            case 1:
                stat = IN1[stat];
                break;
            case 2:
                stat = IN2[stat];
                break;
            case 3:
                stat = IN3[stat];
                break;
            case 4:
                stat = IN4[stat];
                break;
            case 5:
                stat = IN5[stat];
                break;
            case 6:
                stat = IN6[stat];
                break;
            case 7:
                stat = IN7[stat];
                break;
        }
    }

    /*if(interruttore){
        stat = G;
    }*/
    
// parte 2, se lo stato Ë cambiato, scegliere una nuova azione
    if (old_stato != stat) {
        //azioneG();
        switch( stat ) {
            case 0:
                azioneA() ;
                break;
            case 1:
                azioneB() ;
                break;
            case 2:
                azioneC() ;
                break;
            case 3:
                azioneD() ;
                break;
            case 4:
                azioneE() ;
                break;
            case 5:
                azioneF() ;
                break;
            case 6:
                azioneG() ;
                break;
            case 7:
                azioneH() ;
                break;
            case 8:
                azioneI() ;
                break;

        }    
    }


    return stat;
}

//A - ruota destra
void azioneA(void){
    //motore dx indietro
    PORTCbits.RC4=1;
    PORTCbits.RC6=0;
    //motore sx avanti
    PORTCbits.RC0=0;
    PORTCbits.RC2=1;
    ritardolungo();
}

//B - ruota sinistra
void azioneB(void){
    //motore dx avanti
    PORTCbits.RC4=0;
    PORTCbits.RC6=1;
    //motore sx indietro
    PORTCbits.RC0=1;
    PORTCbits.RC2=0;
    ritardolungo();
}

//C - vai a destra
void azioneC(void){
    //motore dx fermo
    PORTCbits.RC4=1;
    PORTCbits.RC6=1;
    //motore sx avanti
    PORTCbits.RC0=0;
    PORTCbits.RC2=1;
    ritardolungo();
}

//D - vai a sinistra
void azioneD(void){
    //motore dx avanti
    PORTCbits.RC4=0;
    PORTCbits.RC6=1;
    //motore sx fermo
    PORTCbits.RC0=1;
    PORTCbits.RC2=1;
    ritardolungo();
}

//E - vai avanti
void azioneE(void){
    //motore dx avanti
    PORTCbits.RC4=0;
    PORTCbits.RC6=1;
    //motore sx avanti
    PORTCbits.RC0=0;
    PORTCbits.RC2=1;
    //ritardolungo();
}

//F - vai indietro
void azioneF(void){
    //motore dx indietro
    PORTCbits.RC4=1;
    PORTCbits.RC6=0;
    //motore sx indietro
    PORTCbits.RC0=1;
    PORTCbits.RC2=0;
    ritardolungo();
}

//G - fermo
void azioneG(void){
    //motore dx fermo
    PORTCbits.RC4=1;
    PORTCbits.RC6=1;
    //motore sx fermo
    PORTCbits.RC0=1;
    PORTCbits.RC2=1;
    ritardolungo();
}

//H - vai indietro verso destra
void azioneH(void){
    //motore dx fermo
    PORTCbits.RC4=1;
    PORTCbits.RC6=1;
    //motore sx indietro
    PORTCbits.RC0=1;
    PORTCbits.RC2=0;
    ritardolungo();
}

//I - vai indietro verso sinistra
void azioneI(void){
    //motore dx indietro
    PORTCbits.RC4=1;
    PORTCbits.RC6=0;
    //motore sx fermo
    PORTCbits.RC0=1;
    PORTCbits.RC2=1;
    ritardolungo();
}



//impostazione porte: portA -> out, portB -> in, portC -> out, portD -> in
void imposta_input_output(void){
  PORTA = 0;
  TRISA = 0b00000000;
  PORTB = 0;
  TRISB = 0b11111111;
  PORTC = 0;
  TRISC = 0b00000000;
  PORTD = 0;
  TRISD = 0b11111111;
}