Altium
Arduino ProjectsLORA PROJECTS

Arduino and Lora based Automation Project with Feedback message, Lora SX1278

LoRa Wireless Range testing

Arduino and Lora based Automation Project:

 Arduino and Lora

Arduino and Lora based Automation Project with Feedback message-In this article, you will learn how to make a completely functional Automation system included with a feedback feature using a pair of Arduino boards, Lora SX1278 transceiver modules, 4-channels relay module, and some electrical loads. I will also share with you the maximum distance and how quickly and accurately it sends the feedback message.

I have already made several videos and have written many articles on SX1278 Lora transceiver modules, however, today’s article is of a somewhat different level, because the project which I am going to design today, will prove useful for you. Why am I saying so? You will get its answer during the practical demonstration.

As I have just said, I have already written many articles on Lora transceiver modules. In my very first article, I explained the pinout, technical specifications, and how to use Lora SX1278 with Arduino. So, during that project, I sent the “hello world” message wirelessly. You are well aware that for the beginners “hello world” project is an ideal project. This was basically a getting started tutorial.


After this, I explained in detail how you can conduct two-way communication over a long distance. For demonstration, I used a push button on one side, whereas on the other side I used a potentiometer as an analog sensor. If you are interested in controlling and monitoring both at the same time, then you must surely watch this video.

Anyways, after this, I implemented a Lora Network, because, in most of the cases, only two Lora modules are not enough. To cover more locations, I created a LoraWAN network based on 3 nodes. In this network, every node had a specific address. So, if you want to monitor multiple sensors from multiple locations, then this video must be worth watching for you guys.

Anyhow, I then designed a Lora Gateway and for this purpose, I used the Lora SX1278 module with ESP8266 Wi-Fi module. This is quite an interesting project because first, you bring the sensor data from a remote location, where no internet facility is available, to the node where the internet is available. And then you send that sensor data to an IoT platform with the help of a gateway. By doing so, you can monitor any sensor from any part of the world, provided you have an internet connection.

Apart from this, there are other projects as well, however, the projects which I have just mentioned, are undoubtedly very important projects, because you can design any project by modifying these projects. Let’s now move on to our todays’ project.

Arduino and Lora

You can see 4 buttons on the transmitter side Arduino. Using these very 4 buttons, I am going to control certain loads on the receiver side. For demonstration purposes, I have put 4 bulbs on the receiver’s side, which are connected to 4 relays. Besides lights, you can use any other 110/220Vac loads or use any other DC type loads.

If you want to use 110/220Vac supply, you must not forget to use protective gloves, because 110/220Vac can prove fatal. So, as far as possible you must ensure the presence of a friend or any companion while carrying on work on such projects. When the AC supply is ON, do not touch the relay module.



I am using the same SX1278 Lora Transceiver modules on the receiver as well as the transmitter side. Anyways, I turned ON the Receiver side using a 12V adaptor.

Arduino and Lora

I am powering up the transmitter side through a 4S lipo battery pack. You may also use a 3S battery pack or any other type of battery or a DC adopter for this purpose. If you also want to make such a 4S Lipo battery pack, then read my article on how to make 3S and 4S lipo battery packs. Anyway, this is my portable Arduino and Lora-based remote controller, which is still passing through the testing phases. When everything gets final, I will design a small PCB and an enclosure for it. Anyways, let us start testing.

Arduino and Lora

I can randomly turn ON or turn OFF any light and it is working quite superbly. This small delay occurs because I have used timers on the transmitter and receiver sides. You can increase or decrease the timer value if you want. During the line-of-sight testing there tends to be no issues. I have checked this system so many times and it is working perfectly.


Arduino and Lora

However, one gets frustrated after finding that no electrical loads are visible. I am turning buttons ON and OFF, however, I cannot determine whether the loads are being controlled on the receiver’s side or not, because I cannot see loads as yet.

