Search Code

Heltec WiFi LoRa 32 V3 арқылы DHT22 көмегімен температураны 1,4 км-ге жіберу

Бұл сабақтың бөлігі: Introduction to WiFi LoRa

Heltec WiFi LoRa 32 V3 арқылы DHT22 көмегімен температураны 1,4 км-ге жіберу

Бұл оқулықта біз Heltec WiFi LoRa 32 V3 модулін DHT22 сенсорынан температура деректерін ұзақ қашықтыққа, 1.4 километрге дейін жеткізу үшін қалай пайдалану керектігін қарастырамыз. Бұл мүмкіндік төмен қуатты, ұзақ қашықтықтағы байланысты қамтамасыз ететін LoRa технологиясын қолдану арқылы жүзеге асырылады. Осы нұсқаулықтың соңында сізде температура көрсеткіштерін сымсыз жібере алатын жұмыс істейтін жүйе болады.

Meshnology N30 RX және TX ішіндегі Wifi LoRa 32 V3

Біз осы жобаға қатысты аппараттық құрамдас бөліктерге шолудан бастаймыз, оның ішінде Heltec WiFi LoRa 32 V3 модулі және DHT22 сенсоры. Осыдан кейін біз осы құрамдас бөліктерді қалай қосу керектігін үйренетін сымдарды жалғау нұсқауларына көшеміз. Соңында, біз осы жүйені жұмысқа қосу үшін қажетті кодты қарастырамыз. Көрнекі нұсқаулық үшін бейнені әртүрлі уақыт белгілерінде қараңыз (бейнеде 00:00).

Аппараттық құралдар түсіндірмесі

Бұл жобаның негізгі құрамдас бөліктері - Heltec WiFi LoRa 32 V3 модулі және DHT22 температура мен ылғалдылық сенсоры. Heltec модулінде ESP32 микроконтроллері бар, ол LoRa байланысымен қатар Wi-Fi және Bluetooth мүмкіндіктерін қамтамасыз етеді. Бұл деректерді жіберудің икемді нұсқаларына мүмкіндік береді.

Температура таратқышы ретінде Meshnology N30 ішіндегі Wifi LoRa 32 V3

DHT22 сенсоры - бұл температура мен ылғалдылықтың дәл көрсеткіштерін беретін цифрлық сенсор. Ол ESP32-мен бір цифрлық шығыс түйреуіші арқылы байланысады, бұл оны жобаларыңызда қосу мен пайдалануды жеңілдетеді. Бірге бұл құрамдас бөліктер сымсыз температура мониторингі үшін сенімді жүйені құрайды.

Деректер парағының мәліметтері

Өндіруші Heltec Automation
Бөлшек нөмірі WiFi LoRa 32 V3
Логика/IO кернеуі 3.3 В
Қоректендіру кернеуі 3.7–4.2 В
Шығыс тогы (арнаға) ~1 А
Ең жоғары ток (арнаға) ~2 А
PWM жиілігі бойынша нұсқау 1 кГц (тип.)
Кіріс логикалық шектері 0.7 В (жоғары), 0.3 В (төмен)
Кернеудің төмендеуі / RDS(on) / қанығу 0.3 В (макс.)
Жылулық шектер 85 °C (макс.)
Қаптама PCB модулі
Ескертулер / нұсқалар Әртүрлі жиілік нұсқалары қолжетімді (мысалы, 433 МГц, 868 МГц, 915 МГц)

 

  • DHT22-ні 3.3В-пен қоректендіруді қамтамасыз етіңіз, 5В емес.
  • ESP32 мен DHT22 арасындағы байланыс үшін тиісті логикалық деңгейлерді қолданыңыз.
  • Ұзақ уақыт бойы жоғары токтарда жұмыс істегенде жылуды таратуды қарастырыңыз.
  • Ауқымды барынша арттыру үшін LoRa антеннасының қосылымын тексеріңіз.
  • Аймағыңыздағы LoRa жиілік ережелерін ескеріңіз.

Сымдарды жалғау нұсқаулары

Heltec_WiFi_loRa_32V3_DHT22_wiring

Heltec WiFi LoRa 32 V3-ті DHT22 сенсорымен жалғау үшін алдымен сенсордың VCC түйреуішін Heltec модуліндегі 3.3V түйреуішіне қосыңыз. Әрі қарай, DHT22-нің GND түйреуішін Heltec-тегі GND түйреуіштерінің біріне қосыңыз. DHT22-нің деректер түйреуіші Heltec-тегі GPIO 3 түйреуішіне қосылуы керек.

Тұрақты көрсеткіштер үшін деректер түйреуіші мен VCC арасында жоғары тарту резисторын (шамамен 10кΩ) қолдануды ұмытпаңыз. Сонымен қатар, тарату ауқымын арттыру үшін LoRa антеннасының сенімді қосылғанын қамтамасыз етіңіз. Сыртқы қуат көзін қолдансаңыз, Heltec модулінің дұрыс қоректендірілгенін тексеріңіз, ақауларды болдырмау үшін.

Heltec ESP32 платаларын орнату

Бейнеде көрсетілгендей Arduino IDE баптауларына осы жолды қосыңыз:https://resource.heltec.cn/download/package_heltec_esp32_index.json

Heltec ESP32 кітапханаларын орнату

Arduino IDE ашылғанда, Кітапхана белгішесін (1) басыңыз, содан кейін іздеу өрісіне (2) "Heltec" теріңіз және Орнату (3) түймесін басыңыз, суретті қараңыз. 

Heltec ESP342 платаларына арналған кітапханаларды орнату

Код мысалдары және түсіндірме

Төмендегі код үзінділері 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 дБм және милливатт

Суреттер

Heltec_WiFi_loRa_32V3_DHT22_wiring
Heltec_WiFi_loRa_32V3_DHT22_wiring
Wifi LoRa 32 V3 inside Meshnology N30 as transmitter of Temperature
Wifi LoRa 32 V3 inside Meshnology N30 as transmitter of Temperature
meshnology-N30-LoRa-v3-red-black
meshnology-N30-LoRa-v3-red-black
Wifi LoRa 32 V3 inside Meshnology N30 RX and TX
Wifi LoRa 32 V3 inside Meshnology N30 RX and TX
Installing libraries for Heltec ESP342 boards
Installing libraries for Heltec ESP342 boards
563-Printing Simple Text on the screen of WiFi LoRa 32 V3
Тіл: C++
/*
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);

}
773-Transmitter Code for Heltec WiFi LoRa 32 V3 to send temperature using DHT11, DHT22
Тіл: C++
/*
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);
}
867-Receiver Code for Heltec WiFi LoRa 32 to receive and display Temperature
Тіл: C++
/*
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);
}

Ресурстар мен сілтемелер

Файлдар📁

Arduino кітапханалары (zip)

Басқа файлдар