Proyecto final de semestre: Se desarrollo un vehículo que recibe comandos por el puerto serial y realiza las siguientes funciones según el comando sea el comando recibido: - Genera distintos tonos por un buzzer. - Controla el movimiento de un carro (con 2 motores) con comandos - Controla el movimiento de un carro (con 2 motores) con Joystick. - Lee y envía el color leido por el puerto serial al PC - Muestra los colores leídos por una pantalla FFT instalada en el vehículo.

Dependencies:   mbed UniGraphic

main.cpp

Committer:
CCastrop1012
Date:
2021-09-03
Revision:
0:3a420fc22672

File content as of revision 0:3a420fc22672:

#include "mbed.h"
#include "Motor.h"
#include "scolor_TCS3200.h"

#include "Arial12x12.h"
#include "Arial24x23.h"
#include "Arial43x48_numb.h"
#include "pict.h"
#include "pavement_48x34.h"
#include "ILI9341.h"

// Puerto de comunicacion Serial
Serial CoolTerm(USBTX, USBRX);

// TFT
ILI9341*   tft;               

// Motores        m1step
TraccionD Motores(PB_5, PB_3, PB_10, PB_4, 200, 3.75, 15.5) ;

/// PWM OUTPUTS
PwmOut Buzzer(D14); // LED1

//  Temporizadores 
Ticker MuestrearCOLOR;

// SENSOR DE COLOR
scolor_TCS3200 SENSOR_COLOR (PA_9, PC_7, PB_6, PA_7, PA_8); 


// Lecturas Analogas de Joystick 
AnalogIn JEjeX(A0);
AnalogIn JEjeY(A1);

 
// Salidas digitales
DigitalOut LED(PA_5);


// Interrupcion Externa
InterruptIn button1(USER_BUTTON);


//******************************************************************************
///         Declarar Variables Globales 




/// Variables sensor de color
long red;                        //Almacenan el Tiempo que dura el CicloUtil de la frecuencia
long blue;                       //Generada por el Sensor TSC3200, al leer el componente
long green;                      //R, G, B o Clear del color que tenga en Frente
long clear;



/// Variables y Constantes para Interrupcion Serial
#define valorInicial 0xAA
uint8_t n_interrupcion = 0;
uint8_t ComandoRecivido = valorInicial; 
uint8_t Parametro = valorInicial;


/// Constantes Sensor de Color
#define CMD_rojo   0x01
#define CMD_azul   0x02
#define CMD_verde  0x03
#define CMD_clear  0x04
#define ColorNoIdentificado 0x00


uint8_t color_identificado = ColorNoIdentificado;
uint8_t color_anterior = 0;


/// Varialbles Buzzer
uint8_t duracion_tono = 1;       // Variable que almacena el Tiempo que es ESCUCHARÁ el Tono
uint8_t tipo_tono = 1;           // Variable que almacena el Tono que se desee escuchar

/// Constantes Buzzer
#define TONO_DO 0x01 /// si tipo_tono == 0x01, se escuchará un DO
#define TONO_RE 0x02 /// si tipo_tono == 0x02, se escuchará un RE
#define TONO_MI 0x03 /// si tipo_tono == 0x03, se escuchará un MI
#define TONO_SI 0x04 /// si tipo_tono == 0x04, se escuchará un SI

#define DO 3.78 /// Duración del periodo en ms, que se pondrá en el Buzzer.period_ms() PARA ESCUCHAR UN DO
#define RE 3.36 /// Duración del periodo en ms, que se pondrá en el Buzzer.period_ms() PARA ESCUCHAR UN RE
#define MI 3.03 /// Duración del periodo en ms, que se pondrá en el Buzzer.period_ms() PARA ESCUCHAR UN MI
#define SI 2.82 /// Duración del periodo en ms, que se pondrá en el Buzzer.period_ms() PARA ESCUCHAR UN SI 

Timeout TimeBuzzer;


#define limite 0.727

// variables de control y flujo de programa

