Componenti · 16 min di lettura

nRF24L01 Arduino: comunicazione wireless, codice e portata

Guida nRF24L01 con Arduino: collegamenti, 3,3 V e condensatore da 10 µF, codice RF24 per trasmettitore e ricevitore, PA+LNA fino a 1 km, joystick ed ESP32.

La coppia nRF24L01 e Arduino è il modo più economico e pratico per inviare dati tra due schede senza stendere un cavo. Questo modulo grande come un'unghia lavora nella banda dei 2,4 GHz, trasmette fino a 2 megabit al secondo e può essere sia trasmettitore sia ricevitore. È ideale per auto radiocomandate, joystick wireless, una stazione che invia in casa i dati di un sensore in giardino o nodi d'allarme che si avvisano a vicenda. La versione standard arriva a circa 100 metri in campo aperto, mentre la versione nRF24L01+PA+LNA con antenna esterna può raggiungere 1 chilometro in buone condizioni.

In questa guida scoprirai come funziona il modulo, quali pin SPI usa, perché va sempre alimentato a 3,3 V e come un condensatore da 10 µF risolve il problema più frequente. Poi scriverai il codice di trasmettitore e ricevitore con la libreria RF24, capirai indirizzi e canali, costruirai un telecomando con joystick, collegherai il modulo a un ESP32 e a un Raspberry Pi Pico e, infine, risolverai passo passo i problemi "radio.begin() false" e "non arrivano dati".

Modulo di comunicazione wireless nRF24L01 a 2,4 GHz
Modulo nRF24L01+ standard: la pista a zigzag in fondo alla scheda è l'antenna stampata; si collega in SPI tramite il connettore a 8 pin.

Che cos'è l'nRF24L01 e come funziona?

L'nRF24L01 è un chip ricetrasmettitore radio a 2,4 GHz prodotto da Nordic Semiconductor; quasi tutti i moduli venduti oggi montano la versione migliorata nRF24L01+ o un clone compatibile. Il modulo comunica con Arduino via SPI: Arduino scrive in SPI le impostazioni e i dati da inviare, e al resto pensa il chip. Il protocollo hardware di Nordic, chiamato Enhanced ShockBurst, aggiunge a ogni pacchetto un indirizzo e un CRC (controllo degli errori). Quando il ricevitore riceve correttamente un pacchetto, invia automaticamente una conferma (ACK) al trasmettitore; se la conferma non arriva, il trasmettitore ritenta da solo. Il tuo codice quindi dice solo "invia", mentre ritrasmissioni e controllo degli errori avvengono in hardware.

Un pacchetto trasporta al massimo 32 byte di dati. Sembrano pochi, ma i due assi di un joystick, qualche pulsante e diversi valori di sensori ci stanno comodamente. Il modulo usa uno di 126 canali, e la frequenza del canale si calcola con 2400 + numero del canale (MHz); il canale 76, per esempio, è a 2476 MHz. Un ricevitore può ascoltare contemporaneamente 6 indirizzi diversi (detti pipe, cioè tubi), quindi un nodo centrale può raccogliere i dati di sei trasmettitori.

CaratteristicaValore
Frequenza2,400–2,525 GHz (126 canali, passo di 1 MHz)
Velocità di trasmissione250 kbps, 1 Mbps, 2 Mbps
Tensione di alimentazione1,9–3,6 V (in pratica 3,3 V)
Pin di ingressoTolleranti ai 5 V (CE, CSN, SCK, MOSI)
Potenza di uscita0, −6, −12, −18 dBm
Corrente (in trasmissione, 0 dBm)Circa 11,3 mA
Corrente (in ricezione, 2 Mbps)Circa 13,5 mA
Power downCirca 900 nA
Sensibilità del ricevitore−94 dBm (250 kbps), −85 dBm (1 Mbps), −82 dBm (2 Mbps)
Dimensione del pacchetto1–32 byte
InterfacciaSPI, fino a 10 MHz
Numero di pipe6

Differenze tra nRF24L01 e nRF24L01+PA+LNA

In commercio troverai due tipi di modulo. In quello standard l'antenna è una pista di rame a zigzag stampata sulla scheda. La versione nRF24L01+PA+LNA aggiunge davanti allo stesso chip un circuito RF: il PA (Power Amplifier, amplificatore di potenza) rinforza il segnale in uscita e il LNA (Low Noise Amplifier, amplificatore a basso rumore) amplifica i segnali deboli in arrivo prima che raggiungano il chip. In più c'è un'antenna esterna avvitata su un connettore SMA. I due moduli hanno la stessa piedinatura e lo stesso codice e comunicano tra loro senza problemi; la differenza sta nella portata e nel consumo. I valori qui sotto sono indicativi e dipendono dall'ambiente.

Modulo RF nRF24L01+PA+LNA con antenna
nRF24L01+PA+LNA: la versione con amplificatori di trasmissione e ricezione e antenna SMA. Funziona con lo stesso codice ma assorbe molta più corrente.
CaratteristicanRF24L01+ (antenna stampata)nRF24L01+PA+LNA
AntennaStampata sulla schedaAntenna SMA esterna
Potenza di uscitaFino a 0 dBm (1 mW)Fino a +20 dBm (100 mW), a seconda del modello
Picco di corrente in trasmissioneCirca 12 mAFino a 115 mA
Picco di corrente in ricezioneCirca 13,5 mAFino a 45 mA
Portata in campo aperto (250 kbps)50–100 m800–1100 m
Portata al chiuso10–30 m, 1–2 paretiPiù piani e qualche decina di metri
Alimentazione consigliataPin da 3,3 V + condensatore da 10 µFRegolatore da 3,3 V separato + condensatore

