RFM95W LoRa running Proteus simulation, Arduino Uno sender and receiver at 868 MHz, RSSI and SNR on Virtual Terminal, distance control panels

RFM95W LoRa Proteus Library | Arduino LoRa Simulation

2.5K Views
40
700
60
25
60
PCBWay

Hello friends, I hope you are doing well. In today's tutorial, I am going to share our RFM95W LoRa Proteus Library. With this library, we can place two RFM95W LoRa modules in one Proteus design, connect each module to an Arduino Uno and send messages from one board to the other at 868 MHz. The receiver prints every message with its signal strength and its signal-to-noise ratio, and a row of distance buttons lets us test a link of up to 20 km.

We will start with the basics of LoRa and the module, install the library files and wire the circuit. After that, we will run the supplied two-Arduino simulation and study the control panel in detail. We will see how the spreading factor, the bandwidth and the output power change the range of the link. We will also understand both Arduino sketches and calculate the values shown on the Virtual Terminal. The download includes the wired project, two compiled HEX files, both sketches and the Arduino driver.

This tutorial uses our V1.0 package, the TEP Arduino UNO V3 and a 16 MHz clock. The package notes record a test of the supplied project in Proteus 8.5 SP0. In the running screenshot below, the sender is on the left and the receiver is on the right. The first six messages arrived with -74 dBm, two messages were too weak, and the last message arrived with -113 dBm after the distance was set to 2 km.

RFM95W LoRa running Proteus simulation, Arduino Uno sender and receiver at 868 MHz, RSSI and SNR on Virtual Terminal, distance control panels
Figure: The sender on the left has sent nine messages. The receiver on the right shows -74 dBm at 100 m, two missing messages that were too weak, and -113 dBm at 2 km.

What Is the RFM95W LoRa Module?

The RFM95W is a long-range radio transceiver module from HopeRF for the 868 and 915 MHz bands. A transceiver can both transmit and receive, so we use the same module on each side of a wireless link. The module is built around the Semtech SX1276 chip and uses the LoRa modulation. The microcontroller configures the module and exchanges data with it through SPI. HopeRF describes it in the RFM95/96/97/98(W) datasheet.

Main Features of the RFM95W

  • It works in the 868 and 915 MHz bands with the LoRa modem.
  • Its output power goes up to +20 dBm, which is 100 mW.
  • Its sensitivity goes down to -148 dBm, and its maximum link budget is 168 dB.
  • It supports the spreading factors 6 to 12 and bandwidths from 7.8 to 500 kHz.
  • Its packet engine handles packets of up to 256 bytes with CRC.
  • Its supply range is 1.8 to 3.7 V.

How LoRa Reaches a Long Range

LoRa spreads every symbol over a wide bandwidth and a long time. The receiver collects the energy of the whole symbol, so it can decode a signal that is weaker than the noise. We pay for this range with time, because a slow setting keeps the packet on the air for much longer. Three settings control this trade:

  • Spreading factor (SF): a number from 6 to 12. Each step doubles the length of a symbol and improves the sensitivity by 2.5 dB.
  • Bandwidth (BW): the width of the signal. A narrow bandwidth has less noise and reaches further, but it is slower.
  • Coding rate (CR): the amount of error correction. A rate of 4/5 sends five bits for every four data bits.

Important Terms

  • dBm: a unit of signal power. A value of 0 dBm is 1 mW, and negative values are weaker signals.
  • RSSI: the received signal strength indicator. It tells us how strong the signal was at the receiver.
  • SNR: the signal-to-noise ratio in dB. A negative SNR means that the signal is weaker than the noise.
  • Sync word: one byte that separates networks. The receiver accepts only packets with its own sync word.
  • Time on air: the time that one packet needs for its transmission.
  • Explicit header: a packet format in which a header carries the length, the coding rate and the CRC setting of the packet.

Features of Our Proteus Model

  • The component is named RFM95TEP and has eight pins.
  • Every LoRa module placed in the same design shares one virtual band, so no wire is needed between the two sides.
  • A control panel beside each module shows its live mode, settings, counters and the last packet.
  • Eight distance buttons, from 10 m to 20 km, set the distance to the other radios.
  • The model calculates the time on air with the formula of the chip manufacturer.
  • The Arduino communicates with the model through real SPI commands and registers.

Keep one distinction in mind. This is a functional model of the LoRa modem with a simple range calculation. It does not simulate antennas, buildings, reflections or interference. The distance buttons are useful for learning how the LoRa settings and the distance are related, but they do not predict the range of a real installation.

Download the RFM95W LoRa Library for Proteus

First of all, download the V1.0 package using the button below. Extract the complete ZIP into a normal folder before opening the project, and keep the files of the simulation folder together.