uint8_t   programa_ejecutar = 0; // Variable que almacena la ORDEN (Telemetria ó Telecomando)
                                 // enviada desde el CoolTerm
uint8_t   coolterm_data;         // Se almacenan Todos los Caracteres recividos por el CoolTerm.

uint8_t   new_command = 0;
// Constantes de velocidad

#define VelAlta  300
#define VelMedia 200
#define VelBaja 100


//******************************************************************************
// COMANDOS

#define iniciar_telemetria      0xFE
#define iniciar_telecomando     0xFF

#define telemetria_1            0x01  //
#define telemcomando_1          0x01

#define C_LeerColor  0x00
#define C_Sonido1    0x01
#define C_Sonido2    0x02
#define C_Sonido3    0x03
#define C_Sonido4    0x04
#define C_Adelante   0x05
#define C_Atras      0x06
#define C_Izquierda  0x07
#define C_Derecha    0x08
#define C_Velocidad  0x09
#define C_Joistck    0x0A

int comando_joystick = 0;


// variables y constantes del Joystick

uint8_t estado_x; 
uint8_t estado_y;
#define E_Derecha 1
#define E_Izquier 0
#define E_Adelante 1
#define E_Atras 0
#define E_Centro 3
#define Lim_JKIn 150
#define Lim_JKSup 180



// Variables y constantes pulsador
volatile bool button1_pressed = false; // Used in the main loop
volatile bool button1_enabled = true; // Used for debouncing
Timeout button1_timeout; // Used for debouncing



bool ComandPend = true;

//****************************************************************************
//                      Prototipo de funciones
void Configuracion_Inicial(void);
void ReadPort(void);                // Lee el puerto Serial
void MainConfig(void);              // Configuracion Inicial de los Perifericos del uC
void Buzzer_Tone(uint8_t tipo_tono, uint8_t duracion_tono); // configura el tono y la duracion escuchada a travez del Buzzer
void leer_color(void);              // funcion que retorna los componentes
                                    // RGB y Clear del color leido
void leer_Joystick(void);               // Ejerce control sobre el Movimiento del carro desde el Joistick  
void intTimeBuzzer(void);

void button1_enabled_cb(void);
void button1_onpressed_cb(void);


//****************************************************************************
//     

/// Variables y constantes para la TFT 

const unsigned short  FOREGROUND_COLORS[] = {White, Cyan, Red, Magenta, Yellow, Orange, GreenYellow};
const unsigned short  BACKGROUND_COLORS[] = {Black, Green, Yellow, Blue, Magenta, Black, Red};
unsigned short  backgroundColor;
unsigned short  foregroundColor;
unsigned short  colorIndex = 0;
char            orient = 1;


void Configuracion_Inicial()
{
    
    Buzzer.write(0);                                    // configura el ciclo util
    Motores.StepFreq(VelMedia);                         // Valor inicial de velocidad = Media
    CoolTerm.attach(&ReadPort, Serial::RxIrq);          // Se Habilita la interrupcion serial o recepcion de datos
    //MuestrearCOLOR.attach(&leer_color, 0.6);            // Se Habilita una interrupcion cada 0.6 Segundos para leer el color
    tft = new ILI9341(SPI_8, 10000000, PC_12, PC_11, PC_10, PA_13, PA_14, PA_15, "tft"); // SPI type, SPI speed, mosi, miso, sclk, cs, reset, dc
    tft->set_orientation(orient); // horizontal 1
    
    CoolTerm.baud(115200);
    //CoolTerm.printf("\n\nSystem Core Clock = %.3f MHZ\r\n",(float)SystemCoreClock/1000000);
    //tft->printf("\n\nSystem Core Clock = %.3f MHZ\r\n",(float)SystemCoreClock/1000000);
    foregroundColor = FOREGROUND_COLORS[0]; // white
    backgroundColor = BACKGROUND_COLORS[0];// DarkCyan
    
    tft->background(backgroundColor);    // set background to black
        tft->set_orientation(orient);
        tft->cls();                     // clear the screen
        
        
        
        
        
        tft->set_font((unsigned char*) Arial24x23,32,127,false); //variable width disabled
        tft->locate(80,80);
        tft->printf("COLOR \n\t\t    NO \n\tIDENTIFICADO \r\n");
        
        
     //button1.mode(PullUp); // Activate pull-up
    button1.fall(callback(button1_onpressed_cb)); // Attach ISR to handle button press event

   
}






