NEWS
LoRaWAN MakerFab Bewässerungssensor
-
Liebe Community,
Ich würde gerne meine gesammelte Erfahrung mit den Bodenfeuchtigkeitssensoren von MakerFab mit euch teilen.
Ziel dieses Projektes war es die Sensoren für meine Bewässerungsanlage zu verwenden und in den sprinkelcontrol Adapter einzubinden. Die zu bewässernden Pflanzen stehen leider außerhalb der Reichweite meines Netzwerkes. Wodurch ich mich auf die Suche nach einer möglichen Alternative gemacht habe. Für mich ergab sich so ein etwas holpriger Einstieg in die LoRaWAN Welt.LoRa Bodenfeuchtigkeitssensoren V3 Kostenpunkt €19,90
Ich hab mich für die Sensoren entschieden, da ich ansonsten leider nichts ähnliches in dieser Preisklasse finden konnte.
Allerdings sind die Sensoren nicht LoRaWAN fähig und für den Betrieb mit einem selbst gebauten Lora Gateway gedacht. Diese Mühe wollte ich mir eigentlich sparen. So habe ich mich auf die Suche nach einer Möglichkeit zur Integration ins LoRaWAN Netzwerk TTN (TheTingsNetwork) gemacht. Die Verarbeitung der Sensoren ist recht ok, Sie sind über die gesamte Platinenfläche und den Sensor mit einem Lack überzogen. Nur das Gehäuse lässt etwas zu wünschen übrig.Tip: Ich habe mich leider bei der Wahl der Sensoren etwas vergriffen, in der Zwischenzeit gibt es bereits Sensoren die LoRaWan unterstützen.So könnte das Flashen der Firmware nicht nötig sein. LoRaWan Sensoren
Wichtige Links:
USB-Serial Converter: CP2104Anleitung: Makerfabs Soil Moisture Sensor v3
Firmware: LORAWAN SOIL MOISTURE SENSOR (Die 3 Files weiter unten im Blog)Arduino IDE: Download
Erfahrungen:
- Das Aufspielen des Sketch hat mir große Schwierigkeiten gemacht. Es müssen genau die richtigen Version von Biblioteken in Arduino IDE installiert werden. Welche hierfür benötigt werden ist in der Anleitung angegeben. Ebenso muss in der Konfigurationsdatei von MCCI LoRaWAN Library folgender Code eingegeben werden um die richtige Region der Library einzustellen. Ansonsten erhaltet ihr immer die Nachricht das der Sketch zu groß ist und nicht auf den Sensor geflashed werden kann.
#define CFG_eu868 1 //define CFG_us915 1 //#define CFG_au915 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 #define DISABLE_PING #define DISABLE_BEACONS #define LMIC_DEBUG_LEVEL 0 #define USE_IDEETRON_AES
- Nachdem ich verstanden habe was in dem Sketch angegeben und gemeint ist, hat das eintragen der EUI aus TTN erstaunlich gut funktioniert. Hier ist lediglich zu beachten, dass diese auch im richtigen Format eingetragen werden. In TTN lassen sich die aber direkt im passenden Format anzeigen und kopieren.
// This EUI must be in little-endian format, so least-significant-byte // first. When copying an EUI from ttnctl output, this means to reverse // the bytes. For TTN issued EUIs the last bytes should be 0xD5, 0xB3, // 0x70. // APPEUI can be left with ceros static const u1_t PROGMEM APPEUI[8]={ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8);} // This should also be in little endian format, see above. static const u1_t PROGMEM DEVEUI[8]={ TTN_DEVEUI }; void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI, 8);} // This key should be in big endian format (or, since it is not really a // number but a block of memory, endianness does not really apply). In // practice, a key taken from ttnctl can be copied as-is. static const u1_t PROGMEM APPKEY[16] = { TTN_APPKEY }; void os_getDevKey (u1_t* buf) { memcpy_P(buf, APPKEY, 16);}
-
Leider hat mir das Flashen immer wieder Schwierigkeiten gemacht, worauf hin ich den Bootloader der Sensoren mit einem Arduino Nano neu programmiert habe. Entsprechende Anleitungen lassen sich leicht finden. Hierfür habe ich den Lack auf den 6 Pins abgekratzt und Kabel angelötet und mit dem Nano verbunden. Aufpassen das beim Flashen des Arduino Nano der Sensor nicht angeschlossen ist.
-
Nachdem ich die Sensoren dann endlich im TTN angezeigt bekommen habe, musste ich noch den Payload Formater passend konfigurieren. Dieser ist bei Device unter Payload formatters / Uplink / Custom Javascript formatter einzutragen.
// TTNV3 Payload Formatter Uplink V0.1 function decodeUplink(input) { if ((input.fPort > 0) && (input.fPort < 223)) { var decodedTemp = 0; var decodedHumi = 0; var decodedBatt = 0; // seperate raw data from payload var rawSoil = input.bytes[0] + input.bytes[1] * 256; var rawTemp = input.bytes[2] + input.bytes[3] * 256; var rawHumi = input.bytes[4] + input.bytes[5] * 256; var rawBatt = input.bytes[6] + input.bytes[7] * 256; // decode raw data to values decodedTemp = sflt162f(rawTemp) * 100; // value calculated to range -1..x..+1 by dividing /100 decodedHumi = sflt162f(rawHumi) * 100; // value calculated to range -1..x..+1 by dividing /100 if (rawBatt !== 0) decodedBatt = rawBatt / 1000; // batterie voltage ist transmitted in mV, recalculate in V // definition of the decimal places decodedTemp = decodedTemp.toFixed(2); decodedHumi = decodedHumi.toFixed(2); decodedBatt = decodedBatt.toFixed(2); // return values return { data: { Feuchtigkeit: rawSoil, Temperatur: decodedTemp, Luftfeuchtigkeit: decodedHumi, Batterie: decodedBatt }, warnings: [], errors: [] }; } else { return { data: {}, warnings: [], errors: ["Invalid data received"] }; } } function sflt162f(rawSflt16) { // rawSflt16 is the 2-byte number decoded from wherever; // it's in range 0..0xFFFF // bit 15 is the sign bit // bits 14..11 are the exponent // bits 10..0 are the the mantissa. Unlike IEEE format, // the msb is transmitted; this means that numbers // might not be normalized, but makes coding for // underflow easier. // As with IEEE format, negative zero is possible, so // we special-case that in hopes that JavaScript will // also cooperate. // // The result is a number in the open interval (-1.0, 1.0); // // throw away high bits for repeatability. rawSflt16 &= 0xFFFF; // special case minus zero: if (rawSflt16 == 0x8000) return -0.0; // extract the sign. var sSign = ((rawSflt16 & 0x8000) !== 0) ? -1 : 1; // extract the exponent var exp1 = (rawSflt16 >> 11) & 0xF; // extract the "mantissa" (the fractional part) var mant1 = (rawSflt16 & 0x7FF) / 2048.0; // convert back to a floating point number. We hope // that Math.pow(2, k) is handled efficiently by // the JS interpreter! If this is time critical code, // you can replace by a suitable shift and divide. var f_unscaled = sSign * mant1 * Math.pow(2, exp1 - 15); return f_unscaled; }
-
Der nächste Schritt das übertragen zu iobroker per MQTT ging ganz leicht. Hierfür eine neue Instanz anlegen und die unter Integrations / MQTT angegebenen Verbindungskonfigurationen eingeben.
-
So habe ich es endlich geschafft die Sensordaten in den iobroker zu integrieren. Diese werden als JSON an einen Datenpunkt geschickt. Mit folgendem Skript lasse ich mir diese in Datenpunkte ablegen.
const soilup = "mqtt.1.v3.030374@ttn.devices.eui-70b3d57ed005e017.up"; const path = '0_userdata.0.Bewässerung.eui-70b3d57ed005e017'; const idBat = '0_userdata.0.Bewässerung.eui-70b3d57ed005e017.Batterie'; const idMoist = '0_userdata.0.Bewässerung.eui-70b3d57ed005e017.Feuchtigkeit'; const idAir = '0_userdata.0.Bewässerung.eui-70b3d57ed005e017.Luftfeuchtigkeit'; const idTemp = '0_userdata.0.Bewässerung.eui-70b3d57ed005e017.Temperatur'; if(!existsState(idBat)) { // Datenpunkte erzeugen createState(idBat, '0', {type: 'number', unit: 'V'}); createState(idMoist, '0', {type: 'number', unit: '%'}); createState(idAir, '0', {type: 'number', unit: 'rF'}); createState(idTemp, '0', {type: 'number', unit: '°C'}); }; on(soilup, function(dp) { // triggert bei Wertänderung let obj = JSON.parse(dp.state.val).uplink_message.decoded_payload; setState(idBat, obj.Batterie, true); setState(idMoist, parseFloat(obj.Feuchtigkeit), true); setState(idAir, parseFloat(obj.Luftfeuchtigkeit), true); setState(idTemp, parseFloat(obj.Temperatur), true); });
Ich hoffe ich kann jedem der auf eine ähnliche Idee kommt mit meinen Tipps etwas helfen!
-
@bloop Sehr interessantes Projekt!
Ich muss mal ganz blöd fragen: Braucht man dafür nicht eon eigenes LoRaWAN-Gateway für?
-
@oxident
Nicht unbedingt!
Wenn in in deiner Region bereits ein Gateway vorhanden ist wird dieses verwendet.
Auf TTN kannst du vorab checken ob die Region abgedeckt ist.