Ich hatte bereits vor knapp zwei Jahren eine Anleitung erstellt um den BME680 an einen NodeMCU (ESP8266) anzuschalten und die Daten mittels LoRaWAN an TTN zu übermitteln. Da ich momentan dabei bin meine alten Nodes und Sketches zu überarbeiten, ist mir auch dieser unter die Finger gekommen. Nun war also die Zeit gekommen das Thema wieder aufzugreifen und auf den neuesten Stand zu bringen.
Rückblick
Mit dem damaligen Sketch habe ich kein EV_TXCOMPLETE Event erhalten und somit musst ich nach jedem Senden wieder den RFM95 neu initialisieren. Damals konnte ich mir das Problem nicht erklären, aber heute bin ich etwas schlauer. In meinem Loop fehlte der Befehl os_runloop_once(); , aber was macht der?
Im Normalfall arbeitet LMIC nicht mit Interrupts und wir müssen regelmäßig nach Events fragen. Dieses erfolgt über den Befehl os_runloop_once(); . Wenn dieser also nun fehlt, dann erfahren wir nicht ob wir Daten gesendet haben, bzw. ob etwas empfangen wurde. Ihr sendet Daten, welche auch erfolgreich gesendet werden, aber der LMIC Stack denkt immer noch das der Job aktiv ist. Eigentlich also nichts kompliziertes, darf halt nur nicht fehlen.
void loop() { os_runloop_once(); }
Damit war dann mein eigentlicher Bug behoben und auch OTAA funktionierte nun. Zusätzlich hat sich aber auch was an der BSEC Library getan, weshalb auch die damalige Anleitung nicht mehr aktuell ist und überarbeitet werden muss. Damit geht es nun weiter. Insgesamt ist es einfacher geworden.
Vorbereitungen Arduino IDE
NodeMCU in die IDE einbinden
Wenn ihr bereits den NodeMCU in die Arduino IDE eingebunden habt, könnt ihr diesen Abschnitt überspringen.
Ihr Öffnet die Arduino IDE und geht auf Datei >> Voreinstelungen >> Zusätzich Boardverwalter-URLs und tragt dort folgenden Link ein.
http://arduino.esp8266.com/stable/package_esp8266com_index.json
Anschließend wechselt ihr zu Werkzeuge >> Board >> Boardverwalter und sucht nach ESP8266 und installiert dort ESP8266 Community.
Benötigte Libraries einbinden
Für den LoRaWAN-Part benötigen wir die MCCI Catena LMIC-Library. Ladet euch das Repository als ZIP herunter (clone or download) und bindet dieses über Sketch >> Bibliothek einbinden >> .ZIP-Bibliothek hinzufügen … ein.
Die BSEC-Library kann nun direkt über Sketch >> Bibliothek einbinden >> Bibliotheken verwalten gefunden werden. Sucht nach BSEC und installiert die Version 1.2.1474. Auch wenn es erst mal nicht so aussieht, sie ist aktueller als die 1.4.703 . Infos findet ich dazu auch auf GitHub.
LMIC konfigurieren
Per Default ist die LMIC für den US-Sektor konfiguriert, dieses müssen wir also anpassen. Auf einem Windows-System findet ihr unter Documents\Arduino\libraries\MCCI_LoRaWAN_LMIC_library\project_config die lmic_project_config.h welche ihr anpassen müsst. So sollte es bei euch aussehen. Wichtig ist der Punkt #define CFG_eu868 1
// project-specific definitions
#define CFG_eu868 1
//#define CFG_us915 1
//#define CFG_au921 1
//#define CFG_as923 1
// #define LMIC_COUNTRY_CODE LMIC_COUNTRY_CODE_JP /* for as923-JP */
//#define CFG_kr920 1
//#define CFG_in866 1
#define CFG_sx1276_radio 1
//#define LMIC_USE_INTERRUPTS
BSEC/ESP8266 spezifische Anpassungen
Das war bisher alles einfach, jetzt wird es etwas komplizierter. Die BSEC beinhaltet vorgefertigte Librarys, welche beim Kompilieren mit eingebunden werden müssen, dazu müssen ein Paar Anpssungen vorgenommen werden. Normalerweise solltet ihr die Software eures Boards unter <USER-HOME>\AppData\Local\Arduino15\packages\esp8266\ finden.
platform.txt anpassen
Die Datei findet wir unter hardware\esp8266\2.5.2\platform.txt und diese muss um den Eintrag {compiler.libraries.ldflags} ergänzt werden:
Alt Zeile 105:
## Combine gc-sections, archives, and objects
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {build.exception_flags} -Wl,-Map "-Wl,{build.path}/{build.project_name}.map" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{archive_file_path}" {compiler.c.elf.libs} -Wl,--end-group "-L{build.path}"
Neu Zeile 105:
## Combine gc-sections, archives, and objects recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {build.exception_flags} -Wl,-Map "-Wl,{build.path}/{build.project_name}.map" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{archive_file_path}" {compiler.c.elf.libs} {compiler.libraries.ldflags} -Wl,--end-group "-L{build.path}"
Ebenfalls müsst ihr den folgenden Block noch um eine Zeile erweitern (danke Reinhard):
# These can be overridden in platform.local.txt compiler.c.extra_flags= compiler.c.elf.extra_flags= compiler.cpp.extra_flags= compiler.S.extra_flags= compiler.ar.extra_flags= compiler.elf2hex.extra_flags=
Hinzu kommt:
compiler.libraries.ldflags=
eagle.app.v6.common.ld.h anpassen
Diese Datei finden wir unter hardware\esp8266\2.5.2\tools\sdk\ld und muss um den Eintrag *libalgobsec.a:(.literal.* .text.*) erweitert werden:
Neu nach Zeile 177 *libwps.a:(.literal.* .text.*):
*libwpa.a:(.literal.* .text.*)
*libwpa2.a:(.literal.* .text.*)
*libwps.a:(.literal.* .text.*)
*libalgobsec.a:(.literal.* .text.*)
*(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom0.text.* .irom.text .irom.text.*)
Aufbau der Schaltung für BME680 und RFM95
Ich verwende ein BME680 Breakout von Watterott. Das Bard von Watterott verwendet die I²C Adresse 0x77. Daher spreche ich in dem späteren Sketch diese auch an über iaqSensor.begin(BME680_I2C_ADDR_SECONDARY, Wire); Sollte euer Board die 0x76 nutzen müsst ihr dieses auf iaqSensor.begin(BME680_I2C_ADDR_PRIMARY, Wire); ändern. Die Anschaltung erfolgte nach folgendem Schema:
Für Besitzer des Adafruit Moduls:
Entgegen des Schaubildes, muss D1 mit G0 verbunden werden und D2 mit G1.
NodeMCU an RFM95
D1 (GPIO5) - DIO0 (SX1275/RFM95)
D2 (GPIO4) - DIO1
D5 (GPIO14) - SCK
D6 (GPIO12) - MISO
D7 (GPIO13) - MOSI
DO (GPIO16) - NSS
GND - GND
3.3v - VCC
BME680 an NodeMCU
D3 (GPIO0) - SDA (BME680)
D4 (GPIO2) - SCL
GND - GND
3.3v - VCC
TTN Payload Decoder
Mit folgendem Decoder bekommt ihr die Werte für Temperatur, Luftfeuchtigkeit, Luftdruck, IAQ und CO2 dekodiert.
function Decoder(b, port) {
var temp = (b[0] | b[1]<<8 | (b[1] & 0x80 ? 0xFF<<16 : 0)) / 100;
var hum = (b[2] | b[3]<<8 | (b[3] & 0x80 ? 0xFF<<16 : 0)) / 100;
var iaq = (b[4] | b[5]<<8 | (b[5] & 0x80 ? 0xFF<<16 : 0)) / 100;
var press = (b[6] | b[7]<<8 | (b[7] & 0x80 ? 0xFF<<16 : 0))/10+7;
var co2 = (b[8] | b[9]<<8 | (b[9] & 0x80 ? 0xFF<<16 : 0));
if (iaq !== 0) {
return {
env: {
temp: temp,
hum: hum,
iaq: iaq,
press: press,
co2: co2
},
};
}
}
Die eigentliche Software
Der Sketch liegt als ABP und OTAA Variante auf GitHub und darf von euch frei verwendet werden.
Nun wünsche ich euch viel Spaß beim Tüfteln!
Hallo Bjoern,
ein wichtiger Punkt fehlt, auf den ich jetzt reingefallen bin und der mich einige Stunden gekostet hat:
(das nicht wegen deinem Blog, ich sehe nur gerade, dass das hier fehlt)
die Datei platform.txt muss um eine weitere Zeile ergänzt werden und zwar
nach dem Textblock
# These can be overridden in platform.local.txt
compiler.c.extra_flags=
compiler.c.elf.extra_flags=
compiler.cpp.extra_flags=
compiler.S.extra_flags=
compiler.ar.extra_flags=
compiler.elf2hex.extra_flags=
diese Zeile ergänzen:
compiler.libraries.ldflags=
Ohne diese Änderung funktioniert zwar die bsec Library, aber alle anderen Sketche produzieren Compiler Fehler.
Auf der github Seite der Library kann man das leicht übersehen.
Gruß
Reinhard
Moin,
danke Dir, hab es aufgenommen.
Ist mir durchgerutscht.
Grüße,
Björn
Hallo Bjoern,
ein super Beitrag zum BME680!
Geht auch eine Umsetzung auf dem WeMos D1 Mini? Ist doch auch ein ESP8266.
Wie müsste dann die Vorgehensweise aussehen? Kannst du dazu auch eine Anleitung erstellen, da ich als „ESP8266-Frischling“ nicht so fit bin 😉
Grüße Jörg
Hallo Jörg,
es sollte alles gleich laufen. Da sollte kein Unterschied vorhanden sein.
Grüße,
Björn
Hallo Björn,
Danke für deine schnelle Antwort, dann werde ich mich mal an die Arbeit machen und mit dem WeMos experimentieren 😉
Grüße Jörg
Hallo Björn,
der Nachbau hat funktioniert- danke für dein geteiltes Projekt!
Ein Problem habe ich mit dem TTN-Uplink:
TTN Payload Format = Custom
im Uplink – Fields werden Daten angezeigt
TTN Payload Format = Cayenne LPP
im Uplink – Fields werden KEINE Daten angezeigt
Hast du dazu einen Hinweis.
Gruß
Kurt
Hallo Kurt,
Cayenne LPP ist ein spezielles Payload Format, was ich nicht verwendet habe.
Die Einstellung Custom ist schon so korrekt. Zusätzlich musst du den Payload Decoder dort unter Decoder reinkopieren.
Grüße,
Björn
Hallo Björn,
Danke für deine Antwort.
Leider wird Cayenne LPP nicht unterstützt 🙁 .
Gruß
Kurt
Hallo Björn,
funktioniert der Payload-Dekoder auch für negative Temperaturen? Es sind gerade Minusgrade auf meinem Balkon und der im TTN angezeigte Wert „temp“: 167770.04 passt nicht so richtig.
var temp = (b[0] | b[1]<<8 | (b[1] & 0x80 ? 0xFF<<16 : 0)) / 100;
Viele Grüße
Roland
Hi Roland,
probier es mal damit:
var temp = ((bytes[0] & 0x80 ? 0xFFFF<<16 : 0) | bytes[0]<<8 | bytes[1]) / 100; Grüße, Björn