Download RFM95W LoRa Proteus Library V1.0 and Arduino Simulation
Contents of the RFM95W LoRa Proteus package
Folder or fileContents and purpose
Proteus Library FilesTEPRFM95.LIB for the radio module, and the TEP Arduino UNO V3 LIB/IDX files.
Proteus Model FilesTEPSX1278.DLL, which provides the simulated behavior of our LoRa modules.
Proteus SimulationRFM95-ArduinoUnoV3.pdsprj, RFM95_Sender.hex, RFM95_Receiver.hex and a local copy of the DLL.
Arduino CodeBoth sketches, the arduino-LoRa 0.8.0 driver, the AVR core archive and a firmware rebuild script.
Model SourceThe chip model, SPI transport, shared radio band and Proteus adapter.
DocumentationModel notes, third-party notices and a preview of the board artwork.
README.txt and SHA256SUMS.txtQuick-start instructions and checksums of the packaged files.

The name of the DLL needs an explanation. One model file serves all of our LoRa modules, and it is named after the SX1278. The device name RFM95TEP tells the model to behave as an RFM95W. All LoRa modules of a design must use the same DLL, because only then do they share one radio band.

The Proteus library and the Arduino library have different jobs. The LIB file defines the component that we place on the schematic, and the DLL gives it its behavior. The LoRa Arduino library gives our sketch the functions for talking to the radio. Installing the Arduino library alone will not make RFM95TEP appear in Proteus.

How to Install the RFM95W Library in Proteus

Copy the Library and Model Files

Save your work and close Proteus before copying the files. Then follow these steps:

  1. Open the extracted Proteus Library Files folder.
  2. Copy TEPRFM95.LIB into the library directory configured for your Proteus installation.
  3. Copy ArduinoV3TEP.LIB and ArduinoV3TEP.IDX from the same folder if our TEP Arduino UNO V3 library is not installed already.
  4. Open Proteus Model Files and copy TEPSX1278.DLL into your configured Proteus MODELS directory.
  5. Restart Proteus, open Pick Devices and search for RFM95TEP.
  6. Place the module on the schematic, or open the supplied project to use the completed circuit.

Points to Remember

  • Use the library and model folders that your installation actually searches. Their locations differ between installations.
  • The module is supplied as a LIB file without a separate IDX. The included IDX belongs to the Arduino board.
  • Keep the extra DLL beside the project in the Proteus Simulation folder.
  • If your MODELS folder already contains an older TEPSX1278.DLL, replace it with the file of this package. The older file does not know the RFM95W. In that case, the panel title shows SX1278 instead of RFM95W.
  • The two HEX files are programs for the two Arduino boards. The radio module does not need a HEX file.
  • Compatibility with Proteus 7 has not been established.

The Arduino board in this project comes from our Arduino Library for Proteus V3.0. Start with the supplied project, so that the boards, wiring and firmware match the demonstration.

RFM95W Pinout and Arduino Uno Wiring

The TEP module has eight pins along its lower edge. From left to right, they are VCC, GND, SCK, MISO, MOSI, NSS, RST and DIO0. Start each wire at the exposed pin endpoint below the board artwork.

Connections used on both Arduino boards
Module pinConnectionPurpose
VCCPositive supply terminalPowers the digital model.
GNDGroundProvides the shared reference.
SCKArduino Uno D13SPI clock from the Arduino.
MISOArduino Uno D12Data from the module to the Arduino.
MOSIArduino Uno D11Data from the Arduino to the module.
NSSArduino Uno D10Selects the module for an SPI command. It is active low.
RSTArduino Uno D9Reset input. It is active low.
DIO0Arduino Uno D2Interrupt output for a received or a sent packet.
RFM95W LoRa Proteus wiring, Arduino Uno SPI pins D10 to D13, RST on D9 and DIO0 on D2, sender and receiver circuit
Figure: The stopped circuit connects SCK, MISO, MOSI and NSS to D13, D12, D11 and D10, RST to D9 and DIO0 to D2 on both boards.

Both boards use the same wiring, which follows the default pins of the driver. The Arduino named ARD1 works with module U1 as the sender, and ARD2 works with U2 as the receiver.

  • RST is active low. The driver pulls the pin low for 10 ms and then high again when it starts the radio.
  • DIO0 goes to D2. The supplied sketches read the radio through SPI, so they do not depend on this wire. It is needed for interrupt-based sketches that use the receive callback of the driver.

Virtual Terminal Connections

  • Connect Arduino D1/TX to RXD on the Virtual Terminal of each board.
  • Set both terminals to 9600 baud, eight data bits, no parity and one stop bit.
  • The return connection to D0/RX is shown in the circuit, but these sketches do not read typed commands.

Notes for Physical Hardware

  • The real RFM95W is a 3.3 V part with a supply range of 1.8 to 3.7 V. Connecting its supply to 5 V can damage it.
  • The model does not check the supply voltage, so a working simulation does not prove that your hardware supply is correct.
  • Check the logic levels required by your module before connecting a 5 V Arduino.
  • Connect a suitable antenna before you transmit with a real module.
  • Use 868 MHz or 915 MHz according to your region, and follow the local rules for power and transmission time.

Run the Two-Arduino Simulation

