Die große LoRa Wettertstation Software

In diesem Artikel setzen wir mit dem Bau der großen LoRa Wetterstation fort und konzentrieren uns auf das Energiemanagement und die Software. Alle Infos zum elektronischen Aufbau der Wetterstation gibt es im ersten Teil.

Für Anfänger: Bevor man mit der Programmierung der Wetterstation anfangen kann, muss der ESP32 korrekt im Arduino IDE installiert sein. Es gibt bereits ein Tutorial (ESP32 LoRa Board Arduino IDE Setup), wo der ESP32 LoRa im Arduino IDE inklusive der notwendigen Bibliotheken installiert wird.

Die verwendeten Librarys

Damit die Software und somit auch die Wetterstation und alle Komponenten funktionieren, müssen im Arduino IDE folgende Bibliotheken installiert sein:

Für den LoRa Chip: Sandeep Mistry LoRa | Version: 0.5.0
Für den BME280: Adafruit BME280 | Version: 1.0.10
Für den BME280: Adafruit Unified Sensor | Version: 1.0.3

Weitere Bibliotheken für SPI, WIRE usw. sollten bereits im Arduino IDE vorhanden sein.

Der BME280

Der BME280 erfasst Temperatur, Luftdruck und Feuchtigkeit und kommuniziert über zwei Datenleitungen (I2C) mit dem ESP32. Bei der I2C-Schnittstelle gibt es für jedes einzelne Gerät eine eindeutige Adresse. Die Adressen sind meist bereits vom Hersteller fix definiert und können je nach Hersteller bei einigen Geräten auch frei programmiert werden. Der BME280 hat eine fixe Adresse, welche meistens 0x76 oder 0x77 lautet. Ist einem die Adresse nicht bekannt und die zwei bekannten funktionierten auch nicht, kann man diese Adresse über eine I2C-Scanner ermitteln. Dazu einfach den Sensor an den entsprechenden Pins anschließen, den Scanner-Code hochladen und über den Serial Monitor die Adresse auslesen. Die Adresse wird bei "void setup" in dieser Zeile definiert:

bme.begin(0x76);
Für diesen Sensor sind die Bibliotheken Adafruit BME280 und Adafruit Sensor notwendig.

Der Sonnensensor

Der Sonnensensor gibt einen analogen Spannungswert an den Mikrocontroller weiter. Der GPIO-PIN 37 liest diesen Wert mit 12-Bit (0-4095) ein. Bekommt der Sonnensensor direktes Sonnenlicht, so liegt der eingelesenen Wert um das Maxima (4095). Mit zunehmender Dunkelheit geht die Spannung hinunter und der eingelesene analoge Wert sinkt auf 0. Die Sonnenintensität wird von der Software in einem Prozentwert ausgegeben, der von der analogen Eingangsspannung abhängig ist. Durch eine Multiplikation mit dem Faktor 0.02442 wird der analoge Eingangswert in einem Prozentwert von 0 bis 100 umgerechnet.

Der Windsensor

Das Anemometer gibt bei jeder Umdrehung einen Impuls ab. Diese Impulse werden über einen digitalen Eingang erfasst und in über einem bestimmten Zeitraum gezählt. Der Zähler wird durch ein Interrupt addiert, dass bei steigender Signalflanke auslöst. Die Anzahl der Gesamtimpulse wird anschließend durch das Zeitfenster, in dem gemessen wurde, dividiert und mit dem Faktor 2.4 multipliziert. Der Faktor 2.4 stammt vom Datenblatt des Anemometers, was besagt, dass eine Umdrehung pro Sekunde einer Windgeschwindigkeit von 2,4 km/h entspricht. Ob dieser Faktor für alle Anemometer gleich ist, ist nicht feststellbar. Grundsätzlich handelt es sich bei dieser Methode um einen Näherungswert. Wer eine exakte Messung haben möchte, wird das Anemometer mit einer geeichten Referenzstation kalibrieren müssen. Anschließend müsste die Formel gegebenenfalls mit entsprechenden Offsets modifiziert werden.

Der erste Sensortest

Wenn die Bibliotheken installiert wurden, kann der Testcode für die Sensoren auf das Board geladen werden. Dieser Code liest alle angeschlossenen Sensoren ein und gibt die Werte im Serial Monitor aus. An dieser Stelle kann die Wetterstation, der LoRa-Chip und alle an das IO-Board angeschlossenen Komponenten durchgetestet werden. Dazu wird einfach der LoRa_IO_Sensor_Test auf das Board hochgeladen. Erst wenn dieser Test bestanden wurde, sollte man mit der Programmierung und Fertigstellung fortsetzen. Nachfolgend die Ausgabe vom Serial Monitor, wenn der LoRa-Test erfolgreich bestanden wurde und von allen Sensoren realistische Daten kommen:

Die große LoRa Wettertstation Hardware Check

Energieverbrauch

Die Energieeffizienz ist gerade bei autarken oder batteriebetrieben Systemen ein wichtiger Aspekt. Darum geht die Wetterstation zwischen den einzelnen Messungen in einem Deep-Sleep-Mode. Bis auf die RTC werden im CPU alle Komponenten in einen Schlaf-Modus versetzt. Der ESP32 führt alle drei Minuten eine Messung durch und sendet die erfassten Daten über LoRa. Anschließend geht dieser für drei Minuten in den Sleep-Mode, bevor wieder eine erneute Messung durchgeführt wird. Der Energieverbrauch ist von der programmabhängigen Operation unterschiedlich. Die nachfolgenden Messwerte wurden zwischen der Batterie und dem Laderegler ermittelt und beinhalten den Gesamtenergieverbrauch vom ESP32 und allen daran angeschlossenen Komponenten:
Im Sleep-Mode: ca. 3,5 mA
Beim Erfassen der Sensordaten: ca. 52 mA
Mit aktiver LoRa Datenübertragung: ca. 176 mA

