Dieses Tutorial ist Teil von: WiFi LoRa 32 Tutorials
Alle Videos zum Thema Heltec WiFi LoRa 32 gehören zu dieser Gruppe. Links zu weiteren Videos finden Sie unter diesem Artikel.
Verwendung des Heltec WiFi LoRa 32 V3 zur Übertragung der Temperatur mittels DHT22 über 1,4 km
In diesem Tutorial werden wir untersuchen, wie man das Heltec WiFi LoRa 32 V3-Modul verwendet, um Temperaturdaten von einem DHT22-Sensor über lange Strecken zu übertragen und Reichweiten von bis zu 1,4 Kilometern zu erreichen. Diese Fähigkeit wird durch den Einsatz von LoRa-Technologie ermöglicht, die eine energieeffiziente Kommunikation über große Entfernungen erlaubt. Am Ende dieses Leitfadens werden Sie ein funktionierendes System haben, das Temperaturmessungen drahtlos senden kann.
Wir werden mit einem Überblick über die Hardwarekomponenten beginnen, die in diesem Projekt verwendet werden, einschließlich des Heltec WiFi LoRa 32 V3 Moduls und des DHT22 Sensors. Danach werden wir zu den Verkabelungsanleitungen übergehen, in denen Sie lernen werden, wie Sie diese Komponenten verbinden. Schließlich werden wir den Code durchgehen, der erforderlich ist, um dieses System betriebsbereit zu machen. Für visuelle Unterstützung beziehen Sie sich bitte auf das Video zu verschiedenen Zeitstempeln (im Video bei 00:00).
Hardware erklärt
Die Hauptkomponenten für dieses Projekt sind das Heltec WiFi LoRa 32 V3 Modul und der DHT22 Temperatur- und Feuchtigkeitssensor. Das Heltec Modul verfügt über einen ESP32 Mikrocontroller, der WLAN- und Bluetooth-Funktionen sowie LoRa-Kommunikation bietet. Dies ermöglicht flexible Datenübertragungsoptionen.
Der DHT22-Sensor ist ein digitaler Sensor, der genaue Temperatur- und Feuchtigkeitsmessungen liefert. Er kommuniziert mit dem ESP32 über einen einzelnen digitalen Ausgangspin, was die Verbindung und Verwendung in Ihren Projekten erleichtert. Zusammen bilden diese Komponenten ein robustes System zur drahtlosen Temperaturüberwachung.
Technische Datenblatt Einzelheiten
| Hersteller | Heltec Automation |
|---|---|
| Teilenummer | WiFi LoRa 32 V3 |
| Logik/IO-Spannung | 3,3 V |
| Versorgungsspannung | 3,7-4,2 V |
| Ausgangsstrom ( pro Kanal) | ~1 A |
| Spitzenstrom (pro Kanal) | ~2 A |
| PWM-Frequenzanleitung | 1 kHz (Typ.) |
| Eingangslogikschwellen | 0,7 V (hoch), 0,3 V (niedrig) |
| Spannungsabfall / RDS(on)/ Sättigung | 0,3 V (max) |
| Thermische Grenzen | 85 °C (max) |
| Paket | PCB-Modul |
| Anmerkungen / Varianten | Verschiedene Frequenzoptionen verfügbar (z. B. 433 MHz, 868 MHz, 915 MHz) |
- Stellen Sie sicher, dass der DHT22 mit 3,3 V und nicht mit 5 V betrieben wird.
- Verwenden Sie geeignete Logikpegel für die Kommunikation zwischen dem ESP32 und dem DHT22.
- Berücksichtigen Sie die Wärmeableitung, wenn Sie über längere Zeiträume bei hohen Strömen betreiben.
- Überprüfen Sie die Antennenverbindung für LoRa, um die Reichweite zu maximieren.
- Achten Sie auf die LoRa-Frequenzvorschriften in Ihrer Region.
Verdrahtungsanweisungen

