Мастерство nRF24L01: беспроводная связь, интеграция с Arduino, схемы и код
В этом уроке мы научимся делать беспроводную связь между двумя платами Arduino с использованием трансиверных модулей nRF24L01. Модуль nRF24L01 — очень популярный выбор для беспроводной связи при использовании Arduino. Я уже использовал этот модуль для множества проектов на Arduino, и вы можете проверить некоторые из них здесь: Вы можете посмотреть следующее видео или прочитать письменный урок ниже. Он включает всё, что нам нужно знать о трансиверном модуле nRF24L01, такое как распиновка модуля, принцип работы, подключение и несколько примеров кода. Для объяснения беспроводной связи мы сделаем два примера: первый будет отправкой простого сообщения «Hello World» с одного Arduino на другой, а во втором примере у нас будет двунаправленная связь между платами Arduino, где, используя джойстик на первом Arduino, мы будем управлять сервоприводом на втором Arduino, и наоборот, используя кнопку на втором Arduino, мы будем управлять светодиодом на первом Arduino. Давайте посмотрим ближе на трансиверный модуль NRF24L01. Он использует диапазон 2.4 GHz и может работать с скоростями от 250 кбит/с до 2 Мбит/с. Если используется в открытом пространстве и с низкой скоростью, его диапазон может достигать до 100 метров. Вот полные спецификации: Модуль может использовать 125 разных каналов, что даёт возможность иметь сеть из 125 независимо работающих модемов в одном месте. Каждый канал может иметь до 6 адресов, или каждый блок может общаться с до 6 другими блоками одновременно. Потребление энергии этого модуля составляет всего около 12 мА во время передачи, что даже ниже, чем у одного светодиода. Рабочее напряжение модуля от 1.9 до 3.6 В, но хорошая новость в том, что другие выводы терпят 5В логику, поэтому мы можем легко подключить его к Arduino без использования любых конвертеров логических уровней. Три из этих выводов для SPI-соединения и их нужно подключить к SPI-выводам Arduino, но заметьте, что у каждой платы Arduino разные SPI-выводы. Выводы CSN и CE могут быть подключены к любому цифровому выводу платы Arduino и они используются для установки модуля в режим ожидания или активный режим, а также для переключения между режимом передачи или командным режимом. Последний вывод — прерывания, который не обязательно использовать. Существует несколько вариаций модулей NRF24L01. Самый популярный — с наборной антенной. Это делает модуль более компактным, но с другой стороны, снижает дальность передачи до расстояния около 100 метров. Вторая вариация, вместо наборной антенны, имеет SMA-разъём, к которому можно подключить «утку» антенну для лучшей дальности передачи. Третья вариация, показанная здесь, в дополнение к «утке» антенне, имеет чип RFX2401C, который включает PA (Усилитель мощности) и LNA (Низкошумящий усилитель). Это усиливает сигнал NRF24L01 и обеспечивает ещё лучшую дальность передачи до 1000 метров в открытом пространстве. Вот подробный взгляд на распиновку NRF24L01, а также модуля NRF24L01+ PA/LNA. Оба модуля, NRF24L01 и NRF24L01+ PA/LNA, имеют одинаковую распиновку, поэтому мы можем подключать их в нашей схеме одинаково. Вот как нам нужно подключить модули NRF24L01 к платам Arduino. Как я уже упоминал, у каждой платы Arduino разные SPI-выводы, так что имейте это в виду при подключении модулей к вашей плате Arduino. Вы можете получить компоненты, необходимые для этого урока Arduino, по ссылкам ниже: Как только мы подключим модули NRF24L01 к платам Arduino, мы готовы сделать коды для передатчика и приёмника. Сначала нам нужно скачать и установить библиотеку RF24, которая делает программирование менее сложным. Мы также можем установить эту библиотеку напрямую из Менеджера библиотек Arduino IDE. Просто поищите «rf24» и найдите и установите ту, что от «TMRh20, Avamander». Вот два кода для беспроводной связи и ниже их описание. Итак, нам нужно подключить базовую SPI и только что установленную библиотеку RF24 и создать объект RF24. Два аргумента здесь — это выводы CSN и CE. Далее нам нужно создать байтовый массив, который будет представлять адрес, или так называемый канал, через который два модуля будут общаться. Мы можем изменить значение этого адреса на любую 5-буквенную строку, и это позволяет выбрать, с каким приёмником мы будем говорить, так что в нашем случае у нас будет тот же адрес и у приёмника, и у передатчика. В разделе setup нам нужно инициализировать объект radio и, используя функцию radio.openWritingPipe(), установить адрес приёмника, которому мы отправим данные, 5-буквенную строку, которую мы ранее установили. С другой стороны, у приёмника, используя функцию radio.openReadingPipe(), мы устанавливаем тот же адрес и тем самым включаем связь между двумя модулями. Затем, используя функцию radio.setPALevel(), мы устанавливаем уровень усилителя мощности, в нашем случае я установлю его на минимум, так как мои модули очень близки друг к другу. Обратите внимание, что при использовании более высокого уровня рекомендуется использовать обходные конденсаторы между GND и 3.3V модулей, чтобы у них было более стабильное напряжение во время работы. Далее у нас есть функция radio.stopListening(), которая устанавливает модуль как передатчик, и с другой стороны у нас есть функция radio.startListening(), которая устанавливает модуль как приёмник. В разделе loop, у передатчика, мы создаём массив символов, которому присваиваем сообщение «Hello World». Используя функцию radio.write(), мы отправим это сообщение приёмнику. Первый аргумент здесь — переменная, которую мы хотим отправить. Используя «&» перед именем переменной, мы фактически устанавливаем указатель на переменную, которая хранит данные, которые мы хотим отправить, и используя второй аргумент мы устанавливаем количество байтов, которые мы хотим взять из этой переменной. В этом случае функция sizeof() получает все байты строки «text». В конце программы мы добавим задержку 1 секунду. Используя функцию radio.write(), мы можем отправить максимум 32 байта за раз. С другой стороны, у приёмника, в разделе loop, используя функцию radio.available(), мы проверяем, есть ли данные для приёма. Если это правда, сначала мы создаём массив из 32 элементов, называемый «text», в котором сохраним входящие данные. Используя функцию radio.read(), мы читаем и сохраняем данные в переменную «text». В конце мы просто печатаем текст на серийном мониторе. Так что как только мы загрузим обе программы, мы можем запустить серийный монитор у приёмника и заметим, что сообщение «Hello World» печатается каждую секунду. Стоит отметить, что шум питания — одна из самых частых проблем, с которыми люди сталкиваются при попытке установить успешную связь с модулями NRF24L01. Обычно схемы РЧ или радиочастотные сигналы чувствительны к шуму питания. Поэтому всегда хорошая идея включить развязывающий конденсатор по линии питания. Конденсатор может быть от 10 мкФ до 100 мкФ. Другая частая проблема — вывод 3.3В плат Arduino не всегда может обеспечить достаточно питания для модуля NRF24L01. Поэтому питание модуля от внешнего источника также хорошая идея. Давайте посмотрим второй пример, двунаправленную беспроводную связь между двумя платами Arduino. Вот схема соединений: Вы можете получить компоненты, необходимые для этого примера, по ссылкам ниже: Вот два кода и их описание ниже. Код передатчика Код приёмника Что отличается здесь от предыдущего примера — нам нужно создать два канала или адреса для двунаправленной связи. В разделе setup нам нужно определить оба канала, и заметьте, что адрес записи у первого Arduino должен быть адресом чтения у второго Arduino, и наоборот, адрес чтения у первого Arduino должен быть адресом записи у второго Arduino. В разделе loop, используя функцию radio.stopListening(), мы устанавливаем первый Arduino как передатчик, считываем и маппим значение джойстика от 0 до 180, и используя функцию radio.write() отправляем данные приёмнику. С другой стороны, используя функцию radio.startListening(), мы устанавливаем второй Arduino как приёмник и проверяем, есть ли доступные данные. Пока есть доступные данные, мы будем их читать, сохранять в переменную «angleV» и затем использовать это значение для поворота сервопривода. Далее, у передатчика, мы устанавливаем первый Arduino как приёмник и с пустым циклом «while» ждём, пока второй Arduino отправит данные, и это данные о состоянии кнопки — нажата ли она или нет. Если кнопка нажата, светодиод загорится. Так этот процесс постоянно повторяется и обе платы Arduino постоянно отправляют и принимают данные. Давайте посмотрим на ещё один пример кода с использованием модулей NRF24L01. Всё остаётся тем же, как в предыдущих примерах, за исключением способа структурирования и отправки данных. Код передатчика Итак, мы можем создать структуру (struct), которая фактически является коллекцией различных типов переменных. Мы должны помнить, что максимальный размер этих структурных данных может быть 32 байта. Здесь мы видим, что я включил три переменные типа byte, одну целочисленную переменную (4 байта), одну переменную float (4 байта) и одну String, содержащую четыре символа (4 байта). Всего 15 байт. Код приёмника На стороне приёмника мы должны определить ту же структуру данных, чтобы иметь возможность принять входящие данные. Для проверки того, работает ли беспроводная связь правильно, я напечатал каждую переменную на серийном мониторе. Модуль NRF24L01 — отличный вариант, когда вам нужна беспроводная связь для вашего проекта Arduino. Я уже использовал этот модуль во многих своих проектах на Arduino. Здесь я перечислю все мои проекты, в которых я использовал эти модули. Каждый из этих проектов/уроков имеет подробное объяснение того, как использовать модуль NRF24L01, включая схемы соединений, улучшенную реализацию кода для лучшей связи и так далее. Мой любимый проект — это самодельный Arduino RC Передатчик. На самом деле это 14-канальный RC-контроллер, который можно использовать для управления практически любым Arduino Проектом. Это всё для этого урока, надеюсь, вам понравилось и вы узнали что-то новое. Как всегда, не стесняйтесь задавать любые вопросы в комментариях ниже.
Обзор

