Обзор радио модуля nrf24l01+

Source Code

Here are the two codes and below is the description of them.

Transmitter Code

/*
* Arduino Wireless Communication Tutorial
*     Example 2 - Transmitter Code
*                
* by Dejan Nedelkovski, www.HowToMechatronics.com
* 
* Library: TMRh20/RF24, https://github.com/tmrh20/RF24/
*/

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

#define led 12

RF24 radio(7, 8); // CE, CSN
const byte addresses[] = {"00001", "00002"};
boolean buttonState = 0;

void setup() {
  pinMode(12, OUTPUT);
  radio.begin();
  radio.openWritingPipe(addresses); // 00002
  radio.openReadingPipe(1, addresses); // 00001
  radio.setPALevel(RF24_PA_MIN);
}

void loop() {
  delay(5);

  radio.stopListening();
  int potValue = analogRead(A0);
  int angleValue = map(potValue, 0, 1023, 0, 180);
  radio.write(&angleValue, sizeof(angleValue));

  delay(5);
  radio.startListening();
  while (!radio.available());
  radio.read(&buttonState, sizeof(buttonState));
  if (buttonState == HIGH) {
    digitalWrite(led, HIGH);
  }
  else {
    digitalWrite(led, LOW);
  }
}

Receiver Code

/*
* Arduino Wireless Communication Tutorial
*     Example 2 - Receiver Code
*                
* by Dejan Nedelkovski, www.HowToMechatronics.com
* 
* Library: TMRh20/RF24, https://github.com/tmrh20/RF24/
*/

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Servo.h>

#define button 4

RF24 radio(7, 8); // CE, CSN
const byte addresses[] = {"00001", "00002"};
Servo myServo;
boolean buttonState = 0;

void setup() {
  pinMode(button, INPUT);
  myServo.attach(5);
  radio.begin();
  radio.openWritingPipe(addresses); // 00001
  radio.openReadingPipe(1, addresses); // 00002
  radio.setPALevel(RF24_PA_MIN);
}

void loop() {
  delay(5);
  radio.startListening();
  if ( radio.available()) {
    while (radio.available()) {
      int angleV = 0;
      radio.read(&angleV, sizeof(angleV));
      myServo.write(angleV);
    }
    delay(5);
    radio.stopListening();
    buttonState = digitalRead(button);
    radio.write(&buttonState, sizeof(buttonState));
  }
}

What’s different here from the previous example is that we need to create two pipes or addresses for the bi-directional communication.

const byte addresses[] = {"00001", "00002"};

In the setup section we need to define both pipes, and note that the writing address at the first Arduino needs to be the reading address at the second Arduino, and vice versa, the reading address at the first Arduino needs to be the writing address at the second Arduino.

// at the Transmitter
radio.openWritingPipe(addresses); // 00001
radio.openReadingPipe(1, addresses); // 00002
// at the Receiver
radio.openWritingPipe(addresses); // 00002
radio.openReadingPipe(1, addresses); // 00001

In the loop section using the radio.stopListening() function we set the first Arduino as transmitter, read and map the value of Joystick from 0 to 180, and using the radio.write() function send the data to the receiver.

radio.stopListening();
int potValue = analogRead(A0);
int angleValue = map(potValue, 0, 1023, 0, 180);
radio.write(&angleValue, sizeof(angleValue));

On the other side, using the radio.startListening() function we set the second Arduino as receiver and we check whether there is available data. While there is data available we will read it, save it to the “angleV” variable and then use that value to rotate the servo motor.