Piedinatura dell'nRF24L01 e collegamento ad Arduino

Il modulo ha 8 pin disposti su un connettore 2×4. Il pin con la piazzola quadrata è il numero 1, cioè GND; subito accanto c'è VCC. CE (Chip Enable) porta il modulo in modalità ascolto o trasmissione, mentre CSN (Chip Select Not) viene portato a LOW per dire "ora parlo con te" sul bus SPI. SCK, MOSI e MISO sono le normali linee SPI e vanno sui pin SPI fissi della tua scheda, mentre CE e CSN possono andare su qualsiasi pin digitale. Il pin IRQ è facoltativo: va a LOW quando arriva un pacchetto o termina un invio e si usa se vuoi lavorare con gli interrupt. Per capire come funziona l'SPI leggi Che cos'è l'SPI, e per la piedinatura completa della tua scheda usa lo strumento Pinout.

Pin nRF24L01FunzioneArduino Uno / NanoArduino MegaESP32Raspberry Pi Pico
1 GNDMassaGNDGNDGNDGND
2 VCCAlimentazione (3,3 V)3.3V3.3V3V33V3(OUT)
3 CESelezione modalitàD9D9GPIO 4GP6
4 CSNSelezione SPID10D10GPIO 5GP5
5 SCKClock SPID13D52GPIO 18GP2
6 MOSIDati dalla scheda al moduloD11D51GPIO 23GP3
7 MISODati dal modulo alla schedaD12D50GPIO 19GP4
8 IRQInterrupt (facoltativo)Non collegatoNon collegatoNon collegatoNon collegato
Non collegare mai VCC ai 5 V. Il chip sopporta al massimo 3,6 V, e i 5 V possono danneggiarlo in modo permanente. I pin di segnale tollerano i 5 V e possono andare direttamente ai pin SPI dell'Uno, ma l'alimentazione deve essere sempre a 3,3 V. Non inserire nemmeno il modulo direttamente nella breadboard: a causa del connettore 2×4, i pin affacciati finiscono nella stessa striscia e vanno in cortocircuito. Usa cavetti jumper femmina-maschio.

L'errore più comune: l'alimentazione e il condensatore da 10 µF

La maggior parte dei problemi con l'nRF24L01 non dipende dal codice ma dall'alimentazione. Nel momento in cui trasmette, il modulo assorbe picchi di corrente brevi e bruschi. Cavetti lunghi e una sorgente a 3,3 V debole non riescono a stargli dietro: la tensione cala per un istante, il chip invia un pacchetto corrotto, perde le conferme o si riavvia. Secondo la documentazione ufficiale, il pin da 3,3 V dell'Arduino Uno fornisce al massimo 50 mA; bastano per il modulo standard ma non per la versione PA+LNA, che arriva a 115 mA. Su alcuni cloni del Nano i 3,3 V arrivano dal chip USB-seriale e sono ancora più deboli. I sintomi ti suoneranno familiari: write() a volte riesce e a volte no, il modulo funziona meglio quando lo tocchi oppure la portata si ferma a pochi metri.

  • Condensatore da 10 µF: Collega un condensatore elettrolitico da 10 µF tra i pin VCC e GND del modulo, il più vicino possibile. La gamba lunga (+) va a VCC e il lato con la striscia (−) a GND. Vanno bene anche valori da 10 a 100 µF; il perché lo trovi in Che cos'è un condensatore.
  • Condensatore ceramico da 100 nF: Un piccolo condensatore ceramico (con la sigla 104) in parallelo all'elettrolitico filtra i disturbi ad alta frequenza. Puoi decifrare le sigle dei condensatori con lo strumento Codice condensatore.
  • Adattatore a zoccolo: Le schede adattatrici a 8 pin vendute per l'nRF24L01 hanno già un regolatore AMS1117-3.3 e i condensatori. Dai 5 V al VCC dell'adattatore e il modulo riceve 3,3 V puliti.
  • Regolatore separato: Alimenta la versione PA+LNA non dal pin da 3,3 V di Arduino ma da un regolatore AMS1117-3.3 separato collegato ai 5 V, e unisci tutte le masse.
  • Cavetti corti: Tieni i cavetti jumper sotto i 10 cm se puoi; cavi lunghi e allentati disturbano sia l'alimentazione sia i segnali SPI.
Regolatore di tensione AMS1117 da 3,3 V
Regolatore AMS1117-3.3: abbassa i 5 V a 3,3 V e regge senza problemi la corrente elevata che il modulo PA+LNA assorbe in trasmissione.

Installare la libreria RF24

  1. Nell'Arduino IDE apri Strumenti > Gestisci librerie oppure fai clic sull'icona delle librerie a sinistra.
  2. Scrivi RF24 nel campo di ricerca e installa la libreria RF24 di TMRh20. RF24Network, RF24Mesh e RF24Ethernet sono librerie separate e per iniziare non servono.
  3. Dopo l'installazione trovi l'esempio GettingStarted in File > Esempi > RF24. Il codice di questo articolo segue la sintassi di RF24 dalla versione 1.5 in poi.
  4. Se è la prima volta che installi una libreria, segui i passaggi di Come aggiungere una libreria Arduino.