Трансиверный модуль nRF24L01

Частотный диапазон
2.4 – 2.5 GHz ISM-диапазон
Скорости передачи данных
250 Кбит/с / 1 Мбит/с / 2 Мбит/с
Макс. выходная мощность
0 дБм
Рабочее напряжение
1.9 – 3.6 В
Макс. рабочий ток
12.3 мА
Ток в режиме ожидания
22 мкА
Логические входы
5В толерантны
Диапазон связи
100 м (открытое пространство)
Как это работает


Вариации модуля

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

Как подключить nRF24L01 к Arduino

Arduino
SCK
MISO
MOSI
SS
Uno
13
12
11
10
Nano
13
12
11
10
Mega
52
50
51
53
Код Arduino и nRF24L01
Код передатчика
/* * Arduino Wireless Communication Tutorial * Example 1 - 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> RF24 radio(7, 8); // CE, CSN const byte address[6] = "00001"; void setup() { radio.begin(); radio.openWritingPipe(address); radio.setPALevel(RF24_PA_MIN); radio.stopListening(); } void loop() { const char text[] = "Hello World"; radio.write(&text, sizeof(text)); delay(1000); }Код приёмника
/* * Arduino Wireless Communication Tutorial * Example 1 - 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> RF24 radio(7, 8); // CE, CSN const byte address[6] = "00001"; void setup() { Serial.begin(9600); radio.begin(); radio.openReadingPipe(0, address); radio.setPALevel(RF24_PA_MIN); radio.startListening(); } void loop() { if (radio.available()) { char text[32] = ""; radio.read(&text, sizeof(text)); Serial.println(text); } }Описание кода
RF24 radio(7, 8); // CE, CSNconst byte address[6] = "00001";radio.openWritingPipe(address);radio.openReadingPipe(0, address);radio.setPALevel(RF24_PA_MIN);// на Передатчике radio.stopListening();// на Приёмнике radio.startListening();void loop() { const char text[] = "Hello World"; radio.write(&text, sizeof(text)); delay(1000); }void loop() { if (radio.available()) { char text[32] = ""; radio.read(&text, sizeof(text)); Serial.println(text); } }Устранение неисправностей

Двунаправленная беспроводная связь с двумя NRF24L01 и Arduino

Исходный код nRF24L01
/* * 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[][6] = {"00001", "00002"}; boolean buttonState = 0; void setup() { pinMode(12, OUTPUT); radio.begin(); radio.openWritingPipe(addresses[1]); // 00002 radio.openReadingPipe(1, addresses[0]); // 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); } }/* * 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[][6] = {"00001", "00002"}; Servo myServo; boolean buttonState = 0; void setup() { pinMode(button, INPUT); myServo.attach(5); radio.begin(); radio.openWritingPipe(addresses[0]); // 00001 radio.openReadingPipe(1, addresses[1]); // 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)); } }const byte addresses[][6] = {"00001", "00002"};// на Передатчике radio.openWritingPipe(addresses[1]); // 00001 radio.openReadingPipe(1, addresses[0]); // 00002// на Приёмнике radio.openWritingPipe(addresses[0]); // 00002 radio.openReadingPipe(1, addresses[1]); // 00001radio.stopListening(); int potValue = analogRead(A0); int angleValue = map(potValue, 0, 1023, 0, 180); radio.write(&angleValue, sizeof(angleValue));radio.startListening(); if ( radio.available()) { while (radio.available()) { int angleV = 0; radio.read(&angleV, sizeof(angleV)); myServo.write(angleV); }Пример 3 – Отправка нескольких переменных в одном пакете
/* Arduino Wireless Communication Tutorial Example 1 - 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> RF24 radio(7, 8); // CE, CSN const byte address[6] = "00001"; // Макс. размер этой структуры 32 байта - лимит буфера NRF24L01 struct Data_Package { byte a = 0; byte b = 125; byte c = 255; int d = 1024; float e = 3.141592; String f = "Test"; }; Data_Package data; // Создать переменную с вышеуказанной структурой void setup() { radio.begin(); radio.openWritingPipe(address); radio.setPALevel(RF24_PA_MIN); radio.stopListening(); } void loop() { // Отправить все данные из структуры приёмнику radio.write(&data, sizeof(Data_Package)); delay(500); }// Макс. размер этой структуры 32 байта - лимит буфера NRF24L01 struct Data_Package { byte a = 0; byte b = 125; byte c = 255; int d = 1024; float e = 3.141592; String f = "Test"; }; Data_Package data; // Создать переменную с вышеуказанной структурой/* Arduino Wireless Communication Tutorial Example 1 - 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> RF24 radio(7, 8); // CE, CSN const byte address[6] = "00001"; // Макс. размер этой структуры 32 байта - лимит буфера NRF24L01 struct Data_Package { byte a = 0; byte b = 125; byte c = 255; int d = 1024; float e = 3.141592; String f = "Test"; }; Data_Package data; //Создать переменную с вышеуказанной структурой void setup() { Serial.begin(9600); radio.begin(); radio.openReadingPipe(0, address); radio.setPALevel(RF24_PA_MIN); radio.startListening(); } void loop() { // Проверить, есть ли данные для приёма if (radio.available()) { radio.read(&data, sizeof(Data_Package)); // Прочитать все данные и сохранить в структуру 'data' } Serial.print("a: "); Serial.print(data.a); Serial.print(" b: "); Serial.print(data.b); Serial.print(" c: "); Serial.print(data.c); Serial.print(" d: "); Serial.print(data.d); Serial.print(" e: "); Serial.print(data.e); Serial.print(" f: "); Serial.println(data.f); }
Заключение

Производственный процесс
- Измерение качества воздуха с OpenSensors: руководство по Arduino и Python
- Создание универсального ИК-пульта на Arduino: пошаговое руководство
- Цифровой стадиометр на Arduino: отслеживание роста лазерным датчиком VL53L0X
- JX Wave Generator — Генератор сигналов на Arduino с DDS AD9833 и OLED-дисплеем
- Сборка DIY VR-скейтборда на Arduino, Google Cardboard и Bluetooth
- Подключение Arduino Mega к GPS-модулю NEO‑6M: пошаговое руководство
- Использование термистора: пошаговое руководство для Arduino
- Генерация музыкальных тонов на Arduino: полный спектр 88 клавиш пианино
- Мастерство Modbus на Arduino: пошаговое руководство
- Мозг-компьютерные интерфейсы: восстановление связи мысли и действия