
RFM95W LoRa Library for Proteus V1.1 (868/915 MHz + Arduino)

Hello friends, I hope you all are doing great. Today, I am going to share the new RFM95W LoRa Library for Proteus V1.1. The RFM95W is HopeRF's small green LoRa module with the Semtech SX1276 chip, a favourite for long-range sensors on the 868 MHz and 915 MHz bands. With this RFM95W LoRa Library for Proteus, two modules in one design talk over a simulated 868 MHz air, and your Arduino drives them over SPI with the same arduino-LoRa library you use on real hardware.
Version 1.1 replaces the first version of this post. You now get two devices: RFM95W Simple, with its control panel on the schematic, and RFM95W Advance, with a pop-up window and four measured LoRa test tools. The new RFM95W Arduino Proteus demo has two Arduino UNOs that send packets, PING each other and change the spreading factor from the keyboard, shown in the compact Simple interface of our TEP Serial Monitor. Have you read version 1.0? Then jump to "What's New" below.
NOTICE: This library is very special to our team. Our RFM95W model has the SX1276's LoRa registers, its 256-byte FIFO, the IRQ flags and the real LoRa time on air, and it works out the signal level and the SNR at every distance up to 20 km. It took our team a lot of hard work, many test runs and many design changes. Your feedback is the fuel that keeps us going, so please tell us what you think in the comments below or in the RFM95W Library board of our forum. And if our free libraries help you, you can buy us a coffee. So, let's get started with the RFM95W LoRa Library for Proteus:
What is the RFM95W LoRa Module?
The RFM95W is a radio transceiver (it sends and receives) made by HopeRF around the Semtech SX1276 chip. It speaks LoRa, short for "Long Range", which trades speed for distance: a few hundred bytes per second, but kilometres of range from a battery-powered sensor. The Arduino talks to the chip over SPI, a 4-wire bus (clock, data in, data out and chip select), plus a reset pin and DIO0, which signals "packet sent" or "packet received".
The module is a 16 x 16 mm green board without a shield can: the SX1276, a 32 MHz crystal, a small RF switch and half-hole pads on two edges, one of them for the antenna. For 433 MHz, use the Ra-02 and our SX1278 LoRa Library for Proteus.
The RFM95W at a Glance
| Feature | Value |
|---|---|
| Chip | Semtech SX1276: a LoRa modem, plus an FSK / OOK modem that our model does not simulate |
| Frequency | 868 MHz (Europe) or 915 MHz (USA, Australia); the chip tunes 137 - 1020 MHz |
| TX power | +2 to +20 dBm on the PA_BOOST output; the demo uses +17 dBm, the arduino-LoRa default |
| LoRa settings | Spreading factor 6 - 12, bandwidth 7.8 - 500 kHz, coding rate 4/5 - 4/8 |
| Sensitivity | Down to -148 dBm at the slowest settings (datasheet); -125 dBm at the demo's SF7 / 125 kHz |
| Packets | A 256-byte FIFO; explicit or implicit header, optional CRC |
| Supply | 1.8 - 3.7 V; the pins are NOT 5 V tolerant |
| Interface | SPI plus RESET and DIO0 (DIO1 - DIO5 exist, but are not modelled) |
RFM95W, SX1278, SX1262, CC1101 or nRF24L01: Which Library Do You Need?
| Your module | What it does | Our library |
|---|---|---|
| RFM95W (HopeRF, green board, wire antenna) | 868 / 915 MHz LoRa, SPI | This article |
| SX1278 / Ra-02 (Ai-Thinker, silver can) | 433 MHz LoRa, SPI | SX1278 LoRa Library for Proteus |
| SX1262 (Ebyte E22) | 868 MHz LoRa up to +22 dBm, SPI, RadioLib | SX1262 LoRa Library for Proteus |
| CC1101 (green D-SUN board, spring antenna) | 315 / 433 / 868 / 915 MHz FSK and OOK, SPI | CC1101 Library for Proteus |
| RFM69HCW | 315 / 433 / 868 / 915 MHz FSK with ACKs, SPI | RFM69HCW Library for Proteus |
| nRF24L01 | 2.4 GHz, SPI, short range | nRF24L01 Library for Proteus |
| HC-12 | 433 MHz wireless serial module (UART) | HC-12 Library for Proteus |
The RFM95W, Ra-02 and SX1262 share one model file, so they even talk to each other in one design. All of them are compared in our RF Module Libraries for Proteus roundup.
Radio Terms You Will See in This Article
| Term | Meaning |
|---|---|
| LoRa | Semtech's long-range modulation: every symbol is a chirp, a tone that sweeps across the bandwidth |
| Spreading factor (SF) | SF7 to SF12: how long one chirp is; each step doubles it and reaches further |
| Bandwidth (BW) | How wide the chirp sweeps: 125 kHz in the demo; narrower is slower and reaches further |
| Coding rate (CR) | Extra bits for error correction: 4/5 sends 5 bits for every 4 data bits |
| dBm | Power compared to 1 mW: 0 dBm = 1 mW, +17 dBm = 50 mW, and every 10 dB is a factor of 10 |
| RSSI | Received Signal Strength Indicator: the level of a packet in dBm |
| SNR | Signal-to-noise ratio in dB: how far the signal stands above (+) or below (-) the noise |
| Noise floor | The noise every receiver hears anyway: about -117 dBm at 125 kHz |
| Sensitivity | The weakest signal the receiver can still decode at its SF and bandwidth |
| Sync word | One byte (0x12 in the demo) that separates networks on the same frequency |
| Explicit header | A short header that tells the receiver the length, coding rate and CRC setting |
| Time on air | How long one packet keeps the transmitter on |
| Duty cycle | The share of time a transmitter is on the air; Europe allows 1 % at 868.0 - 868.6 MHz |
| LDRO | Low data rate optimisation: switched on for very long symbols (over 16 ms) |
| PA_BOOST | The RFM95W's power amplifier output that feeds the antenna |
How Two RFM95W Radios Talk: LoRa Chirps, SF and Bandwidth
In the demo, the chip does the radio work, and the sketch only hands it a message and reads the result. One packet, step by step:
beginPacket()andprint()write "hello TEP 0" into the 256-byte FIFO.endPacket()starts the transmitter and waits until the chip reports TxDone.- The chip sends 8 preamble chirps, the sync word, the explicit header and the 11 data bytes: 41.2 ms at SF7 / 125 kHz.
- A receiver on the same frequency, SF, bandwidth and sync word decodes the packet and stores its RSSI and SNR.
- The chip raises RxDone (also on DIO0), and the sketch's
parsePacket()sees it over SPI and reads the packet.
Notice what is missing: an ACK. LoRa never answers "got it" by itself, so the sender cannot know whether anybody heard it. The PING and PONG of the v1.1 demo add a reply.
Spreading Factor: Longer Chirps Reach Further
A LoRa symbol is a chirp: a tone that sweeps across the bandwidth, and the data sits in where the sweep starts. The spreading factor sets how long a chirp is: SF7 takes 1.024 ms at 125 kHz, and every step up doubles it. A longer chirp carries more energy, so the receiver digs deeper into the noise: each step lowers the SNR it needs by 2.5 dB, from -7.5 dB at SF7 to -20 dB at SF12. The price is time: a 12-byte packet is on the air for 41.2 ms at SF7, but for 991.2 ms at SF12.
Bandwidth and Coding Rate
The bandwidth is how wide the chirp sweeps. 125 kHz is the usual choice; 250 or 500 kHz is faster, but lets in more noise and reaches less far. The coding rate adds error-correction bits: 4/5 (the demo) sends 5 bits for every 4 data bits. The explicit header tells the receiver the coding rate, so it need not match; the frequency, SF, bandwidth, sync word, header mode and IQ setting must.
RSSI and SNR: Why LoRa Hears Below the Noise
Every received packet carries two numbers. The RSSI is its level in dBm. The SNR compares it with the noise floor, the noise every receiver hears anyway: about -117 dBm at 125 kHz. At 100 m, the demo's packets arrive at -74 dBm, far above the noise; the chip reports at most +10 dB, so you see "SNR 10.00 dB". At 5 km, a packet arrives at -125 dBm, 8 dB below the noise. That is LoRa's trick: SF8 still decodes it, because SF8 works down to an SNR of -10 dB.
SF and Range: The Link Budget
The level at the receiver is the TX power minus the path loss. Our model uses free-space loss for the first metre (31.2 dB at 868 MHz) and a path-loss exponent of 3 beyond it, like a built-up area: 30 dB more for every 10 times the distance. The sensitivity is the noise floor plus the SNR the SF needs. With the demo's +17 dBm at SF7:
- 100 m: 31.2 + 60 = 91.2 dB, so +17 - 91.2 = -74 dBm. SF7 needs -117 - 7.5 = -124.5 dBm, so the link is OK with +50.3 dB to spare.
- 2 km: -113 dBm, SNR +3.8 dB: still OK.
- 5 km: -125.2 dBm, SNR -8.2 dB: 0.7 dB too weak for SF7, but OK at SF8, which needs -127 dBm.
So SF7 reaches about 4.8 km and SF12 about 12.4 km at +17 dBm. 868 MHz loses 6 dB more than 433 MHz, which is why a Ra-02 at 433 MHz reaches further with the same settings.
Time on Air and the 1 % Duty-Cycle Rule
In Europe, a transmitter in the 868.0 - 868.6 MHz band may be on the air only 1 % of the time, at up to 25 mW e.r.p. A 12-byte packet at SF7 takes 41.2 ms, so you must wait at least 99 x 41.2 ms = 4.08 s before the next one: at most 873 packets per hour. At SF12, the same packet takes 991.2 ms, and only 36 fit in an hour. More range means fewer messages.
In the USA (902 - 928 MHz) and Australia, the RFM95W runs at 915 MHz instead. The USA limits the dwell time on one channel to 400 ms, so a 12-byte packet at SF11 or SF12 / 125 kHz (577.5 or 991.2 ms) is too long there. The Time on air tool of the Advance device shows the rule for your frequency.
Sync Word and Why Both Nodes Must Match
A receiver accepts only packets with its own sync word. The demo uses 0x12, the "private" default of arduino-LoRa; public LoRaWAN networks use 0x34. So two RFM95W radios form a link only when they agree on the frequency (within a quarter of the bandwidth), the SF, the bandwidth, the sync word, the IQ setting and the header mode. That is why the SF and BW commands of the demo must be typed on both monitors.
What's New in RFM95W LoRa Library for Proteus V1.1
If you used version 1.0, here is what has changed:
- Two devices in
TEPRFM95.LIB: RFM95W Simple (RFM95TEP, the v1.0 device, so old designs keep working) and RFM95W Advance (RFM95ADVTEP) with a pop-up window. - A redrawn board: HopeRF's green, can-less RFM95W instead of v1.0's black carrier; the 8 pins stay where they were.
- A live antenna and three LEDs: the wire glows orange while sending and green while receiving. PWR, TX and RX are a TEP addition: the real module has no LEDs.
- Close and reopen: a red X and a PANEL button on the Simple, OPEN PANEL on the Advance.
- Four measured test tools (Advance): Link test, Time on air, Range and Registers.
- Model: each radio records its packets and SPI accesses for the tools; the air, the link budget and the DISTANCE buttons are unchanged (100 m: -74 dBm, SNR 10 dB).
- A two-UNO demo with the TEP Serial Monitor instead of Virtual Terminals. The sketches keep every v1.0 output line and add commands (SEND, PING, STATUS, SF, BW, PWR, AUTO, HELP) and a link line every 10 s.
- Lighter package: about 1.5 MB, without the C++ source code (v1.0: about 7.4 MB).
A v1.0 design keeps its old symbol: new model, but no new board, LEDs or red X. Before a sketch runs, its panel shows the chip's reset values:
RFM95W LoRa Library for Proteus: Simple vs Advance
Both devices run the same model; only the panel differs:
| Feature | Simple | Advance |
|---|---|---|
| Full SX1276 LoRa model (SPI, registers, FIFO, IRQ flags, DIO0, RX single / continuous, CAD, real time on air) | ✔ | ✔ |
| Green HopeRF board, glowing wire antenna and PWR / TX / RX LEDs | ✔ | ✔ |
| DISTANCE buttons 10 m - 20 km and the link-budget verdict | ✔ | ✔ |
| Control panel on the schematic (mode, settings, counters, last packet) | ✔ | ✘ |
| Pop-up window you can move, resize and minimise | ✘ | ✔ |
| Radio page: what the sketch set, traffic, distance and reach | ✘ | ✔ |
| Link test, Time on air, Range and Registers | ✘ | ✔ |
| TEP Dark / Light theme, text size, Help page with Copy diagnostics | ✘ | ✔ |
| Same device name as v1.0 (old designs keep working) | ✔ | ✘ |
Choose Simple to keep the radio's state beside your circuit, and Advance for hard numbers about your link. The demo has one of each, and the two talk to each other.
Download RFM95W LoRa Library for Proteus
Click the button below to download RFM95-LoRa-Library-for-Proteus-v1.1.zip (about 1.5 MB, without the C++ source code):
RFM95W LoRa Library for Proteus V1.1- README.txt: a detailed guide to the files, the wiring, the model, the test tools and real hardware.
- Proteus Library Files:
TEPRFM95.LIB(both devices),TEPSERIALMON.LIBand our Arduino UNO libraryArduinoV3TEP.LIB/ArduinoV3TEP.IDX. - Proteus Model Files:
TEPSX1278.DLL, our LoRa family model, andTEPSERIALMON.DLL. - Proteus Simulation:
RFM95-ArduinoUnoV3.pdsprj,RFM95_Sender.hex,RFM95_Receiver.hexand copies of both DLLs. - Arduino Code:
RFM95_Sender.ino,RFM95_Receiver.inoand the arduino-LoRa library 0.8.0 by Sandeep Mistry, unmodified, under the MIT License with its LICENSE file.
Why TEPSX1278.DLL? One model serves all our LoRa libraries and is named after the first one; the RFM95W, SX1278 and SX1262 packages ship the identical file. No Proteus yet? Read How to Download and Install Proteus 7 and 8. New to libraries? Follow How to Install a New Library in Proteus.
How to Install RFM95W LoRa Library for Proteus
- Close Proteus and extract the whole zip file.
- Copy the four files from Proteus Library Files into the LIBRARY folder, usually
C:\Program Files (x86)\Labcenter Electronics\Proteus 8 Professional\LIBRARY(on some PCsC:\ProgramData\Labcenter Electronics\Proteus 8 Professional\LIBRARY). - Copy
TEPSX1278.DLLandTEPSERIALMON.DLLinto the MODELS folder. - Start Proteus, press P and search for RFM95. You get the Simple and the Advance device (category Peripherals > Wireless).
Updating from v1.0? Replace TEPRFM95.LIB and TEPSX1278.DLL, and delete TEPRFM95.IDX if there is one in LIBRARY. A v1.0 design keeps its v1.0 symbol and runs with the new model; re-pick the part to get the v1.1 board. If a panel title says SX1278 instead of RFM95W, an old DLL is still in MODELS. Tested in Proteus 8.5; Proteus 7 is not supported.
The RFM95W Board in Proteus
We designed the module as a clean TEP board after HopeRF's own RFM95W: a square green board with the SX1276, the silver 32.000 MHz crystal, the RF switch, a gold RF trace and the quarter-wave wire antenna. At the bottom sit the board button, three LEDs, a SIMPLE or ADVANCE badge and the 8 pins. Here is U1, the Simple device, while it sends:
The wire glows orange, and the waves ripple out. PWR and TX are lit; RX blinks only when a packet comes back. On U2, the Advance device, the wire and the waves turn green when a packet arrives:
Pinout
The eight Proteus pins keep the v1.0 order and the arduino-LoRa default wiring. The real RFM95W has 16 half-hole pads, with DIO1 - DIO5 and extra grounds, so on real hardware always wire by the names:
| Pin | Function | Demo connection |
|---|---|---|
| VCC | Power (3.3 V on a real module) | Supply terminal |
| GND | Ground | GND |
| SCK | SPI clock from the Arduino | Arduino D13 |
| MISO | SPI data from the radio | Arduino D12 |
| MOSI | SPI data to the radio | Arduino D11 |
| NSS | SPI chip select, active LOW | Arduino D10 |
| RST | Reset, active LOW (LoRa.begin() pulses it) | Arduino D9 |
| DIO0 | RxDone / TxDone signal (for interrupt sketches; the demo polls over SPI) | Arduino D2 |
Wire Antenna, LEDs and Waves
| Indicator | What it shows |
|---|---|
| PWR LED (red) | Lit while VCC and GND are connected |
| TX LED (orange) | Blinks for every packet sent |
| RX LED (green) | Blinks for every packet received |
| Wire antenna | Copper at rest, orange while sending, green while receiving |
| Waves above the wire | Ripple out while sending, in while receiving |
| PANEL / OPEN PANEL, SIMPLE / ADVANCE | The panel button and the device badge |
Each blink is held 0.3 - 0.4 s, so you see it even for a 31 ms PONG. There are no properties to edit: your sketch sets the radio over SPI, as on the real chip, and you choose the DISTANCE on the panel (100 m at every Run).
RFM95W Simple: The Control Panel on the Sheet
Beside the Simple board, the RFM95W LoRa CONTROLS panel shows what the radio is doing, without one debug line in your sketch. In the board picture above, U1 shows RX SINGLE, SENT 10, RECEIVED 1 and the PONG of my PING test at -74 dBm:
| Part | What it shows |
|---|---|
| Header, red X | RFM95W LoRa CONTROLS; the X closes the panel |
| Mode bar | RX SINGLE or RX CONTINUOUS (green), TX - SENDING (orange), STANDBY, SLEEP or CAD (blue), NO POWER or OUT OF BAND (red) |
| Settings line 1 | 868.000 MHz SF7 BW 125 kHz CR 4/5: what the sketch wrote |
| Settings line 2 | SYNC 0x12 CRC OFF EXPLICIT +17 dBm |
| Counters | SENT, RECEIVED, TOO WEAK (CRC ERR appears after the first CRC error) |
| LAST PACKET | RSSI and SNR of the last packet received, then its text and length |
| DISTANCE TO THE OTHER RADIOS | 10 m, 100 m, 1 km, 2 km, 5 km, 10 km, 15 km, 20 km |
| Verdict | AT 100 m: -74 dBm, SF7 NEEDS -125 dBm -> OK |
| Hint | CLICK A DISTANCE - HIGHER SF REACHES FURTHER |
Why the Sender Says RX SINGLE
U1 is the sender, yet its bar says RX SINGLE. That is correct: the v1.1 sender calls parsePacket() between its packets, so node 2 can PING it or SEND it a message. A hello packet takes 41 ms every 2 s, so the panel rarely catches TX - SENDING, but the TX LED and the orange wire show every one.
DISTANCE: 5 km Is TOO WEAK at SF7
Now click 5 km on the panel of U1. The verdict turns to TOO WEAK:
"-125 dBm, needs -125 dBm" looks odd, but both numbers are rounded: the signal misses the SF7 limit by 0.7 dB. From now on, U4 stays silent while U3 keeps printing "Sending packet: n": without an ACK, the sender never notices. The link uses the larger of the two radios' DISTANCE settings, so bringing them back needs a short distance on both.
Higher SF Reaches Further: SF 8 at 5 km
The hint at the bottom of the panel says it: a higher SF reaches further. Leave the distance at 5 km and type SF 8 in the send box of BOTH Serial Monitors (one node alone would break the link). The panel of U1 now shows SF8, and the verdict says OK:
On U4, the packets come back:
Received packet 'hello TEP 12' with RSSI -74 dBm, SNR 10.00 dB
Link (10 s): 3 received, RSSI -74 dBm avg, SNR 10.0 dB avg, 0 sent
SF 8
Spreading factor SF8 - set node 1 to the same SF
Received packet 'hello TEP 16' with RSSI -125 dBm, SNR -8.25 dB
Received packet 'hello TEP 17' with RSSI -125 dBm, SNR -8.25 dB
Packets 13 to 15 were lost: too weak at SF7, or sent while only one node was at SF8. From 16 on, every packet arrives at -125 dBm with an SNR of -8.25 dB: below the noise, but above the SF8 limit of -10 dB, and 72.2 ms long instead of 41.2 ms. To go back, click 100 m and type SF 7 on both monitors.
Closing the Panel
Need room on the sheet? Click the red X. The board button says PANEL: CLOSED with a grey dot, while the radio and the sketch keep running. Click PANEL to bring it back.
RFM95W Advance: The Pop-Up Window
The Advance device keeps only the board on the schematic. At Run, the "TEP RFM95W Advance" pop-up opens with the look of our Serial Monitor and no Windows title bar: move it by its header, resize or minimise it, and reopen it with OPEN PANEL. The header shows the state (U2 · RX) and the Radio and Test tabs; the blue status bar counts TX, RX and too-weak packets.
The Radio Page
- RADIO - WHAT THE SKETCH SET: 868.000 MHz, +17 dBm, sync word 0x12 (private), 8 preamble symbols of 1.024 ms; SF7, BW 125 kHz, CR 4/5; sensitivity -125 dBm; explicit header, CRC off; LDRO off, IQ normal.
- TRAFFIC: 1 sent (the 4-byte PONG, 31.0 ms on air), 29 received, 2 too weak from my 5 km test; the last, "hello TEP 31", at -74 dBm and SNR 10.0 dB.
- DISTANCE: the eight buttons, "OK (+50.3 dB)" and my favourite line, "These settings reach about 4.8 km; SF12 would reach 12.4 km".
The Test Page: Four Measured LoRa Test Tools
Every number on the Test tab is measured on the running model, and each tool ends with a "Good for:" line.
1. Link Test: How Far Does Your Link Reach?
Choose 10, 20 or 50 packets and click Run test. The tool records the next real packets this radio sends or hears: decoded, CRC error, too weak or nobody heard it, with RSSI, SNR and time on air. The DISTANCE buttons sit on the tool, too. 10 packets at 100 m:
U2 heard 10 packets from U1, all decoded; every green bar stands far above the dashed "SF7 needs -125 dBm" line. Click 5 km during a test, and the bars turn red. Below, the tool lists the link budget at every distance and the lowest SF that still works there:
| Distance | RSSI | SNR | At SF7 | Lowest SF that works |
|---|---|---|---|---|
| 10 m | -44 dBm | 10.0 dB | OK +80 dB | SF7 · 41.2 ms |
| 100 m | -74 dBm | 10.0 dB | OK +50 dB | SF7 · 41.2 ms |
| 1 km | -104 dBm | 10.0 dB | OK +20 dB | SF7 · 41.2 ms |
| 2 km | -113 dBm | 3.8 dB | OK +11 dB | SF7 · 41.2 ms |
| 5 km | -125 dBm | -8.2 dB | TOO WEAK -1 dB | SF8 · 72.2 ms |
| 10 km | -134 dBm | -17.2 dB | TOO WEAK -10 dB | SF11 · 577.5 ms |
| 15 km | -140 dBm | -22.5 dB | TOO WEAK -15 dB | none (even SF12 is too weak) |
| 20 km | -143 dBm | -26.2 dB | TOO WEAK -19 dB | none (even SF12 is too weak) |
Look at the SNR column: it stays at +10 dB up to 1 km, because the chip reports no more, and drops below zero from 5 km on. Good for: seeing how far your link reaches and how strongly each packet arrives.
2. Time on Air: How Long Is One Packet?
This tool does not use your sketch. Two model radios in a private test air send one packet for every SF from 7 to 12 at 125, 250 and 500 kHz, with 12, 32, 64 or 255 bytes, and time it from TX start to TxDone, with Semtech's formula (AN1200.13) beside it. 12 bytes:
The measured 41.22 ms matches the formula exactly. Each SF step doubles the time, and each doubling of the bandwidth halves it, from 10.3 ms (SF7, 500 kHz) to 991.2 ms (SF12, 125 kHz). LDRO marks the cells where a symbol lasts over 16 ms.
The second card applies the rule of your frequency: "EU 868.0-868.6 MHz: 1 % duty cycle, 25 mW e.r.p.", so wait at least 4.08 s between packets, at most 873 per hour. It also measures real traffic: U2's last packet, the PONG, took 30.98 ms, and the last one it heard, 12 bytes from U1, 41.22 ms. Good for: choosing the SF and bandwidth for your message size and the legal duty cycle.
3. Range: Which SF Reaches How Far?
Run test sends one 12-byte packet per SF at each of the 8 DISTANCE steps between two model radios, at this radio's bandwidth and power. Green cells were decoded, red ones too weak:
SF7 decodes up to 2 km (link budget 4.8 km), SF8 to SF10 up to 5 km, and SF11 and SF12 up to 10 km; 15 and 20 km stay red. The second card compares the TEP LoRa modules at their maximum power:
| Module | SF7 | SF9 | SF12 |
|---|---|---|---|
| This radio (+17 dBm, 868 MHz) | 4.8 km | 7.0 km | 12.4 km |
| Ra-02, 433 MHz, +20 dBm | 9.5 km | 14.0 km | 24.8 km |
| RFM95W, 868 MHz, +20 dBm | 6.0 km | 8.8 km | 15.6 km |
| SX1262, 868 MHz, +22 dBm | 7.0 km | 10.2 km | 18.2 km |
With PWR 20, your RFM95W gains 3 dB and reaches 15.6 km at SF12. Good for: picking the spreading factor that reaches the distance you need.
4. Registers: What Did Your Sketch Write?
This tool reads the SX1276 registers live, as an SPI read would, decodes them and lists the Arduino's last SPI accesses:
- RegOpMode 86: LoRa mode, RX SINGLE. RegFrf D90000: 14,221,312 steps of 61 Hz (32 MHz / 524288) = 868.000 MHz; the 32 MHz crystal sets the step.
- RegPaConfig 8F, RegOcp 2B: PA_BOOST at +17 dBm, over-current protection at 100 mA.
- RegModemConfig1 72, 2 70, 3 04: BW 125 kHz, CR 4/5, explicit header; SF7, CRC off; LDRO off, AGC on.
- RegPktRssi / Snr 53 28, RegRssiValue 28, RegVersion 12: the last packet at -74 dBm and 10.0 dB, -117 dBm right now (the noise floor) and the chip ID that
LoRa.begin()checks.
Read the SPI log from the bottom up, and you watch parsePacket() at work: read RegIrqFlags (00: no packet yet), read and rewrite RegModemConfig1, clear RegIrqFlags, read RegOpMode (86: still listening), and again, 46,614 SPI transactions per second. At the bottom, U1 is marked PARTNER (LISTENING); a mismatch would be marked red. Good for: checking what your sketch really wrote into the radio.
Settings and Help
The gear opens Settings: theme (TEP Dark or Light), text size, open the panel at Run and window size, saved for your Windows user.
The ? icon opens Help & Support: eight cards and Copy diagnostics for a bug report. Report a bug and Suggest a feature open the RFM95W board of our forum; Read the article, User guide and Check for updates open this article; the other three open the donate page, our website and the forum. A links.ini next to the DLL can change the links.
RFM95W LoRa Link with Arduino in Proteus
Open RFM95-ArduinoUnoV3.pdsprj from the Proteus Simulation folder, with the .hex files and the DLLs beside it. It has two Arduino UNOs from our Arduino Library for Proteus V3.0 (the first image shows the whole circuit):
- NODE 1 - SENDER: UNO 1 (ARD1) with
RFM95_Sender.hex, the RFM95W Simple (U1) and Serial Monitor U3. - NODE 2 - RECEIVER: UNO 2 (ARD2) with
RFM95_Receiver.hex, the RFM95W Advance (U2) and Serial Monitor U4.
Wiring
| From | To | Why |
|---|---|---|
| RFM95W VCC / GND | Supply / ground | Power (+5 V in the simulation; a real module needs 3.3 V) |
| RFM95W SCK | Arduino D13 | SPI clock |
| RFM95W MISO | Arduino D12 | Data from the radio |
| RFM95W MOSI | Arduino D11 | Data to the radio |
| RFM95W NSS | Arduino D10 | Chip select |
| RFM95W RST | Arduino D9 | Reset at start-up |
| RFM95W DIO0 | Arduino D2 | RxDone / TxDone |
| Serial Monitor RXD / TXD / GND | Arduino D1 / D0 / ground | Shows what the Arduino prints, sends what you type |
These are the default pins of arduino-LoRa, so no LoRa.setPins() is needed; D11 - D13 are the UNO's hardware SPI pins (see our Introduction to Arduino UNO). No wire joins the two nodes: they share one simulated air.
The Arduino Code
Both sketches use the unmodified arduino-LoRa library (its object is LoRa). One line at the top picks the band, and it must be the same in both sketches:
#define LORA_FREQUENCY 868E6 // 868 MHz (EU band); use 915E6 for US/AU 915 MHz, check your local band plan
Change it to 915E6 for the USA or Australia and rebuild both sketches; STATUS then prints 915.000 MHz (the start-up banner is a fixed text). setup() starts the radio:
if (!LoRa.begin(frequency)) {
Serial.println(F("LoRa module not responding - check the SPI wiring and power"));
while (true) {}
}
LoRa.begin() pulses RST, checks RegVersion (0x12) and sets the frequency and +17 dBm. SF7, 125 kHz, CR 4/5 and the sync word 0x12 are the chip's reset values, which arduino-LoRa keeps. While AUTO is ON, the sender sends the v1.0 message every 2 s:
if (autoSend && millis() - lastSend >= 2000) {
lastSend = millis();
sendHello();
}
LoRa.beginPacket();
LoRa.print("hello TEP ");
LoRa.print(counter);
LoRa.endPacket();
endPacket() returns after TxDone, so for SEND, PING and PONG the sketches time it to get the time on air:
unsigned long transmit(const char* text) {
LoRa.beginPacket();
LoRa.print(text);
unsigned long start = micros();
LoRa.endPacket();
unsigned long us = micros() - start;
Both sketches read packets with the same function; parsePacket() also keeps the radio listening between calls:
bool readPacket(char* text, byte size) {
int packetSize = LoRa.parsePacket();
if (!packetSize) return false;
byte n = 0;
while (LoRa.available()) {
char c = (char)LoRa.read();
if (n < size - 1) text[n++] = c;
}
text[n] = 0;
lastRssi = LoRa.packetRssi();
lastSnr = LoRa.packetSnr();
The receiver prints the v1.0 line for every packet:
Serial.print(F("Received packet '")); // the v1.0 output line
Serial.print(text);
Serial.print(F("' with RSSI "));
Serial.print(lastRssi);
Serial.print(F(" dBm, SNR "));
Serial.print(lastSnr);
Serial.println(F(" dB"));
A PING is answered before anything is printed, so the round trip measures the radios, not the 9600-baud Serial port:
bool ping = strcmp(text, "PING") == 0;
if (ping) transmit("PONG"); // answer first (the round trip), print afterwards
The node that sent the PING waits 500 ms plus three times the PING's own time on air, so the test works at SF12, too:
unsigned long air = transmit("PING");
unsigned long waitMs = 500 + 3 * (air / 1000); // the PONG takes about as long as the PING on air
SF, BW and PWR call the matching arduino-LoRa functions, for example:
spreadingFactor = sf;
LoRa.setSpreadingFactor(sf);
txPower = dbm;
LoRa.setTxPower(dbm);
To change a sketch, install "LoRa" by Sandeep Mistry from the Library Manager (or copy Arduino Code\libraries\LoRa), export the compiled binary and load the new HEX file into its UNO; see How to get the HEX file from Arduino. New to Arduino? Start with our Arduino Tutorial for Beginners.
Serial Monitor Commands
| Command | What it does |
|---|---|
| HELP | The command list |
| STATUS | Frequency, SF, bandwidth, coding rate, sync word, power, counters and the last packet's RSSI / SNR |
| SEND <text> | A message to the other node now (up to 42 characters) |
| PING | The other node answers PONG; prints the round trip time |
| SF <7-12> | The spreading factor, for example SF 9 (type it on both monitors) |
| BW <kHz> | The bandwidth: 7.8, 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125, 250 or 500 (both monitors) |
| PWR <2-20> | The TX power in dBm |
| AUTO <ON|OFF> | Node 1 only: the hello TEP packet every 2 s |
How to Run the Demo
- Press Run. Both Serial Monitors (9600 baud) and the pop-up of U2 open, and the hello packets start.
- Type PING and STATUS on U3.
- Click 5 km on the panel of U1, then type SF 8 on both monitors. Back: 100 m and SF 7.
- Close the panel of U1 with its red X and open it again with PANEL.
- Run the four tools on the Test tab of U2.
RFM95W Proteus Simulation Results
The Serial Monitor in Its Simple Interface
Both monitors in this demo run in the Simple interface of our TEP Serial Monitor, and every monitor screenshot in this article shows them that way. Only the log, the send box and one slim toolbar row stay visible (baud rate, follow, pause, search and clear). The header, the quick buttons and the status bar are hidden, so the window stays small next to your schematic.
- Switch to it: right-click the log and choose Simple interface, or press Ctrl+Shift+U.
- Back to the full view: click the corner button (the expand arrows at the top right), press Esc or Ctrl+Shift+U, or right-click and choose Full interface.
- Your choice is remembered.
Type commands such as PING, STATUS or SF 8 in the send box and press Enter; the quick buttons come back with the full view. RXD2, the monitor's second input, is not used: the RFM95W talks SPI and has no serial line to watch. Read all about the monitor in TEP Serial Monitor Advance for Proteus.
Start-Up: hello TEP Arrives
After Run, U4 prints its banner, and a packet arrives every 2 s:
TEP RFM95W LoRa Receiver Demo v1.1
Listening: 868 MHz, SF7, 125 kHz, CR 4/5, sync 0x12
Type HELP in the Serial Monitor for the commands
Received packet 'hello TEP 0' with RSSI -74 dBm, SNR 10.00 dB
Received packet 'hello TEP 1' with RSSI -74 dBm, SNR 10.00 dB
Received packet 'hello TEP 2' with RSSI -74 dBm, SNR 10.00 dB
Received packet 'hello TEP 3' with RSSI -74 dBm, SNR 10.00 dB
Every packet arrives at -74 dBm with SNR 10.00 dB, the 100 m numbers. U3 prints "Sending packet: 0", 1, 2 ... at the same pace, and every 10 s both nodes add a link line.
Typing Commands: PING, PONG and STATUS
Now U3, the sender. I typed PING, pressed Enter, then STATUS. Lines you send carry a blue TX tag, the Arduino's lines a green RX tag:
Sending packet: 3
PING
PING: PONG from node 2 after 63.6 ms (RSSI -74 dBm, SNR 10.00 dB)
Sending packet: 4
STATUS
Status: 868.000 MHz, SF7, BW 125 kHz, CR 4/5, sync 0x12, +17 dBm
sent 6, received 1, auto-send ON (every 2 s)
last packet: RSSI -74 dBm, SNR 10.00 dB
Sending packet: 5
Link (10 s): 7 sent, 1 received, RSSI -74 dBm avg
PONG came back after 63.6 ms: two 4-byte packets of 31 ms each at SF7, plus the SPI time of both UNOs. A CC1101 at 100 kBaud does the same in 4.4 ms: LoRa buys its range with time. The STATUS counters tell my run: 6 sent (packets 0 to 4 plus the PING) and 1 received, the PONG. On U4, the PING arrives like any message:
Received packet 'hello TEP 3' with RSSI -74 dBm, SNR 10.00 dB
Received packet 'PING' with RSSI -74 dBm, SNR 10.00 dB
-> PONG sent back
Received packet 'hello TEP 4' with RSSI -74 dBm, SNR 10.00 dB
Link (10 s): 6 received, RSSI -74 dBm avg, SNR 10.0 dB avg, 1 sent
Received packet 'hello TEP 5' with RSSI -74 dBm, SNR 10.00 dB
The link line counts the PING among the 6 packets received and the PONG as 1 sent. Try SEND Hello from node 2 on U4, too: U3 prints it with its RSSI and SNR.
Troubleshooting
- "LoRa module not responding - check the SPI wiring and power": check SCK D13, MISO D12, MOSI D11, NSS D10, RST D9 and VCC / GND, and TEPSX1278.DLL in MODELS and beside the project.
- The panel title says SX1278: an old TEPSX1278.DLL (SX1278 v1.0) is installed; copy this package's DLL to MODELS.
- Nothing received: both sketches need the same LORA_FREQUENCY, SF, bandwidth and sync word (the Registers tool lists what does not match), and both DISTANCE settings count.
- PING prints "no PONG": the same checks; node 1 listens only between its packets, so a PING from U4 works best with AUTO OFF on node 1.
- No monitor window or no pop-up: a DLL is missing; click OPEN MONITOR on the monitor part or OPEN PANEL on the board.
- No red X / the old black board: replace the LIB, delete TEPRFM95.IDX and re-pick the part.
- Your own sketch: hardware SPI works on the UNO in Proteus 8.5; only pin-change interrupts never fire there, so SoftwareSerial cannot receive (not needed here).
Things to Know Before Using a Real RFM95W
The demo sketches use only arduino-LoRa, so they run on two real UNOs and modules, too. Keep in mind:
- 3.3 V only: feed VCC from 3.3 V, never from 5 V. In the simulation, VCC goes to +5 V, because the model only checks that it is powered.
- Level shifting: the RFM95W's pins are NOT 5 V tolerant. On a 5 V UNO, Nano or Mega, put a level shifter on SCK, MOSI, NSS and RST, or use a 3.3 V board. A 10 - 100 uF capacitor at VCC helps at +20 dBm.
- Antenna first: fit the wire (8.2 cm at 868 MHz, 7.8 cm at 915 MHz) or an SMA / U.FL antenna before you transmit; sending into a missing antenna can destroy the power amplifier.
- The right band: the RFM95W is the 868 / 915 MHz part; for 433 MHz, use the RFM98W or a Ra-02.
- Europe: 868.0 - 868.6 MHz allows 1 % duty cycle at 25 mW e.r.p., about +14 dBm (869.4 - 869.65 MHz: 10 %). The demo sends 41.2 ms every 2 s (about 2 %) at +17 dBm; on real hardware, type PWR 14 and send at most every 4.08 s.
- USA and Australia: use 915E6; the US band is 902 - 928 MHz, with a dwell time of at most 400 ms on one channel (Australia: 915 - 928 MHz).
Limitations of the Simulation
- Not modelled: the FSK / OOK modem, DIO1 - DIO5, frequency hopping, collisions of simultaneous transmitters, frequency error, fading and terrain, and the supply voltage.
- The range is a teaching model (path-loss exponent 3.0, a built-up area); real range depends on your antennas and surroundings, and the reported SNR is capped at +10 dB.
- The model is our own implementation, written from Semtech's SX1276/77/78/79 datasheet and AN1200.13; it contains no arduino-LoRa code.
- Tested in Proteus 8.5 SP0 on 6 and 7 Oct 2026 (the demo, PING, 5 km and SF 8, the panel, the four tools and every Proteus screenshot here) and with 1,293 automatic PC checks shared with our SX1278 library, all passed, 48 of them with the unmodified arduino-LoRa library and 56 with the real v1.1 sketches. The image marked "PC render" was drawn by the model's own code. Proteus 7 is not supported.
For 433 MHz LoRa, see our SX1278 LoRa Library for Proteus; for +22 dBm and RadioLib, our SX1262 LoRa Library for Proteus. For other radios, try our CC1101 Library for Proteus, RFM69HCW Library for Proteus or nRF24L01 Library for Proteus.
So, that was all about the RFM95W LoRa Library for Proteus V1.1. I hope the DISTANCE buttons, the glowing wire antenna, the four test tools and the SF 8 experiment make LoRa much easier to understand, so your long-range project works the first time you wire two real modules. If you use the RFM95W LoRa Library for Proteus in a project, please share your feedback in the comments or in our forum, and if you have any questions, ask in the comments and I will help you out. Till the next tutorial, take care and have fun!
























Comments
0