Někteří prodejci (hlavně ti z číny) uvádí že to je wifi modul, ale pravda je taková, že se s tímhle k internetu prostě nepřipojíme. Označení wifi má jen kvůli pracovní frekvenci která je stejná jako má náš wifi router. V tomto pásmu funguje i většina dálkových ovladačů RC modelů.
Frekvence 2,4GHz je u nás volně k použití, takže nám odpadá starost s placením licencí, ale na druhou stranu to ssebou nese i nevýhody. Jak už jsem psala, stejnou frekvenci má kde co, takže ve městě se může vyskytnout velké rušení a tím se může snížit efektivní dosah modulů.
Dneska si ukážeme jak posílat různá data bezdrátově s tímhle levným modulem. NRF24L01+ se v číně dá sehnat už za nějakých 15 - 20Kč s integrovanou anténou komunikující běžně na desítky metrů a ve správných podmínkách až na stovky metrů. Anebo NRF24L01+PA+LNA s přídavnou anténou za padesátku s dosahem až 1km.
Stále se prodává i varianta NRF24L01, rozdíl na který jsem narazila je asi jen v rychlosti přenosu. NRF24L01 podporuje pouze 1 a 2 MBPS. NRF24L01+(PA+LNA) podporuje rychlosti 1 a 2MBPS a 250KBPS s o něco větším dosahem.
|
|
|
Nejdřív chci upozornit na pár věcí.
1. Vstupní napětí je pouze 1,9 - 3,6V ale vstupy jsou tolerantní na 5V logiku, takže nepotřebujeme převodník logických úrovní.
2. Problémy se stabilitou můžou způsobit proudové špičky, nebo rušení z okolí. Tím se arduino občas sekne a pak se můžeme divit proč to nejde. To se dá vyřešit elektrolitickým kondenzátorem s kapacitou např. 10uF mezi piny VCC a GND modulu NRF. Hodnota kondenzátorů je jen orientační, větší kapacita by neměla být na škodu. Taky se dá sehnat napájecí modul se vším potřebným z číny asi za desetikorunu. Na otestování na stole je OK, ale nedoporučuji ho na větší výkony ani dlouhodobý provoz.
Napájecí deska pro NRF24L01 |
Knihovnu RF24 od uživatele TMRh20 stáhneme v manažeru knihoven, nebo na GitHubu. Testováno s verzí knihovny 1.1.7.
Teď se už vrhneme na zapojení. Pozor, nákres pinů je zeshora dps, ale lišta s piny je směrem dolů. Poprvé jsem si to málem zapojila opačně.
NRF24L01 | NANO/UNO | MEGA |
GND | GND | GND |
Vcc | 3,3V | 3,3V |
CE | 9 | 9 |
CS | 10 | 10 |
MOSI | 11 | 51 |
MISO | 12 | 50 |
SCK | 13 | 52 |
Můžeme si otestovat jestli to máme správně zapojené tímto kódem
#include <SPI.h> #include <nRF24L01.h> #include <RF24.h> RF24 radio(9,10); // (CE, CS) void setup(void) { Serial.begin(9600); printf_begin(); radio.begin(); radio.printDetails(); } void loop(void) { } int serial_putc( char c, FILE * ) { Serial.write( c ); return c; } void printf_begin(void) { fdevopen( &serial_putc, 0 ); }
Serial monitor:
Pokud máme zapojeno vše jak má být, uvidíme toto.. |
Něco podobného uvidíme když je modul zapojený špatně. |
Máme zapojené 2x Arduino s NRF.
Funkce je jednoduchá.
Vysílač odešle zprávu, přepne se do přijímacího módu a bude čekat na odpověď. Pokud v zadaný čas odpověď nepřijde, odešle další zprávu a bude zase čekat na odpověď.
Přijímač čeká na zprávu a když ji přijme, tak odpoví. Jednoduché.
Na pin 6 si můžeme připojit piezo pípák a po každé přijaté odpovědi arduino pípne.
Vysílač
#include <SPI.h> #include <nRF24L01.h> #include <RF24.h> #define BeepPin 6 #define CE 9 #define CS 10 //MOSI = 11 //MISO = 12 //SCK = 13 //VCC = 3,3V! RF24 radio(CE, CS); // nastavíme si adresy a kanál vysílání const byte vysilac[] = "TX001"; const byte prijimac[] = "RX001"; int kanal = 120; void setup(void) { Serial.begin(9600); radio.begin(); // nastavení rychlosti komunikace // možnosti jsouRF24_250KBPS, RF24_1MBPS, RF24_2MBPS radio.setDataRate(RF24_1MBPS); //kanál na kterém budeme komunikovat radio.setChannel(kanal); // příjem radio.openWritingPipe(prijimac); radio.openReadingPipe(1, vysilac); radio.startListening(); radio.printDetails(); // nastavení výkonu nRF modulu, // možnosti jsou RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH and RF24_PA_MAX, // pro HIGH a MAX je nutný externí 3,3V zdroj radio.setPALevel(RF24_PA_MIN); pinMode(BeepPin, OUTPUT); } // něco proměnných char MyCon[40]; char data[40]; int poradi = 1; bool state = false; int prvni = 0; String druhy = ""; long startmillis; long endmillis; void loop(void) { if (!state) { Serial.println("odesilam"); startmillis = millis(); //vysílání radio.openWritingPipe(vysilac); radio.openReadingPipe(0, prijimac); radio.stopListening(); sprintf(MyCon, "%i:%s:%i:", poradi, "kanal", kanal); radio.write(&MyCon, sizeof(MyCon)); // odeslání zprávy Serial.println(MyCon);//*** poradi++; Serial.println("odeslano"); state = true; Serial.println("cekam na odpoved"); // příjímání radio.openWritingPipe(prijimac); radio.openReadingPipe(1, vysilac); radio.startListening(); } while (state) { if (radio.available()) { //Serial.println("radio available"); // příjem radio.read( &data, sizeof(data)); prvni = atoi(strtok(data, ":")); druhy = strtok(NULL, ":"); Serial.print("mam odpoved: "); Serial.print(prvni); Serial.print(", "); Serial.println(druhy); //Beep(); state = false; } // timeout endmillis = millis() - startmillis; if ((endmillis >= 1000) && (state)) { Serial.println("timeout"); state = false; } } Serial.print("delka komunikace je "); Serial.print(endmillis); Serial.println("ms"); delay(2000); } void Beep() { int freq = 2800; //frekvence v Hz int delka = 60; //délka pípnutí v ms tone(BeepPin, freq, delka); }
Přijímač
#include <SPI.h> #include <nRF24L01.h> #include <RF24.h> #define CE 9 #define CS 10 //MOSI = 11 //MISO = 12 //SCK = 13 //VCC = 3,3V! RF24 radio(CE, CS); // adresy a kanál const byte vysilac[] = "TX001"; const byte prijimac[] = "RX001"; int kanal = 120; void setup(void) { Serial.begin(9600); radio.begin(); // nastavení rychlosti komunikace // možnosti jsouRF24_250KBPS, RF24_1MBPS, RF24_2MBPS radio.setDataRate(RF24_1MBPS); //kanál na kterém budeme komunikovat radio.setChannel(kanal); // příjem radio.openWritingPipe(prijimac); radio.openReadingPipe(1, vysilac); radio.startListening(); //radio.printDetails(); // nastavení výkonu nRF modulu, // možnosti jsou RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH and RF24_PA_MAX, // pro HIGH a MAX je nutný externí 3,3V zdroj radio.setPALevel(RF24_PA_MIN); Serial.println("ready"); } // něco proměnných char MyCon[40]; char data[40]; bool state = false; int prvni = 0; String druhy = ""; int treti = 0; void loop(void) { //Serial.print("state ");Serial.println(state); if (!state) { if (radio.available()) { Serial.println("radio available"); while (radio.available()) { radio.read( &data, sizeof(data) ); prvni = atoi(strtok(data, ":")); String druhy = strtok(NULL, ":"); int treti = atoi(strtok(NULL, ":")); Serial.print("mam zpravu: "); Serial.print(prvni);Serial.print(", "); Serial.print(druhy);Serial.print(": "); Serial.println(treti); state = true; } } } if (state) { // vysílání radio.openWritingPipe(vysilac); radio.openReadingPipe(0, prijimac); radio.stopListening(); delay(30);// pauza před odesláním //aby se druhý modul stihl přepnout pro příjem // odeslat odpoved Serial.println("odpovidam"); sprintf(MyCon, "%i:%s:", prvni, "OK"); Serial.println(MyCon); radio.write(&MyCon, strlen(MyCon)); state = false; Serial.println("odpoved odeslana"); // a zase přepnout na příjem radio.openWritingPipe(prijimac); radio.openReadingPipe(1, vysilac); radio.startListening(); } }
Kanál na kterém moduly komunikují si můžeme nastavit na číslo v rozsahu 0 - 124. Při větších (a záporných) číslech se to chová jako jeden kanál. Kanály nad 108 jsou frekvencí nad většinou domácích wifi routerů.
Adresy pro vysílač a přijímač můžou být jakýkoliv řetězec znaků a čísel. Maximální délku jsem nezkoušela.
Pokud chceme aby nám komunikovalo víc modulů spolu ale nechceme-li aby všechny moduly chytaly zprávy určené jinému, stačí měnit jen kanál před každým vysíláním, nezapomeneme však nastavit stejný kanál i na druhém zařízení jinak se samozřejmně nedomluví.
// TX & Rx adresa pro příjem radio.openWritingPipe(prijimac); radio.openReadingPipe(1, vysilac); radio.setChannel(123); radio.startListening(); // TX & Rx adr pro vysílání radio.openWritingPipe(vysilac); radio.openReadingPipe(0, prijimac); radio.setChannel(123); radio.stopListening();
A na konec sketche ke stažení z google disku. Plus odkaz na můj e-shop, kde si vše potřebné můžete zakoupit
Díky,
OdpovědětVymazattoto mi pomohlo najít dlooho hledaný problém nespolehlivého přenosu:
delay(30);// pauza před odesláním
//aby se druhý modul stihl přepnout pro příjem
Mirek