radio.startListening();
  if ( radio.available()) {
    while (radio.available()) {
      int angleV = 0;
      radio.read(&angleV, sizeof(angleV));
      myServo.write(angleV);
    }

Next, at the transmitter, we set the first Arduino as receiver and with an empty “while” loop we wait for the second Arduino the send data, and that’s the data for the state of the push button whether is pressed or not. If the button is pressed the LED will light up. So these process constantly repeats and both Arduino boards are constantly sending and receiving data.

Датчик напряжения

Мне хотелось следить за уровнем заряда батареи каждого узла, чтобы я мог видеть, когда пришло время заменить батареи. Чтобы сделать это, я подключил VIN от моего источника питания, к «Датчику напряжения» с помощью делителя напряжения:

Я использовал 1М / 470K делители, что позволит снизить 3.44V до 1.1V, а затем использовать 1.1V внутреннее опорное напряжение. Это идеально подходит для моих целей, так как я не использую напряжение свыше 3.44V. В моем случае, когда analogRead (A3) возвращает 1024, у меня есть 3.44V. Вот как это работает в примере SensorNet:

// What voltage is a reading of 1023?
const unsigned voltage_reference = 5 * 256; // 5.0V
// How many measurements to take.  64*1024 = 65536, so 64 is the max we can fit in a uint16_t.
const int num_measurements = 64;
...
    // Take the voltage reading
    i = num_measurements;
    reading = 0;
    while(i--)
      reading += analogRead(voltage_pin);

    // Convert the voltage reading to volts*256
    message.voltage_reading = ( reading * voltage_reference ) >> 16;

Сначала, я делаю 64 чтения чтобы получить хорошую выборку. Второе преимущество выборки из 64 показаний, это то что он использует все 16 бит uint16_tб так что значение 0x8000 составляет половину от максимального 1.1V.

LIBRARIES

To do a brief explanation of the code starting with that for the Transmitter, the first thing we do, as usual, is to include the libraries that we will be using.

#include <SPI.h>  
#include "RF24.h"

Next, we declare the pins of the Arduino to which the CE and the CS pins of the NF24Lo1 are connected as they are arguments for the Rf24 library.

RF24 myRadio (7, 8);

Next, we create the struct package which will be used in sending the data.

#include <SPI.h>  
#include "RF24.h"byte addresses6 = {""};

struct package
{
  int id=1;
  float temperature = 18.3;
  char  text100 = "Text to be transmitted";
};


typedef struct package Package;
Package data;

The void setup() function is next. Here we initialize the NRF module setting the communication channel, signal power, and the data rate.

void setup()
{
  Serial.begin(115200);
  delay(1000);
  myRadio.begin();  
  myRadio.setChannel(115); 
  myRadio.setPALevel(RF24_PA_MAX);
  myRadio.setDataRate( RF24_250KBPS ) ; 
  myRadio.openWritingPipe( addresses);
  delay(1000);
}

Next, we move to the void loop function. the void loop function simply increases the temperature initialized in the struct package described initially then sends it to the receiver.

void loop()
{
  myRadio.write(&data, sizeof(data)); 

  Serial.print("\nPackage:");
  Serial.print(data.id);
  Serial.print("\n");
  Serial.println(data.temperature);
  Serial.println(data.text);
  data.id = data.id + 1;
  data.temperature = data.temperature+0.1;
  delay(1000);

}

The second code is that of the receiver. This receives data from the transmitter and displays it on the serial monitor.

The first thing we do here too is to include the libraries that will be used.

#include <SPI.h>  
#include "RF24.h"

Next, we create an object of the RF24 library and pass the pins of the Arduino to which the CE and CS pins of the NRF24l01 are connected to as arguments.

RF24 myRadio (7, 8);

Next, we create the struct package to receive the data with the temperature initialized to zero.

struct package
{
  int id=;
  float temperature = 0.0;
  char  text100 ="empty";
};

byte addresses6 = {""}; 



typedef struct package Package;
Package data;

With this done, we proceed to the void setup() function. Here we initialize the NRF module, setting the communication channel, signal power, and the data rate to match that of the transmitter.

void setup() 
{
  Serial.begin(115200);
  delay(1000);

  myRadio.begin(); 
  myRadio.setChannel(115); 
  myRadio.setPALevel(RF24_PA_MAX);
  myRadio.setDataRate( RF24_250KBPS ) ; 
  myRadio.openReadingPipe(1, addresses);
  myRadio.startListening();
}

The void loop function for the receiver is fairly simple, All we will need to do is read the data that was received and print it on the serial monitor.

void loop()  
{

  if ( myRadio.available()) 
  {
    while (myRadio.available())
    {
      myRadio.read( &data, sizeof(data) );
    }
    Serial.print("\nPackage:");
    Serial.print(data.id);
    Serial.print("\n");
    Serial.println(data.temperature);
    Serial.println(data.text);
  }

}

The complete code for both the transmitter and the receiver can be downloaded by clicking on the link below.

Объяснение программы для Raspberry Pi

Полный код программы приведен в конце статьи, здесь же мы кратко рассмотрим его основные фрагменты.

Программировать плату Raspberry Pi в нашем проекте мы будем с использованием языка Python3. Также можно использовать и язык C/C++ как и в плате Arduino, однако в данном случае преимуществом написания программы на языке python является то, что на нем написана специальная библиотека для работы с модулями nRF24l01, которую можно скачать с ее официальной страницы на github. Но здесь необходимо отметить, что наша программа на python и указанная библиотека должны находиться в одном и том же каталоге, иначе программа на python не сможет найти библиотеку. После скачивания библиотеки извлеките ее из архива и создайте отдельный каталог, в котором будут храниться все программы и библиотеки вашего проекта. Когда установка библиотеки будет закончена, можно приступать к написанию программы.

Первым делом в программе необходимо подключить (импортировать) все используемые библиотеки.

Python

import RPi.GPIO as GPIO
import time
import spidev
from lib_nrf24 import NRF24

1
2
3
4

importRPi.GPIO asGPIO

importtime

importspidev

fromlib_nrf24 importNRF24

Далее установим режим работы контактов (GPIO mode) платы Raspberry Pi «Broadcom SOC channel», что будет означать что мы будем обращаться к контактам платы по их физическим номерам (а не по их номерам на плате).

Python

GPIO.setmode(GPIO.BCM)

1 GPIO.setmode(GPIO.BCM)

Далее в программе мы зададим адреса каналов (pipe address) – они будут нужны для взаимодействия с приемной частью проекта на основе платы Arduino. Адреса укажем в шестнадцатеричном коде.

Python

pipes = , ]

