element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet & Tria Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • About Us
    About the element14 Community
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Japan
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      •  Vietnam
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Project14
  • Challenges & Projects
  • More
Project14
Make a Connection Using LoRa for remote communication
  • News
  • Member Updates
  • Competitions
  • Forum
  • Documents
  • Theme Suggestions
  • Polls
  • Members
  • More
  • Cancel
  • New
Join Project14 to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: redcharly
  • Date Created: 27 Sep 2026 10:15 PM Date Created
  • Views 13 views
  • Likes 0 likes
  • Comments 0 comments
  • lora
  • dragino
  • stm32
  • make a connection
Related
Recommended

Using LoRa for remote communication

redcharly
redcharly
27 Sep 2026

Introduction

The project I wish to propose stems from my curiosity about the LoRa protocol, which has always fascinated me due to its ultra-low power consumption and long-range capabilities. I built a communication system consisting of several components working together to enable communication between two stations located several kilometers apart.

I used two different boards, both operating at 868 MHz with identical configuration parameters. The first board—which we will call Station0—acts as a receiver for telemetry data sent by the second station (Station1).

My original intention was to build a complete system to manage the irrigation of plants located a few kilometers away. Summers here in Sicily have become extremely hot, making frequent watering necessary—especially for fruit trees planted within the last year or two.

Work commitments made it impossible to complete the full project. Therefore, I will present only the communication aspect between the two boards: how I configured them, the issues I encountered, and the solutions I found—since I was ultimately able to verify the system's operation over a distance of several kilometers.

                       image    image

Station1 

The transmission system consists of an STM Nucleo-F401RE board and a LoRa shield; I have also included a tank level monitoring setup using an ultrasonic sensor, though I have not yet calibrated or tested it.

STM Nucleo-F401RE  Buy Now

Dragino Long Range Shield

Ultrasonic distance sensor:  Buy Now

The two boards are located a few kilometers apart and there is optical visibility between Station0 and Station1.

The aim of the project is to receive data from Station1, located on agricultural land, and decide whether to open irrigation water and for how long. This project was born from a real need that I have, given that, in recent years, the temperature in summer has increased and the rains are very rare, I wanted to create a system that uses a tank to irrigate, when necessary, the younger plants which, in the absence of an extensive root system, would suffer too much from drought.

The tank has a fill valve, used to fill it with water, and a drain valve that activates when I want to water plants. At the moment I am only dealing with the remote control of the pumps, without evaluating the soil humidity, but, once the project is completed, adding such a functionality and making it absolutely automatic is a very trivial thing.

The two stations will exchange messages in the form of strings which, appropriately formatted, will allow me to send simple information from one device to the other.

Station1, at moment, is powered by a powerbank that is kept charged by a solar panel and a simple charge controller.

Station1 detects and sends the following data:

  • packet number
  • status of the tank loading valve;
  • status of the tank drain valve;
  • tank water level

The code is:

#include <SPI.h>
#include <LoRa.h>

// ---------------- PIN DRAGINO -------------------------
const int LORA_SS    = 10;
const int LORA_RST   = 9;
const int LORA_DIO0  = 2;

// ---------------- PARAMETRI LORA ----------------------
const long LORA_FREQ = 868E6;

// ---------------- BUFFER ------------------------------
char rxBuf[64];   // buffer dove scrivo il messaggio ricevuto

// ---------------- VARIABILI E PARAMETRI ----------------------------
String currentTx;
String nameTx = "Station1";     // nome della stazione remota
unsigned long packetNumber = 0;
unsigned long ACKNumber = 0;
int caricoH2O = 0; // 0 acqua chiusa  1 acqua aperta
int scaricoH2O = 0; // 0 acqua chiusa  1 acqua aperta
int livello = 0; // livello % dell'acqua nella vasca

unsigned long lastSend = 0;
const unsigned long sendInterval = 10000; // 10 secondi
unsigned long ledTxTime = 0;
unsigned long ledRxTime = 0;
const unsigned long ledDuration = 200;   // durata del LED acceso

// ---------------- PARAMETRI SERBATOIO ----------------------------
#define TRIG_PIN 4
#define ECHO_PIN 5
const float SERBATOIO_ALTEZZA = 150.0;  // cm
#define LEDTX 6   // LED sul pin 6 PING ricevuto
#define LEDRX 8   // LED sul pin 8 PONG ricevuto

// =======================================================
// MisuraLivello
// =======================================================
float misuraLivello() {

  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);

  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  long durata = pulseIn(ECHO_PIN, HIGH, 30000);

  if (durata == 0) {
    return -1;   // nessuna misura
  }

  // velocità del suono: circa 0,0343 cm/us
  float distanza = durata * 0.0343 / 2.0;

  // livello acqua
  float livello = SERBATOIO_ALTEZZA - distanza;

  // limiti
  if (livello < 0) {
    livello = 0;
  }
  if (livello > SERBATOIO_ALTEZZA) {
    livello = SERBATOIO_ALTEZZA;
  }
  return livello;
}

