MirrorDuino
Campus de Vicálvaro – Grupo 8
¿Qué es MirrorDuino?
MirrorDuino es un producto mínimo viable de IoT. MirrorDuino es un espejo que te muestra qué tiempo va a hacer en el día y la hora que es. Es perfecto para todos aquellos despistados (y no tan despistados) que justo el día que llueve se les olvida el paraguas en casa. Si te has sentido identificado, no te preocupes. MirrorDuino te recordará que cojas el paraguas si está lloviendo o va a llover a lo largo del día. También te dirá si vas a disfrutar de un día soleado ☀️ , nublado ☁️ o incluso si va a nevar ❄️ .
¿Cómo funciona?
MirrorDuino funciona gracias a una placa WiFi, la cual realiza peticiones a una API que nos devolverá el tiempo en nuestra ciudad y la hora actual.
Para poder tener el tiempo de nuestra ciudad en tiempo real vamos a utilizar la API de OpenWeatherMap. Su API es simple, es fácil de usar y es gratis, por lo que es perfecta para nuestro proyecto. Para poder utilzarla, nos tendremos que registrar en su página web y crear una API Key para nosotros. Si estás realizando el proyecto, es útil que guardes el número de tu API Key porque la tendrás que utilizar posteriormente en el Sketch de Arduino para obtener los datos.
Para tener la hora actual, no utilizaremos un RTC (Real Time Clock) sino que nos aprovecharemos de nuestra conexión a internet para configurar la hora en tiempo real de nuestra zona horaria.
Los datos obtenidos se mostrarán mediante un display que formará parte de nuestro espejo.
¿Qué necesitamos para que MirrorDuino funcione?
Para realizar el proyecto utilizamos:
- Placa nodeMCU (ESP8266 ESP-12E)
Esta placa es una de las más utilizadas para realizar proyectos de IoT, es versatil, rápido y compatible con Arduino IDE. Funciona igual que Arduino Uno, tiene 11 pines a los que puedes conectar leds, resistencias, pulsadores, lcds y todo lo que te imagines. Solo tienes que conectarlo mediante el microusb y subir el Sketch. Voilá.
Se utiliza esta placa para realizar el proyecto porque uno de los problemas encontrados para utilizar Arduino Uno con un módulo Wi-Fi, como ESP-01, fue que permitía la conexión mediante comandos por Serial Monitor, lo que imposibilitaba utilizar los datos de la API posteriormente. Además el uso de Arduino Uno junto con ESP-01 requería una gran cantidad de cables y hardware, que con el módulo nodeMCU se elimina. Al pivotar hacía el módulo nodeMCU (ESP8266 ESP-12E) se consiguió optimizar el proyecto, realizándose las conexiones de forma más eficiente.
- LCD Display 20×4
El display utilizado para realizar el proyecto es un display LCD de 20×4, es decir de 20 caracteres por 4 líneas. Se eligió este para realizar el proyecto ya que permite mostrar la información necesaria y no se excede en tamaño, esto es importante tenerlo en cuenta para al montar el espejo posteriormente.
- Cables puente (hembra hembra)
Los cables utilizados para conectar la placa nodeMCU (ESP8266 ESP-12E) y el LCD Display 20×4 son cables de puente hembra hembra. Esto nos permite no tener que soldar en la placa, y poder montar y deshacer el proyecto cuando queramos.
-
Vinilo simulador de espejo
-
Tabla de madera para que actúe como soporte
- Cinta adesiva de doble cara
Se utiliza cinta adesiva de doble cara para que el proyecto se pueda desmontar. También se puede pegar directamente el vinilo sobre la tabla, para que fuera permanente.
- Cable microusb → usb
Para poder conectar el la placa nodeMCU al ordenador, y subir el Sketch.
El presupuesto del proyecto es el siguiente:
¿Cómo llegamos al producto final?
Circuito y código
#include <SPI.h>
#include <Wire.h>
#include <Math.h>
#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
// Replace with your SSID and password details
char ssid[] = "ssdi";
char pass[] = "password";
// Open Weather Map API server name
const char server[] = "api.openweathermap.org";
// Replace with the name of your city
String nameOfCity = "madrid";
//Replace with your time zone
int timezone = 2 * 3600;
int dst = 0;
// Replace with your API Key
String apiKey = "yourAPIKey";
String text;
int jsonend = 0;
boolean startJson = false;
int status = WL_IDLE_STATUS;
#define JSON_BUFF_DIMENSION 2500
unsigned long lastConnectionTime = 10 * 60 * 1000; // last time you connected to the server, in milliseconds
const unsigned long postInterval = 10 * 60 * 1000; // posting interval of 10 minutes (10L * 1000L; 10 seconds delay for testing)
void setup() {
lcd.begin(20,4);
lcd.init();
// Turn on the backlight.
lcd.backlight();
Serial.begin(9600);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid,pass);
Serial.println("connecting");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("WiFi Connected");
printWiFiStatus();
//Open connection for getting time
configTime(timezone, dst, "pool.ntp.org","time.nist.gov");
Serial.println("nWaiting for NTP...");
while(!time(nullptr)){
Serial.print("*");
delay(1000);
}
}
void loop() {
displayTime();
//check the internet connection
if (millis() - lastConnectionTime > postInterval) {
// note the time that the connection was made:
lastConnectionTime = millis();
makehttpRequest();
}
}
void displayTime(){
time_t now = time(nullptr);
struct tm* p_tm = localtime(&now);
//print the time in the serial monitor
Serial.print(p_tm->tm_hour);
Serial.print(":");
Serial.print(p_tm->tm_min);
Serial.print(":");
Serial.println(p_tm->tm_sec);
//print the time in the display
lcd.setCursor(15,0);
lcd.print(p_tm->tm_hour);
lcd.print(":");
lcd.print(p_tm->tm_min);
}
// print Wifi status
void printWiFiStatus() {
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}
// to request data from OWM
void makehttpRequest() {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http; //Object of class HTTPClient
http.begin("http://api.openweathermap.org/data/2.5/forecast?q=madrid&APPID=7bb709545cd426183f0a58f544fb7d6a&mode=json&units=metric&cnt=2");
int httpCode = http.GET();
if (httpCode > 0) {
const size_t bufferSize = JSON_ARRAY_SIZE(3) + 2*JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(2) + 3*JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(5) + JSON_OBJECT_SIZE(6) + JSON_OBJECT_SIZE(12) + 480;
DynamicJsonBuffer jsonBuffer(bufferSize);
String json_string= http.getString();
Serial.println(json_string);
int str_len = json_string.length() + 1;
char json_char_array[str_len];
json_string.toCharArray(json_char_array, str_len);
JsonObject& root = jsonBuffer.parseObject(json_char_array);
JsonArray& list = root["list"];
JsonObject& nowT = list[0];
JsonObject& later = list[1];
String city = root["city"]["name"];
float tempNow = nowT["main"]["temp"];
float tempMax = nowT["main"]["temp_max"];
float humidityNow = nowT["main"]["humidity"];
String weatherNow = nowT["weather"][0]["main"];
float tempLater = later["main"]["temp"];
float humidityLater = later["main"]["humidity"];
String weatherLater = later["weather"][0]["main"];
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("It's ");
lcd.print(tempNow);
lcd.print(" C");
lcd.setCursor(0, 1);
if (weatherNow == "Rain" || weatherNow == "Drizzle" || weatherNow == "Thunderstorm" ){
Serial.println("¡No te dejes el paraguas en casa! Luego va a llover");
lcd.print("Take your umbrella!");
}else if (weatherNow == "Snow"){
Serial.println("Ponte los skis en lugar de los zapatos, ¡va a nevar!");
lcd.print("It's snowing!");
}
else if (weatherNow == "Clear") {
Serial.println("¡Hoy te espera un día soleado!");
lcd.print("Clear now!");
}
else if (weatherNow == "Clouds") {
Serial.println("It's cloudy! Now it's");
lcd.print("It's cloudy!");
}
else {
lcd.print("Look through the window!");
}
lcd.setCursor(0,2);
lcd.print("The high today:");
lcd.print(tempMax);
lcd.print(" C");
lcd.setCursor(0,3);
if (weatherLater == "Rain" || weatherLater == "Drizzle" || weatherLater == "Thunderstorm" ){
Serial.println("Don't forget your umbrella");
lcd.print("Take your umbrella!");
}else if (weatherLater == "Snow"){
Serial.println("Take your skis with you today");
lcd.print("It'll be snowing!");
}
else if (weatherLater == "Clear") {
Serial.println("The sky will be clear today");
lcd.print("Clear later");
}
else if (weatherLater == "Clouds") {
Serial.println("Cloudy later");
lcd.print("Cloudy later");
}
else {
lcd.print("Look through the window!");
}
}
//Close connection
http.end();
}
delay(60000);
}
Para realizar la petición y poder utilizar la API son necesarias las siguientes librerías:
#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
ESP8266Wifi.h → nos permite tener WiFi en la placa. Hace posible que podamos establecer la conexión indicando nuestro ssdi y la contraseña. ✅ ⚠️ Uno de los problemas que encontré fue conectarlo al internet de mi móvil, utilizando este como hotspot. Para conectar ESP8266 ESP-12E al internet compartido por tu móvil hay que añadir:WiFi.mode(WIFI_STA);
Antes de introducir el ssdi y contraseña de la red WiFi. ✅
ESP8266HTTPClient.h → nos permite realizar la petición get y recibir los datos de la API de OpenWeatherMap. ✅
ArduinoJson.h → nos permite interpretar la información recibida del servidor y convertirla en objetos de javaScript para poder sacar los datos que necesitemos. ✅
Si quieres descubrir más de cómo funciona la librería de ArduinoJson, pulsa aquí 👈🏻
Futuros pasos
- Utilizar la API de Google Maps para mostrar el tráfico y la mejor ruta para llegar a tu destino.
- Cambiar el LCD Display por un monitor que permite diseñar una interfaz para una mejor experiencia del usuario.