Moduł nrf24L01 z Raspberry i Arduino

Moduł nrf24l01 służy do nawiązywania bezprzewodowej komunikacji w paśmie 2.4GHz.

Moduł nrf24l01+
Moduł nrf24l01+
Moduł nrf24l01+
Moduł nrf24l01+

Umożliwia nie tylko komunikację jeden-do-jeden, ale również jeden-do-wielu. Do jego niewątpliwych zalet należy bardzo niska cena. I niewielkie zapotrzebowanie na prąd. Uruchomienie takich modułów nie powinno Wam sprawić większych problemów. Jest jednak kilka punktów, na które musicie zwrócić uwagę. I to od nich zacznę.

MOCy przybywaj?!

Moduły nrf24l01 wymagają zasilania na poziomie 3,3v.

Zasilenie nrf24l01 z 5v uszkodzi go!

Na szczęście same piny danych nrf mają tolerancję do 5v, więc możecie je bezpiecznie podłączać bezpośrednio do pinów Arduino (oczywiście również Raspberry).

Uruchomienie nrf24l01 podłączonego bezpośrednio do pinów Arduino często nie kończy się powodzeniem.

Wielu użytkowników skarży się, że po podłączeniu nrf bezpośrednio do Arduino, moduły nie zachowują się poprawnie. Mimo że początkowa inicjalizacja wydaje się kończyć powodzeniem (poprawne rezultaty wyświetlane przez funkcję radio.printDetails()), moduły nie transmitują danych albo ich nie odbierają – bez żadnego widocznego powodu. Problemy najczęściej rozwiązuje podłączenie nrf do zewnętrznego źródła zasilania. Wydawać by się więc mogło, że jest to kwestia mocy. Nic bardziej mylnego! Prąd, jaki dostarczają Arduino przez pin 3,3v jest faktycznie znacząco mniejszy niż ten z pinu 5v (150mA w porównaniu do nawet 900mA). Ale nie to jest przyczyną trudności!
Moduły nrf wymagają maksymalnie 20mA prądu – a zazwyczaj znacznie mniej. Potwierdziły to moje pomiary. Zasilanie dla nrf-a puściłem przez miernik prądu i uzyskałem wartość około 14mA. To znacząco mniej niż możliwości Arduino. To nie moc jest tu więc problemem.
Rozwiązanie podsunął mi jeden z blogów. Okazało się, że wystarczy między GND a VCC modułu wpiąć kondensator a zaczynie on działać poprawnie nawet zasilany z Arduino.

Wystarczy między GND a VCC modułu wpiąć kondensator a moduł zaczyna działać poprawnie

Ja użyłem elektrolitowego o pojemności 4.7uF (60V; taki miałem pod ręką), chociaż mniejsze również powinny spełnić swoje zadanie.

Do prawidłowego działania NRF na Arduino czasami potrzebne są dodatkowe condensatory - tu elektrolit 4,7uF
Do prawidłowego działania NRF na Arduino czasami potrzebne są dodatkowe condensatory – tu elektrolit 4,7uF

Źródła w Internecie mówią o nF aż po 10uF. Znajomy elektronik polecił mi trochę inną konfigurację:

Do prawidłowego działania NRF na Arduino czasami potrzebne są dodatkowe condensatory - tu elektrolit 1uF i ceramik 10nF
Do prawidłowego działania NRF na Arduino czasami potrzebne są dodatkowe condensatory – tu elektrolit 1uF i ceramik 10nF

Kondensatory elektrolityczne muszą być wpięte zgodnie z ich polaryzacją. Na obudowie macie zaznaczony „-” – ta nóżka musi być wpięta do masy (GND). Drugą nóżkę („+”) wpina się do zasilania (Vcc)

Jest to więc bardziej kwestia stabilności zasilania i konieczności eliminacji zakłóceń niż wymaganej mocy. Taki kondensator włożony między masę a linię zasilania działa jak filtr . Nie przepuszcza napięcia stałego – nie musicie więc obawiać się o spowodowanie zwarcia.

Konfiguracja z wieloma kondensatorami jest jednak trochę mało… kompaktowa. Postanowiłem użyć więc kondensatorów SMD z serii 0805 lutowanych bezpośrednio na nrf. Wymaga to odrobinę umiejętności i kilku dodatkowych narzędzi, w tym lutownicy, fluxa w żelu do SMD i samych kondensatorów. Flux to topnik, taki rodzaj pasty, który znacznie ułatwia lutowanie. Kosztuje kilka złotych, a prz elementach SMD jest absolutnie niezbędny. Zlutowana całość wygląda tak:

