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".

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.
| Caratteristica | Valore |
|---|---|
| Frequenza | 2,400–2,525 GHz (126 canali, passo di 1 MHz) |
| Velocità di trasmissione | 250 kbps, 1 Mbps, 2 Mbps |
| Tensione di alimentazione | 1,9–3,6 V (in pratica 3,3 V) |
| Pin di ingresso | Tolleranti ai 5 V (CE, CSN, SCK, MOSI) |
| Potenza di uscita | 0, −6, −12, −18 dBm |
| Corrente (in trasmissione, 0 dBm) | Circa 11,3 mA |
| Corrente (in ricezione, 2 Mbps) | Circa 13,5 mA |
| Power down | Circa 900 nA |
| Sensibilità del ricevitore | −94 dBm (250 kbps), −85 dBm (1 Mbps), −82 dBm (2 Mbps) |
| Dimensione del pacchetto | 1–32 byte |
| Interfaccia | SPI, fino a 10 MHz |
| Numero di pipe | 6 |
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.

| Caratteristica | nRF24L01+ (antenna stampata) | nRF24L01+PA+LNA |
|---|---|---|
| Antenna | Stampata sulla scheda | Antenna SMA esterna |
| Potenza di uscita | Fino a 0 dBm (1 mW) | Fino a +20 dBm (100 mW), a seconda del modello |
| Picco di corrente in trasmissione | Circa 12 mA | Fino a 115 mA |
| Picco di corrente in ricezione | Circa 13,5 mA | Fino a 45 mA |
| Portata in campo aperto (250 kbps) | 50–100 m | 800–1100 m |
| Portata al chiuso | 10–30 m, 1–2 pareti | Più piani e qualche decina di metri |
| Alimentazione consigliata | Pin da 3,3 V + condensatore da 10 µF | Regolatore 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 nRF24L01 | Funzione | Arduino Uno / Nano | Arduino Mega | ESP32 | Raspberry Pi Pico |
|---|---|---|---|---|---|
| 1 GND | Massa | GND | GND | GND | GND |
| 2 VCC | Alimentazione (3,3 V) | 3.3V | 3.3V | 3V3 | 3V3(OUT) |
| 3 CE | Selezione modalità | D9 | D9 | GPIO 4 | GP6 |
| 4 CSN | Selezione SPI | D10 | D10 | GPIO 5 | GP5 |
| 5 SCK | Clock SPI | D13 | D52 | GPIO 18 | GP2 |
| 6 MOSI | Dati dalla scheda al modulo | D11 | D51 | GPIO 23 | GP3 |
| 7 MISO | Dati dal modulo alla scheda | D12 | D50 | GPIO 19 | GP4 |
| 8 IRQ | Interrupt (facoltativo) | Non collegato | Non collegato | Non collegato | Non collegato |
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.

Installare la libreria RF24
- Nell'Arduino IDE apri Strumenti > Gestisci librerie oppure fai clic sull'icona delle librerie a sinistra.
- 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.
- 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.
- Se è la prima volta che installi una libreria, segui i passaggi di Come aggiungere una libreria Arduino.
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.
| Impostazione | Funzione RF24 | Valore in questo articolo | Nota |
|---|---|---|---|
| Canale | setChannel(76) | 76 (2476 MHz) | 0–125; uguale su entrambi i lati |
| Velocità | setDataRate(RF24_250KBPS) | 250 kbps | Meno velocità, più portata |
| Indirizzo | stopListening(indirizzo) / openReadingPipe(1, indirizzo) | "00001" | Destinazione del trasmettitore = pipe del ricevitore |
| Dimensione del pacchetto | setPayloadSize(sizeof(dati)) | 32 byte (5 nell'esempio con joystick) | A dimensione fissa, uguale su entrambi i lati |
| Potenza di uscita | setPALevel(RF24_PA_LOW) | Bassa | Non deve coincidere; determina la portata |
| ACK automatico e CRC | Attivi di default | CRC a 16 bit | Se 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.
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)
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.
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 relativa | Quando usarla? |
|---|---|---|---|
| 250 kbps | −94 dBm | La più lunga | Telecomandi, sensori lontani |
| 1 Mbps | −85 dBm | Media | Uso generale (predefinito in RF24) |
| 2 Mbps | −82 dBm | La più corta | Alta 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:
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:
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.
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:
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.
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}- 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.
- 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.
- 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.
- 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.
- 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.
- 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
| Sintomo | Causa probabile | Soluzione |
|---|---|---|
| begin() è true ma al ricevitore non arriva nulla | Canale, velocità, indirizzo o dimensione del pacchetto diversi sui due lati | Confronta le quattro impostazioni fianco a fianco nei due sketch |
| Nessun dato dall'Uno all'ESP32 | Dimensione della struct diversa (5 e 6 byte) | Usa tipi a dimensione fissa e __attribute__((packed)) |
| write() è false ma il ricevitore riceve i dati | La conferma del ricevitore non arriva al trasmettitore, di solito per l'alimentazione del ricevitore | Aggiungi un condensatore da 10 µF anche sul modulo ricevitore |
| Dati vuoti o senza senso di continuo | Cavetto SPI allentato o MISO interrotto | Sostituisci i cavetti e abbassa l'SPI a 4 MHz |
| Non funziona con i moduli vicini, funziona allontanandoli | Il ricevitore si satura a piena potenza | Usa setPALevel(RF24_PA_LOW) o RF24_PA_MIN |
| Funziona meglio se lo tocchi | Alimentazione instabile o PA+LNA senza schermatura | Condensatore, regolatore separato e schermatura in alluminio |
| Il collegamento cade dopo pochi metri | Velocità a 2 Mbps, alimentazione debole o interferenze Wi-Fi | 250 kbps, alimentazione pulita e un canale tra 74 e 83 |
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.
Progetti da realizzare dopo questo articolo
Vedi tutti i progetti
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

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

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

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

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

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

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

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
Altri articoli
App BlueGrays
Costruisci questo circuito passo passo sul telefono
Schema, codice ed elenco componenti in un’unica schermata. Oltre 200 progetti Arduino, ESP32 e Pico da realizzare.
Inquadra con il telefono
Punta la fotocamera sul codice: si apre lo store del tuo telefono.
oppure apri lo store

