Segunda parte del desarrollo de un proyecto de diseño y fabricación de un display para la domótica, realizado principalmente con Displays de 7 segmentos. Estos displays son muy versátiles y los hay de todos los tipos, tamaños y colores.
En el vídeo de hoy utilizamos un display de 4 dígitos controlado desde un ESP8266. Y además haremos una práctica automatización para convertirlo en un reloj digital.
El material utilizado en el vídeo es el siguiente:
A continuación te dejo el enlace al vídeo:
Este es el Mini PC que gobierna mi domótica
Si estás empezando con la domótica, te bastará con una Raspberry Pi 4
Y a continuación el código ESP8266. En primer lugar main.cpp:
#include <ESP8266WiFi.h> // Librería para manejar la conexión WiFi en ESP8266
#include <ESPAsyncTCP.h> // Librería para manejar conexiones TCP asíncronas
#include <ESPAsyncWebServer.h> // Librería para manejar un servidor web asíncrono
#include <ElegantOTA.h> // Librería para permitir actualizaciones OTA (Over The Air)
#include <PubSubClient.h> // Librería para manejar la comunicación MQTT
#include "secrets.h" // Archivo que contiene las credenciales WiFi (ssid y password)
#include "ota.h" // Archivo que contiene funciones de callbacks para ElegantOTA
AsyncWebServer server(80); // Instancia del servidor web en el puerto 80
WiFiClient espClient; // Instancia del cliente WiFi
PubSubClient client(espClient); // Instancia del cliente MQTT usando el cliente WiFi
unsigned long lastMsg = 0; // Variable para almacenar el tiempo del último mensaje MQTT
#define MSG_BUFFER_SIZE (50) // Tamaño del buffer para mensajes MQTT
char msg[MSG_BUFFER_SIZE]; // Buffer para mensajes MQTT
// Tópicos MQTT para mostrar datos y ajustar el retardo
const char* topic_mostrar = "display7seg/mostrar";
const char* topic_retardo = "display7seg/retardo";
int retardo = 0; // Variable para almacenar el retardo entre actualizaciones
int mostrar[4] = {0, 0, 0, 0}; // Array para almacenar los dígitos a mostrar
// Pines para los segmentos del display de 7 segmentos
int segmentos[7] = {12, 16, 10, 15, 13, 2, 14};
// Pines para los dígitos del display
int digitos[4] = {5, 4, 0, 9};
// Mapeo de los números (0-9) a los segmentos del display
int numeros[10] = {
0b1000000, // 0
0b1111001, // 1
0b0100100, // 2
0b0110000, // 3
0b0011001, // 4
0b0010010, // 5
0b0000010, // 6
0b1111000, // 7
0b0000000, // 8
0b0010000 // 9
};
// Función para configurar la conexión WiFi
void setup_wifi() {
delay(10);
Serial.println();
Serial.print("Conexión a ");
Serial.println(ssid);
WiFi.mode(WIFI_STA); // Configura el modo WiFi como cliente
WiFi.begin(ssid, password); // Inicia la conexión a la red WiFi
// Espera hasta que se establezca la conexión WiFi
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi conectado");
Serial.println("IP: ");
Serial.println(WiFi.localIP()); // Imprime la IP asignada
}
// Callback para manejar mensajes MQTT recibidos
void mqtt_recibido(char* topic, byte* payload, unsigned int length) {
Serial.print("Recibido topic: ");
Serial.print(topic);
// Si el mensaje es para ajustar el retardo
if (String(topic) == topic_retardo) {
Serial.print(" Retardo: ");
retardo = 0;
for (unsigned int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
retardo = retardo * 10 + (char)payload[i] - '0'; // Convierte el payload a entero
}
Serial.println();
}
// Si el mensaje es para mostrar dígitos
if (String(topic) == topic_mostrar) {
Serial.print(" Mostrar: ");
for (unsigned int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
mostrar[i] = (char)payload[i] - '0'; // Convierte el payload a entero
}
Serial.println();
}
}
// Función para reconectar al broker MQTT
void reconectar_mqtt() {
while (!client.connected()) {
Serial.print("Conectando MQTT...");
String clientId = "ESP8266Client-";
clientId += String(random(0xffff), HEX); // Genera un ID de cliente aleatorio
if (client.connect(clientId.c_str())) {
Serial.println("conectado");
client.publish("display7seg/estado", "Display 7 segmentos conectado");
client.subscribe(topic_mostrar); // Suscribe a los tópicos necesarios
client.subscribe(topic_retardo);
} else {
Serial.print("fallo, rc=");
Serial.print(client.state());
Serial.println(" intentando de nuevo en 5 segundos");
delay(5000); // Espera 5 segundos antes de intentar reconectar
}
}
}
// Configuración inicial
void setup() {
Serial.begin(115200); // Inicializa la comunicación serie a 115200 baudios
setup_wifi(); // Configura la conexión WiFi
// Configura el servidor web
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send(200, "text/plain", "MicroPIC Display 7 segmentos. Entra en IP/update para actualizar");
});
server.begin(); // Inicia el servidor web
Serial.println("HTTP server iniciado");
ElegantOTA.begin(&server); // Configura ElegantOTA para actualizaciones OTA
ElegantOTA.onStart(onOTAStart);
ElegantOTA.onProgress(onOTAProgress);
ElegantOTA.onEnd(onOTAEnd);
client.setServer(mqtt_server, 1883); // Configura el servidor MQTT
client.setCallback(mqtt_recibido); // Configura el callback para mensajes MQTT recibidos
// Configura los pines de los dígitos como salidas y los apaga
for (int i = 0; i < 4; i++) {
pinMode(digitos[i], OUTPUT);
digitalWrite(digitos[i], false);
}
// Configura los pines de los segmentos como salidas y los enciende (apagado activo bajo)
for (int i = 0; i < 7; i++) {
pinMode(segmentos[i], OUTPUT);
digitalWrite(segmentos[i], true);
}
}
// Bucle principal
void loop() {
static int i, turno, cifra;
if (!client.connected()) {
reconectar_mqtt(); // Reconecta al broker MQTT si la conexión se ha perdido
}
client.loop(); // Mantiene la conexión MQTT
ElegantOTA.loop(); // Mantiene la funcionalidad de ElegantOTA
// Apaga el dígito actual
digitalWrite(digitos[turno % 4], false);
// Cambia al siguiente dígito
turno++;
// Extrae la forma de la cifra a mostrar
cifra = numeros[ mostrar[turno % 4] ];
// Recorre los 7 segmentos
for (i = 0; i < 7; i++) {
// Enciende o apaga cada segmento según la coincidencia con la matriz de números
digitalWrite(segmentos[i], (cifra & (1 << i)));
}
// Enciende el nuevo dígito configurado
digitalWrite(digitos[j], true);
// Retardo entre actualizaciones, configurable vía MQTT
delay(retardo);
}Las funciones de programación Over The Air las he dejado en un fichero llamado ota.h:
unsigned long ota_progress_millis = 0;
void onOTAStart() {
// Log when OTA has started
Serial.println("OTA update started!");
// <Add your own code here>
}
void onOTAProgress(size_t current, size_t final) {
// Log every 1 second
if (millis() - ota_progress_millis > 1000) {
ota_progress_millis = millis();
Serial.printf("OTA Progress Current: %u bytes, Final: %u bytes\n", current, final);
}
}
void onOTAEnd(bool success) {
// Log when OTA has finished
if (success) {
Serial.println("OTA update finished successfully!");
} else {
Serial.println("There was an error during OTA update!");
}
// <Add your own code here>
}
Y por último también necesitarás un fichero para guardar los strings de configuración, llamado secrets.h:
const char* ssid = "tuSSID";
const char* password = "tuPassword";
const char* mqtt_server = "Dirección IP de tu servidor MQTT";
const char* mqtt_usuario = "Usuario de tu servidor MQTT";
const char* mqtt_contrase ="tuPassword";
const char* topic_estado = "display7seg/estado";

