یہ ٹیوٹوریل کا حصہ ہے: WiFi LoRa 32 سبق
Heltec WiFi LoRa 32 سے متعلق تمام ویڈیوز اس گروپ کے استعمال سے متعلق ہیں۔ دیگر ویڈیوز کے لنکس اس مضمون کے نیچے ہیں۔
Heltec WiFi LoRa 32 V3 کا استعمال کرتے ہوئے DHT22 کے ذریعے درجہ حرارت 1.4 کلومیٹر تک منتقل کرنا
اس ٹیوٹوریل میں، ہم دریافت کریں گے کہ Heltec WiFi LoRa 32 V3 ماجیول کو کیسے استعمال کیا جائے تاکہ DHT22 سینسر سے درجہ حرارت کا ڈیٹا طویل فاصلے تک منتقل کیا جا سکے، جس سے 1.4 کلومیٹر تک کی رینج حاصل کی جا سکتی ہے۔ یہ صلاحیت LoRa ٹیکنالوجی کے استعمال سے ممکن ہوتی ہے، جو کم بجلی اور طویل فاصلے کی کمیونیکیشن کی اجازت دیتی ہے۔ اس گائیڈ کے اختتام تک، آپ کے پاس ایک کام کرنے والا نظام ہوگا جو درجہ حرارت کی ریڈنگز کو وائرلیس طور پر بھیج سکتا ہے۔
ہم اس پروجیکٹ میں شامل ہارڈویئر اجزاء کے جائزے سے آغاز کریں گے، بشمول Heltec WiFi LoRa 32 V3 ماجیول اور DHT22 سینسر۔ اس کے بعد، ہم وائرنگ کی ہدایات کی طرف بڑھیں گے، جہاں آپ سیکھیں گے کہ ان اجزاء کو کیسے جوڑنا ہے۔ آخر میں، ہم اس نظام کو چلانے کے لیے درکار کوڈ کا جائزہ لیں گے۔ بصری رہنمائی کے لیے، براہ کرم مختلف ٹائم اسٹیمپس پر ویڈیو دیکھیں (ویڈیو میں 00:00 پر)۔
ہارڈویئر کی وضاحت
اس پروجیکٹ کے اہم اجزاء Heltec WiFi LoRa 32 V3 ماجیول اور DHT22 درجہ حرارت اور نمی کا سینسر ہیں۔ Heltec ماجیول میں ESP32 مائیکروکنٹرولر شامل ہے، جو LoRa کمیونیکیشن کے ساتھ ساتھ Wi-Fi اور بلوٹوتھ کی صلاحیتیں فراہم کرتا ہے۔ یہ ڈیٹا کی منتقلی کے لچکدار اختیارات کی اجازت دیتا ہے۔
DHT22 سینسر ایک ڈیجیٹل سینسر ہے جو درجہ حرارت اور نمی کی درست ریڈنگز فراہم کرتا ہے۔ یہ ESP32 کے ساتھ ایک ہی ڈیجیٹل آؤٹ پٹ پن کے ذریعے بات چیت کرتا ہے، جس سے اسے آپ کے پروجیکٹس میں جوڑنا اور استعمال کرنا آسان ہو جاتا ہے۔ مل کر، یہ اجزاء وائرلیس درجہ حرارت کی نگرانی کے لیے ایک مضبوط نظام تشکیل دیتے ہیں۔
ڈیٹاشیٹ کی تفصیلات
| مینوفیکچرر | Heltec Automation |
|---|---|
| پارٹ نمبر | WiFi LoRa 32 V3 |
| لاجک/آئی او وولٹیج | 3.3 V |
| سپلائی وولٹیج | 3.7–4.2 V |
| آؤٹ پٹ کرنٹ (فی چینل) | ~1 A |
| پیک کرنٹ (فی چینل) | ~2 A |
| PWM فریکوئنسی رہنمائی | 1 kHz (عام) |
| ان پٹ لاجک تھریشولڈز | 0.7 V (زیادہ)، 0.3 V (کم) |
| وولٹیج ڈراپ / RDS(on) / سیچوریشن | 0.3 V (زیادہ سے زیادہ) |
| تھرمل حدود | 85 °C (زیادہ سے زیادہ) |
| پیکیج | PCB ماجیول |
| نوٹس / ویریئنٹس | مختلف فریکوئنسی اختیارات دستیاب ہیں (مثلاً، 433 MHz، 868 MHz، 915 MHz) |
- DHT22 کو 3.3V سے پاور کریں، 5V سے نہیں۔
- ESP32 اور DHT22 کے درمیان کمیونیکیشن کے لیے مناسب لاجک لیولز استعمال کریں۔
- اگر زیادہ کرنٹ پر طویل عرصے تک چل رہے ہیں تو ہیٹ سنکنگ پر غور کریں۔
- رینج کو زیادہ سے زیادہ کرنے کے لیے LoRa کے لیے اینٹینا کنکشن چیک کریں۔
- اپنے علاقے میں LoRa فریکوئنسی کے ضوابط کا خیال رکھیں۔
وائرنگ کی ہدایات

