Centro de control Smarthome con ArduiTouch parte 7 - dispositivo para sensores I2C BMP280 y BME 280

Entre otras pequeñas extensiones, me gustaría presentar hoy otro dispositivo remoto que suministra valores medidos de los sensores I2C BMP280 y/o BME280 a nuestra sede de hogar inteligente.

El circuito se basa en un D1 Mini y los sensores BMP280 Y BME280. Dado que estos sensores pueden tener una dirección I2C de 0X77 o 0X76, el programa descubre automáticamente qué sensor se conectó con qué dirección. Sin modificaciones suministradas por AZ Delivery, el BMP280 tiene la dirección 0X77 y la BME 280 la dirección 0X76.

El circuito es muy simple. El reloj I2C está conectado con D1 del D1 Mini y la línea de datos al D2 del D1 Mini. Para el BMP280, la línea Chipselect debe estar conectada a 3.3 V de modo que el BMP280 comience en el modo I2C. En el D1 Mini conectamos la entrada RESET al pin D0 (línea púrpura). El programa pone el ESP8266 en un profundo sueño después de que se haya hecho el trabajo. Esta conexión vuelve a activar el ESP8266 después de la hora establecida. Sin embargo, debe quitar esta conexión para parpadear.

Bosquejo:

 

/*
 Sensor de presión WLAN BMP280 y o BME280
 ESP ahora a ArduiTouch SmartHome
 Si el dispositivo no tiene una dirección MAC de servidor válida
 se realizará una búsqueda para encontrar una WLAN con SSID ATSmartHome
 La dirección MAC del servidor se guardará siempre y cuando la fuente de alimentación 
 no se interrumpirá.
 El protocolo ESP Now es casi la corriente más alta para el trabajo de la red
 consumido por un corto tiempo (nosotros) solamente. Después de enviar los valores, el dispositivo
 cambia durante cinco minutos a un modo de sueño profundo con un consumo de energía muy bajo.
*/

biblioteca para WiFi
#include <ESP8266WiFi.H>
bibliotecas para utilizar BMP280 y BME280
#include <Adafruit_Sensor.H>
#include <Adafruit_BME280.H>
#include <Adafruit_BMP280.H>
biblioteca para el protocolo de mensajes utilizado
#include "AT_MessageBuffer.h"


biblioteca para ESP Ahora
Externos "C" {   #include <espnow.H>
}

SSID para buscar
#define GW_SSID "ATSmartHome"

indicador para cambiar los mensajes de depuración en
#define Depuración Verdad

#define SEND_TIMEOUT 2000  Tiempo de espera de 2 segundos 

definir canales para los dos sensores
#define CHANNEL_TEMP_BME 0
#define CHANNEL_PRESS_BME 1
#define CHANNEL_ALT_BME 2
#define CHANNEL_HUM_BME 3
#define CHANNEL_TEMP_BMP 4
#define CHANNEL_PRESS_BMP 5
#define CHANNEL_ALT_BMP 6
 
#define SEALEVELPRESSURE_HPA (1013.25)

Estructura de datos para guardar la dirección MAC del servidor
y una suma de comprobación en la memoria RTC
Estructura MEMORYDATA {   uint32_t crc32; suma de comprobación para la validación   uint8_t Mac[6];
};


Variables globales
Volátil Bool callbackCalled;


Booleana hasBme = 0;
Booleana hasBmp = 0;

Dirección MAC y canal Wi-Fi
MEMORYDATA statinfo;

AT_MessageBuffer Msg;

Adafruit_BME280 Bme; I2c
Adafruit_BMP280 Bmp; I2c

función 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;
}

escribir MAC del servidor y suma de comprobación 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));
}

buscar el punto de acceso
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 ATSmartHome'       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];         obtener el servidor MAC y guardar 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;         no más búsqueda después de AP se encontró         Romper;       }     }   }         Si (Depuración) {     Si (slaveFound) {       Serial.println("Esclavo encontrado, procesamiento.");     } Más {       Serial.println("Esclavo no encontrado, lo intenta de nuevo.");     }   }   liberar RAM   Wifi.scanDelete();
}