nrf24l01 z wlutowanymi kondensatorami między vcc i gnd
nrf24l01 z wlutowanymi kondensatorami między vcc i gnd

Jeden na drugim przylutowałem ceramiczne 1uF i 10nF. Zmodyfikowane w ten sposób nrf działają z Arduino bez potrzeby dodatkowego kondensatora. Więcej o filtrowaniu zakłóceń znajdziecie tutaj.

Jeden z czytelników zasugerował, że lepiej użyć kondensatory z serii 0603 – są mniejsze i pasują między piny.

Kilka dalszych faktów

Jest kilka koncepcji, które trzeba zrozumieć, zanim weźmiecie się za programowanie tych modułów. Oczywiście jeżeli chcecie zejść do poziomu bare-metal i działać na rejestrach nrf – nie ma problemu. Ciekawy tekst na temat programowania znajdziecie tutaj.
Najłatwiej jednak wykorzystać gotowe biblioteki. Większość z nich jest klonami pracy maniacbug. Poniżej kilka przydatnych pojęć:

Fakt Znaczenie
 Rura (ang. pipe)  Koncepcja rur sprowadza się do kanałów komunikacyjnych między odbiornikiem a nadajnikiem. Są to kanały logiczne dzielące przestrzeń określoną przez kanał fizyczny (wybrana częstotliwość)
Adres rury Rury identyfikowane są poprzez adresy. Przykłady do bibliotek posługują się 2-ma adresami: pipes[0]: adres docelowy oraz pipes[1]: adres źródłowy. Domyślnie adresy ustawione są na ciągi 5 bajtowe. Razem do wyboru macie 6 rur:

  • 1 nadająca (ang. writing pipe),
    • do otwarcia służy instrukcja OpenWritingPipe; podajecie tylko jej adres
    • do zapisu służy funkcja funkcja write – podajecie adres bufora do zapisu i jego długość
  • 5 odbierających (ang. reading pipe),
    •  Do otwarcia służy instrukcja openReadingPipe – podajecie numer rury i jej adres;
    • Do sprawdzenia, czy coś czeka do odebrania służy funkcja available – zwraca True, gdy coś może być odebrane;
    • Do odebrania z rury służy funkcja read

Pełne 5-bajtowe adresy nadaje się tylko rurze nadającej (0) i pierwszej odbierającej (1). Pozostałe 4 rury odbierające mają takie same pierwsze 4 bajty adresu rury odbierającej 1 (można ustawić tylko ostatni bajt – LSB – least significant byte). Więcej o nadawaniu rurom adresów znajdziecie tutaj

Potwierdzenie odbioru – EN_AA (ang. auto-acknowledge) Mechanizm ten polega na potwierdzaniu faktu odebrania transmisji. Gdy jest włączony:

  • Nadajnik wysyła dane i przełącza się na odbiór
  • Odbiornik odbiera dane, przełącza się na wysyłanie i wysyła potwierdzenie do nadajnika
  • Nadajnik odbiera potwierdzenie i znów przełącza się w tryb nadawania

Scenariusz z problemem:

  • Nadajnik wysyła dane i przełącza się na odbiór
  • Odbiornik odbiera dane, przełącza się na wysyłanie i wysyła potwierdzenie do nadajnika
  • Nadajnik nie odbiera potwierdzenia: wysyła dane jeszcze raz i znów przełącza się w tryb nadawania oczekując potwierdzenia. Powtarza to zaprogramowaną ilość razy

AutoAck zadziała jedynie, gdy adres odbiorczej rury 0 jest taki sam jak adres do nadawnia (TX) – dla nadajnika i odbiornika.

Stworzenie obiektu radio Do obsługi radia, trzeba najpierw stworzyć obiekt klasy RF24. Przy wywołaniu jego konstruktora podaje się 2 parametry: pin CE i CSN; na przykład dla CE podłączonego do pinu 9 a CSN do 10:
RF24 radio(9,10);
 Uruchomienie radia  Funkcja begin jest odpowiedzalna za uruchomienie radia. Wykonuje również inicjalizację szyny SPI. Musicie zawołać ją przed wywołaniem jakiejkolwiek funkcji obiektu klasy RF24. Dla Arduino, wywyołanie begin umieście wewnątrz funkcji setup():
