Радиомодули nRF24L01+ и Arduino

Невероятно популярные беспроводные модули, идеальное, недорогое решение для объединение микроконтроллеров в беспроводную сеть, ниже код и дополнение к серии видео



Модули построены на микросхеме nRF24L01+, основное предназначение микросхемы беспроводная связь различных периферийных устройств, вроде беспроводных мышек и клавиатур.

Китайская промышленность выпускает несколько модификаций модулей на этих чипах, различающиеся способом монтажа, наличием усилителя мощности и коннектора для внешней антенны.

IMG_2972nrf_pa

Слева типичный китайский модуль, средняя стоимость за такой один доллар. Справа модуль с усилителем мощности и коннектором для внешней антенны, за такой придется отдать около трех.

Основные характеристики модулей.

Рабочая частота: 2.4ггц
Выходная мощность передатчика: 0dBm (1mW), в версии с усилителем 20dBm (100mW)
Радиус действия в прямой видимости: до 30м, в версии с усилителем до 1000м
Скорость беспроводного соединения: 250kbps, 1Mbps или 2Mbps.
Количество каналов: 126

 

Распиновка модуля.

IMG_2972-Edit

Модуль работает с микроконтроллером по средствам интерфейса SPI, соответственно модуль должен подключатся к интерфейсу SPI ардуины, который находится на определенных контактах микроконтроллера, на фото указаны номера выходов для Arduino UNO или других, базирующихся на микроконтроллере ATMega328. Не забываем что у Arduino leonardo, Mega, и тд, интерфейс SPI находится на других контактах.

Питание модуля 3,3 вольта, вообще к питанию модуль очень привередлив, крайне желательно использовать отдельный от Arduino стабилизатор, например на микросхеме AMS1117-3.3, также желательно припаять дополнительный керамический конденсатор фильтра на контакты питания.

Для работы с модулем в среде Arduino написано несколько библиотек, мне понравилась библиотека RF24, скачать можно тут или тут, краткое описание функций библиотеки на английском языке тут.

Также существует более оптимизированное и полностью совместимое ответвление от основной версии RF24, находится тут.


Ниже исходные коды, которые были показаны в роликах на ютубе.
Радиомодули nRF24L01+ и Arduino, часть 1

Первый пример, передача данных с аналогового входа. Приемник
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h> // https://github.com/maniacbug/RF24

const uint64_t pipe = 0xF0F1F2F3F4LL; // индитификатор передачи, "труба"

RF24 radio(9, 10); // CE, CSN
  
void setup(){
  Serial.begin(9600);
  
  radio.begin();  
  delay(2);
  radio.setChannel(9); // канал (0-127)
  
      // скорость, RF24_250KBPS, RF24_1MBPS или RF24_2MBPS
      // RF24_250KBPS на nRF24L01 (без +) неработает.
      // меньше скорость, выше чувствительность приемника.
  radio.setDataRate(RF24_1MBPS);     
  
      // мощьность передатчика RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_MED=-6dBM,
  radio.setPALevel(RF24_PA_HIGH);   
    
  radio.openReadingPipe(1,pipe); // открываем первую трубу с индитификатором "pipe"
  radio.startListening(); // включаем приемник, начинаем слушать трубу
}
 
//  radio.stopListening(); // останавливает приём (нужно перед началом передачи) 


void loop()   
{  
  int data; 
  
  if (radio.available()){ // проверяем не пришло ли чего в буфер.
    radio.read(&data, sizeof(data)); // читаем данные, указываем сколько байт читать
    
    Serial.print("data: ");
    Serial.println(data); 
  } 
} 
Первый пример, передача данных с аналогового входа. Передетчик
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h> // https://github.com/maniacbug/RF24
 
  
const uint64_t pipe = 0xF0F1F2F3F4LL; // индитификатор передачи, "труба"
 
RF24 radio(9, 10); // CE, CSN
 

