Skip to content

MT07 - Interfaces y aplicaciones

Introducción

En este módulo exploramos herramientas y lenguajes clave para el desarrollo de interfaces gráficas, aplicaciones interactivas y sistemas de control conectados. A continuación, se detallan los temas abordados y sus aplicaciones.

Processing

Processing es un entorno de programación orientado a la creación visual y al diseño interactivo.

Características: Fácil de aprender, ideal para principiantes en programación. Potente para crear gráficos 2D y 3D interactivos. Amplia biblioteca de recursos para animación, sonido y visualización de datos.

Aplicaciones: Arte generativo. Visualización de datos interactiva. Instalaciones multimedia.

Arduino

Arduino es una plataforma de hardware y software de código abierto para la creación de prototipos electrónicos.

Características: Hardware asequible y fácil de usar. Compatible con sensores, actuadores y otros periféricos. Código basado en C/C++.

Aplicaciones: Control de motores, luces y dispositivos electrónicos. Automatización y robótica. Internet de las cosas (IoT).

Node-RED

Node-RED es una herramienta de desarrollo basada en flujos para conectar hardware, APIs y servicios en línea.

Características: Editor visual para la creación de flujos lógicos. Extensible con nodos personalizados. Perfecto para integración en IoT y automatización.

Aplicaciones: Sistemas domóticos. Integración de APIs. Flujos de trabajo automatizados.

Ejemplo de flujo: Un flujo sencillo que lee datos de un sensor de temperatura conectado a un Arduino y los muestra en un dashboard.

P5.js

P5.js es una biblioteca de JavaScript inspirada en Processing para la creación de arte interactivo y visualización en la web.

Características: Basada en JavaScript, ideal para aplicaciones web. Similar a Processing, pero con mayor integración web. Compatible con HTML y CSS.

Aplicaciones: Interactividad en sitios web. Animaciones y visualizaciones en el navegador. Diseño creativo para interfaces web.

Python

Python es un lenguaje de programación versátil, ideal para el desarrollo de aplicaciones, análisis de datos y control de hardware.

Características: Gran cantidad de bibliotecas para todas las necesidades (visualización, IA, IoT). Fácil de aprender y altamente legible. Soporte para múltiples paradigmas de programación.

Aplicaciones: Scripts para automatización. Desarrollo de APIs. Control y análisis de datos en proyectos de hardware.

HTTP Request

Las solicitudes HTTP son fundamentales para la comunicación entre clientes y servidores.

Características: Permiten obtener o enviar datos a través de la web. Compatibles con lenguajes como Python, JavaScript, y más. Base de APIs REST.

Miro + OpenAI

La integración de herramientas de colaboración visual como Miro con IA, específicamente modelos de OpenAI, abre nuevas posibilidades para la creatividad y la productividad.

Características: Uso de diagramas y tableros visuales colaborativos. Generación de contenido y automatización con IA. Aplicaciones en brainstorming y diseño interactivo.

Aplicaciones: Creación colaborativa de ideas. Automatización de flujos de trabajo creativos. Generación de contenido visual basado en datos.

Actividad MT07

Objetivos:

Diseña y desarrolla una interfície digital que interaccione (input/output) con el usuario.

Extra: que muestre información de algún sensor, servicio externo, base de datos o cualquier otra fuente de datos.

Desarrollo:

Como temática a abordar en este desafío elegí el café, siempre café. En la imagen superior se puede apreciar el rudimentario recurso implementado en la oficina para informar el estado del café preparado en el trabajo.

Para esto se utiliza un post-it con el mensaje “Hay café” y la fecha de elaboración. Este mismo concepto lo quise implementar mediante el uso de una ESP 32, una pantalla OLED tres pulsadores y un sensor de temperatura digital 18B20.

El funcionamiento del dispositivo es simple, en el display se muestran las indicaciones de uso, cada botón tiene la función de enviar un mensaje destino (Hay café, Acabo de prepararlo y No hay café) el cual se publica en el sitio web acompañado de la hora de preparación y la temperatura del café.