Negli esempi più vecchi che trovi online vedrai radio.openWritingPipe(address) seguito da radio.stopListening(). Dalla versione 1.5 di RF24 si consiglia invece una sola riga: radio.stopListening(address). La vecchia forma compila ancora, ma può mostrare un avviso "deprecated" (deprecato). Se il codice di questo articolo non compila, aggiorna la tua libreria RF24.

Indirizzo, canale e velocità: come mettere d'accordo due moduli

Perché due moduli si sentano, alcune impostazioni devono essere identiche su entrambi i lati. Pensa a una conversazione con i walkie-talkie: se non siete sulla stessa frequenza (canale), allo stesso ritmo (velocità di trasmissione) e con lo stesso nominativo (indirizzo), non senti l'altro. L'indirizzo è un array di 5 byte, e il modo più semplice è scriverlo nel codice come testo di 5 caratteri, per esempio "00001". Non pensare all'indirizzo come all'identità di un dispositivo, ma come a un percorso condiviso tra due dispositivi: il trasmettitore lascia i pacchetti su quel percorso e il ricevitore che lo ascolta li raccoglie. Conta anche la dimensione del pacchetto: RF24 usa di default pacchetti a dimensione fissa, e se il ricevitore non si aspetta la stessa dimensione del trasmettitore, non vede mai il pacchetto.

