Lora based switch projects are simple and very useful for long range application. Specially in the agriculture and industrial field. As the name specify LoRa “long range radio” gives a pretty good RF signal range up to 15km with high gain antenna. In this tutorial we will make Lora based transmitter and receiver to turn ON/OFF two channel output. With a connection LED to know that both the modules are paired. In this way we can monitor the connectivity range as well as real time operation of the LoRa.

LoRa comes with two type of connection interface, SPI and the UART. But here we are using SPI LoRa because it works on 3.3volt logic and Arduino works on 5V logic level. In UART we need an external logic convertor to establish the connection. Also, a software serial is required to get the output of serial monitor on another channel. And due to limited libraries UART based Lora is not available to me in 433Mhz range.

LoRa SPI:

Serial peripheral interface uses MOSI, MISO and SCK pin of the microcontroller. But in LoRa there is a chip select, Reset and Digital pin to be connected. Which extend the wire connection to 8 pins. No need to use any external logic convertor with this type of connection setup. Here in INDIA 433Mhz spectrum is given to LoRa, you can check your country bands accordingly and then update the code.

Win exciting rewards from PCBWAY:

PCBWAY is hosting a PCB design competition 5th time and now there are rewards for everybody. Just register on the website and get your hands on raspberry pi Pico board.

You can share your projects and thoughts there to win more prices. Just upload the full working of your best project using PCBWAY service. Want to know more about contest then click here.

Components required:

1) LoRa Ra01

2) Arduino UNO

3) Battery

4) Tactile Switch

5) LED and 220ohms resistor

6) PCB shield from PCBWAY

Circuit diagram:

The circuit diagram is same for the Lora connection. MOSI to D11, MISO to D12, SCK to D13, D10 for NSS and D9 for the Reset. but there are modifications done on switching side. In the transmitter section two tactile buttons are connected to D3 and D4 pin of the Arduino. Buttons are work in hold state only. The output at receiver end goes ON/OFF by pressing/releasing tactile button respectively.

On the receiver end we are using a string receiver LED on pin D3, which gives the information about connection. This LED will blink after every second and gives the information about the successful connection of LoRa RF signal. We are using D4 and D5 as the output, by default these pins are hold high and go to low as the button pressed from the transmitter. This type of code is done for the Relay based application of the LoRa.

PCB shield and prototype:

I made a prototype for the transmitter but a dedicated PCB is recommended for it. I am using Pcbway service- China based PCB manufacturer. These hole type pref board I got from PCBWAY but you can download the dedicated PCB shield files from here.

There are a lot of connections in the PCB that why shield is recommended to use. Get the PCB in just $5 for 5 pcs of 2layer board. Register now to PCBWAY and get free rewards as coupons. There is some limitation in holed type design because they are made to try different projects. And soldering wires properly through them is not an easy job. Get a full soldering guide soon here.

Code and Libraries:

Here I am using LoRa library by Sandeep Mistry, it is very well optimized library for SPI protocol LoRa modules. You can also see more examples and go through each of them in order to make some new projects.

For Transmitter:

#include <LoRa.h> 
//int pot = A0;
const int SW1 = 3;
const int SW2 = 4;


int SyncWord = 0x22;
 
void setup() {
  Serial.begin(9600);
  pinMode(SW1,INPUT_PULLUP);
  pinMode(SW2,INPUT_PULLUP);

  cli();                                    //stop interrupts
                                            //set timer1 interrupt at 1Hz = 1sec
  TCCR1A = 0;                               // set entire TCCR1A register to 0
  TCCR1B = 0;                               // same for TCCR1B
  TCNT1  = 0;                               // initialize counter value to 0
                                            // set compare match register for 1hz increments
  OCR1A = 15624;                            // = (16*10^6) / (1*1024) - 1 (must be <65536)
                                            
  TCCR1B |= (1 << WGM12);                   // turn on CTC mode                                      
  TCCR1B |= (1 << CS12) | (1 << CS10);      // Set CS10 and CS12 bits for 1024 prescaler                                          
  TIMSK1 |= (1 << OCIE1A);                  // enable timer compare interrupt

  sei();                                    //allow interrupts
  
  while (!Serial);  
  Serial.println("LoRa Sender");
  if (!LoRa.begin(433E6)) { // or 915E6, the MHz speed of yout module
    Serial.println("Starting LoRa failed!");
    while (1);
  }
  
  LoRa.setSpreadingFactor(12);           // ranges from 6-12,default 7 see API docs
  LoRa.setSignalBandwidth(62.5E3 );           // for -139dB (page - 112)
  LoRa.setCodingRate4(8);                   // for -139dB (page - 112)
  LoRa.setSyncWord(SyncWord);
/*
  Serial.print("current spreading factor : ");
  Serial.println(LoRa.getSpreadingFactor());
  Serial.print("current bandwidth : ");
  Serial.println(LoRa.getSignalBandwidth());
  Serial.println("LoRa init succeeded.");
  */
}

int priviousSwitchValue1 = 1;
int priviousSwitchValue2 = 1;
int liveSwitchValue1 = 0;
int liveSwitchValue2 = 0;
bool switchPressFlag1 = false;
bool switchPressFlag2 = false;
bool gLedPin = 0;

int data = 1;

