#include <Arduino_FreeRTOS.h>
#include <Keypad.h>
#include <semphr.h>
#include <queue.h>
const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {5, 4, 3, 2}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {A3, A2, A1, A0}; //connect to the column pinouts of the keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
int redPin = 11;
int greenPin = 10;
int bluePin = 9;
//---------------------------------
#define TIEMPO_EXITO 5
#define TIEMPO_EXPLOSION 30
#define LMAX 4
#define NUM_INTENTOS 3
bool comenzarCuenta = false;
bool bombaDefusada = false;
char codigo[LMAX];
unsigned intentos = NUM_INTENTOS;
unsigned cont = TIEMPO_EXPLOSION;
SemaphoreHandle_t xMutex;
//QueueHandle_t xQueue;
void setup() {
Serial.begin(9600);
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
// xQueue = xQueueCreate(2, sizeof(unsigned));
xMutex = xSemaphoreCreateMutex();
if (xMutex != NULL /* && xQueue != NULL */) {
if (xTaskCreate(inicializarCuentaCodigo, "CuentaCodigo", 96, NULL, 2, NULL) != pdPASS) {
Serial.println("Error CuentaCodigo");
}
if (xTaskCreate(tareaContador, "Contador", 96, NULL, 3, NULL) != pdPASS) {
Serial.println("Error Contador");
}
if (xTaskCreate(tareaKeypad, "Keypad", 96, NULL, 1, NULL) != pdPASS) {
Serial.println("Error Keypad");
}
/*
if (xTaskCreate(muestraCont, "muestraCont", 96, NULL, 0, NULL) != pdPASS) {
Serial.println("Error muestraCont");
}
*/
vTaskStartScheduler();
} else {
Serial.println("Error semáforo");
}
}
void establecerColor(int r, int g, int b) {
analogWrite(redPin, r);
analogWrite(greenPin, g);
analogWrite(bluePin, b);
}
void generarCodigo() {
//xSemaphoreTake(xMutex, portMAX_DELAY);
for (int i = 0; i < LMAX; i++) {
codigo[i] = '0' + random(0, 10);
}
codigo[LMAX] = '\0';
Serial.print("Código de desactivación: ");
Serial.println(codigo);
//xSemaphoreGive(xMutex);
}
void inicializarCuentaCodigo( void *pvParameters ){
//Inicializa la cuenta y el código
bool localComenzarCuenta = false;
while(!localComenzarCuenta){
xSemaphoreTake(xMutex, portMAX_DELAY);
char key = keypad.getKey();
if (key == 'A') { //Dejar un momento pulsado el botón A para que empiece!!!!
generarCodigo();
comenzarCuenta = true;
Serial.println("Comienza la cuenta atrás");
}
localComenzarCuenta = comenzarCuenta;
xSemaphoreGive(xMutex);
vTaskDelay(10 / portTICK_PERIOD_MS); //Para que no consuma tantos recursos
}
vTaskDelete( NULL );
}
void tareaContador( void *pvParameters ){
//Cuenta y hace sonar el zumbador
//Si se desactiva la bomba ganas
//Si el tiempo se agota pierdes
unsigned long delayTime = 1000; //Para que se ejecute cada 1s
TickType_t xLastWakeTime;
//BaseType_t xStatus;
unsigned localCont = TIEMPO_EXPLOSION;
bool localBombaDefusada = false;
xLastWakeTime = xTaskGetTickCount();
while (localCont > 0 && !localBombaDefusada) {
xSemaphoreTake(xMutex, portMAX_DELAY);
if (comenzarCuenta) {
if(cont <= TIEMPO_EXPLOSION * 0.25){
establecerColor(255,0,0);
tone(8, 5000, 15); // PIN / TONO / Duración
}else if(cont <= TIEMPO_EXPLOSION * 0.5){
establecerColor(255,85,0);
tone(8, 5000, 65); // PIN / TONO / Duración
}else if(cont <= TIEMPO_EXPLOSION){
establecerColor(255,255,0);
tone(8, 5000, 200); // PIN / TONO / Duración
}
if(cont > 0){
/* xStatus = xQueueSendToBack(xQueue, &cont, portMAX_DELAY);
if (xStatus != pdPASS) {
Serial.println("Could not send to the queue.\r\n");
}
Cede la CPU a la otra tarea.
taskYIELD();
*/
Serial.println(cont);
cont -= 1;
}
}
localBombaDefusada = bombaDefusada;
localCont = cont;
xSemaphoreGive(xMutex);
vTaskDelayUntil(&xLastWakeTime , delayTime / portTICK_PERIOD_MS);
}
xSemaphoreTake(xMutex, portMAX_DELAY);
if(cont == 0){
Serial.println("¡Boom!");
tone(8, 2000, 2000); // PIN / TONO / Duración
establecerColor(255,255,255);
vTaskDelayUntil(&xLastWakeTime , 2000 / portTICK_PERIOD_MS);
establecerColor(0,0,0);
}else if(bombaDefusada){
Serial.println("The bomb has been defused");
for(unsigned i = 0; i < TIEMPO_EXITO; i++){
tone(8, 800, 65);
establecerColor(0,255,0);
vTaskDelayUntil(&xLastWakeTime , 80 / portTICK_PERIOD_MS);
establecerColor(0,0,0);
vTaskDelayUntil(&xLastWakeTime , 80 / portTICK_PERIOD_MS);
}
}
xSemaphoreGive(xMutex);
vTaskDelete( NULL );
}
/*
void muestraCont( void *pvParameters){
BaseType_t xStatus;
unsigned lcont;
for ( ;; ) {
xStatus = xQueueReceive(xQueue, &lcont, portMAX_DELAY);
if (xStatus == pdPASS) {
Serial.println(lcont);
}
else {
Serial.println("Could not receive from the queue.\r\n");
}vTaskDelay(10 / portTICK_PERIOD_MS);
}
vTaskDelete( NULL );
}
*/
void tareaKeypad( void *pvParameters ){
//Lee del keypad
//Si se introduce el código correcto, se avisa a tareaContador
//3 intentos
unsigned i = 0;
unsigned localCont = TIEMPO_EXPLOSION;
bool localBombaDefusada = false;
while (localCont > 0 && !localBombaDefusada) {
xSemaphoreTake(xMutex, portMAX_DELAY);
if (comenzarCuenta){
char key = keypad.getKey();
if(key == codigo[i]){ //Al igual que al comenzar, mantener un momento pulsada
//la tecla hasta que aparezca el mensaje del valor introducido
i++;
Serial.println("Número introducido: ");
Serial.println(key);
if(i == LMAX){
bombaDefusada = true;
}
}else if(key != NO_KEY ){
intentos--;
i = 0;
if(intentos == 0){
cont = 0;
}
Serial.println("Código incorrecto. Intentos restantes: ");
Serial.println(intentos);
}
}
localBombaDefusada = bombaDefusada;
localCont = cont;
xSemaphoreGive(xMutex);
vTaskDelay(250 / portTICK_PERIOD_MS);
}
vTaskDelete( NULL );
}
void loop() {
}