КОРЗИНА
магазина
8 (499) 500-14-56 | ПН. - ПТ. 12:00-18:00
ЛЕСНОРЯДСКИЙ ПЕРЕУЛОК, 18С2, БЦ "ДМ-ПРЕСС"

Урок 26.5 Соединяем несколько arduino по радиоканалу через nRF24L01+

При создании некоторых проектов, требуется разделить выполняемые задачи между несколькими arduino.

В этом уроке мы научимся соединять несколько arduino по радиоканалу ISM диапазона, используя радио модуль nRF24L01+, на расстоянии до 100 м. Если использовать радио модули NRF24L01+PA+LNA, то расстояние между arduino можно увеличить до 1 км, не меняя код скетча.

Преимущества:

  • Отсутствие проводов между arduino.
  • Высокая скорость передачи данных, до 2 Мб/с. Выше чем у шин I2C и UART.
  • Полудуплексная связь. Режим работы модулей (приёмник / передатчик) можно менять в процессе их работы.
  • Высокая помехозащищенность. Данные в пакетах принимаются с проверкой CRC.
  • Контроль доставки данных. Приемник отправляет передатчику сигнал подтверждения приёма данных (без смены режима работы).
  • Возможность выбора одного из 128 каналов связи. Шаг каждого канала равен 1 МГц (от 2,400 ГГц до 2,527 ГГц).
  • Возможность одновременной работы до 6 передатчиков на одном канале.

Недостатки:

  • Модули nRF24L01+ работают в радиочастотном диапазоне ISM (Industrial, Scientific, Medical) 2,4 ГГц, на котором работают WiFi, Bluetooth и другие устройства, например радио телефоны и даже СВЧ печи. Эти устройства могут «глушить» некоторые каналы данного диапазона. Поэтому вблизи таких устройств дальность связи между модулями, на некоторых каналах, резко уменьшается. Увеличить дальность можно сменив канал связи на любой из 128 доступных модулям nRF24L01+.
  • При выборе скорости 2 Мб/с, задействуются сразу два канала (выбранный и следующий за ним).
  • Модули питаются от напряжения 3,3 В постоянного тока. Но их можно запитать от 5 В через адаптер nRF24L01+.

Нам понадобится:

Для реализации проекта нам необходимо установить библиотеки:

  • Библиотека RF24 (для работы с радио модулями nRF24L01+).
  • Библиотека iarduino_4LED, (для работы с Trema четырехразрядным LED индикатором).
  • Библиотеки SPI и Servo входят в стандартный набор Arduino IDE.

О том как устанавливать библиотеки, Вы можете ознакомиться на странице Wiki - Установка библиотек в Arduino IDE.

Видео:

Схема подключения:

Все радио модули nFR24L01+ подключены, через адаптер, к аппаратной шине SPI. Trema четырехразрядный LED индикатор подключён к цифровым выводам D2 и D3 (можно подключить к любым выводам Arduino). Сервопривод подключён к цифровому выводу D4 (можно подключить к любым выводам). Trema потенциометр и слайдер подключены к аналоговым входам A0 (можно подключить к любым аналоговым входам). Питание адаптера nFR24L01+ взято с контактов GND и Vcc (5 В).

Если Вы будете подключать модуль nFR24L01+ без адаптера, то модуль требуется запитать от напряжения 3,3 В постоянного тока.

Схема соединения нескольких arduino по радиоканалу

Таблица подключения радио модуля nFR24L01+

Адаптер nRF24L01+ Arduino Uno Назначение
CE / SS 9 (меняется в скетче) Шина SPI - выбор устройства
CSN 10 (меняется в скетче) Выбор режима: приёмник / передатчик
SСK 13 (SCK) Шина SPI - линия тактирования
MO 11 (MOSI) Шина SPI - линия данных (от мастера к ведомому)
MI 12 (MISO) Шина SPI - линия данных (от ведомого к мастеру)
IRQ Не используется Прерывание

Алгоритм работы:

Передатчики:

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

При старте (в коде setup) скетч настраивает работу радио модуля в режим передачи данных, указывая номер канала, скорость передачи, мощность передачи и идентификатор трубы.

Далее, каждый передатчик постоянно (в коде loop), считывает показания с аналогового входа A0 в 0 элемент массива data и отправляет этот массив радио модулю для передачи. Код loop выполняется с задержкой в 50 мс, этого времени достаточно для того что бы приемник успел принять и обработать данные другого передатчика.

Приёмник:

