Entfernter Temperatursensor für Thermometer mit ESP8266 - AZ-Delivery

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).

Esp-8266Projekte für fortgeschritteneSensoren

5 comentarios

esp tester

esp tester

Tolles Projekt!

Peter

Peter

Wie weit können die Module denn voneinander entfernt sein?

Peter

Peter

Tolles Projekt! Ist es möglich mehrere entfernte Module zu betreiben?
Viele Grüße Peter

Carsten Jürges

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

Jörg

Super, genau so etwas habe ich gesucht.
Vielen Dank für die interessanten Projektvorstellungen.

Deja un comentario

Todos los comentarios son moderados antes de ser publicados