This tutorial is part of: Mafunzo ya WiFi LoRa 32
Video zote zinazohusiana na Heltec WiFi LoRa 32 zinahusiana kwa kutumia kikundi hiki. Viungo vya video zingine viko chini ya makala haya.
Kutumia Heltec WiFi LoRa 32 V3 kutuma joto kwa kutumia DHT22 hadi kilomita 1.4
Katika mafunzo haya, tutachunguza jinsi ya kutumia moduli ya Heltec WiFi LoRa 32 V3 kutuma data ya joto kutoka kwa sensa ya DHT22 kwa umbali mrefu, kufikia umbali hadi kilomita 1.4. Uwezo huu unapatikana kupitia matumizi ya teknolojia ya LoRa, ambayo inaruhusu mawasiliano ya nguvu ya chini na ya umbali mrefu. Kufikia mwisho wa mwongozo huu, utakuwa na mfumo unaofanya kazi ambao unaweza kutuma usomaji wa joto bila waya.
Tutaanza kwa muhtasari wa vipengele vya maunzi vinavyohusika katika mradi huu, ikijumuisha moduli ya Heltec WiFi LoRa 32 V3 na sensa ya DHT22. Baada ya hapo, tutaendelea na maagizo ya wiring, ambapo utajifunza jinsi ya kuunganisha vipengele hivi. Hatimaye, tutapitia msimbo unaohitajika kufanya mfumo huu ufanye kazi. Kwa mwongozo wa kuona, tafadhali rejelea video katika muda mbalimbali (katika video saa 00:00).
Maunzi Yameelezwa
Vipengele vikuu vya mradi huu ni moduli ya Heltec WiFi LoRa 32 V3 na sensa ya joto na unyevu ya DHT22. Moduli ya Heltec ina microcontroller ya ESP32, ambayo hutoa uwezo wa Wi-Fi na Bluetooth pamoja na mawasiliano ya LoRa. Hii inaruhusu chaguo rahisi za utumaji data.
Sensa ya DHT22 ni sensa ya dijiti ambayo hutoa usomaji sahihi wa joto na unyevu. Inawasiliana na ESP32 kupitia pini moja ya pato la dijiti, na kuifanya iwe rahisi kuunganisha na kutumia katika miradi yako. Kwa pamoja, vipengele hivi vinaunda mfumo imara wa ufuatiliaji wa joto bila waya.
Maelezo ya Datasheet
| Mtengenezaji | Heltec Automation |
|---|---|
| Nambari ya sehemu | WiFi LoRa 32 V3 |
| Voltage ya Logic/IO | 3.3 V |
| Voltage ya usambazaji | 3.7–4.2 V |
| Pato la sasa (kwa kila chaneli) | ~1 A |
| Kilele cha sasa (kwa kila chaneli) | ~2 A |
| Mwongozo wa mzunguko wa PWM | 1 kHz (typ.) |
| Viwango vya kizingiti cha mantiki ya kuingiza | 0.7 V (juu), 0.3 V (chini) |
| Kushuka kwa voltage / RDS(on) / kueneza | 0.3 V (max) |
| Mipaka ya joto | 85 °C (max) |
| Kifurushi | Moduli ya PCB |
| Vidokezo / lahaja | Chaguo mbalimbali za mzunguko zinapatikana (k.m., 433 MHz, 868 MHz, 915 MHz) |
- Hakikisha unawasha DHT22 kwa 3.3V, si 5V.
- Tumia viwango sahihi vya mantiki kwa mawasiliano kati ya ESP32 na DHT22.
- Zingatia kupoeza joto ikiwa unatumia mikondo ya juu kwa muda mrefu.
- Angalia muunganisho wa antenna ya LoRa ili kuongeza umbali.
- Kuwa makini na kanuni za mzunguko wa LoRa katika eneo lako.
Maagizo ya Wiring

