Беспроводной модуль NRF24L01 (2.4 ГГц) служит для связи микроконтроллеров между собой. Работает на частоте 2.4 ГГц (не требующая разрешений частота, которая также используется для Wi-Fi), скорость до 2 Мбит/с, управляется по интерфейсу SPI, питание 3,3 В (можно использовать вывод 3,3 В платы Arduino). Существенно дешевле xbee-модуля, хорошо подходит для промышленных систем управления. Радиус действия – в пределах квартиры, через две стены работает уверенно, через три – могут быть потери сигнала.
Распиновка
Схема подключения
Подключение с помощью переходника для NRF24L01 (3,3 В)
Тесты
nrf_listen_air – тест одного модуля, прослушивание всех каналов
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
#include <SPI.h> #include "nRF24L01.h" #include "RF24.h" RF24 radio(9,10); // инициализировать модуль на пинах 9 и 10 Для Уно //RF24 radio(9,53);// Для Меги const uint8_t num_channels = 128; uint8_t values[num_channels]; void setup(void) { Serial.begin(9600); printf_begin(); radio.begin(); radio.setAutoAck(false); radio.startListening(); radio.printDetails(); // Вот эта строка напечатает нам что-то, если все правильно соединили. delay(5000); // И посмотрим на это пять секунд. radio.stopListening(); int i = 0; // А это напечатает нам заголовки всех 127 каналов while ( i < num_channels ) { printf("%x",i>>4); ++i; } printf("\n\r"); i = 0; while ( i < num_channels ) { printf("%x",i&0xf); ++i; } printf("\n\r"); } const int num_reps = 100; void loop(void) { memset(values,0,sizeof(values)); int rep_counter = num_reps; while (rep_counter--) { int i = num_channels; while (i--) { radio.setChannel(i); radio.startListening(); delayMicroseconds(128); radio.stopListening(); if ( radio.testCarrier() ) ++values[i]; } } int i = 0; while ( i < num_channels ) { printf("%x",min(0xf,values[i]&0xf)); ++i; } printf("\n\r"); } int serial_putc( char c, FILE * ) { Serial.write( c ); return c; } void printf_begin(void) { fdevopen( &serial_putc, 0 ); } |
GettingStarted_CallResponse – тест качества связи между двумя модулями
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
/* March 2014 - TMRh20 - Updated along with High Speed RF24 Library fork Parts derived from examples by J. Coliz <maniacbug@ymail.com> */ /** * Example for efficient call-response using ack-payloads * * This example continues to make use of all the normal functionality of the radios including * the auto-ack and auto-retry features, but allows ack-payloads to be written optionlly as well. * This allows very fast call-response communication, with the responding radio never having to * switch out of Primary Receiver mode to send back a payload, but having the option to switch to * primary transmitter if wanting to initiate communication instead of respond to a commmunication. */ #include <SPI.h> #include "nRF24L01.h" #include "RF24.h" #include "printf.h" // Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 9 & 10 RF24 radio(9,10); // Topology byte addresses[][6] = {"1Node","2Node"}; // Radio pipe addresses for the 2 nodes to communicate. // Role management: Set up role. This sketch uses the same software for all the nodes // in this system. Doing so greatly simplifies testing. typedef enum { role_ping_out = 1, role_pong_back } role_e; // The various roles supported by this sketch const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"}; // The debug-friendly names of those roles role_e role = role_pong_back; // The role of the current running sketch byte counter = 1; // A single byte to keep track of the data being sent back and forth void setup(){ Serial.begin(9600); printf_begin(); printf("nrRF24/examples/GettingStarted/\n\r"); printf("ROLE: %s\n\r",role_friendly_name[role]); printf("*** PRESS 'T' to begin transmitting to the other node\n\r"); // Setup and configure radio radio.begin(); radio.setAutoAck(1); // Ensure autoACK is enabled radio.enableAckPayload(); // Allow optional ack payloads radio.setRetries(0,15); // Smallest time between retries, max no. of retries radio.setPayloadSize(1); // Here we are sending 1-byte payloads to test the call-response speed radio.openWritingPipe(addresses[1]); // Both radios listen on the same pipes by default, and switch when writing radio.openReadingPipe(1,addresses[0]); // Open a reading pipe on address 0, pipe 1 radio.startListening(); // Start listening radio.powerUp(); radio.printDetails(); // Dump the configuration of the rf unit for debugging } void loop(void) { /****************** Ping Out Role ***************************/ if (role == role_ping_out){ // Radio is in ping mode byte gotByte; // Initialize a variable for the incoming response radio.stopListening(); // First, stop listening so we can talk. printf("Now sending %d as payload. ",counter); // Use a simple byte counter as payload unsigned long time = micros(); // Record the current microsecond count if ( radio.write(&counter,1) ){ // Send the counter variable to the other radio if(!radio.available()){ // If nothing in the buffer, we got an ack but it is blank printf("Got blank response. round-trip delay: %lu microseconds\n\r",micros()-time); }else{ while(radio.available() ){ // If an ack with payload was received radio.read( &gotByte, 1 ); // Read it, and display the response time printf("Got response %d, round-trip delay: %lu microseconds\n\r",gotByte,micros()-time); counter++; // Increment the counter variable } } }else{ printf("Sending failed.\n\r"); } // If no ack response, sending failed delay(1000); // Try again later } /****************** Pong Back Role ***************************/ if ( role == role_pong_back ) { byte pipeNo, gotByte; // Declare variables for the pipe and the byte received while( radio.available(&pipeNo)){ // Read all available payloads radio.read( &gotByte, 1 ); // Since this is a call-response. Respond directly with an ack payload. // Ack payloads are much more efficient than switching to transmit mode to respond to a call radio.writeAckPayload(pipeNo,&gotByte, 1 ); // This can be commented out to send empty payloads. printf("Sent response %d \n\r", gotByte); } } /****************** Change Roles via Serial Commands ***************************/ if ( Serial.available() ) { char c = toupper(Serial.read()); if ( c == 'T' && role == role_pong_back ) { printf("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK\n\r"); role = role_ping_out; // Change roles (ping out) radio.openWritingPipe(addresses[0]); // Open different pipes when writing. Write on pipe 0, address 0 radio.openReadingPipe(1,addresses[1]); // Read on pipe 1, as address 1 } else if ( c == 'R' && role == role_ping_out ) { printf("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK\n\r"); role = role_pong_back; // Become the primary receiver (pong back) radio.openWritingPipe(addresses[1]); // Since only two radios involved, both listen on the same addresses and pipe numbers in RX mode radio.openReadingPipe(1,addresses[0]); // then switch pipes & addresses to transmit. radio.startListening(); // Need to start listening after opening new reading pipes } } } |
Приём (RX) / передача (TX) – базовая пара скетчей со всеми настройками модулей, а также примером передачи данных
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
#include <SPI.h> #include "nRF24L01.h" #include "RF24.h" RF24 radio(9,10); // "создать" модуль на пинах 9 и 10 Для Уно //RF24 radio(9,53); // для Меги byte address[][6] = {"1Node","2Node","3Node","4Node","5Node","6Node"}; //возможные номера труб void setup(){ Serial.begin(9600); //открываем порт для связи с ПК radio.begin(); //активировать модуль radio.setAutoAck(1); //режим подтверждения приёма, 1 вкл 0 выкл radio.setRetries(0,15); //(время между попыткой достучаться, число попыток) radio.enableAckPayload(); //разрешить отсылку данных в ответ на входящий сигнал radio.setPayloadSize(32); //размер пакета, в байтах radio.openReadingPipe(1,address[0]); //хотим слушать трубу 0 radio.setChannel(0x60); //выбираем канал (в котором нет шумов!) radio.setPALevel (RF24_PA_MAX); //уровень мощности передатчика. На выбор RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX radio.setDataRate (RF24_250KBPS); //скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS //должна быть одинакова на приёмнике и передатчике! //при самой низкой скорости имеем самую высокую чувствительность и дальность!! radio.powerUp(); //начать работу radio.startListening(); //начинаем слушать эфир, мы приёмный модуль } void loop() { byte pipeNo, gotByte; while( radio.available(&pipeNo)){ // слушаем эфир со всех труб radio.read( &gotByte, sizeof(gotByte) ); // чиатем входящий сигнал Serial.print("Recieved: "); Serial.println(gotByte); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
#include <SPI.h> // библиотека для работы с шиной SPI #include "nRF24L01.h" // библиотека радиомодуля #include "RF24.h" // ещё библиотека радиомодуля RF24 radio(9, 10); // "создать" модуль на пинах 9 и 10 Для Уно //RF24 radio(9,53); // для Меги byte address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"}; //возможные номера труб byte counter; void setup() { Serial.begin(9600); //открываем порт для связи с ПК radio.begin(); //активировать модуль radio.setAutoAck(1); //режим подтверждения приёма, 1 вкл 0 выкл radio.setRetries(0, 15); //(время между попыткой достучаться, число попыток) radio.enableAckPayload(); //разрешить отсылку данных в ответ на входящий сигнал radio.setPayloadSize(32); //размер пакета, в байтах radio.openWritingPipe(address[0]); //мы - труба 0, открываем канал для передачи данных radio.setChannel(0x60); //выбираем канал (в котором нет шумов!) radio.setPALevel (RF24_PA_MAX); //уровень мощности передатчика. На выбор RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX radio.setDataRate (RF24_250KBPS); //скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS //должна быть одинакова на приёмнике и передатчике! //при самой низкой скорости имеем самую высокую чувствительность и дальность!! radio.powerUp(); //начать работу radio.stopListening(); //не слушаем радиоэфир, мы передатчик } void loop() { Serial.print("Sent: "); Serial.println(counter); radio.write(&counter, sizeof(counter)); counter++; delay(10); } |