Perhaps, loads are being controlled, however, I am confused because still I cannot see the loads. In such a situation, we might have problems, as it is possible that Arduino might have turned OFF and you keep thinking that the signals which you are sending, are being successfully implemented, while in reality, nothing might be happening. We can solve this issue if the receiver side sends us a feedback message. And this is what I am going to do next.


Altium Designer & Altium 365:

Arduino and Lora Altium 365

Altium 365 lets you hold the fastest design reviews ever. Share your designs from anywhere and with anyone with a single click. it’s easy, leave a comment tagging your teammate and they’ll instantly receive an email with a link to the design. Anyone you invite can open the design using a web browser. Using the browser interface, you’re able to comment, markup, cross probe, inspect, and more. Comments are attached directly to the project, making them viewable within Altium designer as well as through the browser interface. Design, share, and manufacture, all in the same space with nothing extra to install or configure. Connect to the platform directly from Altium Designer without changing how you already design electronics. Altium 365 requires no additional licenses and comes included with your subscription plan. Start with Altium Designer and Activate Altium 365.

Arduino and Lora

I have modified the code and you can see I have also added a display on the transmitter side. I will display the status of electrical loads on this display. So let us power up the transmitter side and see how this system works.

Arduino and Lora

Now, Arduino and Lora-based automation systems present quite a practical look. Whenever I turn ON/OFF any button on the transmitter side, the receiver side sends me feedback on whether that load has turned ON or not.

Now even if I do not see electrical appliances or loads, there is no problem, because I keep on receiving feedback from the receiver’s side. Now, if there is some issue on the receiver side, I’ll not receive any kind of feedback. Or if I get out of the range, even then I’ll receive no feedback.

Anyways, I have been testing this project for the last two days and it is working exceptionally well.

If you are thinking about its real implementation, do not forget to use the watchdog timer on the receiver side. Because with the help of a watchdog timer, you can restart the receiver side Arduino automatically, if it hangs due to any particular reason.


Tested Range:

Arduino and Lora

You can see my brother is standing on the roof of my maternal uncle’s house. He has the transmitter and as you can see he is controlling these light bulbs from there. The distance between the transmitter and receiver is 118 meters. Over such a long-distance still, we were able to control the bulbs. You can also watch this in the video given at the end of this article. The maximum communication distance may be more, even more than 200 meters. I will test the maximum communication distance in some open fields, as I am planning to make a transmitter for one of my upcoming RC Airplane projects.  

I am sure by now you might have got an idea of how does this system works. So, without any further delay, let’s get started!!!

Amazon Links:

LoRa SX1278 Module

Arduino Nano

Arduino Uno

SSD1306 128×64 Oled i2c display Module

Other Tools and Components:

Top Arduino Sensors:

Super Starter kit for Beginners

Digital Oscilloscopes

Variable Supply

Digital Multimeter

Soldering iron kits

PCB small portable drill machines

*Please Note: These are affiliate links. I may make a commission if you buy the components through these links. I would appreciate your support in this way!



SX1278 Lora:

Arduino and Lora

Lora 1278 long-distance wireless transceiver module integrates Semtech RF transceiver chip SX1278, which adopts LoRa TM Spread Spectrum modulation frequency hopping technique. The features of long-distance and high sensitivity (-139dBm) make this module perform better than FSK and GFSK modules. Multi-signal won’t affect each other even in a crowd frequency environment; it comes with strong anti-interference performance. This module is 100mW and ultra-small size, widely used in AMR, remote industrial control filed.

Features:

  • Frequency Range: 868 / 915 MHz
  • Sensitivity up to -139dBm @Lora
  • Maximum output power: 20 dBm
  • [email protected] mode
  • Sleep current <200 nA
  • Data transfer rate: @FSK,1.2-300 Kbps
  • @Lora TM, 0.018-37.5 Kbps
  • Lora TM, FSK, GFSK & OOK Modulation mode
  • Built-in ESD Protection
  • 127 dB Dynamic Range RSSI
  • Packet engine up to 256 bytes with FIFO and CRC
  • Hopping frequency
  • Built-in temperature sensor and low battery indicator
  • Excellent blocking immunity
  • Operating Temperature Range:-40 ~ + 85 °C