1 pipes=0xE0,0xE0,0xF1,0xF1,0xE0,0xF1,0xF1,0xF0,0xF0,0xE0

Инициализируем модуль nRF24l01 используя контакты GPIO08 в качестве CE и GPIO25 в качестве CSN.

Python

radio.begin(0, 25)

1 radio.begin(,25)

Установим размер пакета (payload size) 32 бита, адрес канала 76, скорость передачи данных 1 Мбит/с и выходную мощность модуля на минимум.

Python

radio.setPayloadSize(32)
radio.setChannel(0x76)
radio.setDataRate(NRF24.BR_1MBPS)
radio.setPALevel(NRF24.PA_MIN)

1
2
3
4

radio.setPayloadSize(32)

radio.setChannel(0x76)

radio.setDataRate(NRF24.BR_1MBPS)

radio.setPALevel(NRF24.PA_MIN)

Откроем каналы и начнем в них запись данных. Также будем выводить на экран основные параметры (details) работы модуля nRF24l01.

Python

radio.openWritingPipe(pipes)
radio.printDetails()

1
2

radio.openWritingPipe(pipes)

radio.printDetails()

Подготовим сообщение в форме строки. Это сообщение мы будем передавать плате Arduino UNO.

Python

sendMessage = list(«Hi..Arduino UNO»)
while len(sendMessage) < 32:
sendMessage.append(0)

1
2
3

sendMessage=list(«Hi..Arduino UNO»)

whilelen(sendMessage)<32

sendMessage.append()

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

Python

while True:
start = time.time()
radio.write(sendMessage)
print(«Sent the message: {}».format(sendMessage))
send
radio.startListening()

1
2
3
4
5
6

whileTrue

start=time.time()

radio.write(sendMessage)

print(«Sent the message: {}».format(sendMessage))

send

radio.startListening()

Если передача сообщения завершена и радио канал закрыт (не доступен) более 2-х секунд, то выведем на экран сообщение о том, что время истекло (timed out).

Python

while not radio.available(0):
time.sleep(1/100)
if time.time() — start > 2:
print(«Timed out.») # print error message if radio disconnected or not functioning anymore
break

1
2
3
4
5

whilenotradio.available()

time.sleep(1100)

iftime.time()-start>2

print(«Timed out.»)# print error message if radio disconnected or not functioning anymore

break

Закрываем прослушивание (listening) радио канала, закрываем соединение и заново открываем соединение спустя 3 секунды чтобы передать другое сообщение.

Python

radio.stopListening() # close radio
time.sleep(3) # give delay of 3 seconds

1
2

radio.stopListening()# close radio

time.sleep(3)# give delay of 3 seconds

Скетчи для nRF24L01 и Arduino

Скетчи для nRF24L01 и Arduino

Пример: передача данных о положении координат джойстика Х и Y от одного модуля nRF24L01 к другому nRF24L01. Второй модуль получает данные положении джойстика и передает их на дальнейшее отображение.

Ниже два скетча. Загрузите первый на ваш первый Arduino, к которому подключен радиопередатчик nRF24L01 и джойстик (или можно использовать потенциометр). Второй скетч загрузите на Arduino с подключенным модулем nRf24L01.

