Beyond Line of Sight: Testing Modules for Extended Wireless Coverage

Long range test (1km+) wireless nRF24L01 | ESP32

Electronic | IoT

Project

 

At the bottom of my drawers were some nRF24L01 modules that I’d been wanting to test for a long time. These wireless modules from Nordic are renowned for their long range and low cost (just a few euros). The aim of the test was to make sure that it was possible to establish a stable wireless link at 1km LOS (line of sight) without any major Fresnel effect problems, because we’re talking about 2.4Ghz after all!

I was particularly interested in this 2.4Ghz frequency because the legislation is flexible, unlike Sub-GHz frequencies (433MHz, 866MHz or 915Mhz), which are long-range but limited to 1% duty cycle in Europe. The frequencies used by Lora and SigFox, to name but two, can only be used one per cent of the time.

On the other hand, it is often difficult, if not impossible, to achieve such a range with a 2.4Ghz protocol (Bluetooth, Wifi, etc.). Hence the test!

Warning: if you want to reproduce this test, take the nRF24L01 PA LNA modules. They contain an amplifier and a noise attenuator that allow them to achieve this range. What’s more, not all modules and antennas are created equal, as shown by the many tests you can find on Youtube.

    Source code and info for ESP32

      The test code uses in particular the RF24  library, which is very well documented with numerous examples for making gateways on Raspberry Pi, Mesh-type networks and so on.

      The nRF24L01 PA LNA module is connected in SPI on the default port (MOSI 23, MISO 19, SCLK 18, CS 16, CE 17).
      The SSD1306 OLED display on the receiver uses the I2C ports (SDA 21, SCL 22).
      For the ESP32 I have NodeMCU modules, but any Arduino module will do (even an Attiny!).

      The transmitter sends a timestamp every second and the receiver displays it on the screen and the serial port.

      Issuer code

        #include <Arduino.h>
        #include <SPI.h>
        #include <nRF24L01.h>
        #include <RF24.h>
        
        RF24 radio(17, 16); // pin CE, CSN à connecter sur les GPIO 17 et 16         
        const byte address[6] = "00001"; // Adresse d'envoie (bien mettre la même dans le récepteur)
        char buf[16];
        
        void setup() {
          radio.begin();                  // Démarrage de la radio
          radio.openWritingPipe(address); // On lui donne son adresse de communication
          radio.setDataRate( RF24_250KBPS );// Vitesse a 250kbps
          radio.setPALevel(RF24_PA_MAX);  // Puissance maximale pour le test de portée
          radio.stopListening();          // Met le module en mode transmission
        }
        
        void loop()
        {
          char buf[16];
          ltoa(millis(),buf,10);
          radio.write(&buf, sizeof(buf)); // Envoie d'un timestamp toutes les secondes
          delay(1000);
        }

        Receiver code

          #include <SPI.h>
          #include <nRF24L01.h>
          #include <RF24.h>
          #include <Adafruit_GFX.h>
          #include <Adafruit_SSD1306.h>
          #include <Wire.h> 
          
          Adafruit_SSD1306 screen(128, 64, &Wire, -1); // Ecran sur port I2C
          RF24 radio(17, 16); // pin CE, CSN à connecter sur les GPIO 22 et 21    
          const byte address[6] = "00001"; // Adresse d'envoie (bien mettre la même dans l'émetteur)
          
          void setup() {
            Serial.begin(115200);                // Communication série pour afficher le Ping
            radio.begin();
            radio.openReadingPipe(0, address);   // On lui donne son adresse de communication
            radio.setDataRate( RF24_250KBPS );   // Vitesse a 250kbps
            radio.setPALevel(RF24_PA_MAX);       // Puissance maximale pour le test de portée
            radio.startListening();              // Met le module en mode réception
          
            // Démarrage de la connexion à l'écran
            if(!screen.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
                Serial.println(F("Screen SSD1306 Not found"));
            }
            else
            {
              Serial.println(F("Screen SSD1306 Found"));
              screen.clearDisplay();
              
              screen.setTextSize(3);      // Normal 1:1 pixel scale
              screen.setTextColor(SSD1306_WHITE); // Draw white text
              screen.setCursor(0, 0);     // Start at top-left corner
              screen.cp437(true);         // Use full 256 char 'Code Page 437' font
            }
          }
          
          void loop()
          {
            if (radio.available())              // A-t-on reçu quelque chose...
            {
              char text[32] = "";                 
              radio.read(&text, sizeof(text));    // Lecture de la donnée recue
              Serial.println(text);               // Affichage sur moniteur serie
              screen.clearDisplay();  
              screen.setCursor(0, 0);
              screen.print(text);                  // Affichage sur écran
              screen.display();
            }
          }

          That concludes this post. The test is validated, I was able to exceed 1km while losing the LOS, which leads me to believe that we could easily go further. If you’re looking for medium-range 2.4Ghz solutions, I’d advise you to have a look at the Nordic suite, which I’ve been using on several projects for a long time. In particular the nRF52 for Bluetooth 5, Enhanced Shockburst etc, which is much more recent than the nRF24L01 and includes an ARM microcontroller, cryptocells and lots of extra functionality.

          Do you have a project or need information?

          Don't hesitate to contact us !

             contact@torrusvr.com

             Bordeaux / Paris (FR)