Aquí se puede apreciar el funcionamiento del prototipo.

Aquí el código implementado:

#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <NTPClient.h>
#include <WiFiUdp.h>

// Configuración Wi-Fi
const char* ssid = "0_0";
const char* password = "claroclaro";

// Configuración del servidor web
AsyncWebServer server(80);

// Configuración del sensor de temperatura 18B20
#define ONE_WIRE_BUS 4
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

// Configuración de botones
#define BTN_CAFE_PIN 15
#define BTN_PREPARADO_PIN 2
#define BTN_NO_CAFE_PIN 13

// Configuración de OLED
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_MOSI   23
#define OLED_CLK    18
#define OLED_DC     16
#define OLED_CS     5
#define OLED_RESET  17

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

// Configuración de NTP para obtener fecha y hora
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 0, 60000); // Actualización cada minuto

// Variables de control
unsigned long lastTempRead = 0;
const long interval = 600000; // 10 minutos
String cafeStatus = "No hay café";
String cafeTimestamp = "";

// Intervalo para el scroll y el tiempo de visualización
unsigned long lastScrollUpdate = 0;
const long scrollInterval = 60000; // 1 minuto
const long displayDuration = 10000; // 10 segundos para cada mensaje

// Bitmap de ejemplo para el logo
const unsigned char logo_bitmap [] PROGMEM = {
  0x00, 0x00, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x3C,
  0x00, 0x3C, 0x42, 0xA5, 0x81, 0x99, 0xA5, 0x42,
  0x00, 0x3C, 0x42, 0xA5, 0x81, 0x99, 0xA5, 0x42,
  0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x3C, 0x00, 0x00
};

// Configuración de la pantalla OLED
void setupOLED() {
  Serial.println("Iniciando pantalla OLED...");
  if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_CS)) {
    Serial.println(F("No se encuentra la pantalla OLED"));
    while (true);
  }
  Serial.println("Pantalla OLED inicializada correctamente.");

  display.clearDisplay();
  display.setTextSize(2); // Aumentar tamaño de texto
  display.setTextColor(WHITE);

  // Mostrar mensaje de bienvenida y logo
  display.setCursor(0, 0);
  display.println("Bienvenido al monitor");
  display.display();
  delay(2000);

  display.clearDisplay();
  display.drawBitmap((display.width() - 32) / 2, (display.height() - 32) / 2, logo_bitmap, 32, 32, WHITE);
  display.display();
  delay(2000);

  // Mostrar instrucciones de uso
  display.clearDisplay();
  display.setCursor(0, 0);
  display.println("Presiona:");
  display.println("Btn1: Hay cafe");
  display.println("Btn2: Preparado");
  display.println("Btn3: No hay cafe");
  display.display();
  delay(2000);
}

// Función para desplazar el texto en el OLED
void scrollDisplay(String message) {
  display.clearDisplay();
  int messageWidth = message.length() * 12; // Aproximación del ancho del texto

  for (int position = SCREEN_WIDTH; position > -messageWidth; position--) {
    display.clearDisplay();
    display.setCursor(position, 0);
    display.println(message);
    display.display();
    delay(1); // Velocidad de desplazamiento
  }
}

// Página HTML para la interfaz web
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <title>Estado del Cafe</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>body { font-family: Arial; text-align: center; }</style>
</head>
<body>
  <h2>Estado del Cafe</h2>
  <p>Mensaje: <span id="estado">%cafeStatus%</span></p>
  <p>Fecha de Preparacion: <span id="timestamp">%cafeTimestamp%</span></p>
  <p>Temperatura: <span id="temperatura">%temp%</span> °C</p>
</body>
<script>
setInterval(() => {
  fetch('/data').then(response => response.json()).then(data => {
    document.getElementById('estado').textContent = data.estado;
    document.getElementById('timestamp').textContent = data.timestamp;
    document.getElementById('temperatura').textContent = data.temp;
  });
}, 10000);
</script>
</html>)rawliteral";