/* YourDuinoStarter пример: nRF24L01 передаем данные о положении джойстика

— Что делает скетч: считывает аналоговые значения на контакте A0, A1 и передает их

с помощью радиопередатчика nRF24L01 приемнику.

Подключение nRF24L01 модуля смотрите на:

1 — GND

2 — VCC 3.3V !!! НЕ 5V

3 — CE к Arduino пину 9

4 — CSN к Arduino пину 10

5 — SCK к Arduino пину 13

6 — MOSI к Arduino пину 11

7 — MISO к Arduino пину 12

8 — НЕ ИСПОЛЬЗУЕТСЯ

Аналоговый джойстик или два потенциометра 10 КОм:

GND к Arduino GND

VCC к Arduino +5V

X потенциометр к Arduino A0

Y потенциометр к Arduino A1 */

/*——(Импортируем необходимые библиотеки)——*/

#include <SPI.h>

#include <nRF24L01.h>

#include <RF24.h>

/*——(Объявляем константы и номера пинов)——*/

#define CE_PIN 9

#define CSN_PIN 10

#define JOYSTICK_X A0

#define JOYSTICK_Y A1 // ПРИМЕЧАНИЕ: «LL» в конце константы — это тип данных «LongLong»

const uint64_t pipe = 0xE8E8F0F0E1LL;

/*——(Объявляем объекты)——*/

RF24 radio(CE_PIN, CSN_PIN); // Создаем объект Radio

/*——(Объявляем переменные)——*/

int joystick; // массив из 2-х элементов, в котором хранятся с джойстика

int i = 0;

void setup() /****** SETUP: ОТРАБАТЫВАЕТ 1 РАЗ ******/

{

Serial.begin(9600);

radio.begin();

radio.openWritingPipe(pipe);

}//—(завершение setup )—

void loop() /****** LOOP: ОТРАБАТЫВАЕТ В БЕСКОНЕЧНОМ ЦИКЛЕ ******/

{

joystick = i++;

joystick = i++;

radio.write( joystick, sizeof(joystick) );

delay(3);

}//—(завершаем главный цикл)—

Если что-то не работает???

В первую очередь проверьте питание 3.3 В. Хотя среднее значение силы тока питания равно 15 мА, бывают резкие скачки. В результате бывает такое, что передатчик отлично работает день/минуту, а потом перестает. Поэтому в схеме подключения желательно использовать конденсаторы на 10 мкФ между контактами GND и 3.3 В.

Оставляйте Ваши комментарии, вопросы и делитесь личным опытом ниже. В дискуссии часто рождаются новые идеи и проекты!

Шаг 1

Загрузить в контроллер платы Ардуино скетч сканера эфира, который можно найти среди примеров Arduino IDE: Файл -> Примеры -> RF24 -> scanner. Ниже под спойлером есть этот скетч с несущественным изменением. В нем изменено время между стартом и остановкой сканирования одного канала с 128 мксек на 512 мксек. Увеличение времени позволило за один цикл сканирования всего диапазона выявлять больше источников помех и сигналов. Это равнозначно замене результата измерений в канале на сумму четырех соседних результатов в этом канале до изменения времени задержки. При этом, время прохода всего прослушиваемого диапазона сканером увеличилось несущественно: примерно с 8 до 10 сек.

В разных скетчах адрес канала в командах приводится в разных форматах: в одних — …(0x6f), в других — …(112). Перевод с одного формата в другой станет понятным с примера перевода. Например, для (0x1а) — это: (1+1)*16 + а = (1+1)*16 + 10 = 42. Отсчет каналов начинается с частоты 2,4 ГГц, далее идет увеличение частоты на 1 МГц с увеличением номера канала на 1.

Далее подключаем модуль nRF24L01 к плате Ардуино или любому прототипу, собранному, допустим, на контроллере ATMEGA328P. Я собрал два образца на платах для прототипирования на контроллере ATMEGA328P по схеме контроллер + резонатор. Один образец подключаю к компу через плату Arduino UNO, а второй — через конвертор USB/TTL.

Мощность стабилизатора платы Arduino UNO вполне приемлема для подключения дополнительной импульсной нагрузки такой, как nRF24L01+ c адаптером 5В/3,3В для этого модуля или без адаптера.

На мониторе последовательного порта Arduino IDE увидите нечто похожее:

Если вы увидели похожую картинку — тест на работоспособность (исправность) радиомодуля и правильность его подключения пройден успешно. Замените радиомодуль другим, с которым планируете работать дальше.

Обратите внимание на чистый диапазон, начиная с канала 4а. У меня он остается чистым даже, если на расстоянии нескольких метров работает старая СВЧ-печь — мощный источник помех в этом диапазоне

А в общем-то, в Интернете рекомендуют выбирать каналы для своих проектов выше «60».

