#include <Arduino.h>
#include <AiEsp32RotaryEncoder.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHT.h>
// Definición de pines para el encoder rotativo y el botón
#define ROTARY_ENCODER_A_PIN 14
#define ROTARY_ENCODER_B_PIN 13
#define ROTARY_ENCODER_BUTTON_PIN 12
#define ROTARY_ENCODER_VCC_PIN -1
// Definición de pines para la pantalla OLED
#define SCL 22
#define SDA 21
#define SCREEN_WIDTH 128 // Ancho de la pantalla OLED en píxeles
#define SCREEN_HEIGHT 64 // Alto de la pantalla OLED en píxeles
#define OLED_RESET -1 // Pin de reset de la pantalla OLED (no se usa)
// Definición de pines para el sensor DHT22
#define DHT_PIN 15
#define DHT_TYPE DHT22
// Definición de pines para la comunicación serial
#define RX_PIN 16 // Pin para la recepción serial
#define TX_PIN 17 // Pin para la transmisión serial
// Variables para el menú
int selectedOption = 0;
const int numOptions = 3; // Número total de opciones del menú
String menuOptions[] = {"Leer Datos DHT", "Leer Datos POT", "Enviar a Serial2"};
// Inicialización del objeto de la pantalla OLED
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Inicialización del encoder rotativo
AiEsp32RotaryEncoder rotaryEncoder = AiEsp32RotaryEncoder(ROTARY_ENCODER_A_PIN,
ROTARY_ENCODER_B_PIN,
ROTARY_ENCODER_BUTTON_PIN,
ROTARY_ENCODER_VCC_PIN,
4);
// Inicialización del sensor DHT22
DHT dht(DHT_PIN, DHT_TYPE);
// Variables para el control del mensaje "Leyendo"
bool isReading = false;
// Lista para almacenar las mediciones de humedad y temperatura
#define NUM_READINGS 50
float humidityReadings[NUM_READINGS];
float temperatureReadings[NUM_READINGS];
int readingsIndex = 0;
// Variable para controlar el estado de la medición
bool hasReadings = false;
void setup() {
// Inicialización de la comunicación serie
Serial.begin(9600);
Serial2.begin(9600, SERIAL_8N1, RX_PIN, TX_PIN);
// Inicialización de la pantalla OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
// Mostrar "Bienvenido" centrado y con letra grande en la pantalla OLED una sola vez
display.clearDisplay();
display.setTextSize(2); // Tamaño de letra grande
display.setTextColor(WHITE);
// Calcular las coordenadas del cursor para centrar el texto en la pantalla
int16_t textWidth = 11 * strlen("Bienvenido"); // Aproximación del ancho del texto
int16_t x = (SCREEN_WIDTH - textWidth) / 2;
int16_t y = (SCREEN_HEIGHT - 16) / 2; // Altura de la fuente
Serial2.println("Y");
display.setCursor(x, y);
display.println("Bienvenido");
display.display();
Serial.println("Iniciando Sistema");
// Esperar unos segundos antes de continuar con la inicialización
delay(2000);
// Inicialización del encoder rotativo
rotaryEncoder.begin();
rotaryEncoder.setup([] { rotaryEncoder.readEncoder_ISR(); });
rotaryEncoder.setBoundaries(0, numOptions - 1, false);
// Inicialización del sensor DHT22
dht.begin();
Serial2.println("Z");
}
void loop() {
// Funciones principales del bucle
rotary_loop();
handle_rotary_button();
}
// Función para manejar el botón del encoder rotativo
void handle_rotary_button() {
static bool wasButtonDown = false;
bool isEncoderButtonDown = rotaryEncoder.isEncoderButtonDown();
if (isEncoderButtonDown && !wasButtonDown) {
wasButtonDown = true;
switch (selectedOption) {
case 0: // Leer Datos DHT
if (!isReading) {
isReading = true;
performDHTReadings();
isReading = false;
}
break;
case 1: // Leer Datos POT
// Agrega aquí la lógica para leer datos de POT si es necesario
break;
case 2: // Enviar a Serial2
if (hasReadings) {
sendReadingsToSerial2();
} else {
display.clearDisplay();
display.setCursor(0, 0);
display.println("Sin mediciones");
display.display();
delay(2000); // Mostrar el mensaje por 2 segundos
}
break;
}
} else if (!isEncoderButtonDown && wasButtonDown) {
wasButtonDown = false;
}
}
// Función para enviar las mediciones al puerto serial2
void sendReadingsToSerial2() {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.println("Enviando Medeiciones...");
display.display();
// INICIARLE AL PROGRAMA DE TKINTER UNA SEÑAL
Serial2.println("F");
delay(100);
for (int i = 0; i < NUM_READINGS; ++i) {
Serial2.print("H: ");
Serial2.print(humidityReadings[i]);
Serial2.print(", T: ");
Serial2.println(temperatureReadings[i]);
delay(10); // Breve retardo para evitar saturar el puerto serial
}
//INDICARLE AL PROGRAMA DE TKINTER OTRA COSA
Serial2.println("C");
delay(100);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.println("Mediciones Enviadas...");
display.display();
delay(1500);
}
// Función para realizar 50 mediciones de DHT
void performDHTReadings() {
hasReadings = false; // Reiniciar el estado de las mediciones
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.println("Realizando mediciones...");
display.display();
Serial.println("Realizando mediciones...");
// Realizar 50 mediciones de DHT y almacenarlas en la lista
for (int i = 0; i < NUM_READINGS; ++i) {
humidityReadings[i] = dht.readHumidity();
temperatureReadings[i] = dht.readTemperature();
// Imprimir las mediciones en el puerto serial
Serial.print("Humedad: ");
Serial.print(humidityReadings[i]);
Serial.print("%\t");
Serial.print("Temperatura: ");
Serial.print(temperatureReadings[i]);
Serial.println("°C");
// Breve retardo entre cada medición
delay(100);
}
hasReadings = true; // Indicar que hay mediciones disponibles
// Mostrar mensaje de completado en la pantalla OLED
display.clearDisplay();
display.setCursor(0, 0);
display.println("Mediciones completadas");
display.display();
}
// Función para manejar el loop del encoder rotativo
void rotary_loop() {
int encoderDelta = rotaryEncoder.encoderChanged();
if (encoderDelta != 0) {
selectedOption = (selectedOption + encoderDelta + numOptions) % numOptions;
}
// Mostrar el título y el menú en la pantalla OLED
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
int16_t titleWidth = 11 * strlen("Opciones");
int16_t titleX = (SCREEN_WIDTH - titleWidth) / 2;
int16_t titleY = 5;
display.setCursor(titleX, titleY);
display.println("Opciones");
for (int i = 0; i < numOptions; ++i) {
if (i == selectedOption) {
display.setTextColor(BLACK, WHITE);
} else {
display.setTextColor(WHITE);
}
int16_t optionY = titleY + 20 + (i * 10);
display.setCursor(0, optionY);
display.println(menuOptions[i]);
}
display.display();
}