Start the Simulation

  1. Open Proteus Simulation/RFM95-ArduinoUnoV3.pdsprj from the extracted package.
  2. Keep both HEX files and TEPSX1278.DLL in that folder.
  3. Double-click ARD1 and confirm that its Program File is RFM95_Sender.hex.
  4. Double-click ARD2 and confirm that its Program File is RFM95_Receiver.hex.
  5. Confirm the 16 MHz clock on both boards and 9600 baud on both terminals.
  6. Press Run. If the two terminal windows open on top of each other, drag them apart.

Read the Terminal Output

  • The sender prints its heading and then LoRa ready: 868 MHz, SF7, 125 kHz, CR 4/5, sync 0x12.
  • Every two seconds, the sender prints a line such as Sending packet: 0.
  • The receiver prints Listening: 868 MHz, SF7, 125 kHz, CR 4/5, sync 0x12.
  • For every message, the receiver prints a line such as Received packet 'hello TEP 0' with RSSI -74 dBm, SNR 10.00 dB.

In the running screenshot at the top, messages 0 to 5 arrived with -74 dBm and an SNR of 10.00 dB. These are the values for the default distance of 100 m. Messages 6 and 7 are missing on the receiver, and its panel shows TOO WEAK 2. For message 8, the sender's panel is set to 2 km. This message arrived with -113 dBm and an SNR of 3.75 dB.

Notice that the sender printed all nine messages. The sketch sends its packets without asking for an answer, so the sender cannot know whether a message has arrived.

Understand the RFM95W Control Panel

The control panel is the most interesting part of this library. It shows what the radio is doing at every moment, and its distance buttons let us test the link without changing the code. The following picture shows the sender's module and its panel during a simulation.

RFM95W LoRa Proteus component close-up, eight module pins, control panel with mode banner, LoRa settings and counters, distance buttons from 10 m to 20 km
Figure: The RFM95TEP component with its control panel. The panel shows the mode, the LoRa settings, the counters, the last packet and the eight distance buttons.

Let us go through the panel from top to bottom.

The Mode Banner and Its Colors

Modes shown on the banner of the control panel
Banner textColorMeaning
SLEEPBlueThe radio is in its power-saving mode.
STANDBYBlueThe radio is on, but it is neither sending nor listening.
FS TX and FS RXBlueThe frequency synthesizer is running for sending or for receiving.
TX - SENDINGOrangeA packet is being sent.
RX SINGLEGreenThe radio listens for one packet and stops after a timeout.
RX CONTINUOUSGreenThe radio listens until the sketch changes the mode.
CADBlueThe radio checks whether a LoRa signal is present on the channel.
FSK/OOK MODE - NOT MODELLEDBlueThe chip is not in LoRa mode. The model covers the LoRa modem only.
NO POWER - CHECK VCC / GNDRedThe module is not powered.
OUT OF BAND, with the chip and the frequencyRedThe selected frequency is outside the range of the chip. Nothing is sent or received.
  • The receiver's banner is green and shows RX SINGLE. The driver function used by the sketch listens in short windows and starts a new window when the old one has ended.
  • The sender's banner is blue and shows STANDBY. At the default settings, a packet is on the air for about 41 ms, and the sketch then waits for two seconds.
  • With a high spreading factor, a packet needs up to one second. You can then see the orange banner clearly.

The Two Settings Lines

The next two lines show the radio settings. They are read from the registers of the chip, so they show what the sketch has really written.

Values on the two settings lines
Value in our exampleMeaningDriver function
868.000 MHzCarrier frequencyLoRa.begin() or LoRa.setFrequency()
SF7Spreading factor, 6 to 12LoRa.setSpreadingFactor()
BW 125 kHzBandwidth, 7.8 to 500 kHzLoRa.setSignalBandwidth()
CR 4/5Coding rate, 4/5 to 4/8LoRa.setCodingRate4()
SYNC 0x12Sync wordLoRa.setSyncWord()
CRC OFFCRC setting, ON or OFFLoRa.enableCrc()
EXPLICITHeader mode, EXPLICIT or IMPLICITThe parameter of LoRa.beginPacket()
+17 dBmOutput powerLoRa.setTxPower()

These lines are the quickest way to find a configuration mistake. Put the two panels side by side. The first settings line must be the same on both panels, except for the coding rate, and the sync word must be the same as well.

The Counters

  • SENT counts the packets that have left this radio. It increases even when no radio receives the packet.
  • RECEIVED counts the packets that this radio has received.
  • TOO WEAK counts the packets that matched the settings of this radio but were too weak for its spreading factor.
  • CRC ERR appears at the end of the line after the first packet with a CRC error.

In the running screenshot, the receiver shows RECEIVED 7 and TOO WEAK 2. The sender shows SENT 9, and 7 + 2 = 9. A packet with different settings is not counted by the receiver at all.