Если на каналах — шум, но радиомодуль определяется (смотрим преамбулу на мониторе Arduino IDE, подробно тут) — это однозначно копия. Не отчаивайтесь — ее тоже можно запустить.

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

Объяснение программы для Arduino

Полный код программы приведен в конце статьи, здесь же мы кратко рассмотрим его основные фрагменты.

Программа для платы Arduino UNO будет во многом похожа на программу для платы Raspberry Pi, только написана она будет на другом языке программирования. Библиотеку для Arduino для работы с модулями nRF24l01 можно скачать с ее страницы в github.

Первым делом в программе нам необходимо подключить используемые библиотеки. Мы используем ЖК дисплей 16×2 с шилдом I2C, поэтому в программе нам необходимо подключить библиотеку Wire.h. Для работы с модулем nRF24l01 кроме скачанной библиотеки с github необходимо также подключить библиотеку SPI.

Arduino

#include<SPI.h>
#include <Wire.h>

1
2

#include<SPI.h>                  
#include <Wire.h>

Также подключаем библиотеку RF24 для работы с радиочастотными модулями и библиотеку LiquidCrystal_I2C.h для работы с ЖК дисплеем по интерфейсу I2C.

Arduino

#include<RF24.h>
#include <LiquidCrystal_I2C.h>

1
2

#include<RF24.h>                  
#include <LiquidCrystal_I2C.h>

ЖК дисплей имеет адрес I2C равный 27, поэтому создадим объект для работы с ним следующим образом:

Arduino

LiquidCrystal_I2C lcd(0x27, 16, 2);

1 LiquidCrystal_I2Clcd(0x27,16,2);

Модуль RF24 подключается по стандартному интерфейсу SPI: CE – к контакту 9, CSN – к контакту 10.

Arduino

RF24 radio(9, 10) ;

1 RF24radio(9,10);

Далее инициализируем радиочастотный модуль, установим для него уровень мощности и зададим номер канала с номером 76. Также установим адрес канала такой же как и в плате Raspberry Pi и откроем канал для чтения.

Arduino

radio.begin();
radio.setPALevel(RF24_PA_MAX) ;
radio.setChannel(0x76) ;
const uint64_t pipe = 0xE0E0F1F1E0LL ;
radio.openReadingPipe(1, pipe) ;

1
2
3
4
5

radio.begin();

radio.setPALevel(RF24_PA_MAX);

radio.setChannel(0x76);

constuint64_tpipe=0xE0E0F1F1E0LL;

radio.openReadingPipe(1,pipe);

Инициализируем связь по интерфейсу I2C и ЖК дисплей.

Arduino

Wire.begin();
lcd.begin();
lcd.home();
lcd.print(«Ready to Receive»);

1
2
3
4

Wire.begin();

lcd.begin();

lcd.home();

lcd.print(«Ready to Receive»);

Начнем прослушивание радиоканала на предмет поступления входящих сообщений и установим длину сообщения равную 32 байтам.

Arduino

radio.startListening() ;
char receivedMessage = {0}

1
2

radio.startListening();

charreceivedMessage32={}

Если радиочастотный модуль доступен, то начинаем считывание сообщения с него и сохраняем сообщение. Выводим полученное сообщение в окно монитора последовательной связи и на экран ЖК дисплея. Останавливаем прослушивание радиоканала и снова начинаем его прослушивание через некоторое время.

Arduino

if (radio.available()) {
radio.read(receivedMessage, sizeof(receivedMessage)); Serial.println(receivedMessage) ;
Serial.println(«Turning off the radio.») ;
radio.stopListening() ;
String stringMessage(receivedMessage) ;
lcd.clear();
delay(1000);
lcd.print(stringMessage);
}

1
2
3
4
5
6
7
8
9

if(radio.available()){

radio.read(receivedMessage,sizeof(receivedMessage));Serial.println(receivedMessage);

Serial.println(«Turning off the radio.»);

radio.stopListening();

StringstringMessage(receivedMessage);

lcd.clear();

delay(1000);

lcd.print(stringMessage);

}

Готовую программу загружаем в плату Arduino UNO и ждем поступления сообщений из радиоканала.

Таким образом, мы рассмотрели проект с использованием Raspberry Pi и nRf24l01 в качестве передающей части и Arduino UNO и nRF24l01 в качестве приемной части. Принимаемое сообщение будет выводиться на экран ЖК дисплея 16×2 и в окно монитора последовательной связи

Обратите особое внимание на адреса каналов (pipe) в программах для Arduino и Raspberry Pi – они критически важны для успешной работы проекта