función para initilizar el sensor BME
probar ambas direcciones válidas 77 o 76
Booleana initBme() {   Booleana Estado = Bme.Comenzar(0x77);     Si (!Estado) Estado = Bme.Comenzar(0x76);   Si (!Estado) {       Serial.println("No se pudo encontrar un sensor BME280 válido, comprobar el cableado!");       hasBme = Falso;       Mientras (1);   }   devolución Estado;
}

función para initilizar el sensor BMP
probar ambas direcciones válidas 77 o 76
Booleana initBmp() {   Booleana Estado = Bmp.Comenzar(0x77);     Si (!Estado) Estado = Bmp.Comenzar(0x76);   Si (!Estado) {       Serial.println("No se pudo encontrar un sensor BME280 válido, comprobar el cableado!");       hasBme = Falso;       Mientras (1);   }   Si (Estado) {   /* Configuración predeterminada de la hoja de datos. */     Bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,     /* Modo de funcionamiento. */                   Adafruit_BMP280::SAMPLING_X2,     /* Temp. sobremuestreo */                   Adafruit_BMP280::SAMPLING_X16,    /* Sobremuestreo de presión */                   Adafruit_BMP280::FILTER_X16,      /* Filtrado. */                   Adafruit_BMP280::STANDBY_MS_500); /* Tiempo de espera. */   }   devolución Estado;
}

Vacío Configuración() {   Si (Depuración) {     Serial.Comenzar(115200);      Serial.println("Comenzar");   }   obtener la dirección MAC local para usarlo como identificador de dispositivo   Cadena strmac = Wifi.macAddress();   Si (Depuración) {     Serial.Impresión("Mi dirección MAC");     Serial.println(strmac);   }   Msg.setId(strmac);   Msg.Claro();   hasBme = initBme();   Si (hasBme && Depuración) {     Serial.println("Sensor encontrado BME");   }   hasBmp = initBmp();   Si (hasBmp && Depuración) {     Serial.println("Sensor encontrado BMP");   }   leer el servidor MAC 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.Modo(WIFI_STA); Modo de estación para el nodo del sensor esp-now   Si (Depuración) Serial.println("WifiMode");   Si (statinfo.crc32 != crcOfData) { si suma de comprobación diferente no tenemos un servidor MAC válido     Si (Depuración) Serial.println("Busca 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", statinfo.Mac[0], statinfo.Mac[1], statinfo.Mac[2], statinfo.Mac[3], statinfo.Mac[4], statinfo.Mac[5]);      }   }   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);   Si (Depuración) Serial.Printf("Canal á %i'r"n",Ch);   inicializar los 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");   registrar la devolución de llamada   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;   });      establecer la bandera en false   callbackCalled = Falso;      iniciar la medición   leer los valores y guardar para el envío   Si (hasBme) {     Si (Depuración){       Serial.Impresión("Temperatura ");       Serial.Impresión(Bme.readTemperature());       Serial.println(" *C");          Serial.Impresión("Presión");          Serial.Impresión(Bme.readPressure() / 100.0F);       Serial.println(" hPa");          Serial.Impresión("Aprox. Altitud á ");       Serial.Impresión(Bme.readAltitude(SEALEVELPRESSURE_HPA));       Serial.println("m");          Serial.Impresión("Humedad");       Serial.Impresión(Bme.readHumidity());       Serial.println(" %");           }     Msg.addCelsius(Bme.readTemperature(), CHANNEL_TEMP_BME);     Msg.addHektoPascal(Bme.readPressure()/100.0F, CHANNEL_PRESS_BME);     Msg.addMeter(Bme.readAltitude(SEALEVELPRESSURE_HPA), CHANNEL_ALT_BME);     Msg.addPercent(Bme.readHumidity(), CHANNEL_HUM_BME);   }   Si (hasBmp) {     Si (Depuración) {       Serial.Impresión(Q("Temperatura "));       Serial.Impresión(Bmp.readTemperature());       Serial.println(" *C");          Serial.Impresión(Q("Presión"));       Serial.Impresión(Bmp.readPressure());       Serial.println("Pa");          Serial.Impresión(Q("Altitud aproximada "));       Serial.Impresión(Bmp.readAltitude(SEALEVELPRESSURE_HPA)); /* Ajustado a la previsión local! */       Serial.println("m");            }     Msg.addCelsius(Bmp.readTemperature(), CHANNEL_TEMP_BMP);     Msg.addHektoPascal(Bmp.readPressure()/100.0F, CHANNEL_PRESS_BMP);     Msg.addMeter(Bmp.readAltitude(SEALEVELPRESSURE_HPA), CHANNEL_ALT_BMP);   }   copiar la estructura de datos en sendbuffer   uint8_t Buf[255];   uint8_t Sz;   Sz = 255;   Si (Msg.fillBuffer(&Buf[0], &Sz)) esp_now_send(Null, Buf, Sz); NULL significa enviar a todos los pares
}

