Ahora para redondear esta serie un simple dispositivo barato basado en ESP8266 con uno o dos DS18B20 Sensores. Dado que el dispositivo sólo está activo cada 5 minutos durante unos pocos milisegundos, se puede operar muy bien con baterías. La batería de la imagen es simbólica. Si utiliza el pin de +5V del D1-Mini para utilizar el regulador de voltaje incorporado a 3,3 V, necesita al menos 3 baterías con 1,5 V cada una.
¡Atención! La conexión de cable naranja se utiliza para despertarlo fuera del modo de suspensión y debe ser eliminado para parpadear.
Ahora el código:
Para la versión final que desea ejecutar con batería, el indicador DEBUG debe establecerse en false.
/* Sensor de temperatura Wi-Fi ESP ahora a la puerta de enlace mqTT Si aún no se ha determinado ninguna dirección MAC el sensor está buscando una red inalámbrica (WLAN) con SSID MQTTGateway Cuando encuentra el AP, recuerda la dirección MAC siempre y cuando la fuente de alimentación no se haya interrumpido El protocolo ESP Now es muy rápido, así que sólo muy poco tiempo (nosotros) flujos de corriente más altos. El sensor envía datos de temperatura y luego entra en el sueño profundo por lo que se consume muy poca energía y el por lo tanto, el sensor se puede operar con baterías. */ Biblioteca para WiFi #include <ESP8266WiFi.H> Bibliotecas para sensor de temperatura DS18B20 #include <OneWire.H> #include <DallasTemperatura.H> #include <CayenneLPP.H> Biblioteca para ESP Ahora Externos "C" { #include <espnow.H> } SSID de la puerta de enlace #define GW_SSID "MQTTGateway" Marcar la depuración si se suprimen todos los mensajes de depuración para ahorrar energía adicional #define Depuración Verdad Constantes para WiFi #define SEND_TIMEOUT 2000 Tiempo de espera de 2 segundos Mapeo de canales #define CHANNEL_TEMPI 1 #define CHANNEL_TEMPE 2 Pines para sensores de temperatura Const Byte bus_int = 2; GPIO2 Const Byte bus_ext = 4; GPIO4 Estructura de datos para la memoria Rtc con suma de comprobación en torno a la validez para comprobar esto la dirección MAC se guarda Estructura MEMORYDATA { uint32_t crc32; uint8_t Mac[6]; uint32_t Canal; }; Datos globales Volátil Bool callbackCalled; Memoria para valores de temperatura Flotador temp_int = 0; Flotador temp_ext = 0; Booleana has_int = 0; Booleana has_ext = 0; Dirección MAC y canal Wi-Fi MEMORYDATA statinfo; búfer de datos en formato LPP CayenneLPP Lpp(64); Autobús a los sensores OneWire oneWire_int(bus_int); OneWire oneWire_ext(bus_ext); DallasTemperatura sensoren_int(&oneWire_int); DallasTemperatura sensoren_ext(&oneWire_ext); Matriz para almacenar direcciones de sensores DeviceAddress adressen_int; DeviceAddress adressen_ext; Subprograma para calcular la suma de comprobación uint32_t calculateCRC32(Const uint8_t *Datos, Size_t Longitud) { uint32_t Crc = 0xffffffff; Mientras (Longitud--) { uint8_t C = *Datos++; Para (uint32_t Ⅰ. = 0x80; Ⅰ. > 0; Ⅰ. >>= 1) { Bool Poco = Crc & 0x80000000; Si (C & Ⅰ.) { Poco = !Poco; } Crc <<= 1; Si (Poco) { Crc ^= 0x04c11db7; } } } devolución Crc; } Escribe la estadística de la estructura de datos con la suma de comprobación correcta en la memoria RTC Vacío UpdateRtcMemory() { uint32_t crcOfData = calculateCRC32(((uint8_t*) &statinfo) + 4, Sizeof(statinfo) - 4); statinfo.crc32 = crcOfData; Esp.rtcUserMemoryWrite(0,(uint32_t*) &statinfo, Sizeof(statinfo)); } busca un AccessPoint adecuado Vacío ScanForSlave() { Bool slaveFound = 0; int8_t scanResults = Wifi.scanNetworks(); restablecer en cada escaneo Si (Depuración) Serial.println("Escaneo hecho"); Si (scanResults == 0) { Si (Depuración) Serial.println("No se han encontrado dispositivos WiFi en el modo AP"); } Más { Si (Depuración) Serial.Impresión("Encontrado"); Si (Depuración) Serial.Impresión(scanResults); Si (Depuración) Serial.println(" dispositivos "); Para (Int Ⅰ. = 0; Ⅰ. < scanResults; ++Ⅰ.) { Imprima SSID y RSSI para cada dispositivo encontrado Cadena Ssid = Wifi.Ssid(Ⅰ.); int32_t Rssi = Wifi.Rssi(Ⅰ.); int32_t Chl = Wifi.Canal(Ⅰ.); Cadena BSSIDstr = Wifi.BSSIDstr(Ⅰ.); Si (Depuración) { Serial.Impresión(Ⅰ. + 1); Serial.Impresión(": "); Serial.Impresión(Ssid); Serial.Impresión(" /"); Serial.Impresión(Chl); Serial.Impresión(" ("); Serial.Impresión(Rssi); Serial.Impresión(")"); Serial.println(""); } Retraso(10); Compruebe si el dispositivo actual comienza con 'Termómetro' Si (Ssid == GW_SSID) { SSID de interés Si (Depuración) { Serial.println("Encontrado un esclavo."); Serial.Impresión(Ⅰ. + 1); Serial.Impresión(": "); Serial.Impresión(Ssid); Serial.Impresión(" ["); Serial.Impresión(BSSIDstr); Serial.Impresión("]"); Serial.Impresión(" ("); Serial.Impresión(Rssi); Serial.Impresión(")"); Serial.println(""); } Int Mac[6]; determinamos la dirección MAC y la almacenamos en la memoria RTC Si ( 6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x%c", &Mac[0], &Mac[1], &Mac[2], &Mac[3], &Mac[4], &Mac[5] ) ) { Para (Int Ⅱ. = 0; Ⅱ. < 6; ++Ⅱ. ) { statinfo.Mac[Ⅱ.] = (uint8_t) Mac[Ⅱ.]; } statinfo.Canal = Chl; UpdateRtcMemory(); } slaveFound = 1; Después de que se encuentre el AP, podemos cancelar Romper; } } } Si (Depuración) { Si (slaveFound) { Serial.println("Esclavo encontrado, procesamiento.".); } Más { Serial.println("Esclavo no encontrado, inténtelo de nuevo."); } } Compartir RAM Wifi.scanDelete(); } función para imprimir una dirección del sensor Vacío printAddress(DeviceAddress Direcciones) { Para (uint8_t Ⅰ. = 0; Ⅰ. < 8; Ⅰ.++) { Si (Direcciones[Ⅰ.] < 16) Serial.Impresión("0"); Serial.Impresión(Direcciones[Ⅰ.], Hexagonal); } } Subprograma para inicializar los sensores DS18B20 Booleana initDS18B20(uint8_t anclar, DallasTemperatura Sensor, DeviceAddress Dirección ) { Booleana Encontrado = 0; pinMode(anclar,INPUT_PULLUP); sensoren_int.Comenzar(); Si (Depuración) { Serial.Impresión(Sensor.getDeviceCount(), Diciembre); Serial.println("Sensores encontrados."); } Ahora comprobamos si uno de los sensores del autobús es un sensor de temperatura Si (!Sensor.getAddress(Dirección,0)) { Si (Depuración) Serial.println("No hay sensor de temperatura disponible!"); } Más { Ver direcciones Si (Depuración) { Serial.Impresión("Dirección: "); printAddress(Dirección); Serial.println(); } Ahora establecemos la resolución deseada (9, 10, 11 o 12 bits) Sensor.setResolution(Dirección,10); Para el control, leemos el valor de nuevo Si (Depuración) { Serial.Impresión("Resolución"); Serial.Impresión(Sensor.getResolution(Dirección), Diciembre); Serial.println(); } Medición de la temperatura de inicio Sensor.requestTemperatures(); Commando para leer las temperaturas Encontrado = 1; } devolución Encontrado; } Vacío Configuración() { uint8_t Buf[70]; sendebuffer Si (Depuración) { Serial.Comenzar(115200); Serial.println("Comenzar"); } determinar su propia dirección MAC y almacenarla como un ID de dispositivo en la memoria de tinge de transmisión Cadena strmac = Wifi.macAddress(); Si (Depuración) { Serial.Impresión("Mi dirección MAC"); Serial.println(strmac); } Int Imac[6]; sscanf(strmac.c_str(), "%x:%x:%x:%x:%x:%x%c", &Imac[0], &Imac[1], &Imac[2], &Imac[3], &Imac[4], &Imac[5] ); Para (uint8_t Ⅱ. = 0; Ⅱ.<6; Ⅱ.++) Buf[Ⅱ.]=Imac[Ⅱ.]; Si (Depuración) { Serial.println("Sensores internos"); } has_int = initDS18B20(bus_int,sensoren_int,adressen_int); Si (Depuración) { Serial.println("Sensores externos"); } has_ext = initDS18B20(bus_ext,sensoren_ext,adressen_ext); Leemos de la Memoria RTC Esp.rtcUserMemoryRead(0, (uint32_t*) &statinfo, Sizeof(statinfo)); Si (Depuración) Serial.println("RTC hecho"); uint32_t crcOfData = calculateCRC32(((uint8_t*) &statinfo) + 4, Sizeof(statinfo) - 4); Wifi.Moda(WIFI_STA); Modo de estación para el nodo del sensor esp-now Si (Depuración) Serial.println("WifiMode"); Si (statinfo.crc32 != crcOfData) { no tenemos una dirección MAC válida Si (Depuración) Serial.println("Escanear antes que Esclavo"); ScanForSlave(); para (uint8_t i a 0; i<6;i++) statinfo.mac[i] á gwmac[i]; Si (Depuración) { Serial.Printf("Este mac: %s,", Wifi.macAddress().c_str()); Serial.Printf("mac objetivo: %02x%02x%02x%02x%02x%02x%02x%02x", statinfo.Mac[0], statinfo.Mac[1], statinfo.Mac[2], statinfo.Mac[3], statinfo.Mac[4], statinfo.Mac[5]); Serial.Printf(", canal: %i'n", statinfo.Canal); } } Si (esp_now_init() != 0) { Si (Depuración) Serial.println("*** ESP_Now init falló"); Esp.Reiniciar(); } Controlador ESP Now Wifi.setAutoConnect(Falso); esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER); uint8_t Ch = esp_now_get_peer_channel(statinfo.Mac); Serial.Printf("Canal á %i'r"n",Ch); Inicializar datos del mismo nivel Int Res = esp_now_add_peer(statinfo.Mac, ESP_NOW_ROLE_CONTROLLER, 1, Null, 0); Si (Res==0) Serial.println("Parejada con éxito"); registramos la función a llamar después de enviar esp_now_register_send_cb([](uint8_t* Mac, uint8_t sendStatus) { Si (Depuración) { Serial.Impresión("send_cb, estado "); Serial.Impresión(sendStatus); Serial.Impresión(", a mac: "); Char macString[50] = {0}; Sprintf(macString,"%02X:%02X:%02x:%02X:%02X:%02X:%02X", statinfo.Mac[0], statinfo.Mac[1], statinfo.Mac[2], statinfo.Mac[3], statinfo.Mac[4], statinfo.Mac[5]); Serial.println(macString); } callbackCalled = Verdad; }); Establezca la marca en false callbackCalled = Falso; Medición de la temperatura de inicio Si (has_int) sensoren_int.requestTemperatures(); Si (has_ext) sensoren_ext.requestTemperatures(); Retraso(750); 750 ms esperar hasta que la medición esté lista Obtenga el valor de temperatura y guárdelo en la estructura de datos para enviarlo Si (has_int) temp_int = sensoren_int.getTempC(adressen_int); Si (has_ext) temp_ext = sensoren_ext.getTempC(adressen_ext); Eliminar búfer Lpp.Restablecer(); Escribir paquetes de datos en el búfer Si (has_int) Lpp.addTemperature(CHANNEL_TEMPI, temp_int); Si (has_ext) Lpp.addTemperature(CHANNEL_TEMPE, temp_ext); uint8_t Sz = Lpp.getSize(); Copiar estructura de datos para enviar búfer Memcpy(&Buf[6], Lpp.Getbuffer(), Sz); Enviar datos al termómetro esp_now_send(Null, Buf, Sz+6); NULL significa enviar a todos los pares Si (Depuración) { Serial.Impresión("Temperatura interna: "); Serial.Impresión(temp_int); Serial.println("C"); Serial.Impresión("Temperatura externa: "); Serial.Impresión(temp_ext); Serial.println("C"); } } Vacío Bucle() { esperar hasta que se envíen datos Si (callbackCalled || (Millis() > SEND_TIMEOUT)) { Si (Depuración) Serial.println("Dormir"); Retraso(100); En modo de sueño profundo durante 300 segundos a continuación, se lleva a cabo un restablecimiento y se reinicia el ESP8266 Los datos de la memoria RTC no se eliminan durante el restablecimiento. Esp.deepSleep(300E6); } }
Después de iniciar el dispositivo, deberíamos verlo en la página web de la puerta de enlace.
Podemos asignar le estar un nombre al dispositivo y registrarlo.
El dispositivo ha recibido el número de dispositivo 1 por lo tanto los canales 8 a 15. Por lo tanto, el canal 1 del dispositivo es el canal 9. Después de un corto tiempo, deberíamos ver los dos nuevos canales (o solo uno si solo se ha conectado un sensor de temperatura) en el panel de Cayenne.
Ahora puede agregar los dos widgets para el canal 9 y el canal 10 y personalizarlos como desee.
Diviértete réplicas