Более подробно работу проекта вы можете посмотреть на видео, приведенном в конце статьи.

Улучшение дальности передачи модуля nRF24L01 +

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

Уменьшить шум источника питания

ВЧ цепь, которая генерирует радиочастотный (РЧ) сигнал, очень чувствительна к шуму источника питания. Если не контролировать шум источника питания да большую дальность связи можно не рассчитывать.

Если источник питания не является автономным аккумулятором, существует высокая вероятность того, что при генерации сигнала будет шум. Чтобы этот шум не попал в систему, рекомендуется разместить фильтрующий конденсатор емкостью 10 мкФ на линии электропитания как можно ближе к модулю nRF24L01 +.

Самый простой способ покончить с этим — использовать очень недорогой адаптерный модуль для nRF24L01.

Адаптер для nRF24L01

Этот адаптер имеет 8-контактный разъем, позволяющий подключить модуль nRF24L01. Он может соединяться как с модулем, который мы обсуждали ранее (со встроенной антенной), так и с внешней антенной (PA/LNA). Адаптер также имеет 6-контактный разъем для подключения SPI и прерываний и 2-контактный разъем для ввода питания.

Модуль адаптера имеет собственный регулятор напряжения 3,3 В и набор конденсаторов фильтра, поэтому вы можете подключить его к источнику питания 5 В.

Изменить частоту канала

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

Чтобы эти сигналы не вызывали проблем, мы рекомендуем использовать модуль nRF24L01 + с самыми высокими 25 каналами. Причиной этого является то, что WiFi использует большинство нижних каналов.

Более низкая скорость передачи данных

NRF24L01 + обеспечивает максимальную чувствительность приемника при скорости 250 Кбит/с, которая составляет -94 дБм. Однако при скорости передачи данных 2 Мбит с чувствительность приемника падает до -82 дБм.

Если вы общаетесь на этой скорости, вы знаете, что приемник на скорости 250 Кбит/с почти в 10 раз более чувствителен, чем на 2 Мбит/с. Это означает, что приемник может декодировать сигнал, который в 10 раз слабее.

Таким образом, снижение скорости передачи данных может значительно улучшить дальность связи, которую вы можете достичь. Кроме того, для большинства наших проектов скорость 250 Кбит/с более чем достаточна.

Более высокая выходная мощность

Установка максимальной выходной мощности также может улучшить дальность связи. NRF24L01 + позволяет вам выбрать уровень выходной мощности, а именно: 0 дБм, -6 дБм, -12 дБм или -18 дБм. Выбор выходной мощности 0 дБм посылает более сильный сигнал.

Скетч для передатчика

В нашем эксперименте мы просто отправим традиционное сообщение «Hello World» от передатчика к приемнику.

Вот скетч, который мы будем использовать для нашего передатчика:

//Include Libraries
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

//create an RF24 object
RF24 radio(9, 8);  // CE, CSN

//address through which two modules communicate.
const byte address = "00001";

void setup()
{
  radio.begin();
  
  //set the address
  radio.openWritingPipe(address);
  
  //Set module as transmitter
  radio.stopListening();
}
void loop()
{
  //Send message to receiver
  const char text[] = "Hello World";
  radio.write(&text, sizeof(text));
  
  delay(1000);
}

Код начинается с подключения  библиотек. Библиотека SPI.h управляет связью SPI, а nRF24L01.h и RF24.h модулем:

//Include Libraries
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

Далее нам нужно создать объект RF24. Объект принимает два номера контактов в качестве параметров, к которым подключены сигналы CE и CSN:

//create an RF24 object
RF24 radio(9, 8);  // CE, CSN

Затем нам нужно создать байтовый массив, который будет представлять адрес канала, через который будут связываться два модуля nRF24L01 +:

//address through which two modules communicate.
const byte address = "00001";

Мы можем изменить значение этого адреса на любую 5-буквенную строку, например «node1». Адрес необходим, если у вас есть несколько модулей в сети. Благодаря адресу вы можете выбрать конкретный модуль, с которым вы хотите общаться, поэтому в нашем случае у нас будет один и тот же адрес как для передатчика, так и для приемника.

Далее в функции setup() нам нужно инициализировать радиообъект, используя radio.begin() и используя radio.openWritingPipe() функцию, мы устанавливаем адрес передатчика:

//set the address
radio.openWritingPipe(address);

Наконец, мы будем использовать radio.stopListening() функцию, которая устанавливает модуль в качестве передатчика:

//Set module as transmitter
radio.stopListening();