void setup(){
  Serial.begin(9600);

  radio.begin();
  delay(2);
  radio.setChannel(9); // канал (0-127)
    
      // скорость, RF24_250KBPS, RF24_1MBPS или RF24_2MBPS
      // RF24_250KBPS на nRF24L01 (без +) неработает.
      // меньше скорость, выше чувствительность приемника.
  radio.setDataRate(RF24_1MBPS); 
   
      // мощьность передатчика, RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_MED=-6dBM,
  radio.setPALevel(RF24_PA_HIGH);   

  radio.openWritingPipe(pipe); // открываем трубу на передачу.void loop()   
{
  
  int data = analogRead(0); // читаем значение
  
  radio.write(&data, sizeof(data)); // отправляем данные и указываем сколько байт пакет
  
  Serial.print("data: ");
  Serial.println(data);
 
} 

 

Радиомодули nRF24L01+ и Arduino, часть 2, датчик DHT11

Второй пример, передача данных с DHT11. Передатчик
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h> // https://github.com/maniacbug/RF24

#include <dht11.h>
  
const uint64_t pipe = 0xF0F1F2F3F4LL; // индитификатор передачи, "труба"
 
dht11 sensor;
RF24 radio(9, 10); // CE, CSN
 
void setup(){
  Serial.begin(9600);
  
  radio.begin();
  delay(2);
  radio.setChannel(9); // канал (0-127)
    
    // скорость, RF24_250KBPS, RF24_1MBPS или RF24_2MBPS
    // RF24_250KBPS на nRF24L01 (без +) неработает.
    // меньше скорость, выше чувствительность приемника.
  radio.setDataRate(RF24_1MBPS); 
   
    // мощьность передатчика, RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_MED=-6dBM,
  radio.setPALevel(RF24_PA_HIGH);   

  radio.openWritingPipe(pipe); // открываем трубу на передачу.
  delay(1000);
} 


void loop()   
{
  int data[2];   
  
  sensor.read(8);
  
  data[0] = int(sensor.temperature); // заполняем массив
  data[1] = int(sensor.humidity);
  
  radio.write(&data, sizeof(data)); // отправляем данные и указываем сколько байт пакет
  
  Serial.print("Humidity (%): ");
  Serial.println(data[1]);

  Serial.print("Temperature (oC): ");
  Serial.println(data[0]);
  delay(1000);
} 

Второй пример, передача данных с DHT11. Приемник
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h> // https://github.com/maniacbug/RF24

const uint64_t pipe = 0xF0F1F2F3F4LL; // индитификатор передачи, "труба"

RF24 radio(9, 10); // CE, CSN

void setup(){
  Serial.begin(9600);
  
  radio.begin();  
  delay(2);
  radio.setChannel(9); // канал (0-127)
  
    // скорость, RF24_250KBPS, RF24_1MBPS или RF24_2MBPS
    // RF24_250KBPS на nRF24L01 (без +) неработает.
    // меньше скорость, выше чувствительность приемника.
  radio.setDataRate(RF24_1MBPS);     
  
    // мощьность передатчика RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_MED=-6dBM,
  radio.setPALevel(RF24_PA_HIGH);   
    
  radio.openReadingPipe(1,pipe); // открываем первую трубу с индитификатором "pipe"
  radio.startListening(); // включаем приемник, начинаем слушать трубу
}
 
//  radio.stopListening(); // останавливает приём (нужно перед началом передачи) 


void loop()   
{
  int data[2];
  
  if (radio.available()){ // проверяем не пришло ли чего в буфер.
    radio.read(&data, sizeof(data)); // читаем данные и указываем сколько байт читать
    
      Serial.print("Humidity (%): ");
      Serial.println(data[1]);
      Serial.print("Temperature (oC): ");
      Serial.println(data[0]);
 
    } 
} 

 

Радиомодули nRF24L01+ и Arduino, часть 3, работа с несколькими модулями

Третий пример, работа с несколькими модулями, передача данных с DS18B20, приемник
/// приемник _18b20_rx_2.ino
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h> // https://github.com/maniacbug/RF24
#include <Wire.h> 
 

const uint64_t pipe01 = 0xF0F1F2F3F4LL; // идентификатор передачи, "труба"
const uint64_t pipe02 = 0xF0F1F2F3F1LL; // могут различатся только на младший байт

RF24 radio(9, 10); // CE, CSN
 

void setup(){
  Serial.begin(9600);
  radio.begin();  
 
  delay(2);
  radio.setChannel(9); // канал (0-127) 
  radio.setDataRate(RF24_250KBPS);      
  radio.setPALevel(RF24_PA_HIGH);   
    
  radio.openReadingPipe(1,pipe01); // открываем трубу с индитификатором "pipe01"
  radio.openReadingPipe(2,pipe02); // открываем трубу с индитификатором "pipe02"  
//  radio.openReadingPipe(0,pipe01); // или открываем все трубы разом
  radio.startListening(); // включаем приемник, начинаем слушать трубу
}
 
//  radio.stopListening(); // останавливает приём (нужно перед началом передачи) 


void loop()   
{
  uint8_t pipeNum = 0; 
  
  if (radio.available(&pipeNum)){ // проверяем не пришло ли чего в буфер.
     if (pipeNum == 1){        
        float temperature = 0;
        radio.read(&temperature, sizeof(temperature)); 
         
          Serial.println(pipeNum);
            if (temperature < 0) Serial.print("-");
            else Serial.print("+");
          Serial.println(temperature);
          Serial.println();
     }
     if (pipeNum == 2){
        int data[2] = {0};
        radio.read(&data, sizeof(data)); 
       
        Serial.println(pipeNum);
            if (data[0] < 0) Serial.print("-");
            else Serial.print("+");
        Serial.print(data[0]);
        Serial.print("C  ");
        Serial.print(data[1]);
        Serial.println("%");
        Serial.println();
     }
  }
} 

Третий пример, работа с несколькими модулями, передача данных с DS18B20 без запроса . Передатчик
// передатчик температуры с 18b20 . _18b20_tx_p1.ino
// без запроса 
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h> // https://github.com/maniacbug/RF24
#include <OneWire.h>
  
const uint64_t pipe = 0xF0F1F2F3F4LL; // индитификатор передачи, "труба"
 
RF24 radio(9, 10); // CE, CSN
OneWire  ds(2);  

void setup(){
//  Serial.begin(9600);
  
  radio.begin();
  delay(2);
  radio.setChannel(9); // канал (0-127)
 
  radio.setDataRate(RF24_1MBPS);    
  radio.setPALevel(RF24_PA_HIGH);   

  radio.openWritingPipe(pipe); // открываем трубу на передачу.
   
} 


void loop(){  
  
  ////////////// 18b20 //////////////
  byte addr[8];  
  byte data[12];
   if (!ds.search(addr)) { // если 18b20 не найден
     float temperature = -128;
     radio.write(&temperature, sizeof(temperature));
     delay(5000);
  }
   ds.reset_search(); 
  
  ds.reset();            
  ds.select(addr);        
  ds.write(0x44);      
  delay(1000);   
 
  ds.reset();
  ds.select(addr);    
  ds.write(0xBE);          

  for (int i = 0; i < 9; i++) data[i] = ds.read();    

  int raw = (data[1] << 8) | data[0];
  if (data[7] == 0x10) raw = (raw & 0xFFF0) + 12 - data[6];  
  float temperature = raw / 16.0;
 /////////////////////////////// 
 
  // отправляем данные и указываем сколько байт пакет
  radio.write(&temperature, sizeof(temperature)); 
   
} 

Третий пример, работа с несколькими модулями, передача данных с DHT11 по запросу. Приемник
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h> // https://github.com/maniacbug/RF24

const uint64_t pipe = 0xF0F1F2F3F4LL; // индитификатор передачи, "труба"

RF24 radio(9, 10); // CE, CSN

void setup(){
  Serial.begin(9600);
  
  radio.begin();  
  delay(2);
  radio.setChannel(9); // канал (0-127)
  
    // скорость, RF24_250KBPS, RF24_1MBPS или RF24_2MBPS
    // RF24_250KBPS на nRF24L01 (без +) неработает.
    // меньше скорость, выше чувствительность приемника.
  radio.setDataRate(RF24_1MBPS);     
  
    // мощьность передатчика RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_MED=-6dBM,
  radio.setPALevel(RF24_PA_HIGH);   
    
  radio.openReadingPipe(1,pipe); // открываем первую трубу с индитификатором "pipe"
  radio.startListening(); // включаем приемник, начинаем слушать трубу
}
 
//  
// для ПроМини

void loop()   
{
  int data[2];

  if (Serial.available() > 0){ // если чтото пришло в сериал
    int val = Serial.parseInt(); // читаем в переменную
    if (val == 1){ // если это 1
      radio.stopListening(); // останавливает приём (нужно перед началом передачи) 
      radio.openWritingPipe(pipe); // открываем трубу на передачу.
      radio.write(&val, sizeof(val)); // отправляем val и указываем сколько байт пакет
      radio.startListening(); // включаем приемник, начинаем слушать трубу
    }
    Serial.flush(); // очищаем буфер  
  }
  
  if (radio.available()){ // проверяем не пришло ли чего в буфер.
    radio.read(&data, sizeof(data)); // читаем данные и указываем сколько байт читать
    
      Serial.print("Humidity (%): ");
      Serial.println(data[1]);
      Serial.print("Temperature (oC): ");
      Serial.println(data[0]); 
    } 
    
} 
Третий пример, работа с несколькими модулями, передача данных с DHT11 по запросу. Передатчик
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h> // https://github.com/maniacbug/RF24

#include <dht11.h>
  
const uint64_t pipe = 0xF0F1F2F3F4LL; // индитификатор передачи, "труба"
 
dht11 sensor;
RF24 radio(9, 10); // CE, CSN
 
void setup(){
//  Serial.begin(9600);
  
  radio.begin();
  delay(2);
  radio.setChannel(9); // канал (0-127)
    
    // скорость, RF24_250KBPS, RF24_1MBPS или RF24_2MBPS
    // RF24_250KBPS на nRF24L01 (без +) неработает.
    // меньше скорость, выше чувствительность приемника.
  radio.setDataRate(RF24_1MBPS); 
   
    // мощьность передатчика, RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_MED=-6dBM,
  radio.setPALevel(RF24_PA_HIGH);   
  
  radio.openReadingPipe(1,pipe); // открываем первую трубу с индитификатором "pipe"
  radio.startListening(); // включаем приемник, начинаем слушать трубу

//  radio.openWritingPipe(pipe); // открываем трубу на передачу.////// для UNO
void loop()   
{
  int data[2];   
  
  if (radio.available()){ // проверяем не пришло ли чего в буфер.
    int val;
    radio.read(&val, sizeof(val)); // читаем данные и указываем сколько байт читать
    
    if (val == 1){ // если пришло 1,
      radio.stopListening(); // останавливает приём (нужно перед началом передачи) 
      
      sensor.read(8);  // читаем градусник
      delay(1000);
      data[0] = int(sensor.temperature); // заполняем массив
      data[1] = int(sensor.humidity);
      
         //отправляем данные      
      radio.openWritingPipe(pipe); // открываем трубу на передачу.
      radio.write(&data, sizeof(data)); // отправляем данные и указываем сколько байт пакет
      radio.startListening(); // включаем приемник, начинаем слушать трубу
    }
  }   
} 

 

Радиомодули nRF24L01+ и Arduino, часть 4, работа с прерыванием.

Радиомодули nRF24L01+ и Arduino, часть 4, работа с прерыванием
/// пример из видео http://youtu.be/1M04kcHcRlw
//
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h> // https://github.com/maniacbug/RF24
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

const uint64_t pipe01 = 0xF0F1F2F3F4LL;  
volatile boolean flag_tx, flag_fail, flag_rx;

int i; ////

RF24 radio(9, 10); // CE, CSN
LiquidCrystal_I2C lcd(0x27, 16, 2);
 
void setup(){
        // настраиваем прерывание на 3 ноге
  attachInterrupt(1, check_radio, FALLING); 
  
  Serial.begin(9600);
  lcd.begin();
  lcd.backlight();
  radio.begin();  

  delay(2);
  radio.setChannel(9); // канал (0-127) 
  radio.setDataRate(RF24_250KBPS);      
  radio.setPALevel(RF24_PA_HIGH);   
    
  radio.openReadingPipe(1,pipe01); // открываем трубу с индитификатором "pipe01"
   radio.startListening(); // включаем приемник, начинаем слушать трубу
}
 
//  radio.stopListening(); // останавливает приём (нужно перед началом передачи) 

void check_radio(){ // обработчик прерывания
  bool tx, fail, rx;
    radio.whatHappened(tx,fail,rx); // читаем регистр
  flag_tx = tx; // 1 если успешно отправили данные
  flag_fail = fail; // 1 если данные не отправленны   
  flag_rx = rx;  // 1 если пришли данные для чтения 
}

void loop(){  
  
   if (flag_rx){ // если пришли данные для чтения
     float temperature = 0; // забераем их и выводим на экран
     radio.read(&temperature, sizeof(temperature));     

       lcd.setCursor(0, 0);
       if (temperature > 0) lcd.print("+");
       lcd.print(temperature);
       lcd.print("   ");
       
//       Serial.println(temperature);
//       Serial.println();
       
     flag_rx = 0;
  }
  
  if (flag_fail){ // если данные не отправленны
    flag_fail = 0;
  
  }
   
  if (flag_tx){ // если данные отправленны 
  flag_tx = 0;
  
  } 
   
 ///////////////////  
      // можно занятся другими делами.      
   lcd.setCursor(0, 1);
   i++;
   lcd.print(i);
   delay(250);
}