Applications:

  • Remote control
  • Remote meter reading
  • Home security alarm and remote keyless entry
  • Industrial control
  • Home automation remote sensing
  • Individual data records
  • Toys control
  • Sensor network
  • Tire pressure monitoring
  • Health monitoring
  • Wireless PC peripherals
  • Tag reading and writing


Arduino Lora Automation Project, Circuit Diagram:

Lora Transmitter Circuit Diagram:

Arduino and Lora

The VCC of the LoRa module is connected with the 3.3V of the Arduino. The MISO Pin of the LoRa module is connected with the Arduino’s pin 12. The MOSI pin is connected with the Arduino’s pin 11. The SCLK pin of the LoRa module is connected with the Arduino’s pin 13. The NSS pin is connected with the Arduino’s pin 10 and the ground pin of the LoRa module is connected with the Arduino’s GND.

4 switches are connected with the Arduino pins 2, 3, 4, and 5.

SSD1306 Oled display module SCL and SDA pins are connected with the Arduino’s A5 and A4 pins.

On the left side is the regulated 5V power supply which accepts a wide range of input DC voltages between 7 and 28volts.


Lora Receiver Circuit Diagram:

Arduino and Lora

On the receiver side, a 4-channel relay module is connected with the Arduino pins 2, 3, 4, and 5. While the connections of the SX1278 Lora module remain exactly the same. Now, let’s take a look at the Transmitter and Receiver side programming.

Arduino Lora Automation Project, Programming:

This project is based on two programs. Download the following libraries.

Download: LoRa.h

Download: Adafruit_GFX.h

Download: Adafruit_SSD1306.h

Lora Transmitter programming:

/*
  Transmitter, nano

*/
#include <SPI.h>              // include libraries
#include <LoRa.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

byte msgCount = 0;            // count of outgoing messages
byte localAddress = 0xBB;     // address of this device
byte destination = 0xFF;      // destination to send to
long lastSendTime = 0;        // last send time
int interval = 50;          // interval between sends

// 4 buttons or switches
int sw1 = 2; 
int sw2 = 4; 
int sw3 = 6; 
int sw4 = 8;

// Stores the switches or buttons status in the form of 0 or 1
// And then these status values are used to control the loads
// on the Receiver side.
int Sensor1 = 0; 
int Sensor2 = 0; 
int Sensor3 = 0;  
int Sensor4 = 0;  

//The receiver side loads status feedback values are stored in the following variables
int load1 = 0; 
int load2 = 0; 
int load3 = 0; 
int load4 = 0;

boolean bflag = false;
String outgoing;              // outgoing message


// For Oled display
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
 
String Mymessage = "";

void setup() {
  Serial.begin(9600);                   // initialize serial
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setTextColor(WHITE);

 
  pinMode(sw1, INPUT_PULLUP);
  pinMode(sw2, INPUT_PULLUP); 
  pinMode(sw3, INPUT_PULLUP); 
  pinMode(sw4, INPUT_PULLUP);

  Serial.println("LoRa Duplex");

  if (!LoRa.begin(433E6)) {             // initialize ratio at 915 MHz
    Serial.println("LoRa init failed. Check your connections.");
    while (true);                       // if failed, do nothing
  }

  Serial.println("LoRa init succeeded.");
}

void loop() {
  
  if (millis() - lastSendTime > interval) {
    Sensor1 = digitalRead(sw1);
    Sensor2 = digitalRead(sw2); 
    Sensor3 = digitalRead(sw3);
    Sensor4 = digitalRead(sw4);
        
    Mymessage = Mymessage + !Sensor1 +"," + !Sensor2 + "," + !Sensor3 +"," + !Sensor4;  
    sendMessage(Mymessage);
    delay(10);
    
    Mymessage = "";
    //Serial.println("Sending " + message);
    lastSendTime = millis();            // timestamp the message
    interval = random(50) + 100;  
    
    }

      // parse for a packet, and call onReceive with the result:
  onReceive(LoRa.parsePacket());
  }