В разделе loop () мы создаем массив символов, которым мы назначаем сообщение «Hello World». Используя radio.write() функцию, мы отправим это сообщение приемнику.

Первый аргумент здесь — это сообщение, которое мы хотим отправить. Второй аргумент — это количество байтов, присутствующих в этом сообщении:

const char text[] = "Hello World";
radio.write(&text, sizeof(text));

С помощью этого метода вы можете отправлять до 32 байтов за раз. Потому что это максимальный размер одного пакета, который может обработать nRF24L01 +. Если вам нужно подтверждение, что получатель получил данные, функция radio.write() возвращает bool значение. Если он возвращает TRUE, данные достигли получателя. Если он возвращает FALSE, данные были потеряны.

Arduino Wireless Servo Motor Control using the RF24Network Library

Before we explain the main example of this tutorial, for better understanding how the library works let’s make a simpler example of two Arduino boards communicating to each other. Here’s the circuit diagram for this example.

You can get the components needed for this Arduino Tutorial from the links below:

  • NRF24L01 Transceiver Module……….. Amazon / Banggood / AliExpress
  • Servo Motor …………………………………… Amazon / Banggood / AliExpress
  • Potentiometer ……………………………….. Amazon / Banggood / AliExpress
  • Arduino Nano ……………………………….. Amazon / Banggood / AliExpress

Disclosure: These are affiliate links. As an Amazon Associate I earn from qualifying purchases.

So using the potentiometer at the first Arduino we will control the servo motor at the second Arduino. Let’s take a look at the source codes now.

Here’s the code at the potentiometer side:

/*
  Arduino Wireless Network - Multiple NRF24L01 Tutorial
 == Example 01 - Servo Control / Node 00 - Potentiometer ==
  by Dejan, www.HowToMechatronics.com
  Libraries:
  nRF24/RF24, https://github.com/nRF24/RF24
  nRF24/RF24Network, https://github.com/nRF24/RF24Network
*/
#include <RF24.h>
#include <RF24Network.h>
#include <SPI.h>

RF24 radio(10, 9);               // nRF24L01 (CE,CSN)
RF24Network network(radio);      // Include the radio in the network
const uint16_t this_node = 00;   // Address of this node in Octal format ( 04,031, etc)
const uint16_t node01 = 01;      

void setup() {
  SPI.begin();
  radio.begin();
  network.begin(90, this_node);  //(channel, node address)
}

void loop() {
  network.update();
  unsigned long potValue = analogRead(A0);  // Read the potentiometer value
  unsigned long angleValue = map(potValue, 0, 1023, 0, 180); // Convert the value to 0-180
  RF24NetworkHeader header(node01);     // (Address where the data is going)
  bool ok = network.write(header, &angleValue, sizeof(angleValue)); // Send the data
}

First we need to include both libraries RF24 and RF24Network, as well as the SPI library. Then we need to create the RF24 object, and include it into the RF24Network object. Here we need define the addresses of the nodes in octal format, or 00 for this node, and 01 for the other node at the servo side.

In the setup section we need to initialize the network, by setting the channel and the address of this node.

In the loop section we constantly need to call the update() function through which all action in the network happens. Then we read the value of the potentiometer and convert it into a value from 0 to 180 which is suitable for the servo control. Then we create a network header where we assign the address of the node where the data is going. At the end, using the write() function we send the data to the other node. So here the first parameter contains the addresses information, the second parameter points which data will be send, and the third parameter is the size of the data.

Here’s the code at the servo side:

/*
  Arduino Wireless Network - Multiple NRF24L01 Tutorial
  == Example 01 - Servo Control / Node 01 - Servo motor ==
*/
#include <RF24.h>
#include <RF24Network.h>
#include <SPI.h>
#include <Servo.h>

RF24 radio(10, 9);               // nRF24L01 (CE,CSN)
RF24Network network(radio);      // Include the radio in the network
const uint16_t this_node = 01;   // Address of our node in Octal format ( 04,031, etc)

Servo myservo;  // create servo object to control a servo

void setup() {
  SPI.begin();
  radio.begin();
  network.begin(90, this_node); //(channel, node address)
  myservo.attach(3);   // (servo pin)
}

void loop() {
  network.update();
  while ( network.available() ) {     // Is there any incoming data?
    RF24NetworkHeader header;
    unsigned long incomingData;
    network.read(header, &incomingData, sizeof(incomingData)); // Read the incoming data
    myservo.write(incomingData);  // tell servo to go to a particular angle
  }
}

