#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "esp_timer.h"
#define DEBOUNCE 200 // Tiempo de debounce para evitar lecturas múltiples del botón
// Pines de entrada para los botones
#define BUTTON_1_PIN 17 // Botón para moneda de 1 peso
#define BUTTON_5_PIN 18 // Botón para moneda de 5 pesos
#define BUTTON_10_PIN 19 // Botón para moneda de 10 pesos
#define BUTTON_20_PIN 21 // Botón para moneda de 20 pesos
// Pines de salida para los LEDs
#define LED_RECEIPT_PIN 2 // LED para expedición del recibo
#define LED_CHANGE_1_PIN 4 // LED para cambio de 1 peso
#define LED_CHANGE_5_PIN 16 // LED para cambio de 5 pesos
#define LED_CHANGE_10_PIN 5 // LED para cambio de 10 pesos
int64_t ultima_int = 0; // Para manejar el debounce
QueueHandle_t handlerQueue; // Cola para manejar las interrupciones de los botones
// Función para manejar las interrupciones de los botones
static void IRAM_ATTR gpio_interrupt_handler(void *args) {
int64_t tiempo_actual = esp_timer_get_time() / 1000; // Tiempo actual en ms
if (tiempo_actual - ultima_int > DEBOUNCE) {
int pinNumber = (int)args;
xQueueSendFromISR(handlerQueue, &pinNumber, NULL);
ultima_int = tiempo_actual; // Actualizamos el tiempo de la última interrupción
}
}
// Tarea para controlar los LEDs de acuerdo con el monto pagado
void Payment_Task(void *params) {
int pinNumber;
int total = 0; // Total acumulado por el usuario
while (true) {
if (xQueueReceive(handlerQueue, &pinNumber, portMAX_DELAY)) {
// Verificamos qué botón se presionó y agregamos el valor correspondiente
switch (pinNumber) {
case BUTTON_1_PIN: total += 1; break;
case BUTTON_5_PIN: total += 5; break;
case BUTTON_10_PIN: total += 10; break;
case BUTTON_20_PIN: total += 20; break;
}
printf("Total pagado: %d pesos\n", total);
// Verificamos si el total acumulado es suficiente para pagar
if (total >= 15) {
int cambio = total - 15;
printf("Monto a devolver: %d pesos\n", cambio);
// Manejo del cambio a devolver
if (cambio >= 10) {
gpio_set_level(LED_CHANGE_10_PIN, 1);
cambio -= 10;
} else {
gpio_set_level(LED_CHANGE_10_PIN, 0);
}
if (cambio >= 5) {
gpio_set_level(LED_CHANGE_5_PIN, 1);
cambio -= 5;
} else {
gpio_set_level(LED_CHANGE_5_PIN, 0);
}
if (cambio >= 1) {
gpio_set_level(LED_CHANGE_1_PIN, 1);
cambio -= 1;
} else {
gpio_set_level(LED_CHANGE_1_PIN, 0);
}
// Encender LED de recibo
gpio_set_level(LED_RECEIPT_PIN, 1);
vTaskDelay(pdMS_TO_TICKS(1000)); // Esperar un segundo para simular la expedición del recibo
gpio_set_level(LED_RECEIPT_PIN, 0);
// Reiniciar total
total = 0;
}
}
}
}
void app_main() {
// Configurar los pines de los LEDs como salidas
gpio_reset_pin(LED_RECEIPT_PIN);
gpio_set_direction(LED_RECEIPT_PIN, GPIO_MODE_OUTPUT);
gpio_reset_pin(LED_CHANGE_1_PIN);
gpio_set_direction(LED_CHANGE_1_PIN, GPIO_MODE_OUTPUT);
gpio_reset_pin(LED_CHANGE_5_PIN);
gpio_set_direction(LED_CHANGE_5_PIN, GPIO_MODE_OUTPUT);
gpio_reset_pin(LED_CHANGE_10_PIN);
gpio_set_direction(LED_CHANGE_10_PIN, GPIO_MODE_OUTPUT);
// Configurar los pines de los botones como entradas
gpio_reset_pin(BUTTON_1_PIN);
gpio_set_direction(BUTTON_1_PIN, GPIO_MODE_INPUT);
gpio_pulldown_en(BUTTON_1_PIN);
gpio_pullup_dis(BUTTON_1_PIN);
gpio_set_intr_type(BUTTON_1_PIN, GPIO_INTR_POSEDGE);
gpio_reset_pin(BUTTON_5_PIN);
gpio_set_direction(BUTTON_5_PIN, GPIO_MODE_INPUT);
gpio_pulldown_en(BUTTON_5_PIN);
gpio_pullup_dis(BUTTON_5_PIN);
gpio_set_intr_type(BUTTON_5_PIN, GPIO_INTR_POSEDGE);
gpio_reset_pin(BUTTON_10_PIN);
gpio_set_direction(BUTTON_10_PIN, GPIO_MODE_INPUT);
gpio_pulldown_en(BUTTON_10_PIN);
gpio_pullup_dis(BUTTON_10_PIN);
gpio_set_intr_type(BUTTON_10_PIN, GPIO_INTR_POSEDGE);
gpio_reset_pin(BUTTON_20_PIN);
gpio_set_direction(BUTTON_20_PIN, GPIO_MODE_INPUT);
gpio_pulldown_en(BUTTON_20_PIN);
gpio_pullup_dis(BUTTON_20_PIN);
gpio_set_intr_type(BUTTON_20_PIN, GPIO_INTR_POSEDGE);
// Crear cola para manejar las interrupciones de los botones
handlerQueue = xQueueCreate(10, sizeof(int));
// Crear la tarea para manejar el pago
xTaskCreate(Payment_Task, "Payment_Task", 2048, NULL, 1, NULL);
// Configurar el servicio de interrupciones y agregar manejadores
gpio_install_isr_service(0);
gpio_isr_handler_add(BUTTON_1_PIN, gpio_interrupt_handler, (void *)BUTTON_1_PIN);
gpio_isr_handler_add(BUTTON_5_PIN, gpio_interrupt_handler, (void *)BUTTON_5_PIN);
gpio_isr_handler_add(BUTTON_10_PIN, gpio_interrupt_handler, (void *)BUTTON_10_PIN);
gpio_isr_handler_add(BUTTON_20_PIN, gpio_interrupt_handler, (void *)BUTTON_20_PIN);
}