Ili kuunganisha Heltec WiFi LoRa 32 V3 na sensa ya DHT22, anza kwa kuunganisha pini ya VCC ya sensa kwenye pini ya 3.3V kwenye moduli ya Heltec. Kisha, unganisha pini ya GND ya DHT22 kwenye moja ya pini za GND kwenye Heltec. Pini ya data ya DHT22 inapaswa kuunganishwa kwenye pini ya GPIO 3 kwenye Heltec.
Hakikisha unatumia resistor ya kuvuta-juu (karibu 10kΩ) kati ya pini ya data na VCC kwa usomaji thabiti. Zaidi ya hayo, hakikisha antenna ya LoRa imeunganishwa kwa usalama ili kuongeza umbali wa utumaji. Ikiwa unatumia nguvu ya nje, hakikisha moduli ya Heltec imewashwa kwa usahihi ili kuepuka matatizo yoyote ya uendeshaji.
Kusakinisha Bodi za Heltec ESP32
Ongeza njia hii kwenye mapendeleo ya Arduino IDE yako kama inavyoonyeshwa kwenye video:https://resource.heltec.cn/download/package_heltec_esp32_index.json
Kusakinisha Maktaba za Heltec ESP32
Kwenye Arduino IDE ikifunguliwa, tafadhali bofya ikoni ya Maktaba (1), kisha andika "Heltec" kwenye utafutaji (2) na bofya Sakinisha (3) angalia picha.
Mifano ya Msimbo na Maelezo
Vipande vya msimbo vifuatavyo vinaonyesha jinsi ya kusanidi moduli ya Heltec kusoma data ya joto kutoka kwa sensa ya DHT22 na kuituma kupitia LoRa. Msimbo huanzisha onyesho na kusanidi sensa ya DHT.
#include
#define DHTPIN 3 // Pini ya GPIO kwa DHT22
#define DHTTYPE DHT22 // Fafanua aina ya DHT
DHT dht(DHTPIN, DHTTYPE);
void setup() {
Serial.begin(115200);
dht.begin(); // Anzisha sensa ya DHT
}
Katika kipande hiki, tunafafanua pini ambayo sensa ya DHT22 imeunganishwa na kuianzisha katika kazi ya setup(). Mstari wa Serial.begin(115200) ni kwa ajili ya pato la utatuzi.
void loop() {
float tempC = dht.readTemperature(); // Soma joto kwa Selsiasi
float tempF = dht.convertCtoF(tempC); // Badilisha kuwa Fahrenheiti
sendData(tempC, tempF); // Kazi ya kutuma data ya joto
}
Sehemu hii inaonyesha jinsi ya kusoma data ya joto katika kazi ya loop(). Kazi ya sendData() inaitwa kutuma usomaji wa joto kupitia LoRa.
void sendData(float tempC, float tempF) {
String data = "Joto: " + String(tempC) + "°C"; // Tengeneza mfuatano wa data
Radio.Send(data.c_str(), data.length()); // Tuma data
}
Hapa, tunaunda mfuatano wa data unaojumuisha joto na kuutuma kwa kutumia mbinu ya Radio.Send(). Hii itasambaza data kwa njia isiyo na waya hadi kwenye moduli inayopokea.
Tafadhali rejea msimbo kamili uliopakiwa chini ya makala kwa utekelezaji wa kina.
Maonyesho / Nini cha Kutarajia
Mara tu kila kitu kitakapowekwa na msimbo kupakiwa kwenye moduli ya Heltec, unapaswa kuona usomaji wa joto ukionyeshwa kwenye skrini ya OLED. Mfumo utasambaza data ya joto, ambayo inaweza kupokelewa na moduli nyingine ya Heltec iliyosanidiwa kusoma data. Unaweza kujaribu umbali kwa kusogeza kipokeaji mbali zaidi kutoka kwa kisambaza, kuthibitisha umbali wa juu uliofikiwa (katika video kwenye 1:30).
Kuwa mwangalifu kuhusu makosa ya kawaida kama vile wiring isiyo sahihi, usambazaji wa nishati usiotosha, au kutumia masafa yasiyo sahihi ya LoRa. Hakikisha DHT22 inafanya kazi vizuri na kwamba antenna imeunganishwa ili kuongeza umbali.
Vidokezo vya Muda wa Video
- 00:00 Mwanzo
- 3:51 Vipimo
- 8:32 Ukurasa wa nyaraka
- 9:52 Kifurushi na betri
- 12:58 Kuiwasha kwa mara ya kwanza
- 16:37 Kusakinisha Maktaba
- 18:19 Msimbo wa msingi wa Kisambaza
- 19:43 Msimbo wa msingi wa Kipokeaji
- 20:39 Maonyesho ya kutuma na kupokea maandishi
- 23:02 Msimbo wa maonyesho ya OLED
- 24:06 Msimbo wa maandishi ya msingi kwenye skrini ya OLED
- 26:26 Maonyesho ya maandishi ya msingi kwenye OLED
- 26:58 Kusoma joto kwa DHT22
- 28:49 Kisambaza cha LoRa cha Joto na Maonyesho
- 30:07 Kipokeaji cha LoRa cha Joto na Maonyesho
- 32:13 Kuwasha LED wakati joto linapoongezeka
- 22:26 Jaribio la Umbali wa Usambazaji wa LoRa
- 35:01 dBm na Milli Watt
This tutorial is part of: Mafunzo ya 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)
- Dhibiti Motor ya Servo kutoka Umbali wa Maili! Mafunzo ya Heltec WiFi LoRa 32 V3 Arduino (TX)
- Mradi wa Relay ya Mbali ya DIY: Moduli ya Heltec LoRa 32 ya Maili 13 Bila Wi-Fi/Bila SIM
- 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
Resurser och referenser
-
Extern.
-
Extern.
-
Extern.
-
Extern.
-
Extern.Purchase a WiFi LoRa 32 V3 from AliExpresss.click.aliexpress.com
-
Extern.Purchase a WiFi LoRa 32 V3 from AliExpress-2s.click.aliexpress.com
-
Extern.
-
Extern.Purchase Wi-Fi LoRa 32 from Meshnologymeshnology.com
Filer📁
Arduino-bibliotek (zip)
-
Heltec ESP32 libraries 2.1.5Libraries for all Heltec ESP32 boards. This is version 2.1.5.
Heltec_ESP32-master.zip3.86 MB
Andra filer
-
Heltec WiFi LoRa 32 V3 Schematic Diagram (V3.1)
Heltec_WiFiLoRAV3_Schematic_Diagram.pdf0.18 MB