ImpostazioneFunzione RF24Valore in questo articoloNota
CanalesetChannel(76)76 (2476 MHz)0–125; uguale su entrambi i lati
VelocitàsetDataRate(RF24_250KBPS)250 kbpsMeno velocità, più portata
IndirizzostopListening(indirizzo) / openReadingPipe(1, indirizzo)"00001"Destinazione del trasmettitore = pipe del ricevitore
Dimensione del pacchettosetPayloadSize(sizeof(dati))32 byte (5 nell'esempio con joystick)A dimensione fissa, uguale su entrambi i lati
Potenza di uscitasetPALevel(RF24_PA_LOW)BassaNon deve coincidere; determina la portata
ACK automatico e CRCAttivi di defaultCRC a 16 bitSe li disattivi, fallo su entrambi i lati

Codice del trasmettitore (TX)

Per la prima prova collega i due Arduino a due porte USB e lascia 1–2 metri tra i moduli. Carica su uno dei due il codice del trasmettitore qui sotto. Ogni secondo invia un messaggio numerato e scrive sul Monitor seriale se il ricevitore lo ha confermato. Ricordati di impostare il Monitor seriale a 115200 baud.

C++ (Arduino IDE)
1#include <SPI.h>
2#include <RF24.h>
3
4RF24 radio(9, 10);                        // CE, CSN pinleri / CE, CSN pins
5const uint8_t address[6] = "00001";       // iki tarafta aynı adres / same address on both sides
6char message[32];                         // en fazla 32 bayt / 32 bytes max
7uint16_t counter = 0;
8
9void setup() {
10  Serial.begin(115200);
11  if (!radio.begin()) {                   // modül cevap vermiyor / module not responding
12    Serial.println(F("nRF24L01 bulunamadi, kablolari kontrol et!"));
13    while (true) {}
14  }
15  radio.setChannel(76);                   // kanal 76 = 2476 MHz / channel 76 = 2476 MHz
16  radio.setDataRate(RF24_250KBPS);        // en uzun menzil / longest range
17  radio.setPALevel(RF24_PA_LOW);          // masa testi için düşük güç / low power for desk tests
18  radio.setPayloadSize(sizeof(message));  // paket boyu 32 bayt / 32-byte payload
19  radio.stopListening(address);           // verici modu + hedef adres / TX mode + target address
20}
21
22void loop() {
23  snprintf(message, sizeof(message), "Merhaba BlueGrays #%u", counter++);
24  bool ok = radio.write(message, sizeof(message));   // onay (ACK) geldi mi? / was it acknowledged?
25  if (ok) {
26    Serial.print(F("Gonderildi: "));
27    Serial.println(message);
28  } else {
29    Serial.println(F("Onay gelmedi"));
30  }
31  delay(1000);
32}

Codice del ricevitore (RX)

C++ (Arduino IDE)
1#include <SPI.h>
2#include <RF24.h>
3
4RF24 radio(9, 10);                        // CE, CSN pinleri / CE, CSN pins
5const uint8_t address[6] = "00001";       // vericiyle aynı adres / same address as the transmitter
6char message[32];
7
8void setup() {
9  Serial.begin(115200);
10  if (!radio.begin()) {
11    Serial.println(F("nRF24L01 bulunamadi, kablolari kontrol et!"));
12    while (true) {}
13  }
14  radio.setChannel(76);                   // ayarlar vericiyle aynı / settings match the transmitter
15  radio.setDataRate(RF24_250KBPS);
16  radio.setPALevel(RF24_PA_LOW);
17  radio.setPayloadSize(sizeof(message));
18  radio.openReadingPipe(1, address);      // 1 numaralı boruyu aç / open pipe 1
19  radio.startListening();                 // alıcı modu / RX mode
20}
21
22void loop() {
23  if (radio.available()) {                // paket geldi mi? / has a packet arrived?
24    radio.read(message, sizeof(message));
25    Serial.print(F("Gelen: "));
26    Serial.println(message);
27  }
28}

radio.write() invia il pacchetto e restituisce true se il ricevitore lo conferma; senza conferma, con le impostazioni predefinite ritenta 15 volte a circa 1,5 ms di distanza e poi restituisce false. Sul ricevitore, openReadingPipe(1, address) imposta la pipe 1 sull'indirizzo del trasmettitore, startListening() mette il modulo in ascolto, available() dice se c'è un pacchetto in attesa e read() lo copia nella tua variabile. Se sul Monitor seriale del ricevitore vedi righe che aumentano come "Gelen: Merhaba BlueGrays #0", "#1", "#2", il collegamento funziona.

Durante le prove non mettere i moduli attaccati e tieni bassa la potenza. Soprattutto i moduli PA+LNA saturano a vicenda i rispettivi ricevitori quando trasmettono a piena potenza a pochi centimetri di distanza, e i pacchetti si perdono, il che sembra un guasto. A breve distanza usa RF24_PA_LOW o RF24_PA_MIN e alza la potenza alla distanza reale.

Portata: da 100 metri a 1 chilometro

Tre fattori determinano la portata: la potenza di uscita, la sensibilità del ricevitore e l'ambiente. Più bassa è la velocità di trasmissione, più deboli sono i segnali che il ricevitore riesce a decodificare; la sensibilità è di −94 dBm a 250 kbps ma di −82 dBm a 2 Mbps. Quei 12 dB di differenza equivalgono, in campo aperto, a circa 4 volte la portata. Pareti, alberi, corpo umano e superfici metalliche attenuano molto il segnale a 2,4 GHz, e router Wi-Fi, dispositivi Bluetooth e forni a microonde condividono la stessa banda.

VelocitàSensibilitàPortata relativaQuando usarla?
250 kbps−94 dBmLa più lungaTelecomandi, sensori lontani
1 Mbps−85 dBmMediaUso generale (predefinito in RF24)
2 Mbps−82 dBmLa più cortaAlta velocità, breve distanza

Conta anche la scelta del canale. I canali Wi-Fi più usati, 1, 6 e 11, occupano circa da 2401 a 2473 MHz; i canali 74–83 dell'nRF24L01 stanno sopra e sono più tranquilli se nelle vicinanze nessun router usa i canali Wi-Fi 12 o 13. In Europa la banda libera dei 2,4 GHz va da 2400 a 2483,5 MHz, quindi non usare canali sopra l'83; i canali da 100 in su suggeriti da alcuni esempi online sono fuori da questa banda. Per aumentare la portata prova questi accorgimenti:

  • Usa 250 kbps: Un telecomando o i dati di un sensore non hanno bisogno di velocità, e con la velocità bassa guadagni portata.
  • Prima sistema l'alimentazione, poi alza la potenza: RF24_PA_MAX ha senso solo con 3,3 V stabili e un condensatore; con un'alimentazione debole, alzare la potenza peggiora le cose.
  • Monta le antenne in alto e con lo stesso orientamento: 1–2 metri da terra e le due antenne verticali nella stessa direzione migliorano nettamente la portata.
  • Tienilo lontano dal metallo: Non mettere il modulo dentro una scatola metallica né subito accanto a un grosso pacco batterie.
  • Avvolgi la scheda PA+LNA senza schermatura: Avvolgere un modulo PA+LNA senza coperchio metallico con nastro isolante e poi con un foglio di alluminio riduce i disturbi che crea a se stesso; l'alluminio non deve toccare nessun pin né il connettore dell'antenna.
  • Non trasmettere senza antenna: Far funzionare un modulo PA+LNA a piena potenza senza antenna sollecita l'amplificatore di potenza.

Telecomando wireless con joystick

Passiamo a un progetto vero: con un joystick collegato a un Arduino comanderemo senza fili un servomotore e un LED su un secondo Arduino. Sul trasmettitore il pin VRx del joystick va su A0, VRy su A1 e il pulsante (SW) su D2; trovi i dettagli in Modulo joystick. Sul ricevitore il filo di segnale del servo va su D3 e il LED su D4 tramite una resistenza da 220 Ω. L'nRF24L01 si collega su entrambi i lati come nella tabella precedente.

Il modo più pulito per inviare più valori in un solo pacchetto è una struct (struttura). C'è un dettaglio importante: usa tipi a dimensione fissa come int16_t e uint8_t. Un int occupa 2 byte sull'Arduino Uno ma 4 sull'ESP32, e inoltre il compilatore dell'ESP32 aggiunge byte di riempimento alla fine della struttura per allinearla. Se la stessa struttura occupa 5 byte sull'Uno e 6 sull'ESP32, le dimensioni dei pacchetti non coincidono e non arriva nessun dato. __attribute__((packed)) elimina quel riempimento e porta la struttura a 5 byte su qualsiasi scheda. Prima il trasmettitore:

C++ (Arduino IDE)
1#include <SPI.h>
2#include <RF24.h>
3
4struct __attribute__((packed)) JoystickData {   // her kartta 5 bayt / 5 bytes on every board
5  int16_t x;
6  int16_t y;
7  uint8_t button;
8};
9
10RF24 radio(9, 10);                        // CE, CSN pinleri / CE, CSN pins
11const uint8_t address[6] = "JOY01";       // kumanda adresi / remote address
12JoystickData data;
13
14void setup() {
15  pinMode(2, INPUT_PULLUP);               // joystick butonu (SW) / joystick button (SW)
16  if (!radio.begin()) {
17    while (true) {}                       // modül yok / no module
18  }
19  radio.setChannel(76);
20  radio.setDataRate(RF24_250KBPS);
21  radio.setPALevel(RF24_PA_HIGH);         // orta-yüksek güç / medium-high power
22  radio.setPayloadSize(sizeof(data));
23  radio.stopListening(address);           // verici modu / TX mode
24}
25
26void loop() {
27  data.x = analogRead(A0);                // VRx ekseni 0-1023 / VRx axis 0-1023
28  data.y = analogRead(A1);                // VRy ekseni 0-1023 / VRy axis 0-1023
29  data.button = (digitalRead(2) == LOW);  // basılıysa 1 / 1 when pressed
30  radio.write(&data, sizeof(data));
31  delay(50);                              // saniyede 20 paket / 20 packets per second
32}

Poi il ricevitore che muove il servo e accende il LED:

C++ (Arduino IDE)
1#include <SPI.h>
2#include <RF24.h>
3#include <Servo.h>
4
5struct __attribute__((packed)) JoystickData {   // vericiyle birebir aynı / identical to the transmitter
6  int16_t x;
7  int16_t y;
8  uint8_t button;
9};
10
11RF24 radio(9, 10);                        // CE, CSN pinleri / CE, CSN pins
12const uint8_t address[6] = "JOY01";       // vericiyle aynı / same as the transmitter
13JoystickData data;
14Servo servo;
15unsigned long lastPacket = 0;
16
17void setup() {
18  pinMode(4, OUTPUT);                     // LED çıkışı / LED output
19  servo.attach(3);                        // servo sinyal pini / servo signal pin
20  if (!radio.begin()) {
21    while (true) {}
22  }
23  radio.setChannel(76);
24  radio.setDataRate(RF24_250KBPS);
25  radio.setPALevel(RF24_PA_HIGH);
26  radio.setPayloadSize(sizeof(data));
27  radio.openReadingPipe(1, address);
28  radio.startListening();                 // alıcı modu / RX mode
29}
30
31void loop() {
32  if (radio.available()) {
33    radio.read(&data, sizeof(data));
34    servo.write(map(data.x, 0, 1023, 0, 180));   // X ekseni -> servo açısı / X axis -> servo angle
35    digitalWrite(4, data.button ? HIGH : LOW);   // buton LED'i yakar / button lights the LED
36    lastPacket = millis();
37  }
38  if (millis() - lastPacket > 500) {      // 0,5 sn paket yok: güvenli konum / no packet for 0.5 s: failsafe
39    servo.write(90);
40    digitalWrite(4, LOW);
41  }
42}

Il trasmettitore invia 20 pacchetti al secondo; a ogni pacchetto il ricevitore converte l'asse X in 0–180 gradi e lo passa al servo. La parte di posizione di sicurezza (failsafe) del ricevitore è fondamentale: se la batteria del telecomando si scarica o esci dalla portata, l'ultimo comando non resta applicato per sempre; se per 0,5 secondi non arriva nessun pacchetto, il servo torna al centro e il LED si spegne. Se stai costruendo un'auto robot, ferma i motori nello stesso punto. Alimentare il servo da una sorgente a 5 V separata invece che dal pin 5 V di Arduino evita anche che i suoi picchi di corrente disturbino l'nRF24L01. Collega l'asse Y a un driver per motori L298N e ottieni un'auto robot wireless; per i dettagli sul servo guarda Che cos'è un servomotore.

Comunicazione bidirezionale e più trasmettitori

L'nRF24L01 non può trasmettere e ascoltare contemporaneamente, ma c'è un modo semplice per ottenere una comunicazione bidirezionale: l'ACK payload, cioè dati inviati dentro il pacchetto di conferma. Il ricevitore prepara in anticipo con writeAckPayload() i dati da allegare alla conferma successiva (per esempio la tensione della batteria o il valore di un sensore) e il trasmettitore, dopo un write() riuscito, legge quella risposta con available() e read(). Per farlo, entrambi i lati devono chiamare enableDynamicPayloads() ed enableAckPayload(). Per più trasmettitori il ricevitore ha 6 pipe: la 0 e la 1 hanno un indirizzo completo di 5 byte, mentre le pipe 2–5 condividono il resto dell'indirizzo della pipe 1 e differiscono per un solo byte. In RF24 quel byte è il primo carattere dell'array dell'indirizzo; per questo si usano indirizzi come "1Node", "2Node" e "3Node", che cambiano solo nel primo carattere. Per reti più grandi esistono le librerie RF24Network e RF24Mesh.

Collegare l'nRF24L01 a un ESP32

Sull'ESP32 la libreria RF24 funziona senza modifiche e radio.begin() usa il bus VSPI predefinito: SCK = GPIO 18, MISO = GPIO 19, MOSI = GPIO 23. Per CSN va bene GPIO 5 e per CE GPIO 4. Il regolatore da 3,3 V delle schede ESP32 DevKit è più robusto di quello dell'Uno, ma non saltare comunque il condensatore da 10 µF. Su modelli come ESP32-C3 o ESP32-S3 i pin SPI predefiniti sono diversi, quindi controlla la piedinatura della tua scheda. Poiché anche il Wi-Fi dell'ESP32 lavora a 2,4 GHz, se usi entrambi insieme scegli un canale dell'nRF24L01 lontano dal canale Wi-Fi del tuo router. Il codice seguente legge sull'ESP32 i pacchetti del trasmettitore con joystick; con la stessa struttura puoi usare l'ESP32 come gateway che inoltra su Internet i dati dei nodi nRF24L01. Se è la prima volta che usi questa scheda, inizia da Che cos'è l'ESP32.

C++ (Arduino IDE)
1#include <SPI.h>
2#include <RF24.h>
3
4struct __attribute__((packed)) JoystickData {   // packed olmasa 6 bayt olurdu / 6 bytes without packed
5  int16_t x;
6  int16_t y;
7  uint8_t button;
8};
9
10RF24 radio(4, 5);                         // CE = GPIO 4, CSN = GPIO 5 pinleri / CE = GPIO 4, CSN = GPIO 5 pins
11const uint8_t address[6] = "JOY01";
12JoystickData data;
13
14void setup() {
15  Serial.begin(115200);
16  if (!radio.begin()) {                   // varsayılan VSPI: SCK 18, MISO 19, MOSI 23 / default VSPI pins
17    Serial.println("nRF24L01 bulunamadi!");
18    while (true) delay(1000);
19  }
20  radio.setChannel(76);
21  radio.setDataRate(RF24_250KBPS);
22  radio.setPALevel(RF24_PA_HIGH);
23  radio.setPayloadSize(sizeof(data));     // packed sayesinde 5 bayt / 5 bytes thanks to packed
24  radio.openReadingPipe(1, address);
25  radio.startListening();
26}
27
28void loop() {
29  if (radio.available()) {
30    radio.read(&data, sizeof(data));
31    Serial.printf("X=%d  Y=%d  Buton=%d\n", data.x, data.y, data.button);
32  }
33}

Se devi far comunicare solo schede ESP32 tra loro, anche ESP-NOW, che non richiede moduli aggiuntivi, è una buona scelta; il vantaggio dell'nRF24L01 è che funziona anche con schede economiche e a basso consumo come Uno, Nano e Pro Mini.

nRF24L01 con Raspberry Pi Pico e MicroPython

Per MicroPython sul Pico si usa il driver nrf24l01.py del repository ufficiale micropython-lib. Puoi copiare il file sul Pico con Thonny oppure installarlo dal computer con mpremote mip install nrf24l01. Il collegamento usa SPI0: SCK = GP2, MOSI = GP3, MISO = GP4, CSN = GP5, CE = GP6 e VCC = 3V3(OUT). I valori predefiniti del driver sono diversi da quelli di RF24 (canale 46, pacchetto da 16 byte), quindi per dialogare con Arduino impostiamo esplicitamente nel codice canale, velocità e dimensione del pacchetto. Il codice seguente decodifica sul Pico i pacchetti del trasmettitore con joystick:

MicroPython
1from machine import Pin, SPI
2import struct
3import utime
4from nrf24l01 import NRF24L01, POWER_2, SPEED_250K
5
6spi = SPI(0, sck=Pin(2), mosi=Pin(3), miso=Pin(4))   # SPI0 pinleri / SPI0 pins
7csn = Pin(5, mode=Pin.OUT, value=1)                  # CSN pini GP5 / CSN pin GP5
8ce = Pin(6, mode=Pin.OUT, value=0)                   # CE pini GP6 / CE pin GP6
9
10nrf = NRF24L01(spi, csn, ce, channel=76, payload_size=5)   # Arduino ile aynı / same as the Arduino
11nrf.set_power_speed(POWER_2, SPEED_250K)             # -6 dBm güç, 250 kbps / -6 dBm power, 250 kbps
12nrf.open_rx_pipe(1, b"JOY01")                        # vericinin adresi / transmitter address
13nrf.start_listening()                                # alıcı modu / RX mode
14print("Dinleniyor... / Listening...")
15
16while True:
17    if nrf.any():                                    # paket geldi mi? / packet waiting?
18        x, y, button = struct.unpack("<hhB", nrf.recv())   # 2 + 2 + 1 bayt / 2 + 2 + 1 bytes
19        print("X:", x, "Y:", y, "Buton:", button)
20    utime.sleep_ms(5)

struct.unpack("<hhB") trasforma i 5 byte ricevuti in due numeri con segno a 16 bit e un byte; il "<" iniziale indica l'ordine dei byte little-endian, lo stesso usato da AVR ed ESP32. Se il modulo non viene trovato, il driver solleva "nRF24L01+ Hardware not responding", l'equivalente MicroPython di begin() che restituisce false su Arduino. Se sei alle prime armi con il Pico, leggi prima Che cos'è il Raspberry Pi Pico.

radio.begin() restituisce false: soluzione passo passo

Se il Monitor seriale mostra "nRF24L01 bulunamadi" o il messaggio "radio hardware is not responding!!" degli esempi RF24, Arduino non riesce proprio a parlare con il modulo via SPI. In questo caso il problema è quasi sempre nei collegamenti o nell'alimentazione, non nel codice. Carica prima lo sketch di diagnostica qui sotto; stampa tutte le impostazioni del modulo in forma leggibile.

C++ (Arduino IDE)
1#include <SPI.h>
2#include <RF24.h>
3#include "printf.h"                       // RF24 ile gelir / ships with RF24
4
5RF24 radio(9, 10);                        // kendi CE, CSN pinlerin / your CE, CSN pins
6
7void setup() {
8  Serial.begin(115200);
9  printf_begin();                         // printPrettyDetails için / needed for printPrettyDetails
10  bool ok = radio.begin();
11  Serial.print(F("begin(): "));
12  Serial.println(ok ? "true" : "false");
13  Serial.print(F("isChipConnected(): "));
14  Serial.println(radio.isChipConnected() ? "true" : "false");
15  radio.printPrettyDetails();             // tüm ayarları yazdır / print every setting
16}
17
18void loop() {
19}
  1. Controlla MOSI e MISO: Sono i due fili che si scambiano più spesso. Su Uno e Nano MOSI = D11, MISO = D12 e SCK = D13; sul Mega sono 51, 50 e 52.
  2. CE e CSN corrispondono al codice? Se hai scritto RF24 radio(9, 10), CE va su D9 e CSN su D10. L'esempio GettingStarted di RF24 usa i pin 7 e 8; se lo provi senza modificarlo, collega i fili di conseguenza.
  3. L'alimentazione è a 3,3 V? Misura con il multimetro tra VCC e GND: dovresti leggere 3,0–3,6 V. Se il modulo è stato collegato ai 5 V anche solo una volta, potrebbe essere danneggiato.
  4. Guarda l'uscita di printPrettyDetails: Se indirizzi e registri valgono tutti 0x00 o 0xff, il bus SPI non funziona. Se i valori sembrano sensati ma la comunicazione non parte, il problema è nel pin CE, nelle impostazioni o nell'alimentazione.
  5. Accorcia i cavetti e abbassa la velocità SPI: Con cavi lunghi o allentati scrivi RF24 radio(9, 10, 4000000) per portare l'SPI dai 10 MHz predefiniti a 4 MHz.
  6. Cambia modulo: Se tutto il resto è a posto, prova un modulo di ricambio; nelle confezioni multiple economiche può capitarne uno difettoso.

Nessun dato o dati a singhiozzo: errori frequenti

SintomoCausa probabileSoluzione
begin() è true ma al ricevitore non arriva nullaCanale, velocità, indirizzo o dimensione del pacchetto diversi sui due latiConfronta le quattro impostazioni fianco a fianco nei due sketch
Nessun dato dall'Uno all'ESP32Dimensione della struct diversa (5 e 6 byte)Usa tipi a dimensione fissa e __attribute__((packed))
write() è false ma il ricevitore riceve i datiLa conferma del ricevitore non arriva al trasmettitore, di solito per l'alimentazione del ricevitoreAggiungi un condensatore da 10 µF anche sul modulo ricevitore
Dati vuoti o senza senso di continuoCavetto SPI allentato o MISO interrottoSostituisci i cavetti e abbassa l'SPI a 4 MHz
Non funziona con i moduli vicini, funziona allontanandoliIl ricevitore si satura a piena potenzaUsa setPALevel(RF24_PA_LOW) o RF24_PA_MIN
Funziona meglio se lo tocchiAlimentazione instabile o PA+LNA senza schermaturaCondensatore, regolatore separato e schermatura in alluminio
Il collegamento cade dopo pochi metriVelocità a 2 Mbps, alimentazione debole o interferenze Wi-Fi250 kbps, alimentazione pulita e un canale tra 74 e 83
Quando cerchi un guasto, torna sempre al montaggio più semplice: due moduli a 1–2 metri, RF24_PA_LOW, 250 kbps, cavetti corti e un condensatore da 10 µF. Una volta che il collegamento funziona così, aumenta passo dopo passo distanza, potenza e complessità del codice; vedrai subito a quale passaggio nasce il problema.

Idee di progetto con l'nRF24L01

  • Telecomando wireless per auto robot: Guida un'auto robot da decine di metri con un telecomando a due joystick.
  • Stazione di sensori per il giardino: Invia i dati di un sensore di umidità del terreno e la temperatura da un trasmettitore a batteria a un display in casa. Con radio.powerDown() il modulo assorbe circa 900 nA in standby; puoi stimare la durata della batteria con lo strumento Durata della batteria.
  • Allarme wireless per porte e movimento: Fai suonare un buzzer sulla centrale quando scatta un sensore PIR o un interruttore reed.
  • Rete di temperatura per più stanze: Raccogli su un solo ricevitore i dati dei sensori di sei stanze tramite sei pipe.
  • Gateway con ESP32: Inoltra con un ESP32 i dati dei nodi nRF24L01 su Internet, sullo smartphone o su una dashboard.
  • Tabellone segnapunti wireless: Aggiorna un tabellone a 7 segmenti in palestra con telecomandi a pulsanti.

Nonostante il prezzo basso, l'nRF24L01 offre più portata, latenza minore e supporto a più dispositivi rispetto al Bluetooth; chiede solo un'alimentazione pulita a 3,3 V e le stesse impostazioni sui due lati. Se vuoi comandare tutto dallo smartphone, il modulo Bluetooth HC-05 può essere più adatto, e per chilometri di portata LoRa; trovi un confronto tra le opzioni in Moduli di comunicazione wireless per Arduino. Nell'app BlueGrays trovi progetti come la comunicazione tra due Arduino, il controllo di servo e LED con joystick o un'auto radiocomandata, passo passo, con schemi elettrici e codice pronto all'uso.

Domande frequenti

Qual è la portata dell'nRF24L01?

L'nRF24L01+ standard con antenna stampata arriva a circa 50–100 metri in campo aperto a 250 kbps e a 10–30 metri al chiuso, a seconda delle pareti. La versione nRF24L01+PA+LNA con antenna esterna può raggiungere 800–1100 metri in spazio aperto e senza ostacoli. Per ottenere questi valori servono un'alimentazione pulita a 3,3 V, un condensatore da 10 µF e una velocità di trasmissione bassa.

L'nRF24L01 funziona a 5V?

No: il pin VCC lavora tra 1,9 e 3,6 V e i 5 V possono distruggere il chip. I pin di ingresso CE, CSN, SCK e MOSI però tollerano i 5 V, quindi si possono collegare ai pin SPI di un Arduino Uno senza convertitore di livello. Se vuoi alimentare il modulo dai 5 V, usa un adattatore a zoccolo con regolatore AMS1117-3.3.

Perché compare l'errore "radio hardware is not responding"?

Questo messaggio viene stampato quando radio.begin() restituisce false e indica che Arduino non riesce a comunicare con il modulo via SPI. Le cause più comuni sono MOSI e MISO invertiti, pin CE e CSN diversi da quelli del codice, un'alimentazione debole o a 5 V e cavetti allentati. Controlla i collegamenti e guarda l'uscita di printPrettyDetails() per circoscrivere il problema.

Meglio nRF24L01 o Bluetooth HC-05?

Se tra più Arduino ti servono lunga portata, bassa latenza e più dispositivi, l'nRF24L01 è la scelta migliore. Se vuoi comandare tutto dallo smartphone, scegli un modulo Bluetooth come l'HC-05 o un ESP32, perché i telefoni non parlano il protocollo dell'nRF24L01. L'HC-05 arriva di solito a circa 10 metri, mentre l'nRF24L01 va molto più lontano a un prezzo simile.

Quanti trasmettitori può ascoltare un ricevitore nRF24L01?

Un ricevitore può ascoltare 6 pipe contemporaneamente, quindi raccogliere direttamente i dati di 6 trasmettitori. Le pipe 2–5 condividono il corpo dell'indirizzo della pipe 1 e differiscono per un solo byte. Per più nodi puoi interrogare i trasmettitori a turno oppure creare reti molto più grandi con le librerie RF24Network e RF24Mesh.

L'nRF24L01 si può collegare allo smartphone?

Non direttamente: anche se lavora nella stessa banda dei 2,4 GHz, l'nRF24L01 non usa i protocolli Wi-Fi o Bluetooth. Per comandarlo dallo smartphone, metti un ESP32 al centro della tua rete nRF24L01 e passa i dati al telefono via Wi-Fi o Bluetooth. Così i nodi remoti parlano nRF24L01 e lo smartphone dialoga con l'ESP32.

Vedi tutti i progetti
Comunicazione unidirezionale tra 2 Arduino
#57Intermedio
Premium

Comunicazione unidirezionale tra 2 Arduino

Fai parlare due Arduino con un solo filo: premi il pulsante sull'uno e il LED dell'altro si accende, premi di nuovo e si spegne. La scheda che invia segnala la pressione con un breve messaggio, e quel

4.4(37)
50
Comunicazione bidirezionale tra 2 Arduino
#58Intermedio
Premium

Comunicazione bidirezionale tra 2 Arduino

Due Arduino collegati con dei fili parlano tra loro: premi il pulsante di uno e si accende la luce dell'altro, premilo di nuovo e si spegne. Entrambe le schede hanno lo stesso programma, quindi ognuna

4.5(20)
26
Controllo LED con joystick
#59Intermedio
Premium

Controllo LED con joystick

Spingi fino in fondo la levetta del joystick in una direzione e si accende il LED di quella direzione: ci sono quattro colori diversi per destra, sinistra, su e giù. Quando lasci la levetta torna al c

4.7(50)
67
Servocomando con joystick
#60Intermedio
Premium

Servocomando con joystick

Comanda due motori con un joystick, proprio come se girassi una telecamera di sicurezza. Spingendo la levetta a destra o a sinistra il servomotore in basso ruota piano, spingendola su o giù quello in

4.7(42)
58
Auto controllata via Bluetooth con L298N
#80Avanzato
Premium

Auto controllata via Bluetooth con L298N

Trasforma il telefono in un telecomando e guida la tua auto robot. L'Arduino riceve tramite un modulo Bluetooth i comandi di un'app di controllo remoto sul telefono e fa girare le ruote con un driver

5.0(38)
65
Controllare un LED dal telefono tramite Bluetooth
#34Principiante
Premium

Controllare un LED dal telefono tramite Bluetooth

Una piccola prova per accendere e spegnere le luci della tua stanza dal telefono. Il modulo Bluetooth passa all'Arduino le lettere che invii dal telefono; una lettera accende il LED rosso, un'altra qu

4.8(68)
89
Accendere e spegnere LED con ricevitore IR e telecomando
#17Intermedio
Premium

Accendere e spegnere LED con ricevitore IR e telecomando

Come comandare tre lampade senza alzarti dalla poltrona: i tasti 1, 2 e 3 del telecomando accendono i LED blu, rosso e verde, e i tasti 4, 5 e 6 li spengono nello stesso ordine. Il tasto di accensione

4.7(45)
66
Telecomando universale ESP32 IR (ricevitore IR + telecomando + 3 LED + cicalino + OLED)
#143Avanzato
Premium

Telecomando universale ESP32 IR (ricevitore IR + telecomando + 3 LED + cicalino + OLED)

Con l'ESP32 puoi leggere un telecomando IR già pronto e controllare il tuo dispositivo! In questo progetto acquisiamo i segnali di un telecomando IR a 20 tasti tramite un ricevitore a infrarossi (protocollo NEC a 38 kHz). Abbiamo definito un'azione diversa per ogni tasto: i tasti 1/2/3 attivano/disattivano tre LED distinti, il tasto PWR li spegne tutti, mentre i numeri da 4 a 9 visualizzano un messaggio specifico sul display OLED. Sul display OLED SSD1306 vengono visualizzati in tempo reale, in

4.5(9)
16