On the other side, at the servo motor, we need to define the libraries and the objects in the same way as explained earlier. Here the address of this node in octal format is 01. After defining the servo motor, in the loop section, using the while() loop and the available() function we constantly check whether there is any incoming data. If true, we create a network header through which the data will be accepted and also a variable where the data will be stored. Then using the read() function we read the data, and store it into the incomingData variable. At the end we use this data to move the servo motor according to the potentiometer from the other node.

NRF24L01 Arduino Guide

In this guide, we’ll be using the first version of NRF2401 that comes with the onboard antenna instead.

It’ll be kept simple by using a regular cherry switch, where when clicked, it’ll send a value that’s picked up by another module and light up a WS2812 LED stick.

Transmitter + Receiver Connections:

Board used: Arduino Nano

Consider Seeeduino Nano, a better alternative

Switch and Nano configuration:

The switch is connected to the GND and Pin 8 on the Nano

Nano and NRF24L01 pin configuration:

  • MISO connects to pin 12 of the Nano
  • MOSI connects to pin 11 of the Nano
  • SCK connects to pin 13 of the Nano
  • CE connects to pin 9 of the Nano
  • CSN connects to pin 10 of the Nano
  • GND and VCC of the NRF24L01 are connected to GND and 3.3V of the Nano

It’s recommended to use Arduino Nano and Uno as they share the same SPI pins.

Transmitter Code:

Copy the sketch code below in your Arduino IDE software to program your Arduino

Board used: Arduino Uno

The receiver part will be the one that has the WS2812 LED stick, receiving information sent by the Transmitter.

WS2812 LED and Uno Pin Configuration:

  • DI pin on the WS2812 is connected to Pin 8 on the Uno
  • GND and VCC on the WS2812 are connected to the GND and 5V of the Uno

NRF24L01 and Uno Pin Configuration:

  • MISO connects to pin 12 of the Uno
  • MOSI connects to pin 11 of the Uno
  • SCK connects to pin 13 of the Uno
  • CE connects to pin 9 of the Uno
  • CSN connects to pin 10 of the Uno
  • GND and VCC are connected to GND and 3.3V of the Uno

Receiver Code:

Copy the sketch code below in your Arduino IDE software to program your Arduino

For the full tutorial, you can head here!

Работа NRF24L01

NRF24L01 — это цифровой приемопередатчик с SPI-подключением, способный передавать и принимать данные в диапазоне 24 ГГц ISM (ISM — промышленный, научный и медицинский; Industrial, Scientific, Medical).

NRF24L01

Это тот же самый диапазон, который используется Bluetooth и WiFi, и не требует лицензирования, так как он маломощный. Это устройство с питанием от 3 В, но линии данных соответствуют 5 В, поэтому преобразование не требуется. Вы можете управлять его VCC выводом прямо с вывода 3,3 В Arduino Uno.

Интерфейс SPI работает со скоростью до 10 Мбит/с. Каждый модуль работает на одной и той же частоте или канале в диапазоне от 2,400 до 2,525 ГГц. Внутри каждого канала имеется 6 «линий», позволяющих установить до 6 связей в каждом канале. Это означает, что один мастер может прослушивать 6 ведомых устройств, все на одном канале, но на разных «линиях».

Распиновка модуля приемопередатчика nRF24L01 +

Давайте посмотрим на распиновку обеих версий радиомодуля nRF24L01 +.

  • GND — это контакт заземления.
  • VCC — обеспечивает питание для модуля. Это может быть где-то от 1,9 до 3,9 вольт. Вы можете подключить его к выводу 3,3 В вашей Arduino. Помните, что подключение его к выводу 5 В может привести к повреждению вашего модуля nRF24L01 +!
  • CE (Chip Enable) — активный-HIGH вывод. При выборе nRF24L01 будет либо передавать, либо получать, в зависимости от того, в каком режиме он находится в данный момент.
  • CSN (Chip Select Not) — активный-LOW вывод и обычно поддерживается на высоком уровне. Когда этот вывод становится низким, nRF24L01 начинает прослушивать данные на шине SPI и обрабатывает их соответствующим образом.
  • SCK (Serial Clock) — принимает тактовые импульсы, предоставляемые шиной SPI Master.
  • MOSI (Master Out Slave In) — является входом SPI для nRF24L01.
  • MISO (Master In Slave Out) — это выход SPI от nRF24L01.
  • IRQ — это вывод прерывания, который может предупредить мастер, когда новые данные доступны для обработки.

В следующей статье рассмотрим вопрос подключения модуля nRF24L01 + к Arduino.