El Electric Imp es un dispositivo increíble para proyectos de IoT y su integración con Ubidots hace que sea muy simple crear gráficos y alertas por SMS/Email en unos pocos minutos. En este tutorial de Electric Imp, te enseñaremos cómo usar la placa de expansión Electric Imp con un sensor DHT11 para medir la temperatura y la humedad relativa, y luego calcular el Punto de Rocío utilizando el motor matemático de Ubidots.
El punto de rocío se puede usar como un índice para la percepción humana de confort en relación con el clima; un punto de rocío entre 13-16°C (55-59°F) te hace sentir cómodo, pero un punto de rocío por encima de 21°C (70°F) te hará sentir demasiado cálido porque el aire tendría demasiada humedad y tu cuerpo no podría enfriarse:
Punto de Rocío Percepción humana 24-26 °C 75-80°F Extremadamente incómodo, opresivo 21-24 °C 70-74°F Muy húmedo, bastante incómodo 18-21 °C 65-69°F Algo incómodo para la mayoría de las personas en el límite superior 16-18 °C 60-64°F Aceptable para la mayoría, pero todos perciben la humedad en el límite superior 13-16 °C 55-59°F Cómodo 10-12 °C 50-54°F Muy cómodo Por debajo de 10 °C Por debajo de 50°F Un poco seco
Afortunadamente, hay una función lineal para calcular el punto de rocío basado en la temperatura y la humedad relativa.
1. Materiales
Un Imp
Una placa de expansión Electric Imp
Tres cables hembra a hembra
Resistor de 10k
Sensor de humedad y temperatura DHT11
2. Cableado
Así es como se conecta el sensor DHT11 a tu placa Electric Imp:
3. Código
¡Es hora de codificar! Al trabajar con Electric Imp, necesitarás dos secciones de código: una para el dispositivo y otra para el agente. Aquí está el código del dispositivo (un poco largo ya que tiene la clase para manejar el DHT11):
SPICLK = 937.5;// Clase para leer el sensor de temperatura/humedad DHT11// Estos sensores utilizan un protocolo propietario de un solo hilo. El imp// emula este protocolo con SPI. // Para usar:// - conecta MOSI a MISO con un resistor de 10k// - conecta MISO a la línea de datos en el sensorclass DHT11 { static STARTTIME_LOW = 0.001000; // 1 ms de tiempo bajo para inicio static STARTTIME_HIGH = 0.000020; // 20 us de tiempo alto mínimo para inicio static STARTTIME_SENSOR = 0.000080; // 80 us bajo / 80 us alto "ACK" del sensor en INICIO static MARKTIME = 0.000050; // 50 us de pulso bajo entre marcas 0 o 1 static ZERO = 0.000026; // 26 us alto para "0" static ONE = 0.000075; // 70 us alto para "1" spi = null; clkspeed = null; bittime = null; bytetime = null; start_low_bits = null; start_low_bytes = null; start_high_bits = null; start_high_bytes = null; start_ack_bits = null; start_ack_bytes = null; mark_bits = null; mark_bytes = null; zero_bits = null; zero_bytes = null; one_bits = null; one_bytes = null; // constructor de clase // Entrada: // _spi: un periférico SPI preconfigurado (por ejemplo, spi257) // _clkspeed: la velocidad a la que se ha configurado el SPI // Retorno: (Ninguno) constructor(_spi, _clkspeed) { this.spi = _spi; this.clkspeed = _clkspeed; bittime = 1.0 / (clkspeed * 1000); bytetime = 8.0 * bittime; start_low_bits = STARTTIME_LOW / bittime; start_low_bytes = (start_low_bits / 8); start_high_bits = STARTTIME_HIGH / bittime; start_high_bytes = (start_high_bits / 8); start_ack_bits = STARTTIME_SENSOR / bittime; start_ack_bytes = (start_ack_bits / 8); mark_bits = MARKTIME / bittime; mark_bytes = (mark_bits / 8); zero_bits = ZERO / bittime; zero_bytes = (zero_bits / 8); one_bits = ONE / bittime; one_bytes = (one_bits / 8); } // función auxiliar // dado un blob largo, encuentra los tiempos entre transiciones y analiza a // valores de temperatura y humedad. Asume un valor de retorno de 40 bits (16 humedad / 16 temp / 8 checksum) // Entrada: // hexblob (blob de longitud arbitraria) // Retorno: // tabla que contiene: // "rh": humedad relativa (float) // "temp": temperatura en celsius (float) // si la lectura falla, rh y temp devolverán 0 function parse(hexblob) { local laststate = 0; local lastbitidx = 0; local gotack = false; local rawidx = 0; local result = blob(5); // 2 bytes de humedad, 2 bytes de temp, 1 byte de checksum local humid = 0; local temp = 0; // iterar a través de cada bit de cada byte de la señal devuelta for (local byte = 0; byte < hexblob.len(); byte++) { for (local bit = 7; bit >= 0; bit--) { local thisbit = (hexblob[byte] & (0x01 << bit)) ? 1:0; if (thisbit != laststate) { if (thisbit) { // transición de bajo a alto; observa cuánto tiempo está alto laststate = 1; lastbitidx = (8 * byte) + (7 - bit); } else { // transición de alto a bajo; laststate = 0; local idx = (8 * byte) + (7 - bit); local hightime = (idx - lastbitidx) * bittime; // ahora tenemos un bit válido de información. Averigua qué símbolo es. local resultbyte = (rawidx / 8); local resultbit = 7 - (rawidx % 8); //server.log(format("bit %d of byte %d",resultbit, resultbyte)); if (hightime < ZERO) { // esto es un cero if (gotack) { // no registrar ningún dato antes de que se vea el ACK result[resultbyte] = result[resultbyte] & ~(0x01 << resultbit); rawidx++; } } else if (hightime < ONE) { // esto es un uno if (gotack) { result[resultbyte] = result[resultbyte] | (0x01 << resultbit); rawidx++; } } else { // esto es un ACK de INICIO gotack = true; } } } } } //server.log(format("parsed: 0x %02x%02x %02x%02x %02x",result[0],result[1],result[2],result[3],result[4])); humid = (result[0] * 1.0) + (result[1] / 1000.0); if (result[2] & 0x80) { // temperatura negativa result[2] = ((~result[2]) + 1) & 0xff; } temp = (result[2] * 1.0) + (result[3] / 1000.0); if (((result[0] + result[1] + result[2] + result[3]) & 0xff) != result[4]) { return {"rh":0,"temp":0}; } else { return {"rh":humid,"temp":temp}; } } // leer el sensor // Entrada: (ninguna) // Retorno: // tabla que contiene: // "rh": humedad relativa (float) // "temp": temperatura en celsius (float) // si la lectura falla, rh y temp devolverán 0 function read() { local bloblen = start_low_bytes + start_high_bytes + (40 * (mark_bytes + one_bytes)); local startblob = blob(bloblen); for (local i = 0; i < start_low_bytes; i++) { startblob.writen(0x00,'b'); } for (local j = start_low_bytes; j < bloblen; j++) { startblob.writen(0xff,'b'); } //server.log(format("Sending %d bytes", startblob.len())); local result = spi.writeread(startblob); return parse(result); }}rele <- hardware.pin9;spi <- hardware.spi257;while(1){clkspeed <- spi.configure(MSB_FIRST, SPICLK);dht11 <- DHT11(spi, clkspeed);data <- dht11.read();server.log(format("Humedad Relativa: %0.1f",data.rh)+" %");server.log(format("Temperatura: %0.1f C",data.temp));agent.send("temp",data.temp);imp.sleep(1);}
ver rawdevice.nut alojado con ❤ por GitHub
Gracias a Thomas Byrne por proporcionar la clase para manejar el sensor DHT11 en Github.
Como puedes ver, el código del Agente es realmente simple, solo no olvides poner tu propio token de autenticación e ID de Variable en la llamada HTTP:
device.on("temp", function(value) { server.log("Intentando publicar en Ubi el valor:"); server.log(value); local headers = { "Content-Type": "application/json", "X-Auth-Token": "NBbF3PWPxWc2IaO40aXOKnhIu8tOv92rYN3ibiEc7Jh6GV3KZUUCHtXuNz7Y" }; // Reemplaza el token con el tuyo local url = "http://things.ubidots.com/api/v1.6/variables/53d2beb37625424630223dac/values"; // Reemplaza el ID de Variable con el tuyo local string = {"value": value}; local request = http.post(url, headers, http.jsonencode(string)); local response = request.sendsync();});
ver rawagent.nut alojado con ❤ por GitHub
4. Crear una variable derivada en Ubidots.
Así como agregarías una nueva variable, ve a "Fuentes"--> "Electric Imp (el nombre de tu fuente de datos)"-->"Agregar nueva Variable":
Ahora ingresa esta ecuación para calcular el Valor del Punto de Rocío:
¡Ahora deberías ver los datos del Punto de Rocío actualizarse cada vez que tu Imp envíe datos de Temperatura y Humedad a Ubidots!
5. Conclusión
En este proyecto pudimos conectar un Imp a Ubidots, midiendo y calculando variables físicas para entender mejor nuestro entorno. Puedes explorar más cosas como crear alertas cuando el Punto de Rocío esté demasiado alto, o crear gráficos compartibles como los que están al principio de este artículo.
No olvides revisar algunas de nuestras últimas publicaciones:
Si eres nuevo en Ubidots, haz clic a continuación para comenzar:
Publicado originalmente en Ubidots Blog el 18 de agosto de 2014.