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.
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 }