// Función para procesar las variables en HTML
String processor(const String& var) {
  if (var == "cafeStatus") return cafeStatus;
  if (var == "cafeTimestamp") return cafeTimestamp;
  if (var == "temp") return String(sensors.getTempCByIndex(0));
  return String();
}

// Función de setup
void setup() {
  Serial.begin(115200);
  Serial.println("Configurando el sistema...");

  // Inicializar OLED y sensor de temperatura
  setupOLED();
  sensors.begin();
  Serial.println("Sensor de temperatura inicializado.");

  // Configurar botones
  pinMode(BTN_CAFE_PIN, INPUT_PULLUP);
  pinMode(BTN_PREPARADO_PIN, INPUT_PULLUP);
  pinMode(BTN_NO_CAFE_PIN, INPUT_PULLUP);
  Serial.println("Botones configurados.");

  // Conexión Wi-Fi
  Serial.print("Conectando a WiFi...");
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nConectado a WiFi");
  Serial.print("Direccion IP: ");
  Serial.println(WiFi.localIP());

  // Mostrar IP en la pantalla OLED
  display.clearDisplay();
  display.setCursor(0, 0);
  display.println("Conectado a WiFi");
  display.println("Direccion IP:");
  display.println(WiFi.localIP());
  display.display();
  Serial.println("Dirección IP mostrada en la pantalla OLED.");

  // Iniciar servidor web y NTP
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
    request->send_P(200, "text/html", index_html, processor);
  });

  server.on("/data", HTTP_GET, [](AsyncWebServerRequest *request) {
    String json = "{\"estado\":\"" + cafeStatus + "\",\"timestamp\":\"" + cafeTimestamp + "\",\"temp\":\"" + String(sensors.getTempCByIndex(0)) + "\"}";
    request->send(200, "application/json", json);
  });

  server.begin();
  timeClient.begin();
  Serial.println("Servidor web y NTP iniciados.");
}

// Función de loop
void loop() {
  // Actualizar hora desde NTP
  timeClient.update();

  // Leer botones
  if (digitalRead(BTN_CAFE_PIN) == LOW) {
    cafeStatus = "Hay café";
    scrollDisplay(cafeStatus); // Desplazar el mensaje
    delay(500);
    Serial.println("Estado cambiado a: Hay café");
  }
  if (digitalRead(BTN_PREPARADO_PIN) == LOW) {
    cafeStatus = "Acabo de prepararlo";
    cafeTimestamp = timeClient.getFormattedTime(); // Guardar fecha y hora de preparación
    scrollDisplay(cafeStatus); // Desplazar el mensaje
    delay(500);
    Serial.println("Estado cambiado a: Acabo de prepararlo");
  }
  if (digitalRead(BTN_NO_CAFE_PIN) == LOW) {
    cafeStatus = "No hay café";
    scrollDisplay(cafeStatus); // Desplazar el mensaje
    delay(500);
    Serial.println("Estado cambiado a: No hay café");
  }

  // Leer temperatura cada 10 minutos
  unsigned long currentMillis = millis();
  if (currentMillis - lastTempRead >= interval) {
    sensors.requestTemperatures();
    lastTempRead = currentMillis;
  }

  // Actualizar la pantalla OLED con la temperatura y el estado
  if (currentMillis - lastScrollUpdate >= scrollInterval) {
    display.clearDisplay();
    display.setCursor(0, 0);
    display.println(cafeStatus);
    display.println(cafeTimestamp);
    display.println("Temp: " + String(sensors.getTempCByIndex(0)) + " °C");
    display.display();
    lastScrollUpdate = currentMillis;
  }
}

Conclusión

El módulo de Interfaces y Aplicaciones proporciona las bases para conectar software, hardware y servicios en proyectos interactivos. Este conocimiento es esencial para diseñar soluciones modernas en áreas como IoT, interfaces creativas y automatización.


Last update: December 18, 2024