// Enables button when bouncing is over
void button1_enabled_cb(void)
{
    button1_enabled = true;
    if (button1_enabled) 
    {
        // Reinicializamos nuestras variables de control a sus valores iniciales
            // Para no seguir entrando a las sentencias IF
            programa_ejecutar = 0;
            coolterm_data = 0; 
            ComandoRecivido = valorInicial;
            Parametro  = valorInicial;
            Motores.Stop();
            TimeBuzzer.attach(&intTimeBuzzer, 0);
            ComandPend = false;
     }    
}

// ISR handling button pressed event
void button1_onpressed_cb(void)
{
    if (button1_enabled) 
    { // Disabled while the button is bouncing
        button1_enabled = false;
        button1_pressed = true; // To be read by the main loop
        button1_timeout.attach(callback(button1_enabled_cb), 0.3); // Debounce time 300 ms
    }
    
    
    
}




void ReadPort()
{
    uint8_t temp = CoolTerm.getc();
    //if(CoolTerm.writable()) CoolTerm.abort_write(); // ELIMINA LO QUE ESTEMOS ESCRIBIENDO AL COOLTERM
    if (ComandPend == true)
    {
        switch(n_interrupcion)
        {
            case 00:    coolterm_data =  temp; 
                        if (coolterm_data == iniciar_telecomando)  
                        n_interrupcion = 1;
                    break;
            case 01:    ComandoRecivido =  temp; 
                        n_interrupcion=2;
                    break;
            case 02:    Parametro =  temp; 
                        n_interrupcion = 0;
                        ComandPend=false;
                        break;
                        
        }
    
  }
  
  
}

///******************************************+


void leer_Joystick()
{   

    /// Variables Joystick
    float EjeX;
    float EjeY;
    float Vx;
    float Vy;
    
     while ( ComandPend == true ) 
     {
        
        EjeX = JEjeX.read();
        Vx = EjeX * 3300; 
        wait (0.1);
        EjeY = JEjeY.read();
        Vy = EjeY * 3300;
        
    //    CoolTerm.printf ("ejex: %f    ejey: %f  Vx: %f  Vy: %f \n   ", EjeX, EjeY, Vx, Vy);
    
        if(int(Vx/10) > Lim_JKIn && int(Vx/10) < Lim_JKSup) {estado_x = E_Centro; }//(CoolTerm.printf ("Estado X Centro \n"); }          
        if(int(Vy/10) > Lim_JKIn && int(Vy/10) < Lim_JKSup) {estado_y = E_Centro; }//CoolTerm.printf ("Estado Y Centro \n"); }
        
        if(int(Vx/10) > Lim_JKSup && estado_y == E_Centro){ estado_x = E_Izquier; }// CoolTerm.printf ("Estado X Izquierda\n"); }
        if(int(Vy/10) > Lim_JKSup && estado_x == E_Centro){ estado_y = E_Atras; }//  CoolTerm.printf ("Estado Y Adelante\n"); }
        
        if(int(Vx/10) < Lim_JKIn && estado_y == E_Centro){ estado_x = E_Derecha; } //CoolTerm.printf ("Estado X Derecha\n"); }
        if(int(Vy/10) < Lim_JKIn && estado_x == E_Centro){ estado_y = E_Adelante; } //CoolTerm.printf ("Estado Y Atras\n"); }
     
     
        // Combinacion de estados para STOP
        if( estado_x == E_Centro && estado_y == E_Centro){ Motores.Stop(); }//CoolTerm.printf ("MOTORES STOP\n"); }
        
        // Combinacion de estados para ADELANTE
        if(estado_x == E_Centro && estado_y == E_Adelante) { Motores.Back(); Motores.Run(0.5); }// CoolTerm.printf ("MOTORES BACK\n"); } 
        
        // Combinacion de estados para ATRAS
        if(estado_x == E_Centro && estado_y == E_Atras) { Motores.Forward(); Motores.Run(0.5); }// CoolTerm.printf ("MOTORES FORWARD\n"); } 
        
        
        // Combinacion de estados para DERECHA
        if(estado_y == E_Centro && estado_x == E_Derecha) {  Motores.Giro(15, false); Motores.Run(0.5); } // CoolTerm.printf ("MOTORES DERECHA\n"); } 
        
        // Combinacion de estados para IZQUIERDA
        if(estado_y == E_Centro && estado_x == E_Izquier) { Motores.Giro(15, true); Motores.Run(0.5); } //  CoolTerm.printf ("MOTORES IZQUIERDA\n"); } 
        //wait(1.5);
        
        if (ComandoRecivido == C_Joistck && Parametro == 0x02) break;
    }

    
}