void loop() {
  //static int data = 1;
  
  liveSwitchValue1 = digitalRead(SW1);
  if( (liveSwitchValue1 == 0) and (switchPressFlag1 == false) )
  {
    delay(50);
    data = 11;
    Serial.println("11");
    switchPressFlag1 = true;
    priviousSwitchValue1 = !priviousSwitchValue1;

    LoRa.beginPacket();  
    LoRa.print(data);
    LoRa.endPacket();
  }
  if( (liveSwitchValue1 == 1) and (switchPressFlag1 == true) )
  {
    delay(50);
    data = 22;
    Serial.println("22");
    switchPressFlag1 = false;
    LoRa.beginPacket();  
    LoRa.print(data);
    LoRa.endPacket();
  }
  
  liveSwitchValue2 = digitalRead(SW2);
  if( (liveSwitchValue2 == 0) and (switchPressFlag2 == false))
  {
    delay(50);
    data = 33;
    Serial.println("33");
    switchPressFlag2 = true;
    priviousSwitchValue2 = !priviousSwitchValue2;
    LoRa.beginPacket();  
    LoRa.print(data);
    LoRa.endPacket();
  }
  if( (liveSwitchValue2 == 1) and (switchPressFlag2 == true) )
  {
    delay(50);
    data = 44;
    Serial.println("44");
    switchPressFlag2 = false;
    LoRa.beginPacket();  
    LoRa.print(data);
    LoRa.endPacket();
  }

  
  if(gLedPin == 1)
  {
    data = 55;
    Serial.println("55");
    gLedPin = 0;
    LoRa.beginPacket();  
    LoRa.print(data);
    LoRa.endPacket();
  }
  
  // LoRa.beginPacket();  
  // LoRa.print(data);
  // LoRa.endPacket();
}

ISR(TIMER1_COMPA_vect){//timer1 interrupt 1Hz toggles pin 13 (LED)
//generates pulse wave of frequency 1Hz/2 = 0.5kHz (takes two cycles for full wave- toggle high then toggle low)
  static volatile int ledFlag = 0;
  if(++ledFlag >= 5)
  {
    gLedPin = 1;
    ledFlag = 0;
  }
}

For Receiver:

#include <LoRa.h> 

const int LED1 = 3;   // indicator LED
const int RLY1 = 4;   // relay 1
const int RLY2 = 5;   // relay 2

String inString = "";    // string to hold input
int val = 0;
int SyncWord = 0x22;
 
void setup() {
  Serial.begin(9600);
  pinMode(LED1,OUTPUT);
  pinMode(RLY1,OUTPUT);
  pinMode(RLY2,OUTPUT);
  
  digitalWrite(LED1 , LOW);
  digitalWrite(RLY1 , HIGH);
  digitalWrite(RLY2 , HIGH);
  
  while (!Serial);
  Serial.println("LoRa Receiver");
  if (!LoRa.begin(433E6)) { // or 915E6
    Serial.println("Starting LoRa failed!");
    while (1);
  }
   LoRa.setSpreadingFactor(12);           // ranges from 6-12,default 7 see API docs
   LoRa.setSignalBandwidth(62.5E3);           // for -139dB (page - 112)
   LoRa.setCodingRate4(8);                   // for -139dB (page - 112)
   LoRa.setSyncWord(SyncWord);           // ranges from 0-0xFF, default 0x12, see API docs
/*
  Serial.print("current spreading factor : ");
  Serial.println(LoRa.getSpreadingFactor());
  Serial.print("current bandwidth : ");
  Serial.println(LoRa.getSignalBandwidth());
  Serial.println("LoRa init succeeded.");
  */
}
bool i=0;
int priviousValue = 0;
int liveValue = 0;

void loop() { 
  // try to parse packet
  int packetSize = LoRa.parsePacket();
  if (packetSize) { 
    // read packet    
    while (LoRa.available())
    {
      int inChar = LoRa.read();
      inString += (char)inChar;
      val = inString.toInt();  
      digitalWrite(LED1 , HIGH);
      delay(10);
      digitalWrite(LED1 , LOW);
      delay(10);     
    }
    inString = "";     
    LoRa.packetRssi();    
  }
  
  Serial.println(val);  
  liveValue = val;
    
  if(priviousValue != liveValue)
  {
    priviousValue = liveValue;
  
    if(val == 11)
    {
      digitalWrite(RLY1 , LOW);
    }
    
    if(val == 22)
    {
      digitalWrite(RLY1 , HIGH);
    }
  
    if(val == 33)
    {
      digitalWrite(RLY2 , LOW);
    }
    
    if(val == 44)
    {
      digitalWrite(RLY2 , HIGH);
    }
  }
  delay(50);
}

/*
 * 1. when switch 1 is pressed turn ON RLY1 & RLY2
 * 2. if 
 */

Code explanation:

Arduino transmitter send a data string to receiver and the changes are done according to that. In normal state the transmitter send "55" which is used to lit up red connection led. The the different strings "11" and "22" to turn OFF/On the receiver channel.

Working and demonstration:

The receiver is made on a PCB shield and for transmitter I am using a breadboard. 5-volt battery/ power supply is enough for proper working. After turning power On, the red LED start as the connection indicator. And we are using two more Green and blue LED to examine the output.

After pressing the button on transmitter, the respective LED is turn OFF, a small delay of 0.5 seconds is there because the system is working on a low frequency. The receiver and transmitter are working very fine you can use this type of trans receiver system with Relays for heavy AC loads.

Sometimes there is problem in establishing the connection because of helical wire antenna. A SMA type antenna with 3dB gain can be used to extend the range up to 10 km. In this case a reset is required from the transmitter for the reconnection.