Arbeiten mit dem Cayenne Dashboard - ESP-Now Temperatursensor Gerät (Teil 7) - AZ-Delivery

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

Esp-8266Projekte für fortgeschritteneSensoren

Deja un comentario

Todos los comentarios son moderados antes de ser publicados