int main()
{

    Configuracion_Inicial();

    MuestrearCOLOR.attach(&leer_color, 1.5);            // Se Habilita una interrupcion cada 0.6 Segundos para leer el color
      
    while(1) 
    {
        
       /// Espera hasta que no se tengan comandos pendientes
        while(ComandPend == true)wait_ms(1);
        ComandPend = true;
        
        
        //  Desactivamos la interrupcion serial o recepcion de datos PORQUE NO NECESITAMOS recibir mas datos por AHORA
        //  CoolTerm.attach(NULL, Serial::RxIrq);
            
        switch(ComandoRecivido)
        {
            
            //case C_LeerColor:   // Ejecutamos la Funcion LeerColor();
              //                  leer_color();
                    //break;
            case C_Sonido1:     //CoolTerm.printf("SONIDO 1\n");
                                duracion_tono = Parametro;  // lo almacenamos en:  duracion_tono
                                tipo_tono     = TONO_DO;
                                Buzzer_Tone(tipo_tono, duracion_tono);         
                    break;
            case C_Sonido2:     //CoolTerm.printf("SONIDO 2\n");
                                duracion_tono = Parametro;  // lo almacenamos en:  duracion_tono
                                tipo_tono     = TONO_RE;
                                Buzzer_Tone(tipo_tono, duracion_tono);         
                    break;
            case C_Sonido3:     //CoolTerm.printf("SONIDO 3\n");
                                duracion_tono = Parametro;  // lo almacenamos en:  duracion_tono
                                tipo_tono     = TONO_MI;
                                Buzzer_Tone(tipo_tono, duracion_tono);         
                    break;
            case C_Sonido4:     //CoolTerm.printf("SONIDO 4\n");
                                duracion_tono = Parametro;  // lo almacenamos en:  duracion_tono
                                tipo_tono     = TONO_SI;
                                Buzzer_Tone(tipo_tono, duracion_tono);         
                    break;
            case C_Adelante:    Motores.Forward(); Motores.RunRound(Parametro);
                    break;
            case C_Atras:       Motores.Back(); Motores.RunRound(Parametro);
                    break;
            case C_Izquierda:   Motores.Giro(65, true);
                    break;
            case C_Derecha:     Motores.Giro(65, false);
                    break;
            case C_Velocidad:   if(Parametro == 0x01)Motores.StepFreq(VelBaja);
                                if(Parametro == 0x02)Motores.StepFreq(VelMedia);
                                if(Parametro == 0x03)Motores.StepFreq(VelAlta);                                
                    break;
            case C_Joistck:     leer_Joystick();     
                    break;
            default: break;    
                    
            
        }


            // Reinicializamos nuestras variables de control a sus valores iniciales
            // Para no seguir entrando a las sentencias IF
            if(ComandPend == true)
            {
                programa_ejecutar = 0;
                coolterm_data = 0; 
                ComandoRecivido = valorInicial; Parametro  = valorInicial;
                
             }   
            
            ////  HABILITAMOS NUEVAMENTE la interrupcion serial o recepcion de datos
            //  CoolTerm.attach(&ReadPort, Serial::RxIrq);  
        
    }
    
}