Um den Heltec WiFi LoRa 32 V3 mit dem DHT22-Sensor zu verdrahten, beginnen Sie damit, den VCC-Pin des Sensors mit dem 3,3V-Pin des Heltec-Moduls zu verbinden. Verbinden Sie als Nächstes den GND-Pin des DHT22 mit einem der GND-Pins am Heltec. Der Datenpin des DHT22 sollte mit dem GPIO-Pin 3 am Heltec verbunden werden.
Stellen Sie sicher, dass Sie einen Pull-Up-Widerstand (ca. 10 kΩ) zwischen dem Datenpin und VCC verwenden, um stabile Messwerte zu erhalten. Stellen Sie außerdem sicher, dass die LoRa-Antenne sicher angeschlossen ist, um die Reichweite der Übertragung zu verbessern. Wenn Sie externe Stromversorgung verwenden, stellen Sie sicher, dass das Heltec-Modul korrekt mit Strom versorgt wird, um Betriebsprobleme zu vermeiden.
Installation der Heltec ESP32-Boards
Fügen Sie diesen Pfad in die Einstellungen Ihrer Arduino IDE ein, wie im Video gezeigt:https://resource.heltec.cn/download/package_heltec_esp32_index.json
Codebeispiele und Anleitung
Die folgenden Codeausschnitte zeigen, wie man das Heltec-Modul einrichtet, um Temperaturdaten vom DHT22-Sensor zu lesen und sie über LoRa zu übertragen. Der Code initialisiert das Display und richtet den DHT-Sensor ein.
#include
#define DHTPIN 3 // GPIO pin for DHT22
#define DHTTYPE DHT22 // Define DHT type
DHT dht(DHTPIN, DHTTYPE);
void setup() {
Serial.begin(115200);
dht.begin(); // Initialize DHT sensor
}In diesem Snippet definieren wir den Pin, an den der DHT22-Sensor angeschlossen ist, und initialisieren ihn in dersetup()Funktion. DieSerial.begin(115200)Diese Zeile dient der Debugging-Ausgabe.
void loop() {
float tempC = dht.readTemperature(); // Read temperature in Celsius
float tempF = dht.convertCtoF(tempC); // Convert to Fahrenheit
sendData(tempC, tempF); // Function to send temperature data
}Dieser Auszug zeigt, wie man Temperaturdaten in derloop()Funktion. DiesendData()Die Funktion wird aufgerufen, um die Temperaturmesswerte über LoRa zu übertragen.
void sendData(float tempC, float tempF) {
String data = "Temperature: " + String(tempC) + "°C"; // Create data string
Radio.Send(data.c_str(), data.length()); // Send data
}Hier erstellen wir die Datenzeichenfolge, die die Temperatur enthält, und senden sie mit demRadio.Send()Methode. Dies wird die Daten drahtlos an das Empfangsmodul übermitteln.
Bitte beziehen Sie sich auf den vollständigen Code, der unter dem Artikel geladen ist, für eine detaillierte Implementierung.
Demonstration / Was zu erwarten ist
Sobald alles eingerichtet ist und der Code auf das Heltec-Modul hochgeladen wurde, sollten die Temperaturwerte auf dem OLED-Bildschirm angezeigt werden. Das System überträgt die Temperaturdaten, die von einem anderen Heltec-Modul empfangen werden können, das so konfiguriert ist, dass es die Daten liest. Sie können die Reichweite testen, indem Sie den Empfänger weiter vom Sender entfernen und die maximale erreichte Entfernung bestätigen (im Video bei 1:30).
Seien Sie vorsichtig bei häufigen Fallstricken wie falscher Verkabelung, unzureichender Stromversorgung oder der Verwendung der falschen LoRa-Frequenz. Stellen Sie sicher, dass der DHT22 ordnungsgemäß funktioniert und dass die Antenne angeschlossen ist, um die Reichweite zu maximieren.
Video-Zeitstempel
- 00:00 Start
- 3:51 Spezifikationen
- 8:32 Dokumentationsseite
- 9:52 Paket und Batterie
- 12:58 Zum ersten Mal einschalten
- 16:37 Bibliothek installieren
- 18:19 Sender Grundcode
- 19:43 Empfänger Grundcode
- 20:39 Demonstration des Sendens und Empfangens von Text
- 23:02 OLED-Democode
- 24:06 Basistext zum OLED-Displaycode
- 26:26 Basistext zur OLED-Demo
- 26:58 Temperaturmessung mit DHT22
- 28:49 LoRa-Sender-Temperatur und Anzeige
- 30:07 LoRa-Empfänger-Temperatur und Anzeige
- 32:13 Auslösen der LED bei Temperaturerhöhung
- 22:26 LoRa Übertragungsreichweite-Test
- 35:01 dBm und Milli Watt
Dieses Tutorial ist Teil von: WiFi LoRa 32 Tutorials
- 13 Meilen 20 km ohne WiFi? Wie LoRa Spannung über verrückte Distanzen sendete! (Heltec WiFi LoRa 32 V3)
- Schalte ein Gerät aus 13 Meilen (21 km) Entfernung ein – Das ultimative Off-Grid LoRa-Projekt mit WiFi LoRa 32!
- Fernzugangswarnsystem aus 21 km (13 Meilen) Entfernung mit LoRa – Unabhängig vom Stromnetz! (Heltec WiFi LoRa 32 V3)
- Steuere einen Servo-Motor aus großer Entfernung! Heltec WiFi LoRa 32 V3 Arduino Tutorial (TX)
- DIY-Fernsteuerrelaisprojekt: 21 km No-Wi-Fi/No-SIM Heltec LoRa 32 Modul
- How to Use the Heltec LoRa CubeCell Development Board HTCC-AB01
/*
This is a simple code to display text on the OLED display
WiFi LoRa 32 V3 ESP32 module
Written by Ahmad Shamshiri 02 April 2025
Watch full video explanation https://youtu.be/WkyQMXkQhE8
Resources page https://robojax.com/tutorial_view.php?id=387
*/
#include <Wire.h>
#include "HT_SSD1306Wire.h"
static SSD1306Wire display(0x3c, 500000, SDA_OLED, SCL_OLED, GEOMETRY_128_64, RST_OLED); // addr , freq , i2c group , resolution , rst
void setup() {
Serial.begin(115200);
Serial.println();
Serial.println();
VextON();
delay(100);
// Initialising the UI will init the display too.
display.init();
display.setFont(ArialMT_Plain_10);
}
void displayTemperature(double temperature, int unit) {
display.clear(); // Clear display before new content
// Line 1: "Temperature:" in 16pt font
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_16);
display.drawString(0, 0, "Temperature:");
// Line 2: Temperature value in 24pt font
display.setFont(ArialMT_Plain_24);
// Format temperature with correct unit symbol
String tempString = String(temperature, 1); // 1 decimal place
switch(unit) {
case 1: tempString += "�C"; break; // Celsius
case 2: tempString += "�F"; break; // Fahrenheit
default: tempString += "�U"; break; // Unknown unit
}
display.drawString(0, 20, tempString); // Display at Y=20 (below label)
display.display(); // Update OLED
}
void VextON(void)
{
pinMode(Vext,OUTPUT);
digitalWrite(Vext, LOW);
}
void VextOFF(void) //Vext default OFF
{
pinMode(Vext,OUTPUT);
digitalWrite(Vext, HIGH);
}
void loop() {
// clear the display
display.clear();
displayTemperature(23.5, 1); // Displays "23.5�C" /1
delay(2000);
}
/*
* geschrieben am 27. März 2025
* geschrieben von Ahmad Shamshiri für www.Robojax.com
* Überträgt Temperatur und Luftfeuchtigkeit über LoRa RF mit dem ESP32 LoRA 32 V3 Modul.
* und zeigt die Informationen auf dem Bildschirm an.
* Siehe vollständige Videoerklärung https://youtu.be/WkyQMXkQhE8
* Ressourcenseite: https://robojax.com/tutorial_view.php?id=387
*/
#include <Wire.h>
#include "HT_SSD1306Wire.h"
static SSD1306Wire display(0x3c, 500000, SDA_OLED, SCL_OLED, GEOMETRY_128_64, RST_OLED); // addr, freq, i2c-Gruppe, Auflösung, rst
#include <DHT.h>
#define DHTPIN 3 // GPIO21
#define DHTTYPE DHT22 // DHT22 (AM2302)
DHT dht(DHTPIN, DHTTYPE);
float tempC, tempF;
int humidity ;
// 1=C
// 2=F
// 3=C, Feuchtigkeit //nur zur Anzeige, nicht für die Übertragung
// 4=F, Luftfeuchtigkeit //nur zur Anzeige, nicht zur Übertragung
// 5=Nur Luftfeuchtigkeit
int dataType = 2;
String labelTemp = "Temperature";
String labelHumidity = "Humidity";
const int TX_POWER = 2; // dBm von 2 bis 20. Bei Stromversorgung über Batterie ist 2 bis 14 dBm die beste Option.
#include "mbedtls/aes.h"
#include <cstring> // Für memset, memcpy
mbedtls_aes_context aes;
const char *userKey = "hyhT676#h~_876s"; // Sicherheitsschlüssel.
#include "LoRaWan_APP.h"
#include "Arduino.h"
#define RF_FREQUENCY 915000000 // Hz
#define TX_OUTPUT_POWER TX_POWER // dBm von 2 bis 20. bei Batterieversorgung 2 bis 14 dBm
#define LORA_BANDWIDTH 0 // [0: 125 kHz,
// 250 kHz,
// 2: 500 kHz,
// 3: Reserviert
#define LORA_SPREADING_FACTOR 7 // [SF7..SF12]
#define LORA_CODINGRATE 1 // [1: 4/5,
// 2: 4/6,
// 3: 4/7,
// 4: 4/8]
#define LORA_PREAMBLE_LENGTH 8 // Das Gleiche gilt für Tx und Rx.
#define LORA_SYMBOL_TIMEOUT 0 // Symbole
#define LORA_FIX_LENGTH_PAYLOAD_ON false
#define LORA_IQ_INVERSION_ON false
#define RX_TIMEOUT_VALUE 1000
#define BUFFER_SIZE 30 // Definieren Sie hier die Payload-Größe.
char txpacket[BUFFER_SIZE];
char rxpacket[BUFFER_SIZE];
double txNumber;
bool lora_idle=true;
static RadioEvents_t RadioEvents;
unsigned long lastTxTime = 0;
void OnTxDone( void );
void OnTxTimeout( void );
void decryptAES(uint8_t *data, const char *key);
void encryptAES(uint8_t *data, const char *key);
void processKey(const char *userKey, uint8_t *processedKey, size_t keySize);
void setup() {
Serial.begin(115200);
Serial.println();
VextON();
delay(100);
// Die Initialisierung der Benutzeroberfläche wird auch das Display initialisieren.
display.init();
display.setFont(ArialMT_Plain_10);
dht.begin();
// LoRa Zeug
Mcu.begin(HELTEC_BOARD,SLOW_CLK_TPYE);
txNumber=0;
RadioEvents.TxDone = OnTxDone;
RadioEvents.TxTimeout = OnTxTimeout;
Radio.Init( &RadioEvents );
Radio.SetChannel( RF_FREQUENCY );
Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
LORA_SPREADING_FACTOR, LORA_CODINGRATE,
LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
true, 0, 0, LORA_IQ_INVERSION_ON, 3000 );
}
void displayTemperature(int unit) {
display.clear(); // Anzeige vor neuem Inhalt löschen
// Zeile 1: "Temperatur:" in 16pt Schriftgröße
display.setTextAlignment(TEXT_ALIGN_LEFT);
// Zeile 2: Temperaturwert in 24pt Schriftart
display.setFont(ArialMT_Plain_24);
// Temperatur mit dem richtigen Einheitssymbol formatieren
String tempStringC = String(tempC, 1) + "°C"; // 1 Dezimalstelle
String tempStringF = String(tempF, 1)+ "°F"; // 1 Dezimalstelle
String tempStringHumidity = String(humidity)+ "% RH";
String tempString;
switch(unit) {
case 1:
tempString =tempStringC;
display.setFont(ArialMT_Plain_16);
display.drawString(0, 0, "Temperature:");
display.setFont(ArialMT_Plain_24);
display.drawString(0, 15, tempString);
break; // Celsius
case 2: tempString =tempStringF;
display.setFont(ArialMT_Plain_16);
display.drawString(0, 0, "Temperature:");
display.setFont(ArialMT_Plain_24);
display.drawString(0, 15, tempString);
break; // Fahrenheit
case 3: tempString =tempStringC;
display.setFont(ArialMT_Plain_16);
display.drawString(0, 0, "Temperature:");
display.setFont(ArialMT_Plain_24);
display.drawString(0, 15, tempString);
display.setFont(ArialMT_Plain_16);
display.drawString(0, 40, "Humidity:");
display.drawString(70, 40, tempStringHumidity);
break; // Celsius
case 4: tempString =tempStringF;
display.setFont(ArialMT_Plain_16);
display.drawString(0, 0, "Temperature:");
display.setFont(ArialMT_Plain_24);
display.drawString(0, 15, tempString);
display.setFont(ArialMT_Plain_16);
display.drawString(0, 40, "Humidity:");
display.drawString(70, 40, tempStringHumidity );
break; // Celsius
case 5:
display.setFont(ArialMT_Plain_16);
display.drawString(0, 0, "Humidity:");
display.setFont(ArialMT_Plain_24);
display.drawString(0, 20, tempStringHumidity);
break; // Celsius
default: tempString =tempStringC + "°C"; break;; // Standard
}
display.display(); // OLED aktualisieren
}
void readSensor()
{
tempC = dht.readTemperature();
humidity = dht.readHumidity();
tempF = dht.convertCtoF(tempC);
}
void VextON(void)
{
pinMode(Vext,OUTPUT);
digitalWrite(Vext, LOW);
}
void VextOFF(void) // Vext standardmäßig AUS
{
pinMode(Vext,OUTPUT);
digitalWrite(Vext, HIGH);
}
void sendData()
{
String tempStringC = String(tempC, 1) + " °C"; // 1 Dezimalstelle
String tempStringF = String(tempF, 1)+ " °F"; // 1 Dezimalstelle
String tempStringHumidity = String(humidity)+ " % RH";
String txData;
// 1=C
// 2=F
// 3=C, Luftfeuchtigkeit
// 4=F, Luftfeuchtigkeit
// 5=Nur Luftfeuchtigkeit
switch(dataType) {
case 1:
txData = labelTemp + " " + tempStringC;
break;
case 2:
txData = labelTemp + " " + tempStringF;
break;
case 3:
txData = labelHumidity + " " + tempStringHumidity;
break;
default:
txData = labelTemp + " " + tempStringC;
break;
}
uint8_t data[32];
memset(data, 0, sizeof(data)); // Nullauffüllung
strncpy((char*)data, txData.c_str(), sizeof(data) - 1); // Kopiere Zeichenfolge sicher
encryptAES(data, userKey); // Vor dem Senden verschlüsseln
if(lora_idle == true)
{
delay(1000);
Radio.Send(data, sizeof(data));
Serial.print("Sending: ");
Serial.println((char *)data);
lora_idle = false;
}
Radio.IrqProcess( );
}
void loop() {
readSensor(); // Daten lesen
// Anzeige löschen
display.clear();
displayTemperature(dataType);
sendData();
delay(100);
}
void OnTxDone( void )
{
Serial.println("TX done......");
lora_idle = true;
}
void OnTxTimeout( void )
{
Radio.Sleep( );
Serial.println("TX Timeout......");
lora_idle = true;
}
/*
* Konvertiert einen vom Benutzer bereitgestellten Klartextschlüssel in einen festen 16-Byte (128-Bit) oder 32-Byte (256-Bit) Schlüssel.
*/
void processKey(const char *userKey, uint8_t *processedKey, size_t keySize) {
memset(processedKey, 0, keySize); // Mit Nullen auffüllen
size_t len = strlen(userKey);
if (len > keySize) len = keySize; // Trunkiere, wenn zu lang
memcpy(processedKey, userKey, len); // Kopieren Sie den gültigen Schlüsselteil
}
/*
* Verschlüsselt eine 16-Byte (ein Block) Nachricht mit AES-128.
*/
void encryptAES(uint8_t *data, const char *key) {
uint8_t processedKey[16]; // 128-Bit-Schlüssel
processKey(key, processedKey, 16);
mbedtls_aes_init(&aes);
mbedtls_aes_setkey_enc(&aes, processedKey, 128);
mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_ENCRYPT, data, data);
mbedtls_aes_free(&aes);
}
/*
* Entschlüsselt eine 16-Byte (ein Block) Nachricht mit AES-128.
*/
void decryptAES(uint8_t *data, const char *key) {
uint8_t processedKey[16]; // 128-Bit-Schlüssel
processKey(key, processedKey, 16);
mbedtls_aes_init(&aes);
mbedtls_aes_setkey_dec(&aes, processedKey, 128);
mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_DECRYPT, data, data);
mbedtls_aes_free(&aes);
}
/*
* Geschrieben am 01. April 2025
* geschrieben von Ahmad Shamshiri für www.Robojax.com
* Diese Skizze empfängt die sichere Temperatur oder Luftfeuchtigkeit von WiFi LoRa 32 und entschlüsselt sie
* und zeigt sie auf dem OLED an. Es gibt eine Aktionsfunktion, die ausgelöst wird, wenn die Temperatur unter triggeredValue liegt.
* Sieh dir das vollständige Video mit Erklärungen an: https://youtu.be/WkyQMXkQhE8
* Ressourcenseite: https://robojax.com/tutorial_view.php?id=387
*/
#include <Arduino.h>
// Alarmkonfiguration
const String triggerdText = "Too High"; // Korrekte Zeichenfolgentyp
const float triggerdValue = 90.0f; // exklusiv (dieser Wert ist nicht enthalten)
const int triggerdYpos = 45;
const bool triggerdType = true; // wahr ist > (größer als triggerdValue) und falsch ist < (kleiner als triggerdValue)
const int triggerdOutputPin = 7; // GPIO07 wird aktiviert, wenn es ausgelöst wird.
const bool triggerdBlink4Me= true; // soll blinken oder nicht
#include "mbedtls/aes.h"
#include <cstring> // Für memset, memcpy
mbedtls_aes_context aes;
const char *userKey = "hyhT676#h~_876s"; // Sicherheitsschlüssel
#define MIN_RSSI -120 // Schlechtestmöglicher Signal
#define MAX_RSSI -50 // Bestmögliches Signal
// Für eine Verbindung über I2C unter Verwendung der Arduino Wire-Bibliothek:
#include <Wire.h>
#include "HT_SSD1306Wire.h"
static SSD1306Wire display(0x3c, 500000, SDA_OLED, SCL_OLED, GEOMETRY_128_64, RST_OLED); // addr, freq, i2c-Gruppe, Auflösung, rst
#include "LoRaWan_APP.h"
#include "Arduino.h"
#define RF_FREQUENCY 915000000 // Hz
#define TX_OUTPUT_POWER 14 // dBm
#define LORA_BANDWIDTH 0 // [0: 125 kHz,
// 1: 250 kHz,
// 2: 500 kHz,
// 3: Reserviert
#define LORA_SPREADING_FACTOR 7 // [SF7..SF12]
#define LORA_CODINGRATE 1 // [1: 4/5,
// 2: 4/6,
// 3: 4/7,
// 4: 4/8]
#define LORA_PREAMBLE_LENGTH 8 // Gleich für Tx und Rx
#define LORA_SYMBOL_TIMEOUT 0 // Symbole
#define LORA_FIX_LENGTH_PAYLOAD_ON false
#define LORA_IQ_INVERSION_ON false
#define RX_TIMEOUT_VALUE 1000
#define BUFFER_SIZE 30 // Definieren Sie hier die Payload-Größe.
char txpacket[BUFFER_SIZE];
char rxpacket[BUFFER_SIZE];
static RadioEvents_t RadioEvents;
int16_t txNumber;
int16_t rssi,rxSize;
bool lora_idle = true;
unsigned long lastRxTime = 0;
const unsigned long SIGNAL_TIMEOUT = 5000; // 5 Sekunden
void decryptAES(uint8_t *data, const char *key);
void encryptAES(uint8_t *data, const char *key);
void processKey(const char *userKey, uint8_t *processedKey, size_t keySize);
void setup() {
Serial.begin(115200);
Serial.println();
Serial.println();
VextON();
delay(100);
// Die Initialisierung der Benutzeroberfläche wird auch das Display initialisieren.
display.init();
display.setFont(ArialMT_Plain_10);
pinMode(triggerdOutputPin, OUTPUT);
// LoRa-Sachen unter dieser Linie
Mcu.begin(HELTEC_BOARD,SLOW_CLK_TPYE);
txNumber=0;
rssi=0;
RadioEvents.RxDone = OnRxDone;
Radio.Init( &RadioEvents );
Radio.SetChannel( RF_FREQUENCY );
Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON,
0, true, 0, 0, LORA_IQ_INVERSION_ON, true );
}
void displayTemperature(String data1, String data2) {
display.clear(); // Anzeige vor neuem Inhalt löschen
// Temperatur: in 16pt Schriftgröße
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_16);
display.drawString(0, 0, data1);
// Zeile 2: Temperaturwert in 24pt Schriftgröße
display.setFont(ArialMT_Plain_24);
display.drawString(0, 20, data2);
displaySignalStrength(rssi);
// display.display(); // OLED aktualisieren
}
void displayLine(String data, int y) {
// Temperatur: in 16pt Schriftgröße
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_10);
if (triggerdBlink4Me) {
// Blink-Effekt: Text anzeigen, warten, Text löschen, warten, dann zurückkehren
display.drawString(0, y, data);
display.display();
delay(500); // Halte den Text für 500 ms sichtbar
display.clear(); // Bildschirm löschen
display.display();
delay(500); // Halte den Bildschirm für 500 ms schwarz.
}
else {
// Normale Anzeige ohne Blinken
display.drawString(0, y, data);
display.display();
}
}
void VextON(void)
{
pinMode(Vext,OUTPUT);
digitalWrite(Vext, LOW);
}
void VextOFF(void) // Vext standardmäßig AUS
{
pinMode(Vext,OUTPUT);
digitalWrite(Vext, HIGH);
}
void loop() {
RaIrqProcessdio( );
if(lora_idle)
{
lora_idle = false;
Serial.println("into RX mode");
Radio.Rx(0);
}
noSignalCheck();
delay(100);
}
void displaySignalStrength(int16_t rssi) {
// Konvertiere RSSI in Prozentsatz (0-100%)
int percent = map(constrain(rssi, MIN_RSSI, MAX_RSSI), MIN_RSSI, MAX_RSSI, 0, 100);
// Anzeige in der unteren rechten Ecke
display.setTextAlignment(TEXT_ALIGN_RIGHT);
display.setFont(ArialMT_Plain_16);
// Erstellen Sie einen Signalstärkeindikator
String strength = String(percent) + "% [";
for (int i = 0; i < 5; i++) {
strength += (percent > (i * 20)) ? "|" : " ";
}
strength += "]";
display.drawString(128, 45, strength); // Position unten rechts
}
void noSignalCheck()
{
// Automatische "Kein Signal" nach Zeitüberschreitung
if (millis() - lastRxTime > SIGNAL_TIMEOUT) {
display.clear();
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.setFont(ArialMT_Plain_16);
display.drawString(64, 20, "No Signal");
display.display();
}
}
/*
* Löst eine Aktion basierend auf einem Schwellenwertvergleich aus.
*
* @param type - Wenn wahr, wird ausgelöst, wenn floatValue **überschreitet** triggerdValue. Wenn falsch, wird ausgelöst, wenn floatValue **unter** triggerdValue **fällt**.
* @param floatValue - Der aktuell gemessene Wert, der verglichen werden soll.
* @param triggerdValue - Der Schwellenwert, der die Auslösebedingung bestimmt.
*/
void triggerAction(float floatValue)
{
if(triggerdType)
{
if (floatValue > triggerdValue) {
displayLine(triggerdText, triggerdYpos);
Serial.println(triggerdText);
digitalWrite(triggerdOutputPin, HIGH); // setzt triggeredOutputPin auf HIGH
}else{
digitalWrite(triggerdOutputPin, LOW);
}
}else{
if (floatValue < triggerdValue) {
displayLine(triggerdText, triggerdYpos);
Serial.println(triggerdText);
digitalWrite(triggerdOutputPin, HIGH); // setzt triggeredOutputPin auf HIGH
} else{
digitalWrite(triggerdOutputPin, LOW); // setzt den triggerdOutputPin auf LOW
}
}
}
void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
{
lastRxTime = millis(); // Zurücksetzen des Timers bei neuen Daten
rssi=rssi;
rxSize=size;
memcpy(rxpacket, payload, size );
rxpacket[size]='\0';
Radio.Sleep( );
Serial.printf("\r\nreceived packet \"%s\" with rssi %d , length %d\r\n",rxpacket,rssi,rxSize);
// Serial.println("Verschlüsselte Daten (Hex):");
// für (int i = 0; i < 16; i++) {
// Serial.printf("%02X ", rxpacket[i]);
// }
// Serial.println();
decryptAES((uint8_t *)rxpacket, userKey);
// Teilen Sie das empfangene Paket in Teile.
String receivedStr = String((char*)rxpacket);
int firstSpacePos = receivedStr.indexOf(' ');
if (firstSpacePos != -1) {
// Erster Teil (vor dem ersten Leerzeichen)
String part1 = receivedStr.substring(0, firstSpacePos); // Temperatur
// Finde den zweiten Raum (nach der Zahl)
int secondSpacePos = receivedStr.indexOf(' ', firstSpacePos + 1);
if (secondSpacePos != -1) {
// Zweiter Teil (numerischer Wert)
String part2 = receivedStr.substring(firstSpacePos + 1, secondSpacePos); // 34,5
float floatValue = part2.toFloat(); // In Float umwandeln 34,5
// Dritter Teil (Einheit)
String part3 = receivedStr.substring(secondSpacePos + 1); // °C
displayTemperature(part1, part2+part3);
display.display();
Serial.print("part1: " + part1);
Serial.print(" part2: " + part2);
Serial.println(" part3: " + part3);
Serial.println("floatValue " + String(floatValue));
// eine Aktion auszulösen.
triggerAction(floatValue);
} else {
Serial.println("No second space found for unit");
}
}else {
Serial.println("No space found in packet - can't split");
}
lora_idle = true;
}
/*
* Konvertiert einen vom Benutzer bereitgestellten Klartextschlüssel in einen Schüssel mit fester Länge von 16 Byte (128-Bit) oder 32 Byte (256-Bit).
*/
void processKey(const char *userKey, uint8_t *processedKey, size_t keySize) {
memset(processedKey, 0, keySize); // Mit Nullen füllen
size_t len = strlen(userKey);
if (len > keySize) len = keySize; // Abschneiden, wenn zu lang
memcpy(processedKey, userKey, len); // Kopiere gültigen Schlüsselteil
}
/*
* Verschlüsselt eine 16-Byte (ein Block) Nachricht mit AES-128.
*/
void encryptAES(uint8_t *data, const char *key) {
uint8_t processedKey[16]; // 128-Bit-Schlüssel
processKey(key, processedKey, 16);
mbedtls_aes_init(&aes);
mbedtls_aes_setkey_enc(&aes, processedKey, 128);
mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_ENCRYPT, data, data);
mbedtls_aes_free(&aes);
}
/*
* Dekodiert eine 16-Byte (ein Block) Nachricht mit AES-128.
*/
void decryptAES(uint8_t *data, const char *key) {
uint8_t processedKey[16]; // 128-Bit-Schlüssel
processKey(key, processedKey, 16);
mbedtls_aes_init(&aes);
mbedtls_aes_setkey_dec(&aes, processedKey, 128);
mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_DECRYPT, data, data);
mbedtls_aes_free(&aes);
}
Common Course Links
Common Course Files
Ressourcen & Referenzen
-
Extern
-
Extern
-
ExternKaufe Wi-Fi LoRa 32 von Meshnologymeshnology.com
-
Extern
-
Extern
Dateien📁
Andere Dateien
-
Heltec WiFi LoRa 32 V3 Schaltbild (V3.1)
Heltec_WiFiLoRAV3_Schematic_Diagram.pdf0.18 MB