void sendMessage(String outgoing) {
  LoRa.beginPacket();                   // start packet
  LoRa.write(destination);              // add destination address
  LoRa.write(localAddress);             // add sender address
  LoRa.write(msgCount);                 // add message ID
  LoRa.write(outgoing.length());        // add payload length
  LoRa.print(outgoing);                 // add payload
  LoRa.endPacket();                     // finish packet and send it
  msgCount++;                           // increment message ID
}

void onReceive(int packetSize) {
  if (packetSize == 0) return;          // if there's no packet, return

  // read packet header bytes:
  int recipient = LoRa.read();          // recipient address
  byte sender = LoRa.read();            // sender address
  byte incomingMsgId = LoRa.read();     // incoming msg ID
  byte incomingLength = LoRa.read();    // incoming msg length

  String incoming = "";

  while (LoRa.available()) {
    incoming += (char)LoRa.read();
  }

  if (incomingLength != incoming.length()) {   // check length for error
    //Serial.println("error: message length does not match length");
    ;
    return;                             // skip rest of function
  }

  // if the recipient isn't this device or broadcast,
  if (recipient != localAddress && recipient != 0xFF) {
   // Serial.println("This message is not for me.");
    ;
    return;                             // skip rest of function
  }

  // if message is for this device, or broadcast, print details:
  //Serial.println("Received from: 0x" + String(sender, HEX));
  //Serial.println("Sent to: 0x" + String(recipient, HEX));
  //Serial.println("Message ID: " + String(incomingMsgId));
 // Serial.println("Message length: " + String(incomingLength));
 // Serial.println("Message: " + incoming);
//  Serial.println("RSSI: " + String(LoRa.packetRssi()));
//  Serial.println("Snr: " + String(LoRa.packetSnr()));
//  Serial.println();


String q = getValue(incoming, ',', 0); 
String r = getValue(incoming, ',', 1); 
String s = getValue(incoming, ',', 2); 
String t = getValue(incoming, ',', 3); 
load1 = q.toInt();
load2 = r.toInt();
load3 = s.toInt();
load4 = t.toInt();

String DisplayData = "";
DisplayData = DisplayData + load1 + "," + load2 + "," + load3 + "," + load4 ;
//new code end
    //clear display
  display.clearDisplay();

  display.setTextSize(2);
  display.setCursor(0,0);
  display.print("Status:");

  display.setTextSize(3);
  display.setCursor(0, 28);
  display.print(DisplayData);

display.display(); 
}
String getValue(String data, char separator, int index)
{
    int found = 0;
    int strIndex[] = { 0, -1 };
    int maxIndex = data.length() - 1;
 
    for (int i = 0; i <= maxIndex && found <= index; i++) {
        if (data.charAt(i) == separator || i == maxIndex) {
            found++;
            strIndex[0] = strIndex[1] + 1;
            strIndex[1] = (i == maxIndex) ? i+1 : i;
        }
    }
    return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}


Lora Transmitter Code Explanation:

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>

I added the Adafruit_GFX and Adafruit_SSD1306 libraries for the Oled display module. You can download these libraries from my article.

byte msgCount = 0;            // count of outgoing messages

byte localAddress = 0xBB;     // address of this device

byte destination = 0xFF;      // destination to send to

long lastSendTime = 0;        // last send time

int interval = 50;          // interval between sends

Next, I defined the localAddress, destination, and these variables for the timer.

// 4 buttons or switches

int sw1 = 2;

int sw2 = 4;

int sw3 = 6;

int sw4 = 8;

Next, I defined 4 switches.

int Sensor1 = 0;

int Sensor2 = 0;

int Sensor3 = 0; 