void Buzzer_Tone(uint8_t tipo_tono, uint8_t duracion_tono)
    {
        
            
        switch (tipo_tono)
            {
                    
                    case TONO_DO:       Buzzer.period_ms(DO);
                                       //CoolTerm.printf("Tono Seleccionado DO!!\n");                                        
                                        
                                        break; // salimos del SWITCH
                                        
                    case TONO_RE:       Buzzer.period_ms(RE);
                                        //CoolTerm.printf("Tono Seleccionado RE!!\n");
                                        
                                        break; // salimos del SWITCH
                                        
                    case TONO_MI:       Buzzer.period_ms(MI);
                                        //CoolTerm.printf("Tono Seleccionado MI!!\n");
                                        
                                        break; // salimos del SWITCH
                                        
                    case TONO_SI:       Buzzer.period_ms(SI);
                                        //CoolTerm.printf("Tono Seleccionado SI!!\n");
                                        
                                        break; // salimos del SWITCH
                                                            
                    // si no fue ninguno de los valores anteriores entonces:                    
                    default:            //CoolTerm.printf("teleComando desconocido, inicie nuevamente !!\n");
                                        
                                        break; // salimos del SWITCH

            }
            
                // COMO EL CICLO UTIL DEL BUZZER ESTABA EN 0, POR LO CUAL NO SONABA
                // SE PONE AL 50% DEL PERIODO
                Buzzer.write(0.5);
                // SE ESPERA DURANTE EN TIEMPO INGRESADO (EN SEGUNDOS )
                // wait(duracion_tono);
                
                TimeBuzzer.attach(&intTimeBuzzer, duracion_tono);
                
                // Se Reinicializa el Periodo y el Ciclo útil de la señal PWM 
                // que va al Buzzer
                // Buzzer.period_ms(1);
                // Buzzer.write(0);             
                   

    
    } 



void intTimeBuzzer(void)
{
    
    // Se Reinicializa el Periodo y el Ciclo útil de la señal PWM 
                // que va al Buzzer
                Buzzer.period_ms(1);
                Buzzer.write(0);
    
    
    }