How to read the counters while the sender's SENT counter increases
Receiver panelMeaning
RECEIVED increases.The link works.
TOO WEAK increases.The settings match, but the distance is too large for the spreading factor and the power.
CRC ERR appears.The CRC is switched on, and the signal is at the edge of the sensitivity.
No counter changes.The frequency, the spreading factor, the bandwidth or the sync word is different, or the receiver is not listening.

The Last Packet Lines

Before the first packet arrives, the panel shows LAST PACKET RECEIVED with a dash below it. After that, the first line shows the RSSI and the SNR of the latest packet. The second line shows the payload in quotation marks, followed by its length. In the running screenshot, the receiver shows -113 dBm, an SNR of 3.8 dB and "hello TEP 8" with 11 bytes. A payload that is not readable text is shown as hexadecimal bytes.

The Distance Buttons and the Prediction Line

Below the heading DISTANCE TO THE OTHER RADIOS, there are eight buttons: 10 m, 100 m, 1 km, 2 km, 5 km, 10 km, 15 km and 20 km. The selected button is blue, and the default is 100 m. Click a button while the simulation runs.

The line below the buttons is a prediction. In the picture above, it reads AT 2 km: -113 dBm, SF7 NEEDS -125 dBm -> OK. It has three parts:

  1. AT 2 km: -113 dBm is the signal strength that a packet from this radio has at the selected distance.
  2. SF7 NEEDS -125 dBm is the weakest signal that the present spreading factor and bandwidth can decode.
  3. OK or TOO WEAK is the result of comparing the two values.

The prediction uses the settings of its own panel only. The Simulation Log records every distance change, the first packet sent and received, and the first packet that was too weak.

Panel Combinations: Distance, Spreading Factor and Power

Now comes the exciting part. The result of a transmission depends on several settings together. We will take the combinations one by one. The values for 100 m and 2 km at SF7 agree with the screenshots of this tutorial, and the package notes record that 5 km is too weak at SF7. The other values are calculated with the formulas of the model, which we will work through after the code.

Combination 1: The Distances on the Two Panels

Each radio has its own distance buttons. For a packet between two radios, the model uses the larger of the two selected distances.

Link distance for different selections at +17 dBm, SF7 and 125 kHz
Sender panelReceiver panelLink distanceRSSISNR on the terminalResult
100 m100 m100 m-74 dBm10.00 dBReceived
2 km100 m2 km-113 dBm3.75 dBReceived
100 m1 km1 km-104 dBm10.00 dBReceived
10 m5 km5 km-125 dBmNoneToo weak
5 km10 m5 km-125 dBmNoneToo weak

The second row is the last message of the running screenshot. The sender is set to 2 km and the receiver to 100 m, and the message arrives with -113 dBm. This rule has three consequences:

  • To move the radios apart, one click on either panel is enough.
  • To bring them together again, both panels must show a short distance.
  • The prediction line of one panel can show OK while the packets are too weak, because the other panel has a larger distance. The LAST PACKET line always shows the real value.

Try the Distance Buttons

  1. Let the simulation run at 100 m and note the RSSI and the SNR.
  2. Click 1 km on one panel. The RSSI changes to -104 dBm, but the SNR stays at 10.00 dB.
  3. Click 2 km. The RSSI changes to -113 dBm, and the SNR drops to 3.75 dB.
  4. Click 5 km. The receiver stops printing, and its TOO WEAK counter increases.
  5. Click a shorter distance to restore the link.

Combination 2: Distance and Spreading Factor

The hint on the panel says that a higher SF reaches further. This is the most important setting of a LoRa link.

Reception at 868 MHz, +17 dBm and 125 kHz for the six spreading factors
DistanceRSSISF7SF8SF9SF10SF11SF12
10 m-44 dBmReceivedReceivedReceivedReceivedReceivedReceived
100 m-74 dBmReceivedReceivedReceivedReceivedReceivedReceived
1 km-104 dBmReceivedReceivedReceivedReceivedReceivedReceived
2 km-113 dBmReceivedReceivedReceivedReceivedReceivedReceived
5 km-125 dBmToo weakReceivedReceivedReceivedReceivedReceived
10 km-134 dBmToo weakToo weakToo weakToo weakReceivedReceived
15 km-139 dBmToo weakToo weakToo weakToo weakToo weakToo weak
20 km-143 dBmToo weakToo weakToo weakToo weakToo weakToo weak

The price of a larger range is time. Every step of the spreading factor almost doubles the time on air.

Spreading factors at 125 kHz for the message "hello TEP 0"
Spreading factorLowest SNRWeakest signalLargest distance at +17 dBmTime on air
SF7-7.5 dB-124.5 dBm2 km41 ms
SF8-10 dB-127.0 dBm5 km72 ms
SF9-12.5 dB-129.5 dBm5 km144 ms
SF10-15 dB-132.0 dBm5 km248 ms
SF11-17.5 dB-134.5 dBm10 km496 ms
SF12-20 dB-137.0 dBm10 km991 ms
  • To change the spreading factor, add LoRa.setSpreadingFactor(9); after LoRa.begin() in both sketches.
  • The spreading factor must be the same on both sides. A packet with a different spreading factor is not received and not counted.
  • After the change, the first settings line shows SF9, and the prediction line shows the new limit.
  • The sender waits until a packet has been sent. At SF12, every message therefore takes about three seconds instead of two.