int Sensor4 = 0;

Next, I defined these 4 variables for storing the status of all the 4 switches in the form of 0 and 1. We use these status values to control relays on the receiver side.

int load1 = 0;

int load2 = 0;

int load3 = 0;

int load4 = 0;

Next, I defined these 4 variables to store the status feedback values of the 4 loads received from the receiver side. Now, let’s go to the loop function.

void loop() {

  if (millis() - lastSendTime > interval) {

    Sensor1 = digitalRead(sw1);

    Sensor2 = digitalRead(sw2);

    Sensor3 = digitalRead(sw3);

    Sensor4 = digitalRead(sw4);

       

    Mymessage = Mymessage + !Sensor1 +"," + !Sensor2 + "," + !Sensor3 +"," + !Sensor4; 

    sendMessage(Mymessage);

    delay(10);

   

    Mymessage = "";

    //Serial.println("Sending " + message);

    lastSendTime = millis();            // timestamp the message

    interval = random(50) + 100; 

   

    }




      // parse for a packet, and call onReceive with the result:

  onReceive(LoRa.parsePacket());

  }

First, we read the status of the switches, then we make a complete message and send it to the receiver side. Arduino checks and sends the control commands after every few milliseconds. If you want you can change the interval. After sending the message then the Arduino checks if any data is received from the receiver side.

void onReceive(int packetSize) {

  if (packetSize == 0) return;          // if there's no packet, return




  // read packet header bytes:

  int recipient = LoRa.read();          // recipient address

  byte sender = LoRa.read();            // sender address

  byte incomingMsgId = LoRa.read();     // incoming msg ID

  byte incomingLength = LoRa.read();    // incoming msg length




  String incoming = "";




  while (LoRa.available()) {

    incoming += (char)LoRa.read();

  }




  if (incomingLength != incoming.length()) {   // check length for error

    //Serial.println("error: message length does not match length");

    ;

    return;                             // skip rest of function

  }




  // if the recipient isn't this device or broadcast,

  if (recipient != localAddress && recipient != 0xFF) {

   // Serial.println("This message is not for me.");

    ;

    return;                             // skip rest of function

  }










String q = getValue(incoming, ',', 0);

String r = getValue(incoming, ',', 1);

String s = getValue(incoming, ',', 2);

String t = getValue(incoming, ',', 3);

load1 = q.toInt();

load2 = r.toInt();

load3 = s.toInt();

load4 = t.toInt();




String DisplayData = "";

DisplayData = DisplayData + load1 + "," + load2 + "," + load3 + "," + load4 ;

//new code end

    //clear display

  display.clearDisplay();




  display.setTextSize(2);

  display.setCursor(0,0);

  display.print("Status:");




  display.setTextSize(3);

  display.setCursor(0, 28);

  display.print(DisplayData);




display.display();

}

The data which is received from the receiver side is the feedback message, this feedback message consists of the relays status in the form 0 and 1. So, the incoming message is split and the feedback status values are stored in their respective variables, where its values are displayed on the Oled display module.

String getValue(String data, char separator, int index)

{

    int found = 0;

    int strIndex[] = { 0, -1 };

    int maxIndex = data.length() - 1;




    for (int i = 0; i <= maxIndex && found <= index; i++) {

        if (data.charAt(i) == separator || i == maxIndex) {

            found++;

            strIndex[0] = strIndex[1] + 1;

            strIndex[1] = (i == maxIndex) ? i+1 : i;

        }

    }

    return found > index ? data.substring(strIndex[0], strIndex[1]) : "";

}

The getValue() function is used to split a string message using a delimiter. In my case, I am using Comma as the delimiter, if you want you can use any other character as the delimiter. So, that’s all about the transmitter side programming, and now let’s take a look at the receiver side programming.



Lora Receiver Programming:

/*
  Receiver, Nano

*/
#include <SPI.h>              // include libraries
#include <LoRa.h>