void leer_color()
    {
        MuestrearCOLOR.attach(NULL, 1.5);            // Se Habilita una interrupcion cada 0.6 Segundos para leer el color
       
        red    = SENSOR_COLOR.ReadRed(); // OBTENEMOS EL TIEMPO DEL CICLO UTIL DE LA FRECUENCIA DE SALIDA 
        green  = SENSOR_COLOR.ReadGreen();
        blue   = SENSOR_COLOR.ReadBlue();
        clear  = SENSOR_COLOR.ReadClear();
        
        //printf("RED: %5d     GREEN: %5d     BLUE: %5d     CLEAR: %5d    \n ", red, green, blue, clear);
         
        red     *= 2;   // Calculamos EL PERIODO de la frecuencia generada por la lectura del fotodiodo rojo         
        blue    *= 2;   // Calculamos EL PERIODO de la frecuencia generada por la lectura del fotodiodo rojo
        green   *= 2;   // Calculamos EL PERIODO  de la frecuencia generada por la lectura del fotodiodo rojo
        clear   *= 2;   // Calculamos EL PERIODO  de la frecuencia generada por la lectura del fotodiodo rojo
        
        //printf("RED: %5d     GREEN: %5d     BLUE: %5d     CLEAR: %5d    \n ", red, green, blue, clear);
       
        
       //////////////////////////////////////////////////////////////     
       ////         identificar azul
       
       
       if(red <=42 && red >=24)
        {
            if(green >= 20 && green <= 28 )
            {
                if(blue >= 10 && blue <= 16)
                {
                        color_identificado = CMD_azul;
                        CoolTerm.putc( iniciar_telemetria);
                        CoolTerm.putc( CMD_azul ); 
                        if (color_anterior != CMD_azul)
                        {
                            foregroundColor = FOREGROUND_COLORS[0]; // white
                            backgroundColor = BACKGROUND_COLORS[3];// DarkCyan
                            tft->background(backgroundColor);    // set background to black
                            tft->set_font((unsigned char*) Arial24x23,32,127,false); //variable width disabled
                            tft->cls();
                            tft->locate(80,80);
                            tft->printf("COLOR \n\tAZUL\r\n");
        
                       }
                         color_anterior = CMD_azul;
                       
                }
            }
         }   
                 
        
        
        
        /////////////////////////////////////////////////////////////
        ///         identificar rojo
        if(red <= 12 )
        {
            if(green >= 10 && green <= 28 ) 
                {
                    if(blue >= 18 && blue <= 24)
                    {
                            color_identificado = CMD_rojo;
                            CoolTerm.putc( iniciar_telemetria);
                            CoolTerm.putc( CMD_rojo ); 
                            
                            if (color_anterior != CMD_rojo)
                        {
                                foregroundColor = FOREGROUND_COLORS[0]; // white
                                backgroundColor = BACKGROUND_COLORS[6];// DarkCyan
                                tft->background(backgroundColor);    // set background to black
                                tft->set_font((unsigned char*) Arial24x23,32,127,false); //variable width disabled
                                tft->cls();
                                tft->locate(80,80);
                                tft->printf("COLOR \n\tROJO\r\n");
                            }
                            color_anterior = CMD_rojo;
                    }
                }
                
            if(green < 10 && green >= 6 )
                {
                    if(blue <= 12  )
                    {
                            color_identificado = CMD_clear;
                            CoolTerm.putc( iniciar_telemetria);
                            CoolTerm.putc( CMD_clear );
                            if (color_anterior != CMD_clear)
                        {
                            foregroundColor = FOREGROUND_COLORS[0]; // white
                            backgroundColor = BACKGROUND_COLORS[2];// DarkCyan
                            tft->background(backgroundColor);    // set background to black
                            tft->set_font((unsigned char*) Arial24x23,32,127,false); //variable width disabled
                            tft->cls();
                            tft->locate(80,80);
                            tft->printf("COLOR \n\tAMARILLO\r\n");
                         }
                            color_anterior = CMD_clear;
                           
                    }
                    
                }
            
         }   
         
         
             if(green >= 36 && green <= 44 )
            {
                if(red >= 40 && red <= 50 )
            
                {
                        color_identificado = CMD_verde;
                        CoolTerm.putc( iniciar_telemetria);
                        CoolTerm.putc( CMD_verde );
                        if (color_anterior != CMD_verde)
                        {
                            foregroundColor = FOREGROUND_COLORS[0]; // white
                            backgroundColor = BACKGROUND_COLORS[1];// DarkCyan
                            tft->background(backgroundColor);    // set background to black
                            tft->set_font((unsigned char*) Arial24x23,32,127,false); //variable width disabled
                            tft->cls();
                            tft->locate(80,80);
                            tft->printf("COLOR \n\tVERDE\r\n");
                        }
                        color_anterior = CMD_verde;
                }
            } 
            
            if  (color_identificado == ColorNoIdentificado)
            {
                
                 
                        CoolTerm.putc( iniciar_telemetria);
                        CoolTerm.putc( ColorNoIdentificado);
                        
                        if (color_anterior != ColorNoIdentificado)
                        {
                            foregroundColor = FOREGROUND_COLORS[0]; // white
                            backgroundColor = BACKGROUND_COLORS[5];// DarkCyan
                            tft->background(backgroundColor);    // set background to black
                            tft->set_font((unsigned char*) Arial24x23,32,127,false); //variable width disabled
                            tft->cls();
                            tft->locate(80,80);
                            tft->printf("COLOR \n\t\t    NO \n\tIDENTIFICADO \r\n");
                        }
                            color_anterior = ColorNoIdentificado;
                            
            }
                
            color_identificado = ColorNoIdentificado;
            
            MuestrearCOLOR.attach(&leer_color, 1.5);            // Se Habilita una interrupcion cada 0.6 Segundos para leer el color
        }