
SX1278 LoRa Library for Proteus V1.1 (Ra-02 433 MHz + Arduino)

Hello friends, I hope you all are doing great. Today, I am going to share the new SX1278 LoRa Library for Proteus V1.1. The SX1278 is Semtech's long-range LoRa radio chip, and the Ai-Thinker Ra-02 board with its silver shield can and spring antenna is the most popular way to use it at 433 MHz. With this SX1278 LoRa Library for Proteus, two Ra-02 modules in one design talk over a simulated 433 MHz air, even 10 km apart, and your Arduino drives them over SPI with the same arduino-LoRa library you use on real hardware.
Version 1.1 replaces the earlier version of this post. You now get two devices: SX1278 Simple, with its control panel on the schematic, and SX1278 Advance, with a pop-up window and four measured LoRa test tools. The new SX1278 Arduino Proteus demo has two Arduino UNOs that send packets, PING each other and switch the spreading factor from our TEP Serial Monitor. Have you read the earlier version? Then jump to "What's New" below.
NOTICE: This library is very special to our team. Our SX1278 model has the chip's LoRa registers and FIFO, works out the signal level and the SNR at every distance and measures the real LoRa time on air. 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 SX1278 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 SX1278 LoRa Library for Proteus:
What is the SX1278 LoRa Module (Ra-02)?
The SX1278 is a radio transceiver (it sends and receives) made by Semtech. Its LoRa modem, short for "Long Range", tunes from 137 to 525 MHz and trades speed for distance: it sends slowly, but over kilometres, so it is popular for weather stations, farm sensors and trackers. The Arduino talks to it over SPI, a 4-wire bus (clock, data in, data out and chip select), plus a reset pin and the DIO0 interrupt pin.
Most Arduino projects use the Ai-Thinker Ra-02 module: a 17 x 16 mm board for 410 - 525 MHz with the SX1278 under a silver shield can and an IPEX socket for the antenna. The print on the can says it all: Ra-02, Ai-Thinker, ISM: 410-525MHz, PA: +18dBm, LoRa/FSK/OOK.
The SX1278 and the Ra-02 at a Glance
| Feature | Value |
|---|---|
| Chip | Semtech SX1278, from the SX1276/77/78/79 family (RegVersion 0x12) |
| Frequency | Chip 137 - 525 MHz; the Ra-02 module 410 - 525 MHz, normally used at 433 MHz |
| Modulation | LoRa (chirp spread spectrum); the chip also has an FSK / OOK modem |
| Spreading factor | SF6 - SF12 (the demo sketches accept 7 - 12) |
| Bandwidth | 7.8 - 500 kHz (the demo: 125 kHz) |
| Coding rate | 4/5 - 4/8 (the demo: 4/5) |
| TX power | Up to +20 dBm on PA_BOOST (the Ra-02 is printed PA: +18dBm); the demo uses +17 dBm, arduino-LoRa's default |
| Sensitivity (our model, 125 kHz) | -125 dBm at SF7 down to -137 dBm at SF12 |
| Buffer | A 256-byte FIFO; packets up to 255 bytes |
| Supply | 3.3 V (Ra-02: 2.5 - 3.7 V); the pins are NOT 5 V tolerant |
| Interface | SPI plus RST and DIO0 (RxDone / TxDone) |
SX1278, RFM95W, SX1262 or Another Radio: Which Library Do You Need?
| Your module | What it does | Our library |
|---|---|---|
| SX1278 / Ra-02 (black square board, spring antenna) | 433 MHz LoRa, long range at low data rates, SPI | This article |
| RFM95W (HopeRF, SX1276) | 868 / 915 MHz LoRa, SPI, the same arduino-LoRa library | RFM95W LoRa Library for Proteus |
| SX1262 (Ebyte E22) | The newer LoRa chip, up to +22 dBm, RadioLib on an Arduino Mega 2560 | SX1262 LoRa Library for Proteus |
| CC1101 | 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 |
All of them are compared in our RF Module Libraries for Proteus roundup. Ra-02, RFM95W and SX1262 modules can even talk to each other in one design, because the three LoRa libraries share one model.
LoRa Terms You Will See in This Article
| Term | Meaning |
|---|---|
| LoRa | Semtech's long-range modulation: every symbol is sent as a chirp |
| Chirp | A tone that sweeps across the whole bandwidth; where the sweep starts carries the data |
| Spreading factor (SF) | SF7 - SF12: how long each chirp is; one step up doubles it and reaches further |
| Bandwidth (BW) | How wide the sweep is: 125 kHz in the demo |
| 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, -120 dBm is a very weak signal |
| RSSI | Received Signal Strength Indicator: the level of a packet in dBm |
| SNR | Signal-to-noise ratio: how far the signal is above the noise (below it, if negative) |
| Noise floor | The noise in the receiver's bandwidth: -117 dBm at 125 kHz in our model |
| Sensitivity | The weakest signal the receiver can still decode at its SF and bandwidth |
| Sync word | One byte (0x12 in the demo) that keeps networks apart: a receiver ignores other sync words |
| 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 channel busy |
| Duty cycle | The share of time a transmitter is on the air; the EU allows 10 % in its 433 MHz band |
| LDRO | Low data rate optimisation: switched on when a symbol lasts more than 16 ms |
| RX single | The receiver listens for one packet and stops after a timeout; arduino-LoRa's parsePacket() uses it |
How LoRa Works: Chirps, Spreading Factor and Range
Simple radios, such as the CC1101, send a 1 or a 0 by moving the frequency a little up or down. LoRa sends every symbol as a chirp: a tone that sweeps steadily up across the whole bandwidth, and the data sits in where the sweep starts. At spreading factor 7 there are 2 to the power of 7 = 128 starting points, so one chirp carries 7 bits. The receiver adds up the energy of the whole sweep, so it finds a chirp even in noise stronger than the signal.
A packet starts with a preamble of plain chirps (8 in the demo), then come the sync word, the header, the data and, if switched on, a CRC; arduino-LoRa leaves the CRC off unless you call LoRa.enableCrc().
Spreading Factor, Bandwidth and Coding Rate
- Spreading factor (SF): 7 to 12 in the demo. Each step up makes every chirp twice as long and lets the receiver decode a signal 2.5 dB weaker.
- Bandwidth (BW): 7.8 to 500 kHz, 125 kHz in the demo. Half the bandwidth lets in 3 dB less noise, but every chirp lasts twice as long.
- Coding rate (CR): 4/5 to 4/8. 4/5 sends 5 bits for every 4 data bits; more extra bits repair more errors.
One chirp lasts 2 to the power of SF, divided by the bandwidth: 128 / 125,000 = 1.024 ms at SF7 and 125 kHz (the "1.024 ms / symbol" on the Radio page), but 32.768 ms at SF12.
RSSI and SNR: Why LoRa Hears Below the Noise
The RSSI is the level of a packet in dBm. The SNR says how far that level is above the noise in the receiver's bandwidth, which our model puts at -174 dBm/Hz + 10 log(BW) + 6 dB: -117 dBm at 125 kHz. LoRa can decode below the noise: each SF has its own lowest SNR, and the sensitivity is the noise floor plus that limit:
| SF | Lowest SNR | Sensitivity at 125 kHz | Time on air (12 bytes) |
|---|---|---|---|
| SF7 | -7.5 dB | -125 dBm | 41.2 ms |
| SF8 | -10 dB | -127 dBm | 72.2 ms |
| SF9 | -12.5 dB | -130 dBm | 144.4 ms |
| SF10 | -15 dB | -132 dBm | 288.8 ms |
| SF11 | -17.5 dB | -135 dBm | 577.5 ms |
| SF12 | -20 dB | -137 dBm | 991.2 ms |
So at 5 km, the demo's packets arrive at -119 dBm, an SNR of -2.1 dB, and SF7 still decodes them. Close up, the SNR is capped at +10 dB, as on real modules: 100 m prints 10.00 dB, although the signal is about 49 dB above the noise.
Why a Higher SF Reaches Further
The level at the receiver is the TX power minus the path loss. Our model uses free-space loss for the first metre (25.2 dB at 433 MHz), then a path-loss exponent of 3.0, typical of a built-up area: 30 dB more for every ten times the distance. With the demo's +17 dBm:
- 100 m: 85.2 dB of loss, so -68 dBm; SF7 needs -125 dBm: OK, with +56.4 dB to spare.
- 10 km: 145.2 dB of loss, so -128 dBm, an SNR of -11.1 dB: too weak for SF7 (-7.5 dB) and SF8 (-10 dB), but OK for SF9 (-12.5 dB).
A chirp twice as long carries twice the energy, so every SF step digs 2.5 dB deeper into the noise: "HIGHER SF REACHES FURTHER", as our panels say. The price is time on air.
Time on Air: The Price of Range
The time on air is how long one packet keeps the channel busy. Our model uses Semtech's formula (application note AN1200.13). For a 12-byte packet such as "hello TEP 10" at SF7, 125 kHz, CR 4/5, explicit header and no CRC:
- One symbol lasts 1.024 ms; the preamble takes 8 + 4.25 = 12.25 symbols.
- The payload takes 8 + ceil((8 x 12 - 4 x 7 + 28) / (4 x 7)) x 5 = 8 + 4 x 5 = 28 symbols (the 5 comes from CR 4/5).
- Together: 40.25 symbols x 1.024 ms = 41.2 ms, exactly what the Time on air tool measures.
At SF12, a symbol lasts 32.768 ms, more than 16 ms, so arduino-LoRa switches on the low data rate optimisation (LDRO): 30.25 symbols, 991.2 ms, almost a second.
Duty Cycle: How Often May You Send?
In the EU band 433.05 - 434.79 MHz, a transmitter may be on the air at most 10 % of the time, at 10 mW: 360 s per hour. With 41.2 ms packets, that is at most 8734 packets per hour, with a pause of at least 0.37 s after each. The demo's packet every 2 s uses about 2 % at SF7; at SF12 it would be on the air half of the time.
Sync Word and the Settings Both Radios Must Share
A receiver accepts only packets with its own sync word: 0x12 for private networks such as the demo (LoRaWAN uses 0x34). Two radios form a link only when the frequency (within a quarter of the bandwidth), SF, bandwidth, sync word, IQ setting and header mode match; the coding rate and CRC may differ, because the explicit header announces them. And there is no ACK: a LoRa radio never answers "got it" by itself, so the demo's PING and PONG show how a sketch adds a reply.
What's New in SX1278 LoRa Library for Proteus V1.1
If you used the earlier version of this post (v1.0 and its 29 Sep model update), here is what has changed:
- Two devices in
TEPSX1278.LIB: SX1278 Simple (SX1278TEP, the v1.0 device, so old designs keep working) and SX1278 Advance (SX1278ADVTEP) with a pop-up window. - A redrawn board: black and square like the real Ra-02, with its shield can and a spring antenna (v1.0: a navy board); the 8 pins stay where they were.
- A live antenna and three LEDs: the spring glows orange while sending and green while receiving. PWR, TX and RX are a TEP addition: the real Ra-02 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: every radio now records its packets and SPI accesses for the tools; the link budget (100 m: -68 dBm, SNR 10 dB) and the 29 Sep update (one model for our three LoRa libraries) are unchanged.
- A two-UNO demo with the TEP Serial Monitor instead of Virtual Terminals: every v1.0 output line plus commands (SEND, PING, STATUS, SF, BW, PWR, HELP; AUTO on node 1) and a link line every 10 s.
- Lighter package: about 1.5 MB, without the C++ source code (before: about 7.4 MB).
A v1.0 design keeps its old symbol: the new model, but no new board, LEDs or red X. Before a sketch starts the radio, its panel shows the chip's reset values:
SX1278 LoRa Library for Proteus: Simple vs Advance
Both devices run the same model; only the panel differs:
| Feature | Simple | Advance |
|---|---|---|
| Full SX1278 LoRa model (SPI, registers, 256-byte FIFO, modes, IRQ flags, DIO0, RSSI / SNR, real time on air) | ✔ | ✔ |
| Black Ra-02 board, glowing spring 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.
Download SX1278 LoRa Library for Proteus
Click the button below to download SX1278-LoRa-Library-for-Proteus-v1.1.zip (about 1.5 MB, without the C++ source code):
SX1278 LoRa Library for Proteus V1.1- README.txt: a guide to the files, the wiring, the model, the tools and real hardware.
- Proteus Library Files:
TEPSX1278.LIB(both devices),TEPSERIALMON.LIBand our Arduino UNO libraryArduinoV3TEP.LIB/ArduinoV3TEP.IDX. - Proteus Model Files:
TEPSX1278.DLLandTEPSERIALMON.DLL. Our RFM95W and SX1262 libraries ship the identical TEPSX1278.DLL, so installing all three is safe. - Proteus Simulation:
SX1278-ArduinoUnoV3.pdsprj,LoRa_Sender.hex,LoRa_Receiver.hexand copies of both DLLs. - Arduino Code:
LoRa_Sender.ino,LoRa_Receiver.inoand the arduino-LoRa library 0.8.0 (Sandeep Mistry), unmodified, with its examples and its LICENSE file, under the MIT License.
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 SX1278 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 SX1278. You get the Simple and the Advance device (category Peripherals > Wireless).
Updating from v1.0? Replace TEPSX1278.LIB and TEPSX1278.DLL, and delete TEPSX1278.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. Tested in Proteus 8.5; Proteus 7 is not supported.
The Ra-02 Board in Proteus
We designed the module as a clean TEP board after the real Ai-Thinker Ra-02: a square black board, the silver shield can with its notch and the real engraving and Ai logo, gold half-hole pads and the IPEX socket with a copper spring antenna. Below the can: the board button, three LEDs, a SIMPLE or ADVANCE badge and the pins. One honest note: the real Ra-02 has its IPEX socket next to pin 1; we draw it top-right, so the antenna stays clear of your wiring. Here is U1, the Simple device, with its panel while it sends:
The spring and its waves glow orange; PWR and TX are lit, RX stays dark. On U2, the Advance device, they glow green when a packet arrives:
Pinout
The eight Proteus pins keep the v1.0 order. A real Ra-02 has more pads (DIO1 to DIO5, extra grounds) in another order, so wire a real module by the pin names in its data sheet:
| 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 | Interrupt output: RxDone or TxDone | Arduino D2 |
Spring, 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 (held 0.3 s) |
| RX LED (green) | Blinks for every packet received (held 0.4 s) |
| Spring antenna | Copper at rest, orange while sending, green while receiving |
| Waves above the spring | Grey at rest; they ripple out while sending and in while receiving |
| PANEL / OPEN PANEL, SIMPLE / ADVANCE | The panel button and the device badge |
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).
SX1278 Simple: The Control Panel on the Sheet
Beside the Simple board, the SX1278 LoRa CONTROLS panel shows what the radio is doing, without one debug line in your sketch. You saw it in the first board image, at the default 100 m. From top to bottom:
| Part | What it shows |
|---|---|
| Header, red X | SX1278 LoRa CONTROLS; the X closes the panel |
| Mode banner | For example RX SINGLE or RX CONTINUOUS (green), TX - SENDING (orange), STANDBY, SLEEP or CAD (blue), NO POWER - CHECK VCC / GND or OUT OF BAND (red); FSK/OOK MODE - NOT MODELLED before a sketch switches the chip to LoRa |
| Settings line 1 | 433.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: -68 dBm, SF7 NEEDS -125 dBm -> OK |
| Hint and footer | CLICK A DISTANCE - HIGHER SF REACHES FURTHER; LoRa 433 MHz Ai-Thinker Ra-02 |
Why the Sender Says RX SINGLE
U1 is the sender, yet its banner says RX SINGLE. That is correct: the v1.1 sender calls parsePacket() in every loop, which keeps the radio listening in windows of 100 symbols (about 102 ms at SF7), so node 2 can PING it; its last packet is the PONG from my PING test. A 41.2 ms hello every 2 s is rarely caught as TX - SENDING, but the TX LED and the orange spring show every one. A sketch that must not miss a packet listens continuously with LoRa.onReceive() and LoRa.receive() (DIO0 on D2).
DISTANCE: 100 m Works, 10 km Is TOO WEAK
Now click 10 km on the panel of U1. The verdict turns to -128 dBm, TOO WEAK, because SF7 needs -125 dBm:
From now on, U4 prints only "Link (10 s): 0 received, 0 sent", while U3 keeps printing "Sending packet: n": without an ACK, the sender never notices. U2 counts the weak packets (6 in my run). The link uses the larger of the two DISTANCE settings, so bringing the radios back needs a short distance on both.
Higher SF Reaches Further: SF 9 at 10 km
The hint on the panel says it: a higher SF reaches further. Leave 10 km and type SF 9 in the send box of BOTH Serial Monitors (one node alone would break the link). The panel of U1 shows SF9, and the verdict says OK again:
On U4, the packets come back:
Received packet 'hello TEP 12' with RSSI -68 dBm, SNR 10.00 dB
Link (10 s): 3 received, RSSI -68 dBm avg, SNR 10.0 dB avg, 0 sent
Link (10 s): 0 received, 0 sent
Link (10 s): 0 received, 0 sent
SF 9
Spreading factor SF9 - set node 1 to the same SF
Received packet 'hello TEP 26' with RSSI -128 dBm, SNR -11.25 dB
Received packet 'hello TEP 27' with RSSI -128 dBm, SNR -11.25 dB
Packets 13 to 25 were sent while the link was too weak or the two nodes used different SFs, and never arrived. From 26 on, every packet arrives at -128 dBm with an SNR of -11.25 dB (the chip counts in steps of 0.25 dB): 11 dB below the noise, yet SF9 decodes down to -12.5 dB. The price: 144.4 ms on air 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.
SX1278 Advance: The Pop-Up Window
The Advance device keeps only the board on the schematic. At Run, the "TEP SX1278 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), the Radio and Test tabs and the theme, Settings and Help icons.
The Radio Page
- RADIO - WHAT THE SKETCH SET: 433.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: 31 packets received and 1 sent (the 4-byte PONG, 31.0 ms on air), 6 too weak from my 10 km test; the last, "hello TEP 43", at -68 dBm and 10.0 dB.
- DISTANCE: "At 100 m: -68 dBm, SF7 needs -125 dBm -> OK (+56.4 dB)" and my favourite line, "These settings reach about 7.6 km; SF12 would reach 19.7 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 their RSSI, SNR and time on air. The DISTANCE buttons sit on the tool, so you can move the radios mid-test. 10 packets at 100 m:
U2 decoded all 10 packets from U1 at -68 dBm and 10.0 dB, 41.2 ms each, every green bar above the dashed "SF7 needs -125 dBm" line; click 10 km during a test, and the bars turn red. Below, the link budget for every distance and the lowest SF that works there:
| Distance | RSSI | SNR | At your SF (SF7) | Lowest SF, time on air |
|---|---|---|---|---|
| 10 m | -38 dBm | 10.0 dB | OK +86 dB | SF7, 41.2 ms |
| 100 m | -68 dBm | 10.0 dB | OK +56 dB | SF7, 41.2 ms |
| 1 km | -98 dBm | 10.0 dB | OK +26 dB | SF7, 41.2 ms |
| 2 km | -107 dBm | 9.8 dB | OK +17 dB | SF7, 41.2 ms |
| 5 km | -119 dBm | -2.1 dB | OK +5 dB | SF7, 41.2 ms |
| 10 km | -128 dBm | -11.1 dB | TOO WEAK -4 dB | SF9, 144.4 ms |
| 15 km | -133 dBm | -16.4 dB | TOO WEAK -9 dB | SF11, 577.5 ms |
| 20 km | -137 dBm | -20.2 dB | TOO WEAK -13 dB | none (even SF12 is too weak) |
From 5 km on, the SNR is negative, yet SF7 still decodes. 10 km needs SF9, 15 km SF11, and at 20 km even SF12 is too weak at +17 dBm. 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, which your design never hears, send one packet for every SF from 7 to 12 at 125, 250 and 500 kHz, with 12, 32, 64 or 255 bytes, and measure TX start to TxDone. 12 bytes:
| SF | BW 125 kHz | BW 250 kHz | BW 500 kHz |
|---|---|---|---|
| SF7 | 41.2 ms | 20.6 ms | 10.3 ms |
| SF8 | 72.2 ms | 36.1 ms | 18.0 ms |
| SF9 | 144.4 ms | 72.2 ms | 36.1 ms |
| SF10 | 288.8 ms | 144.4 ms | 72.2 ms |
| SF11 | 577.5 ms (LDRO) | 247.8 ms | 123.9 ms |
| SF12 | 991.2 ms (LDRO) | 495.6 ms (LDRO) | 247.8 ms |
Your setting measured 41.22 ms, exactly Semtech's formula. Each SF step roughly doubles the time; each doubling of the bandwidth halves it.
The duty-cycle card warns: "just BELOW the EU 433.05-434.79 MHz band: use e.g. 433.92 MHz on real hardware (10 %, 10 mW)", and "SF7 / 125 kHz, 12 bytes: 41.2 ms on air -> wait at least 0.37 s between packets, at most 8734 packets per hour". Good for: choosing the SF and bandwidth for your message size and the legal duty cycle.
3. Range: Which SF Do You Need?
Run test sends one 12-byte packet per SF at each of the 8 DISTANCE steps between two model radios: green = decoded, red = too weak:
| SF | Link budget | Decoded up to | Too weak from |
|---|---|---|---|
| SF7 | 7.6 km | 5 km | 10 km |
| SF8 | 9.2 km | 5 km | 10 km |
| SF9 | 11.1 km | 10 km | 15 km |
| SF10 | 13.4 km | 10 km | 15 km |
| SF11 | 16.3 km | 15 km | 20 km |
| SF12 | 19.7 km | 15 km | 20 km |
SF8's 9.2 km budget falls between the 5 and 10 km steps, so it ends where SF7 does. The second card compares our LoRa modules at full power: Ra-02 (+20 dBm) 9.5 to 24.8 km, RFM95W (868 MHz) 6.0 to 15.6 km, SX1262 (+22 dBm) 7.0 to 18.2 km. Good for: picking the spreading factor that reaches the distance you need.
4. Registers: What Did Your Sketch Write?
This tool reads the registers live, as an SPI read would, decodes them and lists the Arduino's last SPI accesses:
- RegOpMode 86: LoRa, RX SINGLE. RegFrf 6C4000: 7,094,272 steps of about 61 Hz (32 MHz / 524,288) = 433.000 MHz.
- RegPaConfig 8F: PA_BOOST, +17 dBm. RegModemConfig1 / 2 / 3 = 72 / 70 / 04: 125 kHz, CR 4/5, explicit; SF7, CRC off; LDRO off, AGC on.
- RegPktRssi / Snr 60 28: 0x60 = 96, and 96 - 164 = -68 dBm; 0x28 = 40 x 0.25 = 10.0 dB (arduino-LoRa's formulas). RegRssiValue 2F: -117 dBm, the noise between packets.
Read the SPI log from the bottom up to watch parsePacket(): read and write RegModemConfig1, clear RegIrqFlags, read RegOpMode and RegIrqFlags, 9.8 us each, over and over: 46,614 SPI transactions per second. At the bottom, U1 is the PARTNER (LISTENING); a mismatch would be 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 SX1278 board of our forum, three cards open this article, and the others the donate page, our website and the forum; a links.ini next to the DLL can change the links.
SX1278 LoRa Link with Arduino in Proteus
Open SX1278-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
LoRa_Sender.hex, the SX1278 Simple (U1) and Serial Monitor U3. - NODE 2 - RECEIVER: UNO 2 (ARD2) with
LoRa_Receiver.hex, the SX1278 Advance (U2) and Serial Monitor U4.
Wiring
| From | To | Why |
|---|---|---|
| Ra-02 VCC / GND | Supply / ground | Power (+5 V in the simulation; a real Ra-02 needs 3.3 V) |
| Ra-02 SCK | Arduino D13 | SPI clock |
| Ra-02 MISO | Arduino D12 | Data from the radio |
| Ra-02 MOSI | Arduino D11 | Data to the radio |
| Ra-02 NSS | Arduino D10 | Chip select |
| Ra-02 RST | Arduino D9 | Reset |
| Ra-02 DIO0 | Arduino D2 | RxDone / TxDone interrupt (the demo sketches poll over SPI instead) |
| Serial Monitor RXD / TXD / GND | Arduino D1 / D0 / ground | Shows what the Arduino prints, sends what you type |
These are arduino-LoRa's default pins; D11, D12 and D13 are the UNO's hardware SPI pins (see our Introduction to Arduino UNO). To move NSS, RST or DIO0, call LoRa.setPins(ss, reset, dio0) before LoRa.begin(). No wire joins the two nodes: they share one simulated air.
The Arduino Code
Both sketches use the unmodified arduino-LoRa library by Sandeep Mistry (its object is LoRa). The settings live in variables, so the SF, BW and PWR commands can change them:
const long frequency = 433E6;
int spreadingFactor = 7, txPower = 17;
long bandwidth = 125E3;
LoRa.begin() resets the module over RST, checks RegVersion (0x12) and sets the frequency and +17 dBm; SF7, 125 kHz, CR 4/5 and sync word 0x12 are the chip's reset values. If the chip does not answer, the sketch stops:
if (!LoRa.begin(frequency)) {
Serial.println(F("LoRa module not responding - check the SPI wiring and power"));
while (true) {}
}
The sender keeps the v1.0 packet and output line. While AUTO is ON, it sends one every 2 s:
void sendHello() { // the v1.0 output line and packet
Serial.print(F("Sending packet: "));
Serial.println(counter);
LoRa.beginPacket();
LoRa.print("hello TEP ");
LoRa.print(counter);
LoRa.endPacket();
counter++;
++sent; ++linkSent;
}
if (autoSend && millis() - lastSend >= 2000) {
lastSend = millis();
sendHello();
}
endPacket() waits until the chip reports TxDone, so the commands measure the time on air around it:
unsigned long transmit(const char* text) {
LoRa.beginPacket();
LoRa.print(text);
unsigned long start = micros();
LoRa.endPacket();
unsigned long us = micros() - start;
++sent; ++linkSent;
return us;
}
Both sketches read packets the same way. parsePacket() returns 0 while nothing has arrived and keeps the radio in RX single mode, so the sender listens between its own packets, too:
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();
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
Then the receiver prints the v1.0 line:
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"));
PING waits for the PONG for 500 ms plus three times its own time on air, so it still works at SF12:
unsigned long start = micros();
unsigned long air = transmit("PING");
unsigned long waitMs = 500 + 3 * (air / 1000); // the PONG takes about as long as the PING on air
The SF command checks its number and hands it to the library; BW and PWR use LoRa.setSignalBandwidth() and LoRa.setTxPower():
} else if (strcmp(text, "SF") == 0) {
int sf = atoi(arg);
if (sf < 7 || sf > 12) { Serial.println(F("SF needs 7 - 12, e.g. SF 9")); return; }
spreadingFactor = sf;
LoRa.setSpreadingFactor(sf);
To change a sketch, install "LoRa" by Sandeep Mistry (or copy Arduino Code\libraries\LoRa into your sketchbook), 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> | For example SF 9: the spreading factor (type it on both monitors) |
| BW <kHz> | 7.8, 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125, 250 or 500 (both monitors) |
| PWR <2-20> | The transmit 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.
- Type PING and STATUS on U3.
- Click 10 km on the panel of U1, then type SF 9 on both monitors. Back: 100 m and SF 7 on both.
- Close the panel of U1 with its red X, open it with PANEL.
- Run the four tools on the Test tab of U2.
SX1278 Proteus Simulation Results
The Serial Monitor in Its Simple Interface
Both monitors run in the Simple interface of our TEP Serial Monitor, as in every monitor screenshot here: only the log, the send box and one slim toolbar row (baud rate, follow, pause, search and clear) stay visible, 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 or SF 9 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 Ra-02 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, both monitors print their banners, and U3 prints the v1.0 line "Sending packet: n" every 2 s. The first lines of U4 in my run:
TEP SX1278 LoRa Receiver Demo v1.1
Listening: 433 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 -68 dBm, SNR 10.00 dB
Received packet 'hello TEP 1' with RSSI -68 dBm, SNR 10.00 dB
Received packet 'hello TEP 2' with RSSI -68 dBm, SNR 10.00 dB
Received packet 'hello TEP 3' with RSSI -68 dBm, SNR 10.00 dB
Every packet arrives at -68 dBm and 10.00 dB, the 100 m numbers. Every 10 s, U4 adds a link line such as "Link (10 s): 5 received, RSSI -68 dBm avg, SNR 10.0 dB avg, 0 sent".
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 -68 dBm, SNR 10.00 dB)
Sending packet: 4
STATUS
Status: 433.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 -68 dBm, SNR 10.00 dB
Sending packet: 5
PONG came back after 63.6 ms: two 4-byte packets of 31.0 ms on air at SF7, plus a little time on both UNOs. STATUS prints the sketch's settings and counters: 6 sent (hello 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 -68 dBm, SNR 10.00 dB
Received packet 'PING' with RSSI -68 dBm, SNR 10.00 dB
-> PONG sent back
Received packet 'hello TEP 4' with RSSI -68 dBm, SNR 10.00 dB
Link (10 s): 6 received, RSSI -68 dBm avg, SNR 10.0 dB avg, 1 sent
Try the other direction, too: type SEND Hello on U4, and U3 prints it as "Received from node 2:" 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.
- Nothing received, or "PING: no PONG": both radios need the same frequency, SF, bandwidth and sync word (the Registers tool lists what does not match), and the DISTANCE must suit the SF (watch the "-> TOO WEAK" line).
- No monitor window or no pop-up: a DLL is missing; click OPEN MONITOR on the monitor part or OPEN PANEL on the board, or turn "Open the panel at Run" back on.
- No red X / the old navy board: replace the LIB, delete TEPSX1278.IDX and re-pick the part.
- Your own sketch: hardware SPI works in Proteus 8.5; only SoftwareSerial cannot receive there (no pin-change interrupts), which this demo does not need.
Things to Know Before Using a Real Ra-02
The demo sketches use only arduino-LoRa, so they run on two real UNOs and Ra-02 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). A 10 uF capacitor at VCC helps at +17 dBm.
- Level shifting: the Ra-02's pins are NOT 5 V tolerant, so a 5 V UNO must not drive them directly. Use a level shifter (or a 3.3 V board) for SCK, MOSI, NSS and RST.
- Antenna first: fit the antenna before you transmit; sending into a missing antenna can destroy the power amplifier.
- Frequency: the demo's 433.000 MHz lies just below the EU 433.05 - 434.79 MHz band. Use e.g. 433.92 MHz on real hardware: change
433E6to433.92E6in both sketches. - Power and duty cycle: use what your country allows. In that EU band: 10 % duty cycle and 10 mW e.r.p.; +17 dBm is 50 mW, so lower the power with PWR or
LoRa.setTxPower(). - One band: the Ra-02 is a 433 MHz module. For 868 / 915 MHz you need an RFM95W or another SX1276 module.
Limitations of the Simulation
- Not modelled: the FSK / OOK modem, DIO1 to DIO5, frequency hopping, collisions (each packet is judged on its own), frequency error, fading and terrain, and the supply voltage. The RFO output counts 20 dB weaker, because the Ra-02 only connects PA_BOOST.
- The range is a teaching model (exponent 3.0); real range depends on your antennas and surroundings.
- The model is our own implementation, written from Semtech's SX1276/77/78/79 data sheet and AN1200.13; it contains no arduino-LoRa code.
- Tested in Proteus 8.5 SP0 on 6 and 7 Oct 2026 (the demo, PING, 10 km and SF 9, the four tools and every Proteus screenshot here) and with 1,293 automatic PC checks of the SX1278 and RFM95W side, all passed, 48 of them with the unmodified arduino-LoRa 0.8.0 and 56 with the real v1.1 sketches. The "PC render" was drawn by the model's own code. Proteus 7 is not supported.
For 868 / 915 MHz, see our RFM95W LoRa Library for Proteus, and for the newer SX1262, our SX1262 LoRa Library for Proteus. For other radios, try our CC1101 Library for Proteus, RFM69HCW Library for Proteus, HC-12 Library for Proteus or nRF24L01 Library for Proteus.
So, that was all about the SX1278 LoRa Library for Proteus V1.1. I hope the DISTANCE buttons, the glowing spring, the four test tools and the SF 9 experiment at 10 km make LoRa much easier to understand, so your long-range project works the first time you wire two real Ra-02 modules. If you use the SX1278 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