byte msgCount = 0;            // count of outgoing messages
byte localAddress = 0xFF;     // address of this device
byte destination = 0xBB;      // destination to send to
long lastSendTime = 0;        // last send time
int interval = 50;          // interval between sends

// flags to stop the unneccesary repition
boolean flag1 = false;
boolean flag2 = false;
boolean flag3 = false;
boolean flag4 = false; 

int RLY1=2;
int RLY2=3;
int RLY3=4;
int RLY4=5;

// these variables are used to store the control commands received from the Transmitter
int Sensor1 = 0; 
int Sensor2 = 0; 
int Sensor3 = 0; 
int Sensor4 = 0; 

// stores the relays status
int relay1Status;
int relay2Status;
int relay3Status;
int relay4Status;

String outgoing;              // outgoing message



String statusmessage = "";

void setup() {
  Serial.begin(9600);                   // initialize serial


 pinMode(RLY1,OUTPUT);
  pinMode(RLY2,OUTPUT);
    pinMode(RLY3,OUTPUT);
      pinMode(RLY4,OUTPUT);


  Serial.println("LoRa Duplex");

  if (!LoRa.begin(433E6)) {             // initialize ratio at 915 MHz
    Serial.println("LoRa init failed. Check your connections.");
    while (true);                       // if failed, do nothing
  }

  Serial.println("LoRa init succeeded.");
}

void loop() {

  if (millis() - lastSendTime > interval) {
  relay1Status = digitalRead(RLY1);
  relay2Status = digitalRead(RLY2);
  relay3Status = digitalRead(RLY3);
  relay4Status = digitalRead(RLY4);
  
  statusmessage = statusmessage + relay1Status + "," + relay2Status + "," + relay3Status + "," + relay4Status;
  sendMessage(statusmessage); 
  delay(10);
  
   statusmessage = "";
   lastSendTime = millis();            // timestamp the message
   interval = random(50) + 100;    // 2-3 seconds
  }
  

  // parse for a packet, and call onReceive with the result:
  onReceive(LoRa.parsePacket());
}

void sendMessage(String outgoing) {
  LoRa.beginPacket();                   // start packet
  LoRa.write(destination);              // add destination address
  LoRa.write(localAddress);             // add sender address
  LoRa.write(msgCount);                 // add message ID
  LoRa.write(outgoing.length());        // add payload length
  LoRa.print(outgoing);                 // add payload
  LoRa.endPacket();                     // finish packet and send it
  msgCount++;                           // increment message ID
}