Combination 3: Distance and Bandwidth

The bandwidth sets the noise that the receiver collects. Half the bandwidth means 3 dB less noise, but twice the time on air.

Bandwidths at SF7, 868 MHz and +17 dBm for the message "hello TEP 0"
BandwidthNoise floorWeakest signalLargest distanceTime on air
62.5 kHz-120.0 dBm-127.5 dBm5 km82 ms
125 kHz-117.0 dBm-124.5 dBm2 km41 ms
250 kHz-114.0 dBm-121.5 dBm2 km21 ms
500 kHz-111.0 dBm-118.5 dBm2 km10 ms

To change the bandwidth, add LoRa.setSignalBandwidth(62.5E3); after LoRa.begin() in both sketches. The bandwidth must be the same on both sides.

Combination 4: Distance and Output Power

The driver function LoRa.setTxPower() accepts the levels 2 to 20. The output power moves every RSSI value up or down by the same amount.

Output power levels at SF7, 125 kHz and 868 MHz
Output powerRSSI at 100 mRSSI at 2 kmLargest distance
+20 dBm-71 dBm-110 dBm5 km
+17 dBm-74 dBm-113 dBm2 km
+14 dBm-77 dBm-116 dBm2 km
+10 dBm-81 dBm-120 dBm2 km
+5 dBm-86 dBm-125 dBm1 km
+2 dBm-89 dBm-128 dBm1 km
  • To change the power, add LoRa.setTxPower(20); to the sender after LoRa.begin(). The panel then shows +20 dBm.
  • For a packet, only the power of the sending radio matters.
  • With +20 dBm and SF12, the link reaches 15 km. At a bandwidth of 125 kHz, the distance of 20 km stays out of reach at 868 MHz.
  • The driver uses the PA_BOOST output of the module. If a sketch selects the other output with PA_OUTPUT_RFO_PIN, the model reduces the signal by 20 dB, because this output is not connected to the antenna.

Combination 5: SNR and the Edge of the Range

LoRa can decode a signal below the noise, so the SNR is as important as the RSSI.

  • The reported SNR is limited to +10 dB. This is why 100 m and 1 km show the same SNR of 10.00 dB, although their RSSI values are different.
  • At 2 km, the signal is only 3.8 dB above the noise. The terminal shows 3.75 dB, because the chip stores the SNR in steps of 0.25 dB.
  • At 5 km, the signal is 8.2 dB below the noise. SF7 needs at least -7.5 dB, so the packet is too weak. SF8 needs -10 dB, so the same signal is received.

The CRC adds one more case. When the sender has switched the CRC on with LoRa.enableCrc(), a packet that is less than 1 dB above the limit gets a CRC error in the model. The driver does not pass such a packet to the sketch, so the receiver prints nothing, and CRC ERR appears on its panel. With +17 dBm, this happens at 10 km with SF11, where the SNR is -17.2 dB and the limit is -17.5 dB.

Combination 6: Settings That Must Agree

Results of different settings on the two radios
SettingResult of a difference
FrequencyNothing is received, and no counter of the receiver changes.
Spreading factorNothing is received, and no counter of the receiver changes.
BandwidthNothing is received, and no counter of the receiver changes.
Sync wordNothing is received, and no counter of the receiver changes.
Header modeNothing is received, and no counter of the receiver changes.
Coding rateThe packet is received, because the explicit header tells the receiver the coding rate.
CRC settingThe packet is received, because the explicit header tells the receiver whether a CRC follows.
Output powerThe packet is received when the signal is strong enough.

The sync word is a simple way to separate two networks on the same frequency. The driver's default is 0x12. With LoRa.setSyncWord(0x34); in both sketches, the two radios form their own network.

Combination 7: 868 MHz and 915 MHz

Both sketches contain the line LORA_FREQUENCY. Use 868E6 or 915E6 according to your region, and use the same value in both sketches.

The two bands at +17 dBm, SF7 and 125 kHz
FrequencyLoss of the first metreRSSI at 100 mRSSI at 2 kmLargest distance
868 MHz31.2 dB-74.2 dBm-113.2 dBm2 km
915 MHz31.7 dB-74.7 dBm-113.7 dBm2 km

The chip of the RFM95W can be tuned from 137 to 1020 MHz. If a sketch sets a frequency outside this range, the banner turns red and shows OUT OF BAND, and the Simulation Log explains it.

Arduino Code for the RFM95W Sender

The following is the exact sender sketch included in the download. It uses the bundled arduino-LoRa library, version 0.8.0. Use the supplied copy for your first build, so that your firmware matches the packaged HEX file.