RF24 radio(9,10);
//...
void setup(){
//...
radio.begin
//...
}
 Parametry nadawania  Parametry nadawania muszą być identyczne po obydwu stronach. Jeżeli będą różne – transmisja nie dojdzie do skutku (nie zostaniecie w żaden sposób o tym powiadomieni). Biblioteki ustawiają pewne wartości domyślne – ale mogą być one różne dla każdej z nich. Krytyczne są (tzn. jeżeli będą różne dla nadajnika i odbiornika – transmisja się nie uda):

  • Kanał transmisji: ustawiany funkcją setChannel() – domyślnie 0x4C (RF_CH w statusie);
  • Szybkość transmisji: ustawiany funkcję setDataRate() – domyślnie RF24_1MBPS; najstabilniejsze ustawienie to RF24_250KBPS  (‚Data Rate’ w statusie);
  • Rozmiar sumy kontrolnej CRC: ustawiane funkcją setCRCLength(), RF24_CRC_8 lub domyślne RF24_CRC_16 (‚CRC Length w statusie);
  • Automatyczne potwierdzenie: ustawiane funkcją setAutoAck();
  • Rozmiar paczki danych: ustawiany metodą setPayloadSize(); (uwaga: ustawienie na odbiorniku może przeszkodzić w odbiorze)

Pinologia

Piny nrf24l01
Piny nrf24l01

Układ komunikuje się z zarządzającym nim kontrolerem za pomocą szeregowego interfejsu SPI (piny MISO, MOSI, CLK). Transmisja ma charakter pół-dupleksu (ang. half-duplex) – tzn. na raz dane przesyła tylko jedno z urządzeń. Szczegóły pinów znajdziecie poniżej.

Pin Nazwa Kierunek Znaczenie
1: GND  GND Wejście Masa
2: VCC  VCC Wejście Zasilanie 1.6-3.5V; pamiętajcie o kondensatorze filtrującym
3: CE Chip Enable Wejście Wybiera pomiędzy nadawaniem lub odbiorem. Jeżeli urządzenie odbiera dane, CE powinno być w stanie wysokim; monitoruje wtedy otoczenie i nasłuchuje transmisji.
Jeżeli urządzenie nadaje dane, CE powinno być w stanie niskim (nie monitoruje otoczenia) – oprócz momentów, w których dane są wysyłane
4: CSN SPI chip select (NOT) Wejście Normalnie w stanie wysokim; w stanie niskim gdy program wysyła komendy SPI lub czyta z niego dane.
5: SCK Clock Wejście Zegar SPI.
6: MOSI Master (uC) Out, Slave (nrf) In Wejście Odbiór danych z jednostki sterującej nrf – np. Arduino
7: MISO Master In, Slave Out Wyjście Wyjście danych z nrf to uC
8: IRQ  Interrupt  Wyjście  Generuje przerwanie w odpowiedzi na różne zdarzenia.

Podłączenie dla Arduino

Ten moduł wymaga zasilania 3,3V. Nie ma z tym większego problemu na Arduino UNO, Mega czy Nano. Dla 5V ProMini musicie zastosować dodatkową przetwornicę step-down; Pamiętajcie o kondensatorach!

Pin Arduino Pin nrf24 Pin nrf24 Pin Arduino
GND 1:GND 2: VCC 3,3V
Dowolny (u mnie 9) 3:CE 4:CSN Dowolny (u mnie 10)
13 5: SCK 6:MOSI 11
12 7:MISO 8: IRQ

Zacznijcie od zainstalowania biblioteki RF24. Znajdziecie ją tutaj..

W Sieci znajdziecie wiele bibliotek, które najczęściej są klonami oryginalnej pracy maniacbug. Ja korzystam z innej biblioteki, głównie dlatego, że jest dostępna dla Arduino i Raspberry

Zamknijcie wszystkie okna Arduino IDE. Pobierzcie plik zip i rozpakujcie do katalogu instalacyjnego Arduino IDE, np. „C:\Program Files (x86)\Arduino\libraries”. Zmieńcie nazwę katalogu „RF24-master” na „RF24”. uruchomcie Arduino IDE.
Proponuję zacząć od analizy przykładu „Przykłady->RF24->pingpair”. Podstawowa klasa nazywa się RF24. Jej konstruktor przyjmuje 2 parametry: pin ce i csn; w naszym przypadku:
RF24 radio(9,10);
Kod ten znajdziecie w linijce 29 przykładu. Kolejna ważna informacja znajduje się w linijce 40:
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };
Są to adresy rur wychodzącej (…E1) i odbierającej (…D2).
Przykład instaluje się na dwóch Arduino. Jeden z nich będzie pełnił rolę nadajnika (ang. ping out) a drugi odbiornika (ang. pong out). Arduino mogą zmieniać się tymi rolami. Rolę określa się poprzez zwarcie pinu 7 do masy:

  • Pin 7 zwarty do masy: nadawanie (tryb ping-out)
  • Pin 7 „wolny”: odbieranie (tryb pong-back)