Das Hauptprogramm

Genau wie auch beim Sensortest werden die oben angeführten Bibliotheken benötigt und müssen entsprechend am Beginn vom Programm eingebunden werden. Anschließend muss eine "Device ID" vergeben werden. Diese ID wird entweder von der IoT-Cloud vorgegeben, oder wenn man mit dem Server Beispielcode vom LoRa Gateway arbeitet, kann die ID selbst vergeben werden und spielt dann keine besondere Rolle. Anschließend werden noch einige Pins für die angeschlossenen Komponenten vergeben und die Timer definiert. Die Timer sind als Integer definiert und haben dabei folgende Aufgabe:

int wind_m_sec = 3;

Die erste Variable ist die Zeit, die für die Ermittlung der Windgeschwindigkeit genommen wird. Standardmäßig sind das drei Sekunden, aber man kann den Zeitraum auch um einige Sekunden verlängern, um einen genaueren Mittelwert zu bekommen.

int sleep_time = 180;

Die "Sleep-Time" ist die Zeit, die der Mikrocontroller im Energiesparmodus ist. Der Standard-Wert liegt hier bei 3 Minuten (180 Sekunden). Damit wird auch das Intervall bestimmt, in dem die Wetterdaten erfasst und übertragen werden.

Das Hauptprogramm (void loop) besteht im wesentlichen aus drei Methoden:

getSensorData();

In dieser Methode werden alle Messwerte erfasst und in die dafür im Header festgelegten Variablen geschrieben. In dieser Methode befindet sich auch noch eine Submethode, die am Ende aufgerufen wird und nur für die Ermittlung der Windgeschwindigkeit zuständig ist.

send_LoRa_Packet();

Diese Methode befasst sich ausschließlich mit der Datenübertragung. Dabei werden die Device-ID und die von der vorherigen Methode aktualisierten Variablen in ein LoRa-Packet zusammengefasst und abgesendet. Anschließend folgt noch ein kurzes delay und das Programm ruft die nächste und letzte Methode auf.

esp_deep_sleep_start();

Sobald diese Methode aufgerufen wird, wechselt der ESP32 in den Deep-Sleep mode. Dabei wird die CPU und ein großer Teil vom Arbeitsspeicher sowie sämtliche Peripherie ausgeschaltet. Nachdem der Sleep-Timer abgelaufen ist, startet der ESP wieder neu und beginnt mit dem Programmablauf von vorne.

Vollständiger Sketch
//More information at: https://www.aeq-web.com/
//Main software for LoRa-Weatherstation 2020 (V 1.0|03052020)

#include <SPI.h>
#include <LoRa.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

String device_id = "YOUR-IDXYZ";

#define ss 18         //LoRa SS PIN
#define rst 14        //LoRa RST PIN
#define dio0 26       //LoRa DIO PIN

int ldrpin = 37;      //PIN for LDR input
int anopin = 12;      //PIN for anemometer input

int wind_m_sec = 3;   //Wind measure time (seconds)
int sleep_time = 180; //ESP sleep time (seconds)

float temp;
float pressure;
float humidity;
float sunlight;
float wind;
int wind_cnt;

Adafruit_BME280 bme;


void setup() {
  bme.begin(0x76);              //BME280 I2C-address
  SPI.begin(5, 19, 27, 18);     //Pins for LoRa SPI
  LoRa.setPins(ss, rst, dio0);  //Pins for LoRa
  LoRa.begin(868E6);            //Start LoRa @ 868 MHz (EU-Band)
  
  esp_sleep_enable_timer_wakeup(sleep_time * 1000000);
}

void loop() {
  get_sensor_data();
  send_lora_packet();
  esp_deep_sleep_start();
}

void get_sensor_data() {
  temp = bme.readTemperature();
  pressure = bme.readPressure() / 100;
  humidity = bme.readHumidity();

  int ldr_value = analogRead(ldrpin);
  sunlight = (ldr_value * 0.02442);

  meassure_wind();
}

void send_lora_packet() {
  LoRa.beginPacket();
  LoRa.print(device_id);
  LoRa.print(";");
  LoRa.print(temp);
  LoRa.print(";");
  LoRa.print(humidity);
  LoRa.print(";");
  LoRa.print(pressure);
  LoRa.print(";");
  LoRa.print(wind);
  LoRa.print(";");
  LoRa.print(sunlight);
  LoRa.print(";");
  LoRa.endPacket();
  delay(500);
}

void meassure_wind() {
  wind_cnt = 0;
  attachInterrupt(digitalPinToInterrupt(anopin), intrrupt_cnt, RISING);
  delay(wind_m_sec * 1000); //Time for measure counts
  detachInterrupt(digitalPinToInterrupt(anopin));
  wind = ((float)wind_cnt / (float)wind_m_sec * 2.4) / 2; //Convert counts & time to km/h
}

void intrrupt_cnt() {//On count detected
  wind_cnt++;//Add one count
}

Oft gelesen

Anzeige:

Social Media

Newsletter