// =======================================================
// SETUP
// =======================================================
void setup() {
  Serial.begin(115200);

  pinMode(LEDTX, OUTPUT);
  pinMode(LEDRX, OUTPUT);
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);

  Serial.println();
  Serial.println("================================");
  Serial.println("AVVIO PROGRAMMA");
  Serial.println("================================");

  LoRa.setPins(LORA_SS, LORA_RST, LORA_DIO0);

  Serial.println("Pin LoRa impostati");

  LoRa.setTxPower(20);
  LoRa.setSpreadingFactor(12);

  Serial.println("Parametri LoRa impostati");

  if (!LoRa.begin(LORA_FREQ)) {
    Serial.println("ERRORE LoRa");
    while (1) {
      digitalWrite(LEDTX, HIGH);
      delay(200);
      digitalWrite(LEDTX, LOW);
      delay(200);
    }
  }

  Serial.println("LoRa OK");
  Serial.println("Programma avviato");

}
// =======================================================
// LOOP
// =======================================================
void loop() {

  // =====================================================
  // SPEGNIMENTO LED DOPO 200 ms
  // =====================================================

  if (digitalRead(LEDTX) == HIGH && millis() - ledTxTime >= ledDuration) {
    digitalWrite(LEDTX, LOW);
  }

  if (digitalRead(LEDRX) == HIGH && millis() - ledRxTime >= ledDuration) {
    digitalWrite(LEDRX, LOW);
  }

  // =====================================================
  // TRASMISSIONE OGNI 10 SECONDI
  // =====================================================

  if (millis() - lastSend > sendInterval) {

    lastSend = millis();

    currentTx = nameTx + "," +
                String(packetNumber) + "," +
                String(misuraLivello()) + "," +
                String(caricoH2O)) + "," +;
                String(scaricoH2O));

    Serial.print("[TX] Invio: ");
    Serial.println(currentTx);

    LoRa.beginPacket();
    LoRa.print(currentTx);
    LoRa.endPacket();
 
    // LED TX acceso per 200 ms
    digitalWrite(LEDTX, HIGH);
    ledTxTime = millis();

    packetNumber++;
  }


  // =====================================================
  // RICEZIONE
  // =====================================================

  int packetSize = LoRa.parsePacket();

  if (packetSize) {

    // LED RX acceso per 200 ms
    digitalWrite(LEDRX, HIGH);
    ledRxTime = millis();
    int len = 0;
    while (LoRa.available() && len < sizeof(rxBuf) - 1) {
      rxBuf[len++] = (char)LoRa.read();
    }
    rxBuf[len] = '\0';
    Serial.print("[TX] Ricevuto: ");
    Serial.println(rxBuf);

    // =================================================
    // PARSING DEL MESSAGGIO
    // =================================================

    char *token = strtok(rxBuf, ",");

    if (token != NULL) {
      String nome = String(token);

      // Secondo token
      token = strtok(NULL, ",");

      if (token != NULL) {
        ACKNumber = atoi(token);
      }

      // Terzo token
      token = strtok(NULL, ",");

      if (token != NULL) {
        action = atoi(token);
      }

      // Stampa i risultati
      Serial.print("Source: ");
      Serial.println(nome);

      Serial.print("ACK Number: ");
      Serial.println(ACKNumber);

      Serial.print("Action: ");
      Serial.println(action);
    }
  }
}

Station0

Station0 is the base station that collects remote data and allows the user to send commands to Station1 (tank filling and tank emptying).

image   NUCLEO-WL55JC

Station0 receives packets from Station1, allowing the user to decide on the appropriate action.

Commands sent from Station0 to Station1 are handled via a packet formatted as a string with comma-separated fields. These fields are:

  • ACKNumber, matching the PacketNumber of the recently received packet;
  • OpenFillValve to fill the tank with water;
  • OpenDrainValve to empty the tank—and thus irrigate.

By using a PacketNumber and an ACK, we can ensure that the packets have reached their destination.

The code itself is derived directly from an example application in STM32CubeIDE. You can fin it here:  LoRa_Communication Code

Conclusion

Essentially, I am presenting a draft of the project I intended to build; there is still a great deal of work to be done—particularly regarding the field deployment of a stable, reliable, solar-powered unit. I plan to implement several improvements in the future:

  • enhancing the sensor suite on Station1 to enable automated irrigation decisions based on soil moisture levels;
  • managing power supply via photovoltaic panels and charge controllers to make Station1 energy-independent;
  • connecting Station2 to the Internet, enabling remote irrigation control or operation via other devices (such as smartphones) and from everywhere;
  • adding an address field to each transmitted packet to allow a single control station to manage multiple irrigation stations.

After countless attempts tweaking the parameters and configurations of the two boards I own, I realized that using high-quality antennas is crucial. While the small antennas mounted on the boards work fine for indoor testing, moving the boards even a few hundred meters apart causes the signal to degrade so much that communication becomes impossible. For anyone looking to build a real-world system covering several kilometers, I recommend choosing good antennas—either omnidirectional or directional, depending on the specific application. High-quality antennas and cables are essential for the system to function properly. Finally, it is important to ensure a clear line of sight between the two stations; buildings or other obstacles could attenuate the signal too much.

Omnidirectional Antenna

Omnidirectional Antenna 

image

Directional Antenna (Mount Etna in the background)

I will write a new post as soon as I have completed the project.

  • Sign in to reply
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2026 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube