LoRa Network, Master Arduino LoRa to Multiple Arduino Lora Nodes, LoRa End Nodes
Table of Contents
LoRa Network using Arduino, Description:
LoRa Network, Master Arduino LoRa to Multiple Arduino Lora Nodes, LoRa End Nodes- In this article, you will learn how to make a LoRa Network using Arduino boards, SX1278 LoRa transceiver modules, a Servo, an I2C supported SSD1306 Oled display module, and a pair of Potentiometers.
I have already uploaded an article on the LoRa network, in which I have practically demonstrated that how a LoRaWAN can be implemented by using multiple LoRa transceiver modules. Guys, you might be thinking that when I have already implemented LoRaWAN, then what is the need to work on this project once again? Well, you will get its answer in a minute.
As you know, every person or a company has a specific requirement that for what purpose a LoRa network has to be designed. Similarly, I also had to keep certain personal requirements into consideration when I was designing my LoRaWAN or LoRa network. I wanted, that my designed LoRa network had a Master Node and rest of the LoRa Nodes just act as sensor Nodes.
So, keeping in view this necessity before me, I worked out and designed this LoRaWAN network. I used a total of 3 Nodes in this LoRaWAN network.
To the master Lora Node an i2c supported Oled display module is connected which I used for displaying the data received from the other two LoRa nodes.
To the Lora Node1 a potentiometer is connected which I used as the sensor. You can replace this sensor with any other sensor of your choice.
To the Lora Node2, DS18b20 waterproof one-wire digital temperature sensor is connected.
The Master Lora Node, first, send request to the Lora Node1, for this I created a timer using the millis() function. So, for the first 5 seconds the Master Lora node sends multiple requests to the Lora Node1 and receive data from the Node1, this time duration can be changed in the programming. But it’s good to give it enough time so that the master node can get multiple replies from the Lora end device. As you can clearly see for the first 5 seconds it receives data from the Node1 and then for the other 5 seconds it receives data from the Lora Node2 to which the DS18b20 Temperature sensor is connected.
The Node name is also printed on the Oled display module so there is no confusion at all.
You can clearly see, that in this project I am only monitoring the sensors and I am not controlling anything.
A few days back, one of my followers asked me, that how can we send sensors data from the Master LoRa Node to Multiple LoRa END devices? If you remember during my previously designed LoRa network, I used to send data to Master Node from END devices. Whereas, in today’s LoRa Network, I will send data or commands from the Master LoRa node to multiple LoRa END devices.
As you can see a master LoRa Node, having two potentiometers connected to it. Servo is connected to LoRa node 1, whereas the Oled display module is connected with LoRa Node 2. I have programmed the Master LoRa node in such a manner that one of the two potentiometers will control Servo, whereas value of the second potentiometer will be printed on the Oled display module. Instead of using the potentiometers you can use some other types of sensors and the same thing applies to the Servo and Oled display module. It’s totally up to you what exactly you want to control.
By the way, you might be thinking how does Arduino come to know about which potentiometer’s data has to be sent on which LoRa Node or LoRa END device? Well, you don’t have to be confused, in this network every LoRa node has a specific address. And it is with the help of these addresses, the master LoRa node knows which potentiometer data has to be sent onto which LoRa END device. Enough with the talking, let’s practically see this LoRa network in action?
You can see, I have powered up all LoRa Nodes. And, you can also clearly see there is no physical connection between the Nodes, because it is obviously a wireless Network. Right now value on the Oled display module is 827 and you can also see the position of the Servo. Now, I will use the two potentiometers on the Master LoRa Node to change the value on the Oled display and to change the position of the Servo.
So, you can see how easily we can transmit data and commands from a Master LoRa Node to multiple LoRa END devices. You can also convert Master Node into an loT Gateway and as such, you can manage your LoRa Nodes from any country of the world through the application of your cell phone. Therefore, if you are interested to learn how to design a LoRa gateway, you must surely watch out my previous videos. You can find links in the description given below.
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:
Arduino Nano USB-C Type (Recommended)
SSD1306 128×64 Oled i2c display Module
*Disclosure: These are affiliate links. As an Amazon Associate I earn from qualifying purchases.
SX1278 LoRa Module:
Features:
- Frequency Range: 868 / 915 MHz
- Sensitivity up to -139dBm @Lora
- Maximum output power: 20 dBm
- 13mA@receiver 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
Master Lora Node, Circuit Diagram:
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 pin 12. The MOSI pin is connected with pin 11. The SCK pin of the LoRa module is connected with 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.
Two potentiometers are connected with the Arduino analog pins A2 and A3. Now, let’s take a look at the circuit diagram of the LoRa Node 1.
Lora Node1, Circuit Diagram:
The Lora module connections with the Arduino Nano remains exactly the same.
On the left side, you can see a 5V regulated power supply based on the LM7805 voltage regulator. We use this regulated 5 volts to power up the Arduino and all the other electronics.
The signal wire of the Servo is connected with the PWM 3 of the Arduino. If you want to use a large servo motor then you should use a separate 5v power supply with the Servo. Otherwise, your Arduino will keep resetting. Now, let’s take a look at the circuit diagram of the LoRa Node 2.
Lora Node2, Circuit Diagram:
The Lora module connections with the Arduino and the 5V regulated power supply wiring remains exactly the same.
The SDA and SCL or SCK pins of the SSD1306 Oled display module are connected with the A4 and A5 pins of the Arduino. While the VCC and GND pins of the Oled display module are connected with the Arduino’s 5 volts and GND pins.
Lora Network Arduino Programming:
Before, you start the programming; first of all, make sure you download all the necessary libraries.
Master LoRa Node, Arduino Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
/* Master Lora Node https://www.electroniclinic.com/ */ #include <SPI.h> // include libraries #include <LoRa.h> byte MasterNode = 0xFF; byte Node1 = 0xBB; byte Node2 = 0xCC; int pot1=A2; int pot2=A3; String SenderNode = ""; String outgoing; // outgoing message String message1; String message2; byte msgCount = 0; // count of outgoing messages // Tracks the time since last event fired unsigned long previousMillis=0; unsigned long int previoussecs = 0; unsigned long int currentsecs = 0; unsigned long currentMillis = 0; int Secs = 0; long lastSendTime = 0; // last send time int interval = 20; // interval between sends void setup() { Serial.begin(9600); // initialize serial pinMode(pot1,INPUT); pinMode(pot2,INPUT); 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) { int sensor1, sensor2; sensor1 = analogRead(pot1); message1=message1+ sensor1 +","; sensor2 = analogRead(pot2); message2=message2 + sensor2 +","; sendMessage(message1,MasterNode,Node1); delay(50); sendMessage(message2,MasterNode,Node2); delay(50); //Serial.println("Sending " + message); lastSendTime = millis(); // timestamp the message // interval = random(50); message1=""; message2 = ""; } } void sendMessage(String outgoing, byte MasterNode, byte otherNode) { LoRa.beginPacket(); // start packet LoRa.write(otherNode); // add destination address LoRa.write(MasterNode); // 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 } |
LoRa Node 1, Arduino Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
/* Lora Node1 https://www.electroniclinic.com/ */ #include <SPI.h> // include libraries #include <LoRa.h> #include<Servo.h> Servo myservo; String outgoing; // outgoing message byte msgCount = 0; // count of outgoing messages byte MasterNode = 0xFF; byte Node1 = 0xBB; void setup() { Serial.begin(9600); // initialize serial myservo.attach(3); while (!Serial); 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() { // parse for a packet, and call onReceive with the result: onReceive(LoRa.parsePacket()); } 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 != Node1 && recipient != MasterNode) { //Serial.println("This message is not for me."); ; return; // skip rest of function } Serial.println(incoming); //int Val = incoming.toInt(); String q = getValue(incoming, ',', 0); int Val = q.toInt(); int sval = map(Val, 0, 1023, 0, 180); // scale it to use it with the servo (value between 0 and 180) myservo.write(sval); // sets the servo position according to the scaled value delay(15); } 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 Node 2, Arduino Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
/* Lora Node2 https://www.electroniclinic.com/ */ #include <SPI.h> // include libraries #include <LoRa.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #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 outgoing; // outgoing message byte msgCount = 0; // count of outgoing messages byte MasterNode = 0xFF; byte Node2 = 0xCC; void setup() { Serial.begin(9600); // initialize serial display.begin(SSD1306_SWITCHCAPVCC, 0x3C); delay(2000); display.clearDisplay(); display.setTextColor(WHITE); 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() { // parse for a packet, and call onReceive with the result: onReceive(LoRa.parsePacket()); } 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 != Node2 && recipient != MasterNode) { //Serial.println("This message is not for me."); ; return; // skip rest of function } // Serial.println(incoming); // int Val = incoming.toInt(); String q = getValue(incoming, ',', 0); int Val = q.toInt(); Serial.println(Val); display.clearDisplay(); display.setTextSize(2); display.setCursor(0,0); display.print("Node 2:"); display.setTextSize(3); display.setCursor(0, 28); display.print(Val); 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]) : ""; } |
Hi can you Make blogs on some advanced Lora topics like creating a Lora node with micro controller which you already did in your posts and sending the Lora node data to the gateway ( may be indoor gateway or outdoor gateway ) and from from the gateway to the things network server and here once we receive our pay load from things network ,it will be in hex format format ,we need to write a decoder script to understand in human readable formats , Iam finding no topic on Lora how to write customized decoder scrips for Various sensors , it will be a great help if we get more information on payload formatters like how to write decoder scripts for sensors and after that there is no use if we have sensor data even though in readable format until unless it is visualized ,please make some blogs how to visualize the data from TTN network server to integrate to aws iot core ,IBM cloud ,azure webbooks (like ubidots ..etc) EVEN THOUGH WE HAVE DOCUMENTATIONS ON INTERNET its is bit difficult to understand to the beginners LACK of proper support from those cloud platforms
This kind of Research project will give us an end to end solution and it will be great lesson for lot research students like me . I really appreciate your time to make awesome content like this Hats off to you Shahzada Fahad
Waiting for your future content
god bless you
thanks
sai from canada