Introducción
La idea con este juego que realizaremos con nuestro robot mBot es experimentar las características del sensor de luz integrado dentro de la placa mCore y el módulo adicional de sensor de sonido.
Por otro lado también experimentaremos con la matriz de LEDs de 8×16 que nos permitirá poner caras divertidas a nuestro robot.
También utilizaremos otros componentes integrados en la placa como el zumbador y los LEDs RGB.
Operativa del juego:
-
- Pondremos un umbral de luminosidad en el cual consideramos que es de día y el robot está “despierto”. Si no se supera este umbral querrá decir que es de noche y por tanto el robot estará “dormido”.
- Si está “despierto” el robot mostrará una serie de secuencia de gestos de ojos en la matriz de LEDs que cambiará si se encuentra “dormido”.
- Cuando se detecte un sonido que supere un cierto umbral el robot se “asustará” y se iniciará una secuencia de gestos en la matriz de LEDs (ojos de sorpresa) acompañados de sonidos.
- Si se considera que es de noche y por tanto está “dormido” esta secuencia se acompañará con la iluminación de los dos LEDs que se encuentran integrados en la placa por el contrario si consideramos que es de día y por tanto está “despierto” en vez de encender los LEDs haremos que realice unos pequeños movimientos a izquierda y derecha. Durante la noche el umbral de sonido será más sensible que durante el día.
Para ver el funcionamiento de lo anteriormente descrito aquí os dejo el video demostrativo del juego:
Listado de componentes
-
- Robot mBot.
- Matriz de LEDs.
- Pack de estructuras para mBot.
- 2 x Cable RJ25 20cm.
Montaje de componentes
Para poder realizar el juego necesitaremos instalar el módulo de sensor de sonido mediante el pack de estructuras para mBot.
También instalaremos la matriz de LEDs en la parte frontal del robot.
La conexiones de los diferentes módulos a los puertos de la placa mCore serán:
-
- Módulo sensor de sonido: Puerto 4.
- Matriz de LEDs: Puerto 3.
Programación
Antes de mostrar el sketch con toda la programación del juego hay que tener en cuenta la siguiente observación:
En la función secuenciaCara() no podemos utilizar instrucciones como el delay o permanecer en un bucle ya que pararía la ejecución en un punto concreto.
Para ello se ha utilizado la instrucción millis() : if (millis() – t > intervalo) que nos permite ejecutar cada “x” tiempo ciertas instrucciones sin detenerse en un punto.
De esta manera no paramos la ejecución en ningún punto concreto y el hilo de ejecución podrá detectar si se produce un sonido mientras se está ejecutando una secuencia de la cara y por tanto iniciar la secuencia de alerta lo antes posible.
Por otro lado para la realización de las caras he utilizado el entorno de programación mBlock de Makeblock que tiene una herramienta visual para realizar esta tarea de un modo fácil.
Por último os dejo el sketch con toda la programación:
// --------------------------------------------------------------------------- // mBot (asuntando al mBot) - v1.0 - 04/02/2018 // // AUTOR/LICENCIA: // Creado por Angel Villanueva - @avilmaru // Copyright 2018 Licencia: GNU GPL v3 http://www.gnu.org/licenses/gpl-3.0.html // // LINKS: // Blog: https://mecatronicalab.es // // // HISTORICO: // 04/02/2018 v1.0 - Release inicial. // // --------------------------------------------------------------------------- #include <MeMCore.h> MeLEDMatrix ledMx(PORT_3); MeSoundSensor sensorSonido(PORT_4); MBotDCMotor motor(PORT_1); MeLightSensor sensorLuz(PORT_6); MeRGBLed rgbLed(PORT_7,2); MeBuzzer buzzer; const int UMBRAL_LUZ = 300; const int UMBRAL_SONIDO_DIURNO = 500; const int UMBRAL_SONIDO_NOCTURNO = 300; unsigned char *cara; String ultimoModo = ""; unsigned int luminosidad; unsigned int sonido; unsigned long t0 = 0; uint8_t secuencia = 0; void setup() { ledMx.setBrightness(6); ledMx.setColorIndex(1); ledMx.clearScreen(); motor.move(1,0); rgbLed.setColor(0,0,0,0); rgbLed.show(); } void loop() { luminosidad = sensorLuz.read(); if (luminosidad > UMBRAL_LUZ) { sonido = sensorSonido.strength(); if (sonido > UMBRAL_SONIDO_DIURNO) secuenciaAlerta("DESPIERTO"); else secuenciaCara(1000,"DESPIERTO"); }else{ sonido = sensorSonido.strength(); if (sonido > UMBRAL_SONIDO_NOCTURNO) secuenciaAlerta("DORMIDO"); else secuenciaCara(1000,"DORMIDO"); } } /* En esta función no podemos utilizar instrucciones como el delay o permanecer en un bucle ya que pararía la ejecución en un punto concreto. Para ello se ha utilizadola instrucción millis() (Ej:. if (millis() - t > intervalo) ) que nos permite ejecutar cada x tiempo ciertas instrucciones sin detenerse en un punto. De esta manera no paramos la ejecución en ningún punto concreto y el hilo de ejecución podrá detectar si se produce un sonido mientras se está ejecutando una secuencia de la cara y por tanto iniciar la secuencia de alerta lo antes posible */ void secuenciaCara(unsigned long intervalo, String modo) { if (millis() - t0 > intervalo) { t0 = millis(); if (ultimoModo != modo) secuencia = 0; secuencia++; if (modo == "DESPIERTO") { switch (secuencia) { case 1: cara = new unsigned char[16]{0,60,66,74,74,66,60,0,0,60,66,74,74,66,60,0}; break; case 2: cara = new unsigned char[16]{0,60,66,66,66,90,60,0,0,60,66,66,66,90,60,0}; break; case 3: cara = new unsigned char[16]{0,60,90,66,66,66,60,0,0,60,90,66,66,66,60,0}; secuencia=0; break; } }else if (modo == "DORMIDO") { switch (secuencia) { case 1: cara = new unsigned char[16]{0,16,8,8,8,16,0,0,0,0,16,8,8,8,16,0}; break; case 2: cara = new unsigned char[16]{0,0,16,8,8,8,16,0,0,0,0,16,8,8,8,16}; secuencia=0; break; } } mostrarCara(cara); ultimoModo = modo; } } /* En esta función si que utilizaremos delays ya que nos interesa que se ejecute entera y no tenga en cuenta si existe o no un sonido mientras se ejecuta a diferencia de la función anterior. */ void secuenciaAlerta(String modo) { bool activaMovimiento = false; rgbLed.setColor(0,0,0,0); rgbLed.show(); if (modo == "DESPIERTO") { activaMovimiento = true; } else { rgbLed.setColor(0,0,0,255); // Azul rgbLed.show(); } cara = new unsigned char[16]{60,66,129,153,153,129,66,60,60,66,129,153,153,129,66,60}; mostrarCara(cara); buzzer.tone(784, 500); // esto ya produce delay cara = new unsigned char[16]{60,66,129,129,129,129,66,60,60,66,129,129,129,129,66,60}; mostrarCara(cara); if (activaMovimiento) motor.move(3,255); delay(300); cara = new unsigned char[16]{60,66,129,153,153,129,66,60,60,66,129,153,153,129,66,60}; mostrarCara(cara); if (activaMovimiento) motor.move(4,255); buzzer.tone(330, 300); // esto ya produce delay cara = new unsigned char[16]{60,66,129,129,129,129,66,60,60,66,129,129,129,129,66,60}; mostrarCara(cara); if (activaMovimiento) motor.move(3,255); delay(300); cara = new unsigned char[16]{60,66,129,153,153,129,66,60,60,66,129,153,153,129,66,60}; mostrarCara(cara); if (activaMovimiento) motor.move(4,255); buzzer.tone(330, 300); // esto ya produce un delay motor.move(1,0); rgbLed.setColor(0,0,0,0); rgbLed.show(); delay(400); } void mostrarCara(unsigned char *cara) { unsigned char drawBuffer[16]; memcpy(drawBuffer,cara,16); free(cara); ledMx.drawBitmap(0,0,16,drawBuffer); }