Heltec WiFi LoRa 32 V3 کو DHT22 سینسر کے ساتھ جوڑنے کے لیے، سینسر کے VCC پن کو Heltec ماجیول کے 3.3V پن سے جوڑ کر شروع کریں۔ اگلا، DHT22 کے GND پن کو Heltec کے کسی ایک GND پن سے جوڑیں۔ DHT22 کا ڈیٹا پن Heltec کے GPIO پن 3 سے منسلک ہونا چاہیے۔
مستحکم ریڈنگز کے لیے ڈیٹا پن اور VCC کے درمیان پل اپ ریزسٹر (تقریباً 10kΩ) استعمال کرنا یقینی بنائیں۔ اس کے علاوہ، ٹرانسمیشن رینج بڑھانے کے لیے LoRa اینٹینا کو محفوظ طریقے سے منسلک کریں۔ اگر آپ بیرونی پاور استعمال کر رہے ہیں، تو یقینی بنائیں کہ Heltec ماجیول صحیح طریقے سے پاورڈ ہے تاکہ آپریشنل مسائل سے بچا جا سکے۔
Heltec ESP32 بورڈز انسٹال کرنا
اس پاتھ کو اپنے Arduino IDE کی ترجیحات میں شامل کریں جیسا کہ ویڈیو میں دکھایا گیا ہے:https://resource.heltec.cn/download/package_heltec_esp32_index.json
Heltec ESP32 لائبریریز انسٹال کرنا
Arduino IDE کھلنے پر، براہ کرم لائبریری آئیکن (1) پر کلک کریں، پھر سرچ میں "Heltec" ٹائپ کریں (2) اور انسٹال پر کلک کریں (3) تصویر دیکھیں۔
کوڈ کی مثالیں اور واک تھرو
درج ذیل کوڈ سنیپٹس واضح کرتے ہیں کہ Heltec ماجیول کو DHT22 سینسر سے درجہ حرارت کا ڈیٹا پڑھنے اور اسے LoRa کے ذریعے منتقل کرنے کے لیے کیسے ترتیب دیا جائے۔ کوڈ ڈسپلے کو انیشیالائز کرتا ہے اور DHT سینسر کو سیٹ اپ کرتا ہے۔
#include
#define DHTPIN 3 // DHT22 کے لیے GPIO پن
#define DHTTYPE DHT22 // DHT کی قسم کی وضاحت
DHT dht(DHTPIN, DHTTYPE);
void setup() {
Serial.begin(115200);
dht.begin(); // DHT سینسر کو انیشیالائز کریں
}
اس سنیپٹ میں، ہم اس پن کی وضاحت کرتے ہیں جس سے DHT22 سینسر منسلک ہے اور اسے setup() فنکشن میں انیشیالائز کرتے ہیں۔ Serial.begin(115200) لائن ڈیبگنگ آؤٹ پٹ کے لیے ہے۔
void loop() {
float tempC = dht.readTemperature(); // درجہ حرارت سیلسیس میں پڑھیں
float tempF = dht.convertCtoF(tempC); // فارن ہائیٹ میں تبدیل کریں
sendData(tempC, tempF); // درجہ حرارت کا ڈیٹا بھیجنے کا فنکشن
}
یہ اقتباس دکھاتا ہے کہ loop() فنکشن میں درجہ حرارت کا ڈیٹا کیسے پڑھا جائے۔ sendData() فنکشن کو LoRa پر درجہ حرارت کی ریڈنگز منتقل کرنے کے لیے بلایا جاتا ہے۔
void sendData(float tempC, float tempF) {
String data = "درجہ حرارت: " + String(tempC) + "°C"; // ڈیٹا سٹرنگ بنائیں
Radio.Send(data.c_str(), data.length()); // ڈیٹا بھیجیں
}
یہاں، ہم درجہ حرارت پر مشتمل ڈیٹا سٹرنگ بناتے ہیں اور اسے Radio.Send() طریقہ استعمال کرتے ہوئے بھیجتے ہیں۔ یہ ڈیٹا وائرلیس طور پر وصول کرنے والے ماجیول تک منتقل کرے گا۔
تفصیلی نفاذ کے لیے براہ کرم مضمون کے نیچے لوڈ کردہ مکمل کوڈ دیکھیں۔
مظاہرہ / کیا توقع کریں
ایک بار جب سب کچھ سیٹ ہو جائے اور کوڈ Heltec ماجیول پر اپ لوڈ ہو جائے، تو آپ کو OLED اسکرین پر درجہ حرارت کی ریڈنگز نظر آئیں گی۔ سسٹم درجہ حرارت کا ڈیٹا منتقل کرے گا، جسے ایک اور Heltec ماجیول جو ڈیٹا پڑھنے کے لیے ترتیب دیا گیا ہے، وصول کر سکتا ہے۔ آپ وصول کنندہ کو ٹرانسمیٹر سے دور لے جا کر رینج جانچ سکتے ہیں، جس سے زیادہ سے زیادہ فاصلے کی تصدیق ہوگی (ویڈیو میں 1:30 پر)۔
عام غلطیوں جیسے غلط وائرنگ، ناکافی بجلی کی فراہمی، یا غلط LoRa فریکوئنسی استعمال کرنے سے محتاط رہیں۔ یقینی بنائیں کہ DHT22 صحیح طریقے سے کام کر رہا ہے اور رینج کو زیادہ سے زیادہ کرنے کے لیے اینٹینا منسلک ہے۔
ویڈیو ٹائم اسٹیمپس
- 00:00 آغاز
- 3:51 خصوصیات
- 8:32 دستاویزات کا صفحہ
- 9:52 پیکیج اور بیٹری
- 12:58 پہلی بار پاور آن کرنا
- 16:37 لائبریری انسٹال کرنا
- 18:19 ٹرانسمیٹر بنیادی کوڈ
- 19:43 وصول کنندہ بنیادی کوڈ
- 20:39 ٹیکسٹ بھیجنے اور وصول کرنے کا مظاہرہ
- 23:02 OLED ڈیمو کوڈ
- 24:06 OLED ڈسپلے پر بنیادی ٹیکسٹ کوڈ
- 26:26 OLED پر بنیادی ٹیکسٹ ڈیمو
- 26:58 DHT22 کے ساتھ درجہ حرارت پڑھنا
- 28:49 LoRa ٹرانسمیٹر درجہ حرارت اور ڈسپلے
- 30:07 LoRa وصول کنندہ درجہ حرارت اور ڈسپلے
- 32:13 درجہ حرارت بڑھنے پر LED متحرک کرنا
- 22:26 LoRa ٹرانسمیشن رینج ٹیسٹ
- 35:01 dBm اور ملی واٹ
یہ ٹیوٹوریل کا حصہ ہے: WiFi LoRa 32 سبق
- 13 Miles 20km with NO WiFi? How LoRa Sent Voltage Across Crazy Distances! (Heltec WiFi LoRa 32 V3)
- Turn On a Device from 13 mile 21km Away – The Ultimate Off-Grid LoRa Project with WiFi LoRa 32!
- Remote Door Alert System from 13 mile 21 km Away With LoRa – Off the Grid! (Heltec WiFi LoRa 32 V3)
- Control a Servo motor from Miles Away! Heltec WiFi LoRa 32 V3 Arduino Tutorial (TX)
- DIY Remote Relay Project: 13 Mile No-Wi-Fi/No-SIM 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
وسائل اور حوالہ جات
-
باہرونی
-
باہرونی
-
باہرونی
-
باہرونی
-
باہرونیPurchase a WiFi LoRa 32 V3 from AliExpresss.click.aliexpress.com
-
باہرونیPurchase a WiFi LoRa 32 V3 from AliExpress-2s.click.aliexpress.com
-
باہرونی
-
باہرونیPurchase Wi-Fi LoRa 32 from Meshnologymeshnology.com
فائلیں📁
آرڈوینو لائبریریاں (زپ)
-
Heltec ESP32 libraries 2.1.5Libraries for all Heltec ESP32 boards. This is version 2.1.5.
Heltec_ESP32-master.zip3.86 MB
دیگر فائلیں
-
Heltec WiFi LoRa 32 V3 Schematic Diagram (V3.1)
Heltec_WiFiLoRAV3_Schematic_Diagram.pdf0.18 MB