При старте (в коде setup) скетч настраивает работу радио модуля в режим приёма данных, указывая те же данные, что и у обоих передатчиков: номер канала, скорость передачи данных, мощность передачи. Но, в отличии от передатчиков, создаёт (открывает) не одну, а две трубы для приёма данных, указывая 1 трубе идентификатор 1 передатчика, а 2 трубе идентификатор 2 передатчика.

Далее приёмник инициирует работу с LED индикатором и сервоприводом. После чего, постоянно (в коде loop), проверяет нет ли в буфере данных, принятых радио модулем. Если данные есть, то они читаются в массив data, а в переменную pipe читается номер трубы, по которой эти данные пришли, таким образом определяя от какого передатчика приняты данные.

  • Если данные приняты от передатчика №1, то значение 0 элемента массива data (показания Trema потенциометра) преобразуются в градусы и используется для поворота сервопривода.
  • Если данные приняты от передатчика №2, то значение 0 элемента массива data (показания Trema слайдера) выводятся на LED индикатор.

Идентификаторы труб:

  • Приемнику можно задать до 6 труб с номерами от 0 до 5. Каждой трубе присваивается идентификатор передатчика, данные которого требуется принимать.
  • Значение идентификатора 0 трубы может отличаться от остальных идентификаторов всеми байтами.
  • Значения идентификаторов 1-5 труб должны отличаться друг от друга только младшим байтом.

Код программы:

Передатчик №1:

#include <SPI.h>                                               // Подключаем библиотеку для работы с шиной SPI
#include <nRF24L01.h>                                          // Подключаем файл настроек из библиотеки RF24
#include <RF24.h>                                              // Подключаем библиотеку для работы с nRF24L01+
RF24           radio(9, 10);                                   // Создаём объект radio для работы с библиотекой RF24, указывая номера выводов nRF24L01+ (CE, CSN)
int            data[1];                                        // Создаём массив для передачи данных (так как мы будем передавать только одно двухбайтное число, то достаточно одного элемента массива типа int)
                                                               // Для данного примера, можно использовать не массив data из одного элемента, а переменную data типа int
void setup(){
    radio.begin();                                             // Инициируем работу nRF24L01+
    radio.setChannel(5);                                       // Указываем канал передачи данных (от 0 до 127), 5 - значит передача данных осуществляется на частоте 2,405 ГГц (на одном канале может быть только 1 приёмник и до 6 передатчиков)
    radio.setDataRate     (RF24_1MBPS);                        // Указываем скорость передачи данных (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS), RF24_1MBPS - 1Мбит/сек
    radio.setPALevel      (RF24_PA_HIGH);                      // Указываем мощность передатчика (RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_HIGH=-6dBm, RF24_PA_MAX=0dBm)
    radio.openWritingPipe (0xAABBCCDD11LL);                    // Открываем трубу с идентификатором 0xAABBCCDD11 для передачи данных (на одном канале может быть открыто до 6 разных труб, которые должны отличаться только последним байтом идентификатора)
}
void loop(){
    data[0] = analogRead(A0);                                  // считываем значение с аналогового входа A0
    radio.write(&data, sizeof(data));                          // отправляем данные из массива data указывая сколько байт массива мы хотим отправить. Отправить данные можно с проверкой их доставки: if( radio.write(&data, sizeof(data)) ){данные приняты приёмником;}else{данные не приняты приёмником;}
    delay(50);                                                 // устанавливаем задержку на 50 мс, за это время приемник успеет принять и обработать данные этого и другого передатчика.
}

Скачать

Передатчик №2:

#include <SPI.h>                                               // Подключаем библиотеку для работы с шиной SPI
#include <nRF24L01.h>                                          // Подключаем файл настроек из библиотеки RF24
#include <RF24.h>                                              // Подключаем библиотеку для работы с nRF24L01+
RF24           radio(9, 10);                                   // Создаём объект radio для работы с библиотекой RF24, указывая номера выводов nRF24L01+ (CE, CSN)
int            data[1];                                        // Создаём массив для передачи данных (так как мы будем передавать только одно двухбайтное число, то достаточно одного элемента массива типа int)
                                                               // Для данного примера, можно использовать не массив data из одного элемента, а переменную data типа int