Po zwarciu/rozwarciu musicie zrestartować Arduino. Zgodnie z powyższym:

  • Podłączcie pierwszy NRF do Arduino, nie zapomnijcie o kondensatorach;
  • Pin 7 tego Arduino zewrzyjcie do masy (GND). To będzie nadajnik (tryb ping-out);
  • Wgrajcie przykład pingpair na pierwsze Arduino
  • Podłączcie NRF do drugiego Arduino, nie zapomnijcie o kondensatorach;
  • Wgrajcie przykład pingpair na drugie Arduino; to będzie odbiornik (tryb pong-out);
  • Zasilacie obydwa Arduino i na monitorze ortu obserwujecie komunikację.

Zasilcie obydwa Arduino. Na monitorze portu nadającego Arduino powinniście zaobserwować:

RF24/examples/pingpair/
ROLE: Ping out
STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1 = 0xf0f0f0f0e1 0xf0f0f0f0d2
RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6
TX_ADDR = 0xf0f0f0f0e1
RX_PW_P0-6 = 0x08 0x08 0x00 0x00 0x00 0x00
EN_AA = 0x3f
EN_RXADDR = 0x03
RF_CH = 0x4c
RF_SETUP = 0x07
CONFIG = 0x0f
DYNPD/FEATURE = 0x00 0x00
Data Rate = 1MBPS
Model = nRF24L01+
CRC Length = 16 bits
PA Power = PA_HIGH
Now sending 87...ok...Got response 87, round-trip delay: 7
Now sending 1096...ok...Got response 1096, round-trip delay: 4
Now sending 2101...ok...Got response 2101, round-trip delay: 4
Now sending 3105...ok...Got response 3105, round-trip delay: 3
Now sending 4110...ok...Got response 4110, round-trip delay: 5

Jeżeli macie taki właśnie wydruk – gratulacje, wszystko się udało.
Do tego doświadczenia użyłem nrf-ów z wlutowanymi SMD (patrzcie powyżej). Możecie osiągnąć to samo z elementami przewlekanymi, po prostu wymaga to trochę więcej przewodów łączących.

2 Arduino rozmawiają przez nrf24L01
2 Arduino rozmawiają przez nrf24L01

Coś nie wyszło…

  • Jeżeli na konsoli zobaczycie coś w stylu:
    RF24/examples/pingpair/
    ROLE: Ping out
    STATUS = 0xff RX_DR=1 TX_DS=1 MAX_RT=1 RX_P_NO=7 TX_FULL=1
    RX_ADDR_P0-1 = 0xffffffffff 0xffffffffff
    RX_ADDR_P2-5 = 0xff 0xff 0xff 0xff
    TX_ADDR = 0xffffffffff
    RX_PW_P0-6 = 0xff 0xff 0xff 0xff 0xff 0xff
    …zapewne coś jest nie tak z podłączeniem pinów; sprawdźcie połączenia.
  • Jeżeli na konsoli zobaczycie:
    Now sending 87...failed.
    Failed, response timed out.
    Now sending 1792...failed.
    Failed, response timed out.
    Now sending 3493...failed.
    Failed, response timed out.
    …sprawdźcie parametry transmisji – jak adresy rur i konfiguracja ustawiana przez setChannel(), setDataRate(), setCRCLength(), setAutoAck(), setPayloadSize()

Instalacja dla Raspberry Pi

Moduł należy podłączyć w następujący sposób:

Pin nrf Pin RPi – fizyczny GPIO RPi (BCM)
GND (1) 6 (lub inny GND)
PWR (2) 1 (lub inny 3,3V)
CE (3) 22 GPIO25
CSN (4) 24 GPIO8
SCK (5) 23 GPIO11
MOSI (6) 19 GPIO10
MISO (7) 21 GPIO9

Do podłączenia wystarczy 7 kabli żeńsko-żeńskich (pinu IRQ nie będziemy tu wykorzystywać). Zasilanie Raspberry jest na tyle stabilne, że najczęściej nie wymaga kondensatora filtrującego.

