Casharradan waa qayb ka mid ah: Casharrada WiFi LoRa 32
Dhammaan fiidiyowyada la xiriira Heltec WiFi LoRa 32 waxay la xiriiraan kooxdan. Xiriirinta fiidiyowyada kale waxay ku yaalliin maqaalkan.
Isticmaalka Heltec WiFi LoRa 32 V3 si loo gudbiyo heerkulka iyadoo la isticmaalayo DHT22 ilaa 1.4km
Cashiggan, waxaan ku baran doonaa sida loo isticmaalo module-ka Heltec WiFi LoRa 32 V3 si loogu gudbiyo xogta heerkulka ee sensor-ka DHT22 masaafo dheer, iyadoo la gaarayo masaafo ilaa 1.4 kiiloomitir. Awooddan waxaa suurtageliyay isticmaalka teknoolojiyadda LoRa, taas oo u oggolaanaysa isgaarsiin tamar yar oo masaafo dheer ah. Markaad dhammayso hagahan, waxaad yeelan doontaa nidaam shaqeeya oo kuu soo diri kara akhrinta heerkulka si wireless ah.
Waxaan ku bilaabi doonaa dulmar guud oo ku saabsan qaybaha hardware-ka ee ku lug leh mashruucan, oo ay ku jiraan module-ka Heltec WiFi LoRa 32 V3 iyo sensor-ka DHT22. Ka dib, waxaan u gudbi doonaa tilmaamaha fiilada, halkaas oo aad ku baran doonto sida loogu xiro qaybahan. Ugu dambayntii, waxaan ku dhex mari doonaa koodhka loo baahan yahay si nidaamkan uu u shaqeeyo. Hagaag, fadlan fiiri fiidiyowga waqtiyada kala duwan (fiidiyowga 00:00).
Sharaxaadda Hardware-ka
Qaybaha ugu muhiimsan ee mashruucan waa module-ka Heltec WiFi LoRa 32 V3 iyo sensor-ka heerkulka iyo qoyaanka DHT22. Module-ka Heltec wuxuu leeyahay microcontroller-ka ESP32, kaas oo bixiya awoodaha Wi-Fi iyo Bluetooth-ka oo ay weheliso isgaarsiinta LoRa. Tani waxay u oggolaanaysaa ikhtiyaarro kala duwan oo gudbinta xogta ah.
Sensor-ka DHT22 waa sensor dijitaal ah oo bixiya akhrin sax ah oo heerkulka iyo qoyaanka ah. Wuxuu la xidhiidhaa ESP32-ka hal pin oo wax soo saar dijitaal ah ah, taasoo ka dhigaysa mid fudud in la xiro oo loo isticmaalo mashruucyadaada. Marka la wada geeyo, qaybahani waxay sameeyaan nidaam adag oo lagula socon karo heerkulka wireless-ka.
Faahfaahinta Xaashida Xogta
| Soo saaraha | Heltec Automation |
|---|---|
| Nambarka qaybta | WiFi LoRa 32 V3 |
| Danabka Logic/IO | 3.3 V |
| Danabka sahayda | 3.7–4.2 V |
| Korontada soo saarta (kanal kasta) | ~1 A |
| Korontada ugu sarreysa (kanal kasta) | ~2 A |
| Hagaha soo noqnoqoshada PWM | 1 kHz (caadi ahaan) |
| Heerarka caqabadaha gelinta | 0.7 V (sare), 0.3 V (hoose) |
| Hoos u dhaca danabka / RDS(on) / dheregsanaanta | 0.3 V (ugu badnaan) |
| Xadka kulaylka | 85 °C (ugu badnaan) |
| Baakad | Module PCB |
| Qoraallo / noocyo kala duwan | Ikhtiyaarro soo noqnoqosho oo kala duwan ayaa diyaar ah (tusaale, 433 MHz, 868 MHz, 915 MHz) |
- Hubi inaad ku shiddo DHT22-ka 3.3V, ma aha 5V.
- Isticmaal heerarka logic-ka ku habboon isgaarsiinta u dhaxaysa ESP32-ka iyo DHT22-ka.
- Tixgeli kulayl-qaadista haddii aad ku shaqeyneyso koronto sare muddo dheer.
- Hubi xidhiidhka anteenada ee LoRa si aad u kordhiso masaafada.
- Ka warqab xeerarka soo noqnoqoshada LoRa ee gobolkaaga.
Tilmaamaha Fiilada