Vacío Bucle() {   esperar a que se envíen datos   Si (callbackCalled || (Millis() > SEND_TIMEOUT)) {     Si (Depuración) Serial.println("Dormir");     Retraso(100);     ir durante 10 segundos en modo de sueño profundo     despertar por restablecer     reset no elimina los datos en RTCmemory     Esp.deepSleep(10E6);   }
}

 

Para que este boceto sea compilado, además de las bibliotecas para los sensores, necesita la última versión de mi ATMessageBuffer Biblioteca.

El código del boceto también se puede encontrar en los ejemplos de la nueva versión de la ATSmartHome Biblioteca.

Después de actualizar la sede de Smart-Home, compilamos el Sketch y lo cargamos en el D1 Mini. Después de un corto tiempo, la dirección MAC del D1 Mini debe aparecer en la barra azul inferior de la sede de Smarthome. Hacemos clic una vez largo (más de 3 s) en esta dirección MAC. Se muestra la página de registro. Podemos dar un nombre al dispositivo y después de hacer clic en Guardar deberíamos ver las nuevas lecturas en la pantalla. Si otros dispositivos ya se han registrado en la sede central de Smarthome, los nuevos canales también pueden aparecer en una de las otras páginas. El registro automático busca lugares gratuitos en la pantalla y muestra los nuevos canales como pequeños widgets.

Un clic largo en los widgets lo lleva a su página de configuración y puede cambiar su apariencia y posición. La siguiente imagen muestra una posible configuración si utilizamos ambos sensores BMx al mismo tiempo.

Monitor

 

Finalmente, una pequeña extensión en el sitio web de la sede de Smarthome. Si se muestra un widget de actuador, tiene la opción de encender o apagar el dispositivo remoto, al igual que en la unidad central Smarthome, haciendo clic. Para el widget del actuador, vea también la parte 3 de esta serie

Aquí están los enlaces a todas las partes anteriores:

Diviértete :)

 

 

 

Precipitador electrostático - 8266Proyectos para avanzados.SensoresCasa inteligente

10 comentarios

Franz Patzal

Franz Patzal

Hi Greg,

look in part 6:

Ein wichtiger Hinweis zu Beginn!

Die ArduiTouch Smarthome Zentrale funktioniert nur mit dem ESP32 stabil. Es zeigte sich, dass auf Grund des deutlich geringeren RAM des ESP8266 kein stabiler Betrieb möglich ist. Ich habe daher die Version für den ESP8266 wieder aus dem Repository entfernt. Die aktuelle Version der ATSmartHome Bibliothek kann nicht mehr mit dem Sketch für ESP8266 kompiliert werden!

Greg

Greg

Hi. I am trying to follow the examples fro the SmartHome project, but it refers to the library ESP8266WiFi.H, even for ESP32 examples . Where can I find this library?
Many thanks!
Greg.

Wolfgang Händel

Wolfgang Händel

Hallo Herr Lechner….
Bis auf die etwas begrenzte Reichweite der Arduitouch Zentrale funktioniert bei mir alles recht gut.
Was das Herz des Smarthome Einsteigers natürlich höher schlagen lassen würde, wäre ein Sensormodul für ein binäres Signal (Klingeltaster, Bewegungssensor, Dämmerungssensor uvm.)
Das binäre Signal eines solchen Moduls müsste in der Zentrale ausgewertet werden und bestimmte Funktionen (wie z.B. das Relaismodul aus Teil 3) auslösen.
Haben sie so etwas geplant? Meines Erachtens gehört so etwas zu den Standard-Features eines SmartHome-Systems.
Ansonsten vielen Dank für die interessanten Blogs zum Thema SmartHome und für die Mühe, die sie sich damit gegeben haben bzw. noch geben..
Wolfie

