Este post complementa el post anterior. Describe un sensor de temperatura con ESP8266 que envía la temperatura actual al termómetro presentado en el último artículo cada cinco minutos. Durante la ruptura entre dos mediciones, el ESP8266 se coloca en modo de sueño profundo, en el que apenas consume energía. El protocolo ESP Now se utiliza para enviar los datos, que envía los datos directamente a la dirección MAC del termómetro sin la necesidad de establecer una conexión.
Usamos el Módulo ESP8266-E12 con adaptador, como esto, a diferencia del módulo ESP8266-01, ha llevado a cabo el Wake Pin GPIO-16 y no tiene un LED permanentemente luminoso en la tensión de alimentación. Necesitamos el Wake Pin para despertar del sueño profundo y el LED de alimentación sólo consume energía innecesariamente.
Circuito:
El cable naranja conecta el Pin de activación a la entrada de restablecimiento y garantiza que el módulo se reinicie al final de la pausa para dormir. El sensor está conectado al GPIO2 (cable blanco).
Para cargar el programa necesitamos un adaptador FDTI para programar el ESP8266 a través de la interfaz serie.
Conectamos el adaptador FDTI al conector GND y TX a RX y RX a TX. Además, el Flash Pin GPIO 0 debe estar conectado a tierra (cable verde) para que el ESP8266 entre en modo de programación.
Después de la programación, el cable verde debe ser removido de nuevo. Si DEBUG se estableció en true en el sketch, puede seguir los mensajes del módulo a través de la interfaz serie.
Atención: Un suministro del ESP8266 por la placa FDTI provoca bloqueos cuando se llama a la función scanNetwork, porque el consumo de energía es entonces demasiado alto.
Bosquejo:
Para compilar la pizarra en
¡¡Establecer!!
/* Sensor de temperatura Wi-Fi ESP Ahora con el termómetro Si aún no se ha determinado ninguna dirección MAC el sensor está buscando una WLAN con termómetro SSID 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> Biblioteca para ESP Ahora #include <DallasTemperatura.H> Externos "C" { #include <espnow.H> } 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 WIFI_CHANNEL 1 #define SEND_TIMEOUT 2450 Tiempo de espera de 245 milisegundos Pines para sensor de temperatura Const Byte Autobús = 2;pin GPIO2 Estructura de datos para el intercambio de datos Estructura DATEN_STRUKTUR { Flotador Temp = 0; }; 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]; }; Datos globales Volátil Bool callbackCalled; MEMORYDATA statinfo; OneWire oneWire(Autobús); DallasTemperatura Sensores(&oneWire); Matriz para almacenar direcciones de sensores DeviceAddress Direcciones; 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(Ⅰ.); Cadena BSSIDstr = Wifi.BSSIDstr(Ⅰ.); Si (Depuración) { Serial.Impresión(Ⅰ. + 1); Serial.Impresión(": "); Serial.Impresión(Ssid); 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.Indexof("Termómetro") == 0) { 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[Ⅱ.]; } 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); } } Vacío Configuración() { Si (Depuración) { Serial.Comenzar(115200); Serial.println("Comenzar"); } pinMode(Autobús,INPUT_PULLUP); Determinamos la anzah de los sensores en el bus de un solo cable Sensores.Comenzar(); Si (Depuración) { Serial.Impresión(Sensores.getDeviceCount(), Diciembre); Serial.println("Sensores encontrados."); } Ahora comprobamos si uno de los sensores del autobús es un sensor de temperatura Si (!Sensores.getAddress(Direcciones,0)) { Si (Depuración) Serial.println("No hay sensor de temperatura disponible!"); } Ver direcciones Si (Depuración) { Serial.Impresión("Dirección: "); printAddress(Direcciones); Serial.println(); } Ahora establecemos la resolución deseada (9, 10, 11 o 12 bits) Sensores.setResolution(Direcciones,10); Para el control, leemos el valor de nuevo Si (Depuración) { Serial.Impresión("Resolución"); Serial.Impresión(Sensores.getResolution(Direcciones), Diciembre); Serial.println(); } Sensores.requestTemperatures(); Commando para leer las temperaturas 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(); 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", WIFI_CHANNEL); } } Si (esp_now_init() != 0) { Si (Depuración) Serial.println("*** ESP_Now init falló"); Esp.Reiniciar(); } Controlador ESP Now esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER); Inicializar datos del mismo nivel esp_now_add_peer(statinfo.Mac, ESP_NOW_ROLE_SLAVE, WIFI_CHANNEL, Null, 0); 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 Sensores.requestTemperatures(); Retraso(750); 750 ms esperar hasta que la medición esté lista Obtenga el valor de temperatura y guárdelo en la estructura del satélite para enviar DATEN_STRUKTUR Datos; Datos.Temp = Sensores.getTempC(Direcciones); uint8_t Bs[Sizeof(Datos)]; Copiar estructura de datos para enviar búfer Memcpy(Bs, &Datos, Sizeof(Datos)); Enviar datos al termómetro esp_now_send(Null, Bs, Sizeof(Datos)); NULL significa enviar a todos los pares Si (Depuración) { Serial.Impresión("Temperatura: "); Serial.Impresión(Datos.Temp); 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); } }
Prueba:
Después de que el módulo se haya accionado, todavía no conoce una dirección MAC válida del termómetro. Intenta encontrar una red abierta con el SSID "Termómetro". Dado que el termómetro oculta su SSID unos cinco minutos después del inicio, necesitamos activar un reinicio del termómetro. Ahora el módulo del sensor debe encontrar el termómetro y transmitir el valor de temperatura actual cada cinco minutos. El termómetro debe mostrar alternativamente la temperatura local (símbolo de la casa) y la temperatura del módulo del sensor (símbolo del árbol).
5 comentarios
esp tester
Tolles Projekt!
Peter
Wie weit können die Module denn voneinander entfernt sein?
Peter
Tolles Projekt! Ist es möglich mehrere entfernte Module zu betreiben?
Viele Grüße Peter
Carsten Jürges
Wenn kein “Thermometer” gefunden wird, landet irgendeine MAC-Adresse in statinfo und das war’s dann erstmal. Daher habe ich Funktion DeleteRtcMemory spendiert, den CRC-Wert “zerstört”. Diese Funktionen wird aufgerufen, wenn das Senden nicht erfolgreich (sendStatus) war …
Dann gibt es beim nächsten Start einen neuen Verbindungsversuch …
Jörg
Super, genau so etwas habe ich gesucht.
Vielen Dank für die interessanten Projektvorstellungen.