void onReceive(int packetSize) {
  if (packetSize == 0) return;          // if there's no packet, return

  // read packet header bytes:
  int recipient = LoRa.read();          // recipient address
  byte sender = LoRa.read();            // sender address
  byte incomingMsgId = LoRa.read();     // incoming msg ID
  byte incomingLength = LoRa.read();    // incoming msg length

  String incoming = "";

  while (LoRa.available()) {
    incoming += (char)LoRa.read();
  }

  if (incomingLength != incoming.length()) {   // check length for error
   // Serial.println("error: message length does not match length");
   ;
    return;                             // skip rest of function
  }

  // if the recipient isn't this device or broadcast,
  if (recipient != localAddress && recipient != 0xFF) {
    //Serial.println("This message is not for me.");
    ;
    return;                             // skip rest of function
  }

  // if message is for this device, or broadcast, print details:
 // Serial.println("Received from: 0x" + String(sender, HEX));
 // Serial.println("Sent to: 0x" + String(recipient, HEX));
  //Serial.println("Message ID: " + String(incomingMsgId));
 // Serial.println("Message length: " + String(incomingLength));
 // Serial.println("Message: " + incoming);
  //Serial.println("RSSI: " + String(LoRa.packetRssi()));
  //Serial.println("Snr: " + String(LoRa.packetSnr()));
 // Serial.println();

 
String q = getValue(incoming, ',', 0); 
String r = getValue(incoming, ',', 1); 
String s = getValue(incoming, ',', 2); 
String t = getValue(incoming, ',', 3); 
Sensor1 = q.toInt();
Sensor2 = r.toInt();
Sensor3 = s.toInt();
Sensor4 = t.toInt();

if((Sensor1 == 1)&&(flag1==false))
{
 
  digitalWrite(RLY1,HIGH);
   relay1Status = 1;
  Serial.println("Relay 1 is turned on");
  flag1=true;
}

if((Sensor1 == 0)&&(flag1 ==true))
{

  digitalWrite(RLY1,LOW);
   relay1Status = 0;
  Serial.println("Relay 1 is turned off");
  flag1=false;
}
if((Sensor2 == 1)&&(flag2==false))
{
 
  digitalWrite(RLY2,HIGH);
   relay2Status = 0;
  Serial.println("Relay 2 is turned on");
  flag2=true;
}

if((Sensor2 == 0)&&(flag2 ==true))
{

  digitalWrite(RLY2,LOW);
  relay2Status = 0;
  Serial.println("Relay 2 is turned off");
  flag2=false;
}
if((Sensor3 == 1)&&(flag3==false))
{
 
  digitalWrite(RLY3,HIGH);
  relay3Status = 1;
  Serial.println("Relay 3 is turned on");
  flag3=true;
}

if((Sensor3 == 0)&&(flag3 ==true))
{

  digitalWrite(RLY3,LOW);
  relay3Status = 0;
  Serial.println("Relay 3 is turned off");
  flag3=false;
}

if((Sensor4 == 1)&&(flag4==false))
{
 
  digitalWrite(RLY4,HIGH);
  relay4Status = 1;
  Serial.println("Relay 4 is turned on");
  flag4=true;
}

if((Sensor4 == 0)&&(flag4 ==true))
{

  digitalWrite(RLY4,LOW);
  relay4Status = 0;
  Serial.println("Relay 4 is turned off");
  flag4=false;
}

incoming = "";
  
}
String getValue(String data, char separator, int index)
{
    int found = 0;
    int strIndex[] = { 0, -1 };
    int maxIndex = data.length() - 1;
 
    for (int i = 0; i <= maxIndex && found <= index; i++) {
        if (data.charAt(i) == separator || i == maxIndex) {
            found++;
            strIndex[0] = strIndex[1] + 1;
            strIndex[1] = (i == maxIndex) ? i+1 : i;
        }
    }
    return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}


Lora Receiver code Explanation:

#include <SPI.h>              // include libraries

#include <LoRa.h>




byte msgCount = 0;            // count of outgoing messages

byte localAddress = 0xFF;     // address of this device

byte destination = 0xBB;      // destination to send to

long lastSendTime = 0;        // last send time

int interval = 50;          // interval between sends

On the receiver side, I am using the same libraries, addresses, and timer intervals.

boolean flag1 = false;

boolean flag2 = false;

boolean flag3 = false;

boolean flag4 = false;

This time I also defined these 4 flags, I am using these flags to stop the unnecessary repetition of code.

int RLY1=2;

int RLY2=3;

int RLY3=4;

int RLY4=5;

Next, you can see I also defined pins for the 4 relays.

int Sensor1 = 0;

int Sensor2 = 0;

int Sensor3 = 0;

int Sensor4 = 0;

Next, I defined these 4 variables for storing the control commands received from the transmitter. These control commands are used to control all the 4 relays.

int relay1Status;

int relay2Status;

int relay3Status;

int relay4Status;

Finally, I am using these 4 variables to store the status of all the 4 relays. These values are used to create the feedback message which is sent to the transmitter side. Now, let’s go to the loop function.