// TEP RFM95W LoRa Sender Demo v1.0
// The Engineering Projects - www.TheEngineeringProjects.com
//
// Sends "hello TEP n" every 2 seconds on 868 MHz (SF7, 125 kHz, CR 4/5, sync 0x12).
// Pair it with RFM95_Receiver on a second Arduino.
//
// Wiring (Arduino UNO, RFM95W module): VCC -> 3.3V, GND -> GND, SCK -> D13, MISO -> D12,
//   MOSI -> D11, NSS -> D10, RST -> D9, DIO0 -> D2   (the arduino-LoRa default pins)
// Library: LoRa by Sandeep Mistry (Arduino Library Manager: "LoRa")

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

#define LORA_FREQUENCY 868E6         // 868 MHz (EU band); use 915E6 for US/AU 915 MHz, check your local band plan

int counter = 0;

void setup() {
  Serial.begin(9600);
  Serial.println(F("TEP RFM95W LoRa Sender Demo v1.0"));
  if (!LoRa.begin(LORA_FREQUENCY)) {
    Serial.println(F("LoRa module not responding - check the SPI wiring and power"));
    while (true) {}
  }
  Serial.println(F("LoRa ready: 868 MHz, SF7, 125 kHz, CR 4/5, sync 0x12"));
}

void loop() {
  Serial.print(F("Sending packet: "));
  Serial.println(counter);

  LoRa.beginPacket();
  LoRa.print("hello TEP ");
  LoRa.print(counter);
  LoRa.endPacket();

  counter++;
  delay(2000);
}

Start the Radio

The line LORA_FREQUENCY sets the frequency to 868 MHz. The call LoRa.begin(LORA_FREQUENCY) does the following work:

  1. It uses the default pins of the driver, which are D10 for NSS, D9 for RST and D2 for DIO0 on the Arduino Uno.
  2. It resets the module with the RST pin.
  3. It reads the version register of the chip. If the value is wrong, the function fails and the sketch prints LoRa module not responding.
  4. It sets the frequency and an output power of 17 dBm.
  5. It puts the radio into standby.

The sketch does not set the spreading factor, the bandwidth or the coding rate. The values SF7, 125 kHz, CR 4/5 and the sync word 0x12 are the reset values of the chip, which the driver keeps. The CRC is switched off, and the packets use the explicit header.

Send a Packet

  1. LoRa.beginPacket() puts the radio into standby and starts a new packet.
  2. LoRa.print() writes the text and the counter into the transmit buffer of the chip.
  3. LoRa.endPacket() starts the transmission and waits until the chip reports that the packet has been sent.

The message "hello TEP 0" has 11 characters, and the panel of the receiver shows 11 bytes. The third step takes as long as the time on air. After it, the sketch increases the counter and waits for two seconds.

Arduino Code for the RFM95W Receiver

The setup part of the receiver is the same as in the sender. Here is the exact sketch from the package:

// TEP RFM95W LoRa Receiver Demo v1.0
// The Engineering Projects - www.TheEngineeringProjects.com
//
// Listens on 868 MHz (SF7, 125 kHz, CR 4/5, sync 0x12) and prints every packet
// with its RSSI and SNR. Pair it with RFM95_Sender on a second Arduino.
//
// Wiring (Arduino UNO, RFM95W module): VCC -> 3.3V, GND -> GND, SCK -> D13, MISO -> D12,
//   MOSI -> D11, NSS -> D10, RST -> D9, DIO0 -> D2   (the arduino-LoRa default pins)
// Library: LoRa by Sandeep Mistry (Arduino Library Manager: "LoRa")

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

#define LORA_FREQUENCY 868E6         // 868 MHz (EU band); use 915E6 for US/AU 915 MHz, check your local band plan

void setup() {
  Serial.begin(9600);
  Serial.println(F("TEP RFM95W LoRa Receiver Demo v1.0"));
  if (!LoRa.begin(LORA_FREQUENCY)) {
    Serial.println(F("LoRa module not responding - check the SPI wiring and power"));
    while (true) {}
  }
  Serial.println(F("Listening: 868 MHz, SF7, 125 kHz, CR 4/5, sync 0x12"));
}

void loop() {
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    Serial.print(F("Received packet '"));
    while (LoRa.available()) {
      Serial.print((char)LoRa.read());
    }
    Serial.print(F("' with RSSI "));
    Serial.print(LoRa.packetRssi());
    Serial.print(F(" dBm, SNR "));
    Serial.print(LoRa.packetSnr());
    Serial.println(F(" dB"));
  }
}

Wait for a Packet

The function LoRa.parsePacket() is called in every loop. It does two things:

  • When a packet has arrived without a CRC error, it returns the length of the packet.
  • Otherwise it returns zero and makes sure that the radio is listening in single receive mode.

A single receive window ends after 100 symbols, which is about 102 ms at SF7. The next call of the function opens a new window. This is why the banner of the receiver shows RX SINGLE.

Read the Packet and Its Values

  • LoRa.available() and LoRa.read() return the bytes of the packet one after the other.
  • LoRa.packetRssi() returns the signal strength of the packet in dBm.
  • LoRa.packetSnr() returns the SNR of the packet in dB. It is a number with decimals, so the terminal prints 10.00 and 3.75.

