In today’s fast-growing Internet of Things (IoT) ecosystem, reliable long-distance wireless communication with minimal power consumption is essential. Technologies like Wi-Fi, Bluetooth, RF modules, and cellular networks are widely used, but each has limitations:
- Wi-Fi & Bluetooth → High power consumption
- RF modules → Limited range or higher transmission power required
- Cellular networks → Expensive and power-intensive
For low-data IoT applications, these technologies are often inefficient.
This is where LoRa (Long Range) technology provides a major advantage. It enables long-distance wireless communication (several kilometers) while consuming extremely low power.
In this guide, we will explore how to interface the Reyax RYLR999 LoRa Module with an Arduino board and build a simple point-to-point communication system.
Introduction to RYLR999 ModuleThe RYLR999 Lite is a high-power long-range wireless transceiver module developed by REYAX Technology that integrates LoRa communication (868/915 MHz) and 2.4 GHz Bluetooth Low Energy (BLE) into a single compact module. It allows developers to implement both short-range BLE connectivity and long-range LoRa communication using independent UART interfaces. The module supports AT-command configuration, enabling users to set parameters such as device address, network ID, RF frequency, spreading factor, bandwidth, and transmission power.
On the LoRa side, it offers up to +30 dBm (1W) output power, with a frequency range of 820–960 MHz, receive current of approximately 15.5 mA, transmit current up to 650 mA, sleep current of about 1.25 mA, and ultra-low deep sleep current near 18.2 µA, making it suitable for battery-operated systems. The BLE subsystem operates in the 2400–2483.5 MHz band with output power up to +20 dBm and supports smartphone connectivity. With its ability to function as a BLE-to-LoRa bridge, the RYLR999 enables mobile devices to indirectly transmit data across several kilometers, making it ideal for remote monitoring, agriculture, industrial automation, smart metering, and alarm systems where long-distance, low-data-rate communication is required.
RYLR999 Pinout
VDD (Pin 1): 5V regulated supply input.
RST (Pin 2): Active-low reset pin.
TXD_BLE (Pin 3): BLE UART transmit pin.
RXD_LoRa (Pin 4): LoRa UART receive pin. Accepts AT commands and configuration data.
TXD_LoRa (Pin 5): LoRa UART transmit pin.
RXD_BLE (Pin 6): BLE UART receive pin.
GND (Pin 7): Common ground connection.
Wiring Connections for the Initiator Setup /*
Code to send “Are you there?” from one Arduino to another Arduino using RLYR999 Module
and receive reply and display complete communication on I2C LCD by platwithcircuit.com
*/
#include <LiquidCrystal_I2C.h>
#define REPLY_TIMEOUT_IN_MS 300
#define REPLY_END_CHAR '\n'
#define MODULE_ADDRESS 0
#define RECEIVERS_ADDRESS 1
#define MIN_CHAR_TO_RCV 1
#define WAIT_FOR_RECIVERS_REPLY 3000
#define DELAY_BW_REPS 1000
// Init LCD at 0x27, 16x2
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup() {
boolean boRetVal = false;
// begin serial communication at baud 115200,n,8,1
// to communicate with the RF module
Serial.begin(115200);
// initialize the LCD
lcd.init();
// Turn ON the Backlight
lcd.backlight();
// Clear the display buffer
lcd.clear();
flushBuffer(); // clear rx data
// Reset settings to factory defaults
boRetVal = boRestoreFactoryDefaults();
// setting the address if reset successfully
if (boRetVal == true) {
flushBuffer(); // clear rx data
boRetVal = boSetAddress();
}
if (boRetVal == true) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Module Init");
lcd.setCursor(0, 1);
lcd.print("Successful");
delay(1000);
} else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Module Init");
lcd.setCursor(0, 1);
lcd.print("Failed");
while (1)
;
}
}
void loop() {
String request = "Are you there?";
String expected_reply = "Yes";
bool boRetVal = false;
flushBuffer(); // clear rx data
// transmits String named request
boRetVal = boSendData(request);
if (boRetVal == true) {
// Displaying Sent Msg
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Msg Sent:");
lcd.setCursor(0, 1);
lcd.print(request);
delay(1000);
boRetVal = chkReply(expected_reply, REPLY_END_CHAR, WAIT_FOR_RECIVERS_REPLY);
if (boRetVal == true) {
// Displaying received Msg
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Msg Received:");
lcd.setCursor(0, 1);
lcd.print(expected_reply);
} else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("No reply received.");
}
} else {
// Displaying Failed Msg
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Msg Sending");
lcd.setCursor(0, 1);
lcd.print("Failed");
}
delay(DELAY_BW_REPS); // wait before sending again
}
void sendCrLf(void) {
Serial.write(0x0D); // Carriage Return
Serial.write(0x0A); // Line Feed
}
void flushBuffer(void) {
while (Serial.available() > 0) {
Serial.read();
}
}
bool chkReply(String chkString, char receiveUntil, unsigned int timeout) {
String receivedString; // save received data in this string object
bool boReturnValue = false; // function's return value
// wait for reply
do {
timeout--;
delay(1); // delay of 1 ms
} while ((Serial.available() < MIN_CHAR_TO_RCV) && (timeout > 0));
if (timeout) {
// if timeout is left then a reply is received check for the string in the reply
receivedString = Serial.readStringUntil(receiveUntil);
if (receivedString.indexOf(chkString) != -1) {
boReturnValue = true;
} else {
boReturnValue = false;
}
} else {
boReturnValue = false;
}
// return result
return boReturnValue;
}
bool boRestoreFactoryDefaults(void) {
const char factoryDefaultCmd[] = "AT+FACTORY"; // command to be sent
bool boReturnValue = false; // function's return value
char downCounter = 100; // Down counter to wait for reply
String receivedString; // save received data in this string object
String chkRcvString1 = "+FACTORY";
String chkRcvString2 = "+READY";
// send command
Serial.print(factoryDefaultCmd);
sendCrLf();
// check first string in reply
boReturnValue = chkReply(chkRcvString1, REPLY_END_CHAR, REPLY_TIMEOUT_IN_MS);
if (boReturnValue == true) {
// check second string in reply
boReturnValue = chkReply(chkRcvString2, REPLY_END_CHAR, REPLY_TIMEOUT_IN_MS);
}
// return result
return boReturnValue;
}
bool boSetAddress(void) {
const char setAddressCmd[] = "AT+ADDRESS="; // command to be sent
bool boReturnValue = false; // function's return value
String chkRcvString = "+OK";
// send command
Serial.print(setAddressCmd);
Serial.print(MODULE_ADDRESS);
sendCrLf();
// check reply
boReturnValue = chkReply(chkRcvString, REPLY_END_CHAR, REPLY_TIMEOUT_IN_MS);
// return result
return boReturnValue;
}
bool boSendData(String data) {
const char sendDataCmd[] = "AT+SEND="; // command to be sent
bool boReturnValue = false; // function's return value
String chkRcvString = "+OK";
// send command
Serial.print(sendDataCmd);
Serial.print(RECEIVERS_ADDRESS);
Serial.print(',');
Serial.print(data.length());
Serial.print(',');
Serial.print(data);
sendCrLf();
// check reply
boReturnValue = chkReply(chkRcvString, REPLY_END_CHAR, REPLY_TIMEOUT_IN_MS);
// return result
return boReturnValue;
}For Arduino Code for Responder Setup Visit: How to Interface Reyax RYLR999 LoRa Module with Arduino




Comments