void loop() {




  if (millis() - lastSendTime > interval) {

  relay1Status = digitalRead(RLY1);

  relay2Status = digitalRead(RLY2);

  relay3Status = digitalRead(RLY3);

  relay4Status = digitalRead(RLY4);




  statusmessage = statusmessage + relay1Status + "," + relay2Status + "," + relay3Status + "," + relay4Status;

  sendMessage(statusmessage);

  delay(10);




   statusmessage = "";

   lastSendTime = millis();            // timestamp the message

   interval = random(50) + 100;    // 2-3 seconds

  }







  // parse for a packet, and call onReceive with the result:

  onReceive(LoRa.parsePacket());

}

Now, this time I am reading the status of all the four relays, then we create a complete message, which is the feedback message and send it to the transmitter side.

void onReceive(int packetSize) {

  if (packetSize == 0) return;          // if there's no packet, return




  // read packet header bytes:

  int recipient = LoRa.read();          // recipient address

  byte sender = LoRa.read();            // sender address

  byte incomingMsgId = LoRa.read();     // incoming msg ID

  byte incomingLength = LoRa.read();    // incoming msg length




  String incoming = "";




  while (LoRa.available()) {

    incoming += (char)LoRa.read();

  }




  if (incomingLength != incoming.length()) {   // check length for error

   // Serial.println("error: message length does not match length");

   ;

    return;                             // skip rest of function

  }




  // if the recipient isn't this device or broadcast,

  if (recipient != localAddress && recipient != 0xFF) {

    //Serial.println("This message is not for me.");

    ;

    return;                             // skip rest of function

  }










String q = getValue(incoming, ',', 0);

String r = getValue(incoming, ',', 1);

String s = getValue(incoming, ',', 2);

String t = getValue(incoming, ',', 3);

Sensor1 = q.toInt();

Sensor2 = r.toInt();

Sensor3 = s.toInt();

Sensor4 = t.toInt();




if((Sensor1 == 1)&&(flag1==false))

{




  digitalWrite(RLY1,HIGH);

   relay1Status = 1;

  Serial.println("Relay 1 is turned on");

  flag1=true;

}




if((Sensor1 == 0)&&(flag1 ==true))

{




  digitalWrite(RLY1,LOW);

   relay1Status = 0;

  Serial.println("Relay 1 is turned off");

  flag1=false;

}

if((Sensor2 == 1)&&(flag2==false))

{




  digitalWrite(RLY2,HIGH);

   relay2Status = 0;

  Serial.println("Relay 2 is turned on");

  flag2=true;

}




if((Sensor2 == 0)&&(flag2 ==true))

{




  digitalWrite(RLY2,LOW);

  relay2Status = 0;

  Serial.println("Relay 2 is turned off");

  flag2=false;

}

if((Sensor3 == 1)&&(flag3==false))

{




  digitalWrite(RLY3,HIGH);

  relay3Status = 1;

  Serial.println("Relay 3 is turned on");

  flag3=true;

}




if((Sensor3 == 0)&&(flag3 ==true))

{




  digitalWrite(RLY3,LOW);

  relay3Status = 0;

  Serial.println("Relay 3 is turned off");

  flag3=false;

}




if((Sensor4 == 1)&&(flag4==false))

{




  digitalWrite(RLY4,HIGH);

  relay4Status = 1;

  Serial.println("Relay 4 is turned on");

  flag4=true;

}




if((Sensor4 == 0)&&(flag4 ==true))

{




  digitalWrite(RLY4,LOW);

  relay4Status = 0;

  Serial.println("Relay 4 is turned off");

  flag4=false;

}




incoming = "";




}

Then the Arduino checks if any data is received. This time the received message consists of the control commands which are received from the Transmitter. The Arduino splits the entire message and then using the if conditions the relays are turned ON or turned OFF depending on the received values. So, that’s all about the programming.


Watch Video Tutorial:

Engr Fahad

My name is Shahzada Fahad and I am an Electrical Engineer. I have been doing Job in UAE as a site engineer in an Electrical Construction Company. Currently, I am running my own YouTube channel "Electronic Clinic", and managing this Website. My Hobbies are * Watching Movies * Music * Martial Arts * Photography * Travelling * Make Sketches and so on...

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button