Calculate the Link Budget

A link budget tells us whether the signal at the receiver is strong enough. The model uses four steps, and we can repeat them with a calculator.

Step 1: Calculate the Path Loss

The model uses the free-space loss for the first metre, and then a loss that grows with 30 dB for every ten-fold increase in distance:

Path loss in dB = 20 × log10(4 × pi × f / c) + 30 × log10(distance in metres)

Here, f is the frequency in Hz and c is the speed of light. At 868 MHz, the first part is 31.2 dB. For 2 km, the second part is 30 × 3.30 = 99.0 dB. The path loss at 2 km is therefore 130.2 dB.

Step 2: Calculate the RSSI

RSSI = output power - path loss

  • 100 m: +17 - 91.2 = -74.2 dBm, which is displayed as -74 dBm.
  • 2 km: +17 - 130.2 = -113.2 dBm, which is displayed as -113 dBm.
  • 5 km: the path loss is 31.2 + 111.0 = 142.2 dB, so the RSSI is -125.2 dBm.

Step 3: Calculate the Noise Floor

Noise floor in dBm = -174 + 10 × log10(bandwidth in Hz) + 6

The value -174 dBm is the thermal noise in a bandwidth of 1 Hz, and 6 dB is the noise that the model adds for the receiver. For 125 kHz, the middle part is 51.0 dB. The noise floor is -174 + 51.0 + 6 = -117.0 dBm.

Step 4: Calculate the SNR and Compare

SNR = RSSI - noise floor

  • 100 m: -74.2 + 117.0 = 42.8 dB. The reported value is limited to 10 dB.
  • 2 km: -113.2 + 117.0 = 3.8 dB. SF7 needs -7.5 dB, so the packet is received.
  • 5 km: -125.2 + 117.0 = -8.2 dB. This is below -7.5 dB, so the packet is too weak for SF7.

The weakest signal for a spreading factor is the noise floor plus its lowest SNR. For SF7, this is -117.0 - 7.5 = -124.5 dBm, which the panel shows as -125 dBm.

Calculate the Time on Air

The model uses the time-on-air formula of the chip manufacturer. For our example, we need these values: SF7, 125 kHz, coding rate 4/5, a preamble of 8 symbols, the explicit header, no CRC and a payload of 11 bytes.

  1. The symbol time is 2 to the power of SF, divided by the bandwidth. This is 128 / 125,000 = 1.024 ms.
  2. The preamble needs 8 + 4.25 = 12.25 symbols.
  3. For the payload, we calculate 8 × 11 - 4 × 7 + 28 = 88 and divide it by 4 × 7 = 28. The result of 3.14 is rounded up to 4.
  4. The payload needs 8 + 4 × 5 = 28 symbols. The number 5 comes from the coding rate 4/5.
  5. The packet has 12.25 + 28 = 40.25 symbols, which take 40.25 × 1.024 = 41.2 ms.

A longer message needs more time. At these settings, a payload of 50 bytes needs about 98 ms, and a payload of 255 bytes needs about 395 ms.

Convert the Registers to dBm and dB

  • The chip stores the RSSI of a packet as one byte. For frequencies above 525 MHz, the driver calculates RSSI = register value - 157. At 2 km, the register holds 44, and 44 - 157 = -113 dBm.
  • The chip stores the SNR in steps of 0.25 dB. The driver calculates SNR = register value × 0.25. At 2 km, the register holds 15, and 15 × 0.25 = 3.75 dB.

Calculate the Frequency Setting

The chip uses a 32 MHz crystal. One frequency step is 32 MHz / 524,288 = 61 Hz. For 868 MHz, the driver calculates 868,000,000 × 524,288 / 32,000,000 = 14,221,312 and writes this number into three registers.

Experiments to Try in Proteus

Change one thing at a time and predict the result before you press Run. The results below follow from the model's rules. The supplied project and the distance buttons were tested in Proteus. The package notes list the other cases as tests of the model on a PC, so check them in your own simulation.

Suggested experiments and their expected results
ChangeExpected result
Click 5 km on either panel.The receiver prints nothing, and its TOO WEAK counter increases.
Add LoRa.setSpreadingFactor(8) to both sketches.The link works at 5 km with an SNR of -8.25 dB.
Add LoRa.setSpreadingFactor(8) to one sketch only.Nothing is received, and no counter of the receiver changes.
Add LoRa.setTxPower(20) to the sender.The receiver shows -71 dBm at 100 m, and the link works at 5 km with SF7.
Add LoRa.setSyncWord(0x34) to the sender only.Nothing is received, and the panels show different sync words.
Change LORA_FREQUENCY to 915E6 in one sketch only.Nothing is received, and the panels show different frequencies.
Add LoRa.setSpreadingFactor(12) to both sketches.The sender's banner shows TX - SENDING for about one second for every message.

