En el artículo anterior vimos como podías configurar lo necesario para poder tener un repositorio de información que te sirviera para comenzar con tu proyecto de internet de las cosas. Ahora continuamos con la segunda parte (la más divertida) que es armar el prototipo para generar la información a partir del sensor.
Los materiales
Para este artículo, vamos a utilizar los siguientes materiales:
1 Arduino (de preferencia UNO, no importa siempre y cuando pueda soportar un shield de ethernet).
1 Un shield de ethernet.
1 Sensor DHT11.
1 Pantalla LCD con I2C (puede ser sin el módulo, solo por ahorrar pines).
Si no tienes los componentes, puedes escribir a este correo, hacen entregas a todo el país y pueden mandarte hasta armado el prototipo.
El montaje del prototipo
Viene la parte más divertida, montar todo tu equipo. Sigue el siguiente diagrama para poder hacerlo.
¿Listo? Vamos por el código de Arduino por partes. Primero las declaraciones de variables y bibliotecas de clases requeridas.
#include <dht.h> #include <Wire.h> #include <LiquidCrystal_I2C.h> #include <SPI.h> #include <Ethernet.h> LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); dht weatherSensor; byte mac[] = { 0x90, 0xA2, 0xDA, 0x0F, 0xEC, 0x6C }; String bodyMessage; EthernetClient client; |
Las referencias a las bibliotecas de clases son para el sensor DHT11, las dos siguientes son para la pantalla LCD y las dos últimas para la conexión vía ethernet. Por el lado de las variables, la primera se refiere a la pantalla con el módulo I2C, la segunda al sensor de temperatura y humedad, el arreglo de bytes a la dirección mac del shield, la cuarta la usaremos para envío de información y por último la variable para ethernet.
El primer método indispensable para Arduino, el método setup establece los valores para el monitoreo serial y la pantalla, después para el cliente de conexión. Notarás que hay un método llamado printLcdMessage, ya lo escribiremos.
void setup() { Serial.begin(9600); lcd.begin(16,2); lcd.backlight(); printLcdMessage( 0, "Datos: Iniciando"); if (Ethernet.begin(mac) == 0) { printLcdMessage( 0, "Datos: Fallida"); for (;;) ; } } |
En el segundo método básico para una aplicación de Arduino vamos a establecer los métodos necesarios que estarán repitiendose de manera cíclica con una frecuencia de cinco segundos.
void loop() { bodyMessage = BodyMessageGenerator(); send_request(); wait_response(); read_response(); end_request(); delay(5000); } |
Solo por el nombre de los métodos notarás para que es cada uno y serán muy fáciles de comprender por lo mismo. Vamos a ver a cada uno comenzando por el más importante, el que envía información vía el API REST a un mobile service de Azure. Utiliza los encabezados requeridos y es importante que la longitud del mensaje sea exacta.
void send_request() { printLcdMessage( 0, "Datos:Conectando"); if (client.connect("internetofthingsservice.azure-mobile.net", 80)) { client.println("POST /tables/<<la tabla que estarás usando>> HTTP/1.1"); client.println("Host: <<la direccion de tu sitio>>"); client.println("X-ZUMO-APPLICATION: <<tus llaves de acces>>"); client.println("Accept: application/json"); client.println("Content-Length: 109"); client.println(); client.print(bodyMessage); client.println(); printLcdMessage( 0, "Datos: Enviados "); } else { printLcdMessage(0, "Conexion: Fallida"); } } |
Vamos con el método que esperará pacientemente la respuesta que nos dará el resultado de la operación.
void wait_response() { while (!client.available()) { if (!client.connected()) { return; } } } |
Después el método que lee la respuesta.
void read_response() { bool print = true; while (client.available()) { char c = client.read(); if (c == '\n') print = false; if (print) Serial.println(c); } } |
Un método muy simple para cerrar conexión.
void end_request() { client.stop(); } |
Después vamos por el método que se encargará de imprimir mensajes en la pantalla, todos los mensajes relacionados a nuestra conexión de datos, al final, no pensamos tener todo el tiempo el prototipo en modo de depuración.
void printLcdMessage(int line, String message) { lcd.setCursor(0,0); lcd.print(message); } |
Una variable del método anterior te ayudará a mostrar en la pantalla la información que viene del sensor. Esta será una gran referencia para que puedas comprobar que lo que tienes en tu base de datos será lo que tienes también en tu pantalla.
void printLcdWeather(double temp, double humi) { lcd.setCursor(0,1); lcd.print("T= "); lcd.print(int(temp)); lcd.print(" C H= "); lcd.print(int(humi)); lcd.print(" %"); } |
Por último, solo debes obtener el cuerpo del mensaje que desplegarás al servicio móvil de Azure para que vaya directo a la base de datos. Este mensaje estará en formato JSON y debes formarlo de esa manera para evitar cualquier error.
String BodyMessageGenerator() { weatherSensor.read11(A0); printLcdWeather(weatherSensor.temperature, weatherSensor.humidity); String sensorName = "\"SensorName\": \"Sensor Microsoft\", \"Latitude\": 19.3662, \"Longitude\": -99.2445"; String temperature = "\"Temperature\": " + String(int(weatherSensor.temperature)); String humidity = "\"Humidity\": " + String(int(weatherSensor.humidity)); String wrapper = "{" + sensorName + ", " + temperature + ", " + humidity + "}"; return wrapper; } |
El video a continuación te dará una mejor referencia de lo que debes tener hasta este momento.
¡Listo! Hemos cumplido con la aprte electrónica. Ahora es momento de ir con la siguiente. La creación de la infraestructura necesaria para almacenar todo esto.
Si quieres descargar el código de este ejercicio, puedes hacerlo desde aquí.
Si deseas descargar el código completo, puedes hacerlo desde aquí.
Hola Amin, oye una duda me pudieras explicar como puedo mandar una cadena de longitud de datos variable a la nube de Azure, te adjunto el código.
CuerpoMensaje = GeneradorCuerpoMensaje();
client.println(«POST /tables/X HTTP/1.1»);
client.println(«Host: XXX.azure-mobile.net»);
client.println(«X-ZUMO-APPLICATION: XXX-YYY»);
client.println(«Content-Type: application/json»);
client.println(«Content-Length: «);
client.println(CuerpoMensaje.length());
client.println(CuerpoMensaje);
client.println();
Serial.println(«Datos enviados»);
String GeneradorCuerpoMensaje()
{
float gps_lat = gps.location.lat();
float gps_lng = gps.location.lng();
String nombreSensor = «\»Nombresensor\»:\»GPS\»»;
String latitud = «\»Latitud\»:» + String((float)gps_lat);
String longitud = «\»Longitud\»:» + String((float)gps_lng);
String wrapper = «{» + nombreSensor + «,» + latitud + «,» + longitud + «}»;
Serial.println(wrapper);
return wrapper;
}
Lo que me gustaría seria enviar el String de datos sin necesidad agregar el numero de caracteres en la parte de Content-Length:, dado que la longitud puede variar.
Quedo al pendiente de tu respuesta.
Saludos.
Ops! Perdona la respuesta tan lenta! Es fácil, solo calcula la longitud de tu cadena final, colócala como una variable global en tu código y listo!!
Hola, como puedo hacer lo mismo pero por medio de wifi sin usar ethernet?
Solo usando un módulo de Wifi en lugar de uno de Ethernet, en cuanto al código es esencialmente el mismo.
Buenas tardes soy nuevo en esto pero me gustaria enlazar una cerradura electrica con enlace azure que esto mw permita abrir y cerrar la cerradura desde cualquier sitio del pais.si se puede me reponde
hola desearia enlazar una chapa electrica de 12 v desde arduino para enviar datos a azure y por medio de ello abrir la chapa y cerrarlo
Muy buen reto de proyecto, dame un poco de tiempo para hacerlo y lo subiré.
Estimado, los link del código están rotos. Por favor los podrías volver a cargar.
POSITIVE no me reconoce:
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
Se que solo se necesita dos lineas para el I2C, porque tantos argumentos de entrada.
Hola Alberto, dame unos días para renovar por completo el post, la tecnología mostrada acá ya no existe ahora. Saludos!!
Excelente Bloc, he estado leyendo tus artículos todos me parecer estupendos. Gracias por compartir tu conocimiento y experiencia.
hola, excelente trabajo… quiero hacer lo mismo con una goblin 2. Que necesito hacer en el codigo?
Funciona para HTTPS ?
Esencialmente si, el problema es que usar un certificado aquí puede incrementar mucho el peso de la transacción y quizá Arduino no sea lo mejor para soportar una operación de ese tipo.
Hola excelente explicacion. Como harias, si quisieras enviar informacion desde azure al arduino? Gracias.
Para ello el proceso es mucho más complejo, necesitas hacer un agente en tu script de Arduino para monitorear periodicamente la información que quisieras jalar desde Azure.
Muchas Gracias Amin, muy amable. Una ultima, tendrás información para hacer algo similar con Sinalr o Mqqt? Saludos desde Venezuela.