Si aad ugu xirtid Heltec WiFi LoRa 32 V3 sensor-ka DHT22, waxaad ku bilaabaysaa inaad ku xirtid pin-ka VCC ee sensor-ka pin-ka 3.3V ee module-ka Heltec. Marka xigta, ku xir pin-ka GND ee DHT22-ka mid ka mid ah pin-yada GND ee Heltec-ka. Pin-ka xogta ee DHT22-ka waa in lagu xiraa pin-ka GPIO 3 ee Heltec-ka.
Hubi inaad isticmaasho resistor-ka kor-u-jiidashada (qiyaastii 10kΩ) inta u dhaxaysa pin-ka xogta iyo VCC si aad u hesho akhrin deggan. Intaa waxaa dheer, hubi in anteenada LoRa si ammaan ah u xiran tahay si loo kordhiyo masaafada gudbinta. Haddii aad isticmaalayso koronto dibadeed, hubi in module-ka Heltec si sax ah u shaqeynayo si looga fogaado dhibaatooyin shaqo.
Ku Rakibida Boards-ka Heltec ESP32
Kudar waddankan doorbidyada Arduino IDE-ga sida lagu muujiyey fiidiyowga:https://resource.heltec.cn/download/package_heltec_esp32_index.json
Ku Rakibida Maktabadaha Heltec ESP32
Marka Arduino IDE la furo, fadlan guji astaanta Maktabadda (1), kadib ku qor "Heltec" ee raadinta (2) oo guji Rakib (3) eeg sawirka.
Tusaalooyinka Koodhka & Sharaxaada
Qaybaha koodhka ee soo socda waxay muujinayaan sida loo habeeyo module-ka Heltec si uu u akhriyo xogta heerkulka ee sensor-ka DHT22 oo uu ugu gudbiyo iyada oo loo marayo LoRa. Koodhku wuxuu bilaabaa shaashadda oo wuxuu dejiyaa sensor-ka DHT.
#include
#define DHTPIN 3 // GPIO pin ee DHT22
#define DHTTYPE DHT22 // Qeex nooca DHT
DHT dht(DHTPIN, DHTTYPE);
void setup() {
Serial.begin(115200);
dht.begin(); // Bilaabi sensor-ka DHT
}
Qaybtan, waxaan ku qeexaynaa pin-ka uu sensor-ka DHT22 ku xiran yahay oo waxaan ku bilaabaynaa shaqada setup(). Xariiqda Serial.begin(115200) waxay u taagan tahay wax soo saarka lagu ogaanayo khaladaadka.
void loop() {
float tempC = dht.readTemperature(); // Akhri heerkulka Celsius
float tempF = dht.convertCtoF(tempC); // U beddel Fahrenheit
sendData(tempC, tempF); // Shaqo lagu soo diro xogta heerkulka
}
Qaybtani waxay muujinaysaa sida loo akhriyo xogta heerkulka shaqada loop(). Shaqada sendData() ayaa loo yaqaan si loogu gudbiyo akhrinta heerkulka iyada oo loo marayo LoRa.
void sendData(float tempC, float tempF) {
String data = "Heerkulka: " + String(tempC) + "°C"; // Abuuri xogta
Radio.Send(data.c_str(), data.length()); // Dir xogta
}
Halkan, waxaan abuuraynaa xogta ku jirta heerkulka oo waxaan u dirnaa iyada oo la adeegsanayo habka Radio.Send(). Tani waxay si wireless ah u gudbin doontaa xogta qaybta qaabulka.
Fadlan fiiri koodhka buuxa ee hoos ku qoran maqaalka si aad u hesho faahfaahin dhamaystiran.
Muuujin / Waxa Lagu Filan Karaa
Marka wax walba la hagaajiyo oo koodhka la geliyo qalabka Heltec, waa inaad aragtaa akhrinta heerkulka oo ku muuqanaya shaashadda OLED. Nidaamku wuxuu diri doonaa xogta heerkulka, taas oo qaabi kara qalab kale oo Heltec ah oo loo habeeyay inuu akhriyo xogta. Waxaad tijaabin kartaa masaafada adiga oo ka fogaynaya qaabulka xagga gudbiyaha, taasoo xaqiijinaysa masaafada ugu badan ee la gaaro (fiidiyowga 1:30).
Ka digtoonow khataraha caadiga ah sida xiriirinta khaldan, koronto ku filan, ama isticmaalka soo noqnoqoshada LoRa ee khaldan. Hubi in DHT22 si fiican u shaqeynayo iyo in antenna ku xiran tahay si loo kordhiyo masaafada.
Waqtiyada Fiidiyowga
- 00:00 Bilow
- 3:51 Sifooyinka
- 8:32 Bogga dukumeentiga
- 9:52 Baakad iyo batteriga
- 12:58 Markii ugu horreysay oo la shido
- 16:37 Ku rakibida Maktabadda
- 18:19 Koodhka aasaasiga ah ee Gudbiyaha
- 19:43 Koodhka aasaasiga ah ee Qaabulka
- 20:39 Muujinta dirista iyo qaabista qoraalka
- 23:02 Koodhka muujinta OLED
- 24:06 Koodhka qoraalka aasaasiga ah ee shaashadda OLED
- 26:26 Muujinta qoraalka aasaasiga ah ee OLED
- 26:58 Akhrinta heerkulka DHT22
- 28:49 Gudbiyaha LoRa Heerkulka iyo Muujinta
- 30:07 Qaabulka LoRa Heerkulka iyo Muujinta
- 32:13 Kicinta LED marka heerkulku kordho
- 22:26 Tijaabinta masaafada gudbinta LoRa
- 35:01 dBm iyo Milli Watt
Casharradan waa qayb ka mid ah: Casharrada WiFi LoRa 32
- 13 Mayl 20km oo WiFi la’aan? Sida LoRa u soo diray koronto masaafo cajiib ah! (Heltec WiFi LoRa 32 V3)
- Jibixi Aalad 13 mayl 21km ka fog – Mashruuca LoRa ee Off-Grid ee ugu dambeeya ee leh WiFi LoRa 32!
- Nidaam Qaylinta Albaabka Fog ee 13 mayl 21 km Kadib La LoRa – Ka Baxsan Shabakadda! (Heltec WiFi LoRa 32 V3)
- Kontorool Servo motor meel fog! Heltec WiFi LoRa 32 V3 Arduino Tutorial (TX)
- Mashruucka Relay-ka Fogga ah ee DIY: 13 Mayl oo aan Wi-Fi/aan SIM lahayn Heltec LoRa 32 Module
- 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);
}
/*
written on March 27, 2025
written by Ahmad Shamshiri for www.Robojax.com
Transmits Temperature and Humidity over LoRa RF using ESP32 LoRA 32 V3 module.
and displays the information on the screen.
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
#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, Humidity //only for display not for transmission
//4=F, Humidity //only for display not for transmission
//5=Humidity only
int dataType = 2;
String labelTemp = "Temperature";
String labelHumidity = "Humidity";
const int TX_POWER = 2;//dBm from 2 to 20. when powered via battery 2 to 14dBm is the best option
#include "mbedtls/aes.h"
#include <cstring> // For memset, memcpy
mbedtls_aes_context aes;
const char *userKey = "hyhT676#h~_876s"; //Security key.
#include "LoRaWan_APP.h"
#include "Arduino.h"
#define RF_FREQUENCY 915000000 // Hz
#define TX_OUTPUT_POWER TX_POWER // dBm from 2 to 20. when powered via battery 2 to 14dBm
#define LORA_BANDWIDTH 0 // [0: 125 kHz,
// 1: 250 kHz,
// 2: 500 kHz,
// 3: Reserved]
#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 // Same for Tx and Rx
#define LORA_SYMBOL_TIMEOUT 0 // Symbols
#define LORA_FIX_LENGTH_PAYLOAD_ON false
#define LORA_IQ_INVERSION_ON false
#define RX_TIMEOUT_VALUE 1000
#define BUFFER_SIZE 30 // Define the payload size here
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);
// Initialising the UI will init the display too.
display.init();
display.setFont(ArialMT_Plain_10);
dht.begin();
//LoRa stuff
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(); // Clear display before new content
// Line 1: "Temperature:" in 16pt font
display.setTextAlignment(TEXT_ALIGN_LEFT);
// Line 2: Temperature value in 24pt font
display.setFont(ArialMT_Plain_24);
// Format temperature with correct unit symbol
String tempStringC = String(tempC, 1) + "°C"; // 1 decimal place
String tempStringF = String(tempF, 1)+ "°F"; // 1 decimal place
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;; // default
}
display.display(); // Update OLED
}
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 default OFF
{
pinMode(Vext,OUTPUT);
digitalWrite(Vext, HIGH);
}
void sendData()
{
String tempStringC = String(tempC, 1) + " °C"; // 1 decimal place
String tempStringF = String(tempF, 1)+ " °F"; // 1 decimal place
String tempStringHumidity = String(humidity)+ " % RH";
String txData;
//1=C
//2=F
//3=C, Humidity
//4=F, Humidity
//5=Humidity only
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)); // Zero-padding
strncpy((char*)data, txData.c_str(), sizeof(data) - 1); // Copy string safely
encryptAES(data, userKey); // Encrypt before sending
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();//read the data
// clear the display
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;
}
/**
* Converts a user-provided plaintext key into a fixed-length 16-byte (128-bit)
* or 32-byte (256-bit) key.
*/
void processKey(const char *userKey, uint8_t *processedKey, size_t keySize) {
memset(processedKey, 0, keySize); // Fill with zeros
size_t len = strlen(userKey);
if (len > keySize) len = keySize; // Truncate if too long
memcpy(processedKey, userKey, len); // Copy valid key part
}
/**
* Encrypts a 16-byte (one block) message using AES-128.
*/
void encryptAES(uint8_t *data, const char *key) {
uint8_t processedKey[16]; // 128-bit key
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);
}
/**
* Decrypts a 16-byte (one block) message using AES-128.
*/
void decryptAES(uint8_t *data, const char *key) {
uint8_t processedKey[16]; // 128-bit key
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);
}
/*
Written on April 01, 2025
written by Ahmad Shamshiri for www.Robojax.com
this sktech receives the secure temperature or humidity from WiFi LoRa 32 and decrypts it
and displays it on the OLED. There is action feature to triggerd if the temperature is below triggerdValue
Watch full video explaination https://youtu.be/WkyQMXkQhE8
Resources page: https://robojax.com/tutorial_view.php?id=387
*/
#include <Arduino.h>
// Alert configuration
const String triggerdText = "Too High"; // Correct String type
const float triggerdValue = 90.0f; // exclusive (this value is not included)
const int triggerdYpos = 45;
const bool triggerdType = true;//true is > (greter than triggerdValue) and false is < (less than triggerdValue)
const int triggerdOutputPin = 7;//GPIO07 goes HIGH when triggered
const bool triggerdBlink4Me= true;//should blink or not
#include "mbedtls/aes.h"
#include <cstring> // For memset, memcpy
mbedtls_aes_context aes;
const char *userKey = "hyhT676#h~_876s"; //Security key
#define MIN_RSSI -120 // Worst possible signal
#define MAX_RSSI -50 // Best possible signal
// For a connection via I2C using the Arduino Wire include:
#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
#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: Reserved]
#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 // Same for Tx and Rx
#define LORA_SYMBOL_TIMEOUT 0 // Symbols
#define LORA_FIX_LENGTH_PAYLOAD_ON false
#define LORA_IQ_INVERSION_ON false
#define RX_TIMEOUT_VALUE 1000
#define BUFFER_SIZE 30 // Define the payload size here
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 seconds
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);
// Initialising the UI will init the display too.
display.init();
display.setFont(ArialMT_Plain_10);
pinMode(triggerdOutputPin, OUTPUT);
//LoRa stuff blow this line
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(); // 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, data1);
// Line 2: Temperature value in 24pt font
display.setFont(ArialMT_Plain_24);
display.drawString(0, 20, data2); //
displaySignalStrength(rssi);
// display.display(); // Update OLED
}
void displayLine(String data, int y) {
// Line 1: "Temperature:" in 16pt font
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_10);
if (triggerdBlink4Me) {
// Blink effect: Display text, wait, clear text, wait, then return
display.drawString(0, y, data);
display.display();
delay(500); // Keep text visible for 500ms
display.clear(); // Clear the screen
display.display();
delay(500); // Keep screen blank for 500ms
}
else {
// Normal display without blinking
display.drawString(0, y, data);
display.display();
}
}
void VextON(void)
{
pinMode(Vext,OUTPUT);
digitalWrite(Vext, LOW);
}
void VextOFF(void) //Vext default OFF
{
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) {
// Convert RSSI to percentage (0-100%)
int percent = map(constrain(rssi, MIN_RSSI, MAX_RSSI), MIN_RSSI, MAX_RSSI, 0, 100);
// Display at bottom right corner
display.setTextAlignment(TEXT_ALIGN_RIGHT);
display.setFont(ArialMT_Plain_16);
// Create signal strength indicator
String strength = String(percent) + "% [";
for (int i = 0; i < 5; i++) {
strength += (percent > (i * 20)) ? "|" : " ";
}
strength += "]";
display.drawString(128, 45, strength); // Position at bottom-right
}
void noSignalCheck()
{
// Automatic "No Signal" after timeout
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();
}
}
/**
* Triggers an action based on a threshold comparison.
*
* @param type - If true, triggers when floatValue **exceeds** triggerdValue.
* If false, triggers when floatValue **falls below** triggerdValue.
* @param floatValue - The current measured value to compare.
* @param triggerdValue - The threshold value that determines the trigger condition.
*/
void triggerAction(float floatValue)
{
if(triggerdType)
{
if (floatValue > triggerdValue) {
displayLine(triggerdText, triggerdYpos);
Serial.println(triggerdText);
digitalWrite(triggerdOutputPin, HIGH);//turns triggerdOutputPin to HIGH
}else{
digitalWrite(triggerdOutputPin, LOW);
}
}else{
if (floatValue < triggerdValue) {
displayLine(triggerdText, triggerdYpos);
Serial.println(triggerdText);
digitalWrite(triggerdOutputPin, HIGH);//turns triggerdOutputPin to HIGH
} else{
digitalWrite(triggerdOutputPin, LOW);//turns triggerdOutputPin to LOW
}
}
}
void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
{
lastRxTime = millis(); // Reset timer on new data
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("Encrypted Data (Hex):");
// for (int i = 0; i < 16; i++) {
// Serial.printf("%02X ", rxpacket[i]);
// }
// Serial.println();
decryptAES((uint8_t *)rxpacket, userKey);
// Split the received packet into parts
String receivedStr = String((char*)rxpacket);
int firstSpacePos = receivedStr.indexOf(' ');
if (firstSpacePos != -1) {
// First part (before first space)
String part1 = receivedStr.substring(0, firstSpacePos); // "Temperature"
// Find second space (after the number)
int secondSpacePos = receivedStr.indexOf(' ', firstSpacePos + 1);
if (secondSpacePos != -1) {
// Second part (numeric value)
String part2 = receivedStr.substring(firstSpacePos + 1, secondSpacePos); // "34.5"
float floatValue = part2.toFloat(); // Convert to float 34.5
// Third part (unit)
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));
//to trigger an action.
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;
}
/**
* Converts a user-provided plaintext key into a fixed-length 16-byte (128-bit)
* or 32-byte (256-bit) key.
*/
void processKey(const char *userKey, uint8_t *processedKey, size_t keySize) {
memset(processedKey, 0, keySize); // Fill with zeros
size_t len = strlen(userKey);
if (len > keySize) len = keySize; // Truncate if too long
memcpy(processedKey, userKey, len); // Copy valid key part
}
/**
* Encrypts a 16-byte (one block) message using AES-128.
*/
void encryptAES(uint8_t *data, const char *key) {
uint8_t processedKey[16]; // 128-bit key
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);
}
/**
* Decrypts a 16-byte (one block) message using AES-128.
*/
void decryptAES(uint8_t *data, const char *key) {
uint8_t processedKey[16]; // 128-bit key
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
Kheyraadka & Tixraacyada
-
Dibedda
-
Dibedda
-
Dibedda
-
Dibedda
-
DibeddaPurchase a WiFi LoRa 32 V3 from AliExpresss.click.aliexpress.com
-
DibeddaPurchase a WiFi LoRa 32 V3 from AliExpress-2s.click.aliexpress.com
-
Dibedda
-
DibeddaPurchase Wi-Fi LoRa 32 from Meshnologymeshnology.com
Faylasha📁
Arduino Libraries (zip)
-
Heltec ESP32 libraries 2.1.5Libraries for all Heltec ESP32 boards. This is version 2.1.5.
Heltec_ESP32-master.zip3.86 MB
Faylal kale
-
Heltec WiFi LoRa 32 V3 Schematic Diagram (V3.1)
Heltec_WiFiLoRAV3_Schematic_Diagram.pdf0.18 MB