Siegl Reinhard

Siegl Reinhard

Hallo
Ich bekomme die Smart Home V" nicht zum laufen.Es stoppt schon bei #include “SPIFFS.h”.
Bei der alten Smart Home konnte ich alle Beiträge nachbauen.
Danke für die Unterstützung schon im Vorraus.

Matthias H.

Matthias H.

Hallo Herr Lechner,
könnte man die Stimmungslaterne https://www.az-delivery.de/blogs/azdelivery-blog-fur-arduino-und-raspberry-pi/mehrere-feuer-programme-fuer-unsere-stimmungslaterne?pos=3&_sid=3afeceff9&ss=r nicht mit der Smarthome Zenrale steuern?

Reinhard Schneider

Reinhard Schneider

Wie das mit den Fehlern so ist, es hat sich auch bei mir einer eingeschlichen.
Richtig muss es für 5 min deep-sleep heißen:

ESP.deepSleep(300*10E6);

Reinhard Schneider

Reinhard Schneider

Leider haben sich in das o.g. Programm einige kleine Fehler eingeschlichen:
1. /function to initilize BMP Sensor
….
Richtig:
Serial.println(“Could not find a valid BMP280 sensor, check wiring!”);
hasBmp = false;

2. In der Beschreibung heißt es
….
After sending the values, the device switches for five minutes into a deep sleep mode with very low power consumption.
Der Code ist aber in void loop()
….
//go for 10 seconds into deep sleep mode
//wakeup by reset
//reset does not delete data in RTCmemory
ESP.deepSleep(10E6);

Für 5 Minuten müsste es heißen:

ESP.deepSleep(600*10E6);

Reinhard  Schneider

Reinhard Schneider

Das obige Programm läuft nur mit der Version 0.15.0 von “ESPiLight”.
Die aktuelle Version 0.16.0 erzeugt Fehlermeldungen.
Ist eine Anpassung des ino-Files geplant?

Joe

Joe

Bei den Daten der beiden Sensoren kann man sagen das es Roh-Daten sind.
Jetzt muß man nur eine Kalibrierung mit einem Referenz-Meßgerät höherer Genauigkeit durchführen. Und dann die Rohdaten entsprechen mit einem Justage-Wert belegen.
Es wird immer eine geringfügige Abweichung zwischen den Sensoren geben.
(Rauschen, Eigentemperatur etc, Meßfehler).
Die redudante Messung ist in Bereichen bei denen der Ausfall, starker Unterschied der Meßwerte, ermittelt werden muß. Rreinraum, technische zu überwachende Prozeße.
Temperatur-Differenzen werden auch genutzt um Strömungen, in dem Fall Luft, zu ermitteln.

Also nicht vergessen Justage-Wert und Kalibrierung.

Marcus Klein

Marcus Klein

Beide Sensoren sind offenbar recht nah beieinander untergebracht. Sie messen trotzdem eine Differenz von einem kompletten Grad Celsius. Das ist ein absolutes No-Go, wenn man damit versucht Heimautomatisierung zu betreiben und die Heizung zu steuern. Daraus folgt direkt, dass der Heizkreis am Sensor mit der kleineren Temperatur immer heizt und der Kreis am Sensor mit der größeren Temperatur immer aus ist. Bei einem Grad Unterschied und nicht verschlossenen Türen zwischen den beiden Räumen und gut isolierter Hütte, wandert die Wärme ausreichend zwischen den beiden Räumen. Das trägt nicht wirklich zum Wohnkomfort bei, sondern stört diesen besonders.
Wie gedenken Sie, diesen Fehler zu kompensieren?

Deja un comentario

Todos los comentarios son moderados antes de ser publicados

Artículos de blog

  1. Ahora instalamos el esp32 a través de la administración.
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. Transporte Aéreo - programación de ESP mediante redes locales inalámbricas