After each experiment, compare both panels before reading the code again. A difference in frequency, spreading factor, bandwidth or sync word is visible there.

Compile and Load Your Own Arduino Changes

  1. Open Arduino Code/RFM95_Sender/RFM95_Sender.ino or the receiver sketch in Arduino IDE.
  2. Install the LoRa library by Sandeep Mistry. For the same version as the example, copy Arduino Code/libraries/LoRa into your sketchbook's libraries folder.
  3. Select Arduino Uno as the board.
  4. Compile the sketch and use the Export Compiled Binary command.
  5. Select the new application HEX in the Program File property of the correct Arduino.
  6. Restart the simulation.

Remember that the project has two programs. If you change a radio setting, rebuild both sketches and load each HEX into its own board. The package also contains a rebuild script and the AVR core source archive.

Common Problems and Their Solutions

Troubleshooting the RFM95W Proteus simulation
ProblemWhat to check
RFM95TEP is missing from Pick Devices.Check that TEPRFM95.LIB is in the active library folder and restart Proteus.
The module is placed, but its model cannot load.Check TEPSX1278.DLL in MODELS and beside the project.
The panel title shows SX1278 instead of RFM95W.An older TEPSX1278.DLL is installed. Copy the file of this package into MODELS.
The terminal prints LoRa module not responding.Check SCK, MISO, MOSI, NSS and RST, then VCC and GND.
No packets are received.Compare the frequency, the spreading factor, the bandwidth and the sync word on both panels. Check that the receiver shows RX SINGLE.
The TOO WEAK counter increases.Select a shorter distance on both panels, raise the spreading factor or raise the power.
The banner shows OUT OF BAND.Use a frequency that the chip can reach, such as 868E6 or 915E6.
A terminal is blank or unreadable.Check the Program File, the 16 MHz clock, D1/TX to RXD and 9600 baud.

If a problem remains, return to the unmodified project and change one thing at a time. When you ask for help, include both terminal windows and a screenshot of both control panels.

Practical Review and Model Limitations

This library is useful for learning how a LoRa link is configured and how the spreading factor, the bandwidth and the power work together. The two panels show the settings of both radios side by side, and the distance buttons turn the link budget into an experiment that we can repeat.

What the Model Supports

  • The LoRa registers of the chip and its 256-byte buffer.
  • The modes sleep, standby, transmit, continuous receive, single receive and channel activity detection.
  • The interrupt flags and the DIO0 pin.
  • The RSSI and the SNR of every packet.
  • The time on air, the preamble detection and the receive timeout.
  • A range calculation from output power, frequency, distance, bandwidth and spreading factor.

What the Model Does Not Simulate

  • The FSK and OOK modem of the chip.
  • The pins DIO1 to DIO5 and frequency hopping.
  • Collisions between transmitters that send at the same moment.
  • Frequency errors between two crystals.
  • Real antennas, terrain, fading and interference.
  • The supply voltage and the current of the module.

Treat the range values as teaching examples. The range of real hardware depends on the antenna, its height, the surroundings and the local rules for the frequency band, so it must be measured with the actual devices.

More Proteus Libraries of This Series

This library belongs to a series of wireless and RFID libraries for Proteus. Every library has its own control panel and its own tutorial:

Frequently Asked Questions

Can the RFM95W Talk to Our SX1278 Module in Proteus?

Yes, when both use the same frequency and LoRa settings. Both components use the same model file and share one radio band. Remember that each chip has its own frequency range. The SX1278 cannot be tuned to 868 MHz, so a common frequency must lie inside both ranges. The module is explained in our SX1278 LoRa Proteus Library tutorial.

Why Is the SNR Always 10.00 dB at a Short Distance?

The model limits the reported SNR to +10 dB, as real modules do at close range. Use the RSSI to compare short distances.

Why Does the Sender Print a Message That Was Not Received?

The sketch sends a packet without asking for an answer. The sender only knows that the packet has left the radio. If you need a confirmation, the receiver must send a reply packet, and the sender must wait for it.

Which Spreading Factor Should I Use?

Use the lowest spreading factor that gives a reliable link. A higher value reaches further, but it keeps the channel busy for longer and uses more energy for every packet.

Can a Packet Be Missed Although the Signal Is Strong?

The supplied receiver listens in short windows. When a new window starts in the middle of the preamble of a packet, that packet can be missed. For a receiver that must not miss packets, use the continuous receive mode of the driver with its receive callback.

Do I Need to Connect DIO0?

Not for the supplied sketches. They check the radio through SPI. The wire to D2 is needed when you use the receive callback of the driver.

Do I Need Arduino IDE to Run the Supplied Circuit?

No. Both compiled HEX files are included. You need Arduino IDE, or the documented build tools, only when you change a sketch.

That completes our RFM95W LoRa Proteus Library tutorial. Start with the supplied project, watch both panels and then change the distance step by step. Once the RSSI and SNR values make sense, change the spreading factor or the power and compare the results with your own calculation. Share your questions and simulation results in the comments below.


Comments

0

Join the conversation