void setup(){
    radio.begin();                                             // Инициируем работу nRF24L01+
    radio.setChannel(5);                                       // Указываем канал передачи данных (от 0 до 127), 5 - значит передача данных осуществляется на частоте 2,405 ГГц (на одном канале может быть только 1 приёмник и до 6 передатчиков)
    radio.setDataRate     (RF24_1MBPS);                        // Указываем скорость передачи данных (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS), RF24_1MBPS - 1Мбит/сек
    radio.setPALevel      (RF24_PA_HIGH);                      // Указываем мощность передатчика (RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_HIGH=-6dBm, RF24_PA_MAX=0dBm)
    radio.openWritingPipe (0xAABBCCDD22LL);                    // Открываем трубу с идентификатором 0xAABBCCDD22 для передачи данных (на одном канале может быть открыто до 6 разных труб, которые должны отличаться только последним байтом идентификатора)
}
void loop(){
    data[0] = analogRead(A0);                                  // считываем значение с аналогового входа A0
    radio.write(&data, sizeof(data));                          // отправляем данные из массива data указывая сколько байт массива мы хотим отправить. Отправить данные можно с проверкой их доставки: if( radio.write(&data, sizeof(data)) ){данные приняты приёмником;}else{данные не приняты приёмником;}
    delay(50);                                                 // устанавливаем задержку на 50 мс, за это время приемник успеет принять и обработать данные этого и другого передатчика.
}

Скачать

Приемник:

#include <SPI.h>                                               // Подключаем библиотеку  для работы с шиной SPI
#include <nRF24L01.h>                                          // Подключаем файл настроек из библиотеки RF24
#include <RF24.h>                                              // Подключаем библиотеку  для работы с nRF24L01+
#include <iarduino_4LED.h>                                     // Подключаем библиотеку  для работы с четырёхразрядным LED индикатором
#include <Servo.h>                                             // Подключаем библиотеку  для работы с сервоприводами
RF24           radio(9, 10);                                   // Создаём объект radio   для работы с библиотекой RF24, указывая номера выводов nRF24L01+ (CE, CSN)
iarduino_4LED  dispLED(2,3);                                   // Создаём объект dispLED для работы с функциями библиотеки iarduino_4LED, с указанием выводов дисплея ( CLK , DIO ) 
Servo          myservo;                                        // Создаём объект myservo для работы с функциями библиотеки Servo
int            data[1];                                        // Создаём массив         для приёма данных (так как мы будем принимать от каждого передатчика только одно двухбайтное число, то достаточно одного элемента массива типа int)
uint8_t        pipe;                                           // Создаём переменную     для хранения номера трубы, по которой пришли данные
                                                               // Для данного примера, можно использовать не массив data из одного элемента, а переменную data типа int
void setup(){
    delay(1000);
    myservo.attach(4);                                         // Подключаем объект myservo к 4 выводу Arduino
    dispLED.begin();                                           // Инициируем работу индикатора
    radio.begin();                                             // Инициируем работу nRF24L01+
    radio.setChannel(5);                                       // Указываем канал приёма данных (от 0 до 127), 5 - значит приём данных осуществляется на частоте 2,405 ГГц (на одном канале может быть только 1 приёмник и до 6 передатчиков)
    radio.setDataRate     (RF24_1MBPS);                        // Указываем скорость передачи данных (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS), RF24_1MBPS - 1Мбит/сек
    radio.setPALevel      (RF24_PA_HIGH);                      // Указываем мощность передатчика (RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_HIGH=-6dBm, RF24_PA_MAX=0dBm)
    radio.openReadingPipe (1, 0xAABBCCDD11LL);                 // Открываем 1 трубу с идентификатором 1 передатчика 0xAABBCCDD11, для приема данных
    radio.openReadingPipe (2, 0xAABBCCDD22LL);                 // Открываем 2 трубу с идентификатором 2 передатчика 0xAABBCCDD22, для приема данных
    radio.startListening  ();                                  // Включаем приемник, начинаем прослушивать открытые трубы
//  radio.stopListening   ();                                  // Выключаем приёмник, если потребуется передать данные
}

void loop(){
    if(radio.available(&pipe)){                                // Если в буфере имеются принятые данные, то получаем номер трубы, по которой они пришли, по ссылке на переменную pipe
        radio.read(&data, sizeof(data));                       // Читаем данные в массив data и указываем сколько байт читать
        if(pipe==1){myservo.write(map(data[0],0,1023,0,180));} // Если данные пришли от 1 передатчика, то поворачиваем сервопривод на угол заданный Trema потенциометром
        if(pipe==2){dispLED.print(data[0]);}                   // Если данные пришли от 2 передатчика, то выводим показания Trema слайдера на индикатор
    }
}

Скачать

Ссылки:




Обсуждение

Гарантии и возврат Используя сайт Вы соглашаетесь с условями