Ten moduł jest zasilany napięciem 3,3V. Niektóre instrukcje zalecają podłaczenie CSN do pinu 26 (CE1). Jeżeli to nie zadziała – podłączcie CSN do pinu 24 (GPIO8, CE0) – u mnie tylko tak działa.

Po podłączeniu, kolejnym krokiem jest konfiguracja Raspbiana i instalacja odpowiedniego oprogramowania:

  • Jak zawsze na początek:
    $ sudo apt-get update
  • Upewnijcie się, że SPI jest włączone:
    $ lsmod
    ...
    spi_bcm2708 6018 0

    Jeżeli modułu spi nie ma na liście:

    • Upewnijcie się, że nie jest na liście blokowanych:
      $ sudo nano /etc/modprobe.d/raspi-blacklist.conf

      Jeżeli istnieje, wstawcie znak komentarza ‚#’ przed wpisem typu spi-bcm2708
    • Dodajcie moduł SPI do startu:
      $ sudo nano /boot/config.txt

      Dodajcie linijkę:
      dtparam=spi=on

      Zrestartujcie:
      $ sudo reboot
  • Przejdźcie do katalogu domowego i zainstalujcie biblioteki:
    $ cd ~
    $ git clone https://github.com/stanleyseow/RF24
    $ cd RF24/RPi/RF24
    $ make
    $ sudo make install
  • Przejdźcie do katalogu z przykładami i spójrzcie na plik gettingstarted.cpp:
    $ cd ~/RF24/RPi/RF24/examples/
    $ nano gettingstarted.cpp

    Od linijki 36 zmień na (moje komentarze pod [am]):

    //[am] Usun komentarz i zmien pin z 26 na 24
    RF24 radio(RPI_V2_GPIO_P1_22, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_1MHZ);
    // Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 4Mhz
    //RF24 radio(RPI_V2_GPIO_P1_15, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ);
    // Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 8Mhz
    //[am] Wstaw komentarz
    //RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ);
    // Radio pipe addresses for the 2 nodes to communicate.
    //[am] Wstaw znaki komentarza
    //const uint8_t pipes[][6] = {"1Node","2Node"};
    //[am] Odkomentuj i zmień
    const uint64_t pipes[2] = { 0xf0f0f0f0e1LL, 0xf0f0f0f0d2LL };
    ...
    int main(int argc, char** argv){
     ...
     radio.begin();
     //[am] Dodajcie: ustawienie szybkosci przesylu danych
     radio.setDataRate(RF24_1MBPS);
    
  • Skompilujcie przykłady i uruchomcie ten zmodyfikowany:
    $ make
    $ sudo ./gettingstarted

Na ekranie powinieneś zobaczyć coś w stylu (efekt funkcji printDetails):
================ SPI Configuration ================
CSN Pin = CE0 (PI Hardware Driven)
CE Pin = Custom GPIO25
Clock Speed = 1 Mhz
================ NRF Configuration ================
STATUS = 0x02 RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=1 TX_FULL=0
RX_ADDR_P0-1 = 0xf0f0f0f0d2 0xf0f0f0f0e1
RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6
TX_ADDR = 0xf0f0f0f0d2
RX_PW_P0-6 = 0x20 0x20 0x00 0x00 0x00 0x00
EN_AA = 0x3f
EN_RXADDR = 0x03
RF_CH = 0x4c
RF_SETUP = 0x07
CONFIG = 0x0e
DYNPD/FEATURE = 0x00 0x00
Data Rate = 1MBPS
Model = nRF24L01+
CRC Length = 16 bits
PA Power = PA_MAX
************ Role Setup ***********
Choose a role: Enter 0 for pong_back, 1 for ping_out (CTRL+C to exit)

Oznacza to, że moduł wystartował poprawnie.
W tym przykładzie, wybranie:

  • 0 (pong back): moduł najpierw czeka, aż coś jest do odebrania; potem odsyła to samo (liczbę);
  • 1 (ping out): moduł wysyła liczbę a potem czeka na odpowiedź (tą samą liczbę); wtedy podaj czas podróży wiadomości (ang. round-trip time)

Program zatrzymuje się wciskająć [Ctrl]+[C]. Jeżeli przerwiecie go w inny spoób, musicie zabić jego proces (instrukcją sudo kill -9 ...).

Uwaga: jeżeli widzicie, że adresy rur nie ustawiają się poprawnie, uruchomcie aplikację ./gettingstarted i – pomimo dziwnych danych w statusie – wybierzcie opcję 0 lub 1 a później wyjdźcie z programu wciskając CTRL-C. Przy następnym uruchomieniu powinno być lepiej.

Słowo o statusie

Odczarujmy jeszcze wyjście z instrukcji printDetails:

STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1 = 0xf0f0f0f0d2 0xf0f0f0f0e1
RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6
TX_ADDR = 0xf0f0f0f0d2
RX_PW_P0-6 = 0x20 0x20 0x00 0x00 0x00 0x00
EN_AA = 0x3f
EN_RXADDR = 0x03
RF_CH = 0x4c
RF_SETUP = 0x07
CONFIG = 0x0f
DYNPD/FEATURE = 0x00 0x00
Data Rate = 1MBPS
Model = nRF24L01+
CRC Length = 16 bits
PA Power = PA_HIGH

 Pole Znaczenie
Status: 1 bajt Ten bajt jest rezultatem testowego zapisu do SPI. Wywoływana jest tu funkcja bcm2835_spi_transfer
RX_DR Przerwanie: sygnalizuje odebranie pakietu – stan wysoki, gdy dane nadchodzą
TX_DS Przerwanie: sygnalizuje nadanie pakietu – stan wysoki, gdy nadany
MAX_RT Przerwanie: aktywowane gdy przekroczono maksymalną ilość nadanych pakietów (musi być wyczyszczony, żeby kontynuować nadawanie)
RX_P_NO Rura, na której odbierane są dane; 7 to binarnie 111 – pusto
TX_FULL Flaga przepełnienia bufora nadawania
RX_ADDR_P0-1 Adresy rur 0 i 1
RX_ADDR_P2-5 Adresy rur 2-5 (tylko LSB, pierwsze 4 MSB jak dla 1)
TX_ADDR Adres nadawania
RX_PW_P0-6 Ilość bajtów danych przesyłanych w jednym pakiecie dla każdej z rur: 0 – nie używana, 0x20 = 32 bajty, maksymalna wartość
EN_AA Automatyczne potwierdzenie (ang. AutoAcknowledge)
EN_RXADDR Które z rur odbierających jest włączone, 0x3 = binarnie 101, czyli P0 i P2
RF_CH Kanał, częstotliwość na której zachodzi komunikacja
RF_SETUP  Ustawienia sekcji RF
Config bajt konfiguracji; np. 2 bit ustawiony na 1 to power up
DYNPD/FEATURE  <nie znalazłem tego opcode>
Data Rate Szybkość przesyłu danych
Model model nadajnika (może być z ‚+’)
CRC Length Długość pola CRC – sumy kontrolnej danych
PA Power Moc nadajnika

Podsumowanie

Uruchomienie modułów nrf24L01 wcale nie jest skomplikowane. Mogą być one bardzo przydatne w Waszych projektach. Są tanie, pobierają niewiele prądu a ich obsługa również nie powinna nastręczyć Wam zbyt wiele problemów. Myślę, że są ciekawą alternatywą dla dużo bardziej skomplikowanych esp8266. Jeżeli potrzebujecie po prostu skomunikować bezprzewodowo dwa (lub więcej) moduły – mogą okazać się bardzo przydatne.

Źródła

Dużo i na temat
Biblioteka RF24 maniacbug
Biblioteka z której skorzystałem
Bardzo ciekawy i wyczerpujący tekst o nrf
Więcej o nadawaniu rurom adresów znajdziecie tutaj
Więcej o filtrowaniu zakłóceń

18 myśli nt. „Moduł nrf24L01 z Raspberry i Arduino”

  1. ….”Jest to więc bardziej kwestia stabilności zasilania i konieczności eliminacji zakłóceń niż wymaganej mocy. Taki kondensator włożony między masę a linię zasilania działa jak filtr . Nie przepuszcza napięcia stałego – nie musicie więc obawiać się o spowodowanie zwarcia.”

    nie mogę się z tym zgodzić w 100%, NRF pracuje na bardzo wysokiej częstotliwości, pomiar miernikiem przystosowanym do pomiarów DC nie zdąży pokazać szpilek prądowych jakie pobiera NRF w czasie ułamka sekundy zwłaszcza w trybie pracy Burst Mode – odsyłam do noty NRF. Zobaczymy tylko UŚREDNIONY wynik pomiaru…. potrzebny jest szybki oscyloskop mierzący napięcie na oporniku szeregowym.

    „Nie przepuszcza napięcia stałego” tak, ale tylko gdy połączony jest z odbiornikiem energii w szeregu a tu jest przecież równolegle… nieprawdaż ? więc to nie jest prawdą.

    Dodanie małego kondensatora załatwia sprawę ponieważ kondensator szybko dostarcza prądu o dużej wartości w momencie nadawania ramek przez NRF (Burst) natomiast długi przewód lub scieżka drukowana ma spory opór przez co chwilowo „siada” napięcie na NRF i działa niestabilnie. Przykład z życia – jak zapalamy silnik to przygasa światło w samochodzie…..tu dzieje się to samo tylko o wiele szybciej i częściej. Za duży kondensator nie zda egzaminu bo nie będzie wstanie szybko oddać energii w momencie nadania ramki przez NRF.
    Proponuję kondensator ceramiczny 1…10nF oraz elektrolit LOW SR 10uF przylutowane jak najbliżej układu.
    Można też spróbować połączyć NRF w szeregu przez diodę schotkeyego przez co ładunek z kondensator nie cofnie się do arduino/raspberry itp lecz pozostanie przy NRF. Dioda spowoduje spadek napięcia o ok 0,4V o czym trzeba pamiętać.

    Pozdrawiam

  2. Chciałbym zauważyć, iż pomiędzy VCC a GDN można z powodzeniem wstawić ceramiczne kondensatory smd wielkości nie 0805 a 0603 – które po wlutowaniu nie wystają (idealnie mieszczą się w przestrzeni między wystającymi pinami). Właściwie wystarczy dać 1 kondensator 4,7uF/6.3V 0603 i wszystko działa dobrze oraz co najważniejsze wygląda o niebo lepiej niż w tym artykule.

    1. Witaj,
      dziękuję za komentarz. 0603 nie przymierzałem – są trochę dla mnie… za małe – ale następnym razem na pewno spróbuję:)
      Pozdrawiam

  3. Co do systemów wielorurowych – to jest z tym wiele problemów.
    Delikatnie mówiąc to nie działa, ja to testowałem bez powodzenia – nie wiem jaki jest tego problem, ale wiem, że nie tylko u mnie to nie działało. Trzeba np. otworzyć dwie rury np. 0 i 1 spróbować do nich wysłać coś. Niestety odbiera tylko rura 0 i powoduje przerwanie, rura 1 jest nieaktywna (oczywiście adresy Tx należy zmieniać). TX adresowany na rure 0 (pipe 0) idealnie działa, TX adresowany na rure 1 – nie działa:-))))
    Tyle o systemie wielorurowym. Teoria teorią – praktyka praktyką. pzd!!!

    1. Witam,
      nie próbowałem żadnej konfiguracji z wieloma rurami – ale dzięki za wskazówkę!
      Pozdrawiam

  4. Witam. Ciekawe czy ktoś to jeszcze czyta:(
    Mam ten moduł w urządzeniu i potrzebuje przechwycić z niego sygnał ale nie mam bladego pojęcia jak to zrobić itp:(
    pomocy

    1. Witaj,
      przynajmniej autor:) Powiedz o co Ci chodzi – nie wiesz jak z sparować nadajnik z odbiornikiem?
      Pozdrawiam,
      A

  5. Witaj
    Moduły działają poprawnie.W związku z czym mam pytanie użytkowe.
    Może głupie pytanie ale jak wysłać za jego pomocą zmienna np z DS18b20 i potem odczytać ją na drugim (Arduino).

    1. Witaj,
      myślę, że najlepiej będzie spojrzeć na przykłady z Plik/Przykłady/RF24 np. GettingStarted. Znajdziesz tam dokładny szkielet programu. Połączenie go z biblioteką do obsługi ds18b20 nie powinno być problemem.
      Pozdrawiam,
      A

  6. Może ktoś będzie mi w stanie pomóc z moim problemem.
    Kupione moduły gdzieś półtora roku temu, dopiero kilka dni temu postanowiłem odpalić. I od samego początku same problemy. Mam dodany kondensator przy pinach od napięcia, a jednak nic to nie dało. Po wielu godzinach prób i błędów ostatecznie jedynym pewnym rozwiązaniem było dolutowanie po kawałku przewodu na końcu ścieżki będącej anteną. W takiej postaci moduł komunikuje się z drugim w programie pod Arduino o nazwie pinkpair i Getstarted.
    Jednak jakikolwiek inny program nie działa bo te moduły zwyczajnie się nie komunikują ze sobą. A mam na myśli programy przykładowe, gdzie wystarczy tylko wgrać i zaczynają działać. Nie wiem na ile ma to związek z tym, że te moduły od samego początku sprawiały problemy ale skoro na jednym programie współpracują to jaki to może być powód, że na drugim już nie współpracują?

  7. Witam,

    Targnąłem się na sterowanie modułami z poziomu uC przez SPI bez wsparcia jakiejkolwiek biblioteki. Do pojedynczego uC podłączyłem 2 układy i do testów wysyłam z jednego i odbieram na drugim. Udało mi się przesłać dane z jednego do drugiego poprawnie (moduł RX odebrał wszystko poprawnie, wystawił RX_DS – status 0x40, zczytałem dane i po zczytaniu danych mam RX_FIFO_EMPTY=1, czyli wszystko ok). Niestety nadajnik zwraca TX_FIFO_EMPTY=0 oraz status 0x1e, czyli pojawia się przerwanie na MAX_RT. Najdziwniejsze jest to, że odbiornik odebrał tylko jeden pakiet i jest on poprawny. Oba moduły skonfigurowane są w trybie shock_burst i mają włączony tryb auto_ack. Adresy w TX_ADDR i RX_ADDR_P0 poprawnie sparowane. (TX_ADDR_DRV = RX_ADDR_P0_MON i vice versa).

    1. Ok, namierzyłem przyczynę. Nie doczytałem, że w trybie ESB w nadajniku TX_ADDR i RX_ADDR_P0 muszą być takie same, bo odbiornik nadaje ACK z adresem nadajnika.

        1. Nie podaję kontaktu w komentarzach publicznych. Jeżeli masz pytania, to zapraszam na XboxForum.pl – user Petroz. Odezwij się na prv.

          Pozdrawiam!

    1. Witam,
      nie sądzę, że to najlepszy pomysł. analogWrite generuje sygnał PWM. W tym przypadku będzie to sygnał o wypełnieniu jakieś 16%. Nadaje się to do sterowania np. jasnością LED albo serwem – ale będzie zbyt mało stabilne do zasilania nrf.
      Pozdrawiam,
      Arek

  8. Witam. Walczę z tymi modułami. Zakupiłem na ebayu. Po wraniu prostego kodu
    „// nRF24L01+ Active Test
    #include
    #include
    #include „printf.h”
    #define RF_CS 9
    #define RF_CSN 7
    RF24 radio(9,10);
    void setup() {
    Serial.begin(9600);
    printf_begin();
    radio.begin();
    radio.printDetails();
    }
    void loop() {

    }”

    dostaje takie wyniki ”
    1 moduł
    STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
    RX_ADDR_P0-1 = 0xe7e7e7e7e7 0xc2c2c2c2c2
    RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6
    TX_ADDR = 0xe7e7e7e7e7
    RX_PW_P0-6 = 0x00 0x00 0x00 0x00 0x00 0x00
    EN_AA = 0x3f
    EN_RXADDR = 0x03
    RF_CH = 0x4c
    RF_SETUP = 0x07
    CONFIG = 0x0e
    DYNPD/FEATURE = 0x00 0x00
    Data Rate = 1MBPS
    Model = nRF24L01+
    CRC Length = 16 bits
    PA Power = PA_MAX

    i drugi moduł:
    STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
    RX_ADDR_P0-1 = 0xe7e7e7e7e7 0xc2c2c2c2c2
    RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6
    TX_ADDR = 0xe7e7e7e7e7
    RX_PW_P0-6 = 0x00 0x00 0x00 0x00 0x00 0x00
    EN_AA = 0x3f
    EN_RXADDR = 0x03
    RF_CH = 0x4c
    RF_SETUP = 0x07
    CONFIG = 0x0e
    DYNPD/FEATURE = 0x00 0x00
    Data Rate = 1MBPS
    Model = nRF24L01+
    CRC Length = 16 bits
    PA Power = PA_MAX

    Czy wyniki otrzymane są poprawne ??

  9. Hej, zainteresował mnie Twój artykuł na tyle, że postanowiłem się zainteresować tematem w domowym zaciszu;)
    Czy wiesz może, czy jest szansa na podsłuchanie (sklonowanie) nadajnika (pilot) działającego właśnie na 2.4Ghz? Mam w domu oświetlenie LED sterowane właśnie poprzez takie piloty (nie jest to milight tylko jakiś chiński wynalazek) i zastanawiam się jak ugryźć temat.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *