Подключение радиомодуля nrf24l01 + к arduino uno

Содержание

Объяснение программы для 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 – они критически важны для успешной работы проекта

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

Пример

В комплекте с библиотекой я составил примеры, чтобы запустить этих ребят, pingpair пример.

Физическое переключение режимов

Одна деталь, я решил написать один код для устройств передачи и приема. Это значительно упрощает логику. Для этого я использовал свободный пин устройства, для переключения между двумя режимами. Я называю их «roles». Существует передатчик «tole» и приемник «role». Пин 7 соединенный с землей задействует один режим, соединенный с питанием — второй.

//
// Управление режимами
//
// Настройка адреса и режима. Этот скетч использует один и то же
// код для всех устройств в этой системе
// Это сильно упрощает тестирование. Устройство само определяет в
// каком оно режиме
//
// Это делается через addr_pin. Установите его в низкий уровень для адреса # 0, высокой # 1.
//

// Этим скетчем поддерживаются разные режимы
typedef enum { role_rx = 1, role_tx1, role_end } role_e;

// Удобные для отладки названия режимов
const char* role_friendly_name[] = { "invalid", "Receive", "Transmit"};

// Режимы какие имеет каждый из возможных аппаратных адресов
const role_e role_map = { role_rx, role_tx1 };

// Текущий режим
role_e role;

void <b>setup</b>(void)
{
//
// Адрес и режим
//

// установка номера пина
pinMode(addr_pin, INPUT);
digitalWrite(addr_pin,HIGH);
delay(20); // Просто чтобы получить точное чтение с адреса пина

// прочитать значение пина, устанавливаем адрес и режим
node_address = digitalRead(addr_pin) ? 0 : 1;
role = role_map;

НАСТРОЙКА Radio

Первичные настройки модулей …

  //
// Установка и настройка rf radio
//

radio.begin();

// Устанавливаем канал (по желанию)
radio.setChannel(1);

// Установка размера данных (не обязательно, но рекомендуется)
// Библиотека использует фиксированный размер данных, так что если вы не установите,
// то будет установлено автоматически.
radio.setPayloadSize(sizeof(unsigned long));

//
// Открытие канала на другие узлы для связи (обязательно)
//

// Этот простой скетч открывает два канала для общения этих двух узлов
// туда и обратно

// Открываем "наш" канал для записи
radio.openWritingPipe(pipes);

// Мы открываем 'Другой' канал для чтения, в позиции №1 (мы можем иметь до 5 каналов открытых для чтения)
int other_node_address;
if (node_address == 0)
other_node_address = 1;
else
other_node_address = 0;
radio.openReadingPipe(1,pipes);

//
// Начинаем слушать
//

radio.startListening();

//
// Выводим конфигурацию RF-модуля для отладки
//

radio.print_details();
}

Режим передачи

Блок передатчика отправляет текущее millis() ждет тайм-аут или ответ от другого модуля, получает ответ, измеряет разницу, и выводит результат.

void <b>loop</b>(void)
{
//
// Режим передачи. Неоднократное отправление текущего времени
//

if (role == role_tx1)
{
// Во-первых, перестать слушать, потому что нам нужно говорить.
radio.stopListening();

// Получим время, и отправим его.
unsigned long time = millis();
printf("Now sending %lu...",time);
bool ok = radio.write( &amp;time );

// Теперь, продолжаем слушать
radio.startListening();

// Ждем, пока мы не получим ответ, или тайм-аут (250 мс)
unsigned long started_waiting_at = millis();
bool timeout = false;
while ( ! radio.available() &amp;&amp; ! timeout )
if (millis() - started_waiting_at &gt; 250 )
timeout = true;

// Выводим результат
if ( timeout )
printf("Failed, response timed out.\n\r");
else
{
// Получаем ответ, сравниваем и выводим
unsigned long got_time;
radio.read( &amp;got_time );

// Выводим
printf("Got response %lu, round-trip delay: %lu\n\r",got_time,millis()-got_time);
}

// Повторяем через 1 с.
delay(1000);
}

режим приема

… А приемник делает противоположное, получив пакет, он отправляет его обратно к другому модулю.

if ( role == role_rx )
{
// Если есть готовые данные
if ( radio.available() )
{
// Повторяем пока не получили все данные
unsigned long got_time;
boolean done = false;
while (!done)
{
// Получаем данные, все до последнего.
done = radio.read( &amp;got_time );

// Выводим это
printf("Got payload %lu...",got_time);
}

// Во-первых, перестаем слушать, чтобы могли отправлять
radio.stopListening();

// Отправить результат обратно.
radio.write( &amp;got_time );
printf("Sent response.\n\r");

// Теперь, возобновляем прослушивание и ждем следующие пакеты.
radio.startListening();
}
}
}

Работа BMP280

BMP280 поставляется в различных типах в зависимости от того, где вы его покупаете. Имейте в виду, так как некоторые из них являются устройствами с 5 В, а некоторые — с 3.3 В. Кроме того, некоторые — SPI или I2C, а некоторые — нет. В этой статье будет использована версия I2C 3.3 В. Эта, хотя и 3 В, соответствует 5 В на выводах данных. Мы используем I2C версию, так как NRF24L01 использует шину SPI.

BMP280

Диапазон давления составляет от 300 до 1100 гПа, что примерно на 500 м ниже уровня моря до 9 км в высоту и между 950 и 1050 гПа, а точность высоты +/-1 м, что довольно неплохо. Диапазон температур составляет от 40 до 85 °C с точностью +/-1 °C и 0,5 при 25.

На некоторых устройствах адрес I2C установлен на 0x77, а на других — на 0x76. На официальном сайте Arduino есть полезный сканер адресов по этой ссылке. Если он не найдет адрес, проверьте проводку.

Объяснение программы для 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

Receiver loop() — Цикл приема

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

void loop(void)
{
  // Pump the network regularly
  network.update();

  // Is there anything ready for us?
  while ( network.available() )
  {
    // If so, grab it and print it out
    RF24NetworkHeader header;
    payload_t payload;
    network.read(header,&payload,sizeof(payload));
    Serial.print("Received packet #");
    Serial.print(payload.counter);
    Serial.print(" at ");
    Serial.println(payload.ms);
  }
}

 Адресация

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

Узел 00 это базовый узел. Узлы 01-05 непосредственно взаимодействуют с узлом 00, но не друг с другом. Таким образом чтобы узлу 01 передать сообщение на узел 02, нужно будет пройти через узел 00. Узлы 011, 021, 031 и так далее — это дети узла 01. Таким образом, для узла 011, чтобы отправить сообщение на узел 02, сообщение пойдет к 01, а потом к 00, и только после этого на 02.

На практике, я обозначал узлы «маршрутизаторы» номерами 01-05, которые были размещены на каждом этаже, и имели мощные антенны. Тогда все узлы на этом этаже общались с родителем этажа. Фото выше стандарт узла V3 с питанием от специального «блока питания», чтобы подключать в настенную розетку, и радио модуль с усиленной антенной.

Построение сети беспроводных датчиков

«Sensornet» это пример начала построения сети датчиков. Этот пример демонстрирует, как отправить показания датчиков на базу из сети с любым числом узлов. Датчика температуры подключен к аналоговому входу 2, а датчик напряжения подключен к аналоговому входу 3. Каждый узел посылает пинг в базу каждые 4 секунды, этот интервал хорошо использовать для тестирования, но на практике вы можете установить интервал и больше. Дочерние узлы будут спать между передачами, для экономии заряда аккумулятора.

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

Работа 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 — софт и библиотеки

Ниже будет приведен пример софта для передачи и приема данных. Кроме того, есть множество примеров на странице загрузок библиотеки RF24 Library. Как уже не раз упоминалось, для работы передатчика/приемника будем использовать библиотеки, в которых решены многие мелкие задачи, усложняющие наладку работы передатчика с Arduino.

Библиотека TMRh20’s RF24 Library.

После загрузки ZIP архива, на вашем ПК появится архив RF24-master.ZIP. Измените название архива на RF24.ZIP. Внутри архива находится папка с тем же названием RF24-master. Ее тоже переименуйте в RF24.

Для начинающих разбираться в Arduino, есть отличная инструкция по установке библиотек в Arduino IDE.

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

О проекте

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

В данном руководстве мы будем использовать барометрический датчик давления и температуры BMP280, подключенный к одному Arduino, а затем использовать 24 ГГц радиосвязь, предоставляемую двумя цифровыми приемопередатчиками NRF24L01 (трансивер), для передачи этих данных на второй Arduino, который расположен на некотором расстоянии.

Это расстояние должно быть менее 50 м в зависимости от наличия стен между ними. Трансивер означает комбинированный передатчик и приемник в одном устройстве.

В проекте один Arduino будет оснащен BMP280, подключенный как I2C, а также NRF24L01 соединенный через SPI. Он будет передавать радиосигнал на второй Arduino, который также оснащен другим NRF24L01 работает в качестве приемника, который будет отображать входящие данные на последовательном мониторе.

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

Следует иметь в виду, что это настоящая радиосвязь SHF (Super High Frequency — Супер высокая частота), и чем она выше, тем лучше, как и во всех подобных радиосвязях. К тому же, она имеет тенденцию «вести себя» как разряженный световой луч, поэтому чем меньше препятствий, т.е. стен, тем лучше.

nRF24L01 Прерывистый / Нет работы.

ВСЕГДА проверяйте питание 3.3 В. Многократная периодическая работа связана с проблемами регулирования электропитания. Несмотря на то, что средний ток может быть меньше 15 мА, по-видимому, происходят быстрые переходные процессы, когда происходит каждый пакет передачи. Первые примеры в библиотеке RF24 TMRH20 имеют низкую мощность, и это не проблема.У меня были проблемы с nRF24L01. Работал один день / одна минута, провалился следующий. Теперь я положил конденсатор 0.1uf и 10uf прямо с GND на 3.3V штырьки на модули, и все намного лучше. Отличным решением является базовый модуль, показанный в верхней части этой страницы.

Программное обеспечение

Получите RF24 библиотеку из GitHub. Существует достаточно документации на эту ссылку, а также указатель на страницу загрузки. Распакуйте архив в папку вашего Arduino IDE  (моя в /home/users/maniacbug/Source/Arduino/libraries), и перезагрузите Arduino IDE.

В меню Файл, выберите пункт «Примеры», затем «RF24», и, наконец, “GettingStarted”. После этого загрузится GettingStarted пример. Выглядит примерно так. Взгляните на примере GettingStarted в документации во всех деталях.

/**
* Пример Приступая к работе с nRF24L01+.
*
* Это пример того, как использовать класс RF24. Написан этот пример к двум
* различным узлам. Переключите один из узлов в режиме "передачи" переключение
* происходит с помощью serial monitor и отправки 'T'. Узел посылает пинг и
* текущее время в понг узел, который отвечает, посылая данные обратно. Узел
* пинг может посмотреть, как долго длился весь цикл передачи.
** /
#include "SPI.h";
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"

//
// Hardware configuration
//

// Подключение nRF24L01 к SPI шине к пинам 9 и 10

RF24 radio(9,10);

Загрузить пример, запустите serial monitor, установите скорость 57600, и вы должны увидеть это:

RF24/examples/GettingStarted/
ROLE: Pong back
STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1 = 0xf0f0f0f0d2 0xf0f0f0f0e1
RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6
TX_ADDR = 0xf0f0f0f0d2
RX_PW_P0-6 = 0x08 0x08 0x00 0x00 0x00 0x00
EN_AA = 0x3f
EN_RXADDR = 0x03
RF_CH = 0x4c
RF_SETUP = 0x07
CONFIG = 0x0f
DYNPD/FEATURE = 0x00 0x00
Data Rate = 1MBPS
Model = nRF24L01
CRC Length = 16 bits
PA Power = PA_HIGH

Если вы вместо этого везде видите много нулей, то что-то не так с вашим соединением. Дважды проверьте все снова! В ходе создания этого материала, я даже перепутал два провода и пришлось перепаять их. Если вы подключили все правильно, вы увидите номера так же, как те, что выше.

Step 3: Transmitting Text

Open two Arduino ide and Select the boards from tools and the correct COM Ports in order to upload the code correctly

Before you upload the code you need to download and install the RF24 library from GitHub because it will make the program easy.

The link is- https://github.com/nRF24/RF24

Now we will create a simple communication where an Arduino sends a data to the Arduino

Upload the given code to the transmitter —

// Transmitter code

#include <SPI.h> // for SPI communication

#include <nRF24L01.h>

#include <RF24.h>

RF24 radio(7, 8); // CE, CSN

const byte address = «00001»; // the address the the module

void setup() {

radio.begin();

radio.openWritingPipe(address);

radio.setPALevel(RF24_PA_MAX);

radio.stopListening();

}

void loop() {

const char text[] = «Hello World»; // you can customize this text to your wish

radio.write(&text, sizeof(text));

}

Upload the given code to reciever —

//Reciever Code

#include // for SPI communication #include

#include

RF24 radio(7, 8); // CE, CSN

const byte address = «00001»; // the address the the module

void setup() {

Serial.begin(9600);

radio.begin();

radio.openReadingPipe(0, address);

radio.setPALevel(RF24_PA_MAX);

radio.startListening();

}

void loop() {

if (radio.available()) { // if nrf has any incoming data

char text = «»;

radio.read(&text, sizeof(text));

Serial.println(text);

delay(5);

Статическая инициализация

Первое, статические настройки для подготовки радио модуля и установка адреса. Для этого он — «Node # 1», и будет общаться с «Node # 0»

Еще важно установить правильные пины. Используя модуль из Приступая к работе, вы должны использовать выводы 9 и 10

// nRF24L01(+) radio attached using Getting Started board
RF24 radio(9,10);

// Network uses that radio
RF24Network network(radio);

// Address of our node
const uint16_t this_node = 1;

// Address of the other node
const uint16_t other_node = 0;

// How often to send 'hello world to the other unit
const unsigned long interval = 2000; //ms

// When did we last send?
unsigned long last_sent;

// How many have we sent already
unsigned long packets_sent;

// Structure of our payload
struct payload_t
{
  unsigned long ms;
  unsigned long counter;
};

Sketch code

#include <SPI.h>

#include <Mirf.h>

#include <nRF24L01.h>

#include <MirfHardwareSpiDriver.h>

#define MAX_BUFF 32 // Буфер приема-передачи

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

Mirf.spi = &MirfHardwareSpi; Mirf.init();

Mirf.setRADDR((byte *)»module1″); // Здесь задаем адрес

Mirf.payload = MAX_BUFF; // Здесь задаем буфер Mirf.channel = 10;

// Это канал приема-передачи — должен

// быть одинаковым у устройств. Mirf.config();

Serial.println(«Start..»);

}

char buff; int c_count = 0;

void loop(){ int i;

//sending

if (c_count = Serial.available()) { if (c_count <= MAX_BUFF) {

for (i=0; i<c_count; i++) { buff = Serial.read();

}

} else {

for (i=0; i<MX_BUFF; i++) { buff = Serial.read();

}

}

buff = 0;

Mirf.setTADDR((byte *)» module2″); //Адрес! Serial.print(«>»);

Mirf.send((uint8_t *)buff); while(Mirf.isSending()){

}

Serial.println(buff);

}

delay(10);

//receiving if(Mirf.dataReady()) { Mirf.getData((uint8_t *)buff); Serial.print(«<«); Serial.println(buff);

}

delay(100);

}

Transmitter loop() — Цикл передачи

И, наконец, «loop()» регулярно посылает сообщение на другой модуль

Обратите внимание, что RF24Network требует регулярный вызов «update()» для обработки пакетов с радио модуля

void loop(void)
{
  // Pump the network regularly
  network.update();

  // If it's time to send a message, send it!
  unsigned long now = millis();
  if ( now - last_sent >= interval  )
  {
    last_sent = now;

    Serial.print("Sending...");
    payload_t payload = { millis(), packets_sent++ };
    RF24NetworkHeader header(/*to node*/ other_node);
    bool ok = network.write(header,&payload,sizeof(payload));
    if (ok)
      Serial.println("ok.");
    else
      Serial.println("failed.");
  }
}

Принцип работы и основные настройки nRF24L01 +

Частота 2.4ГГц очень популярна и на ней работает достаточно большое количество приборов, например: WiFi, радиоуправляемые модели, и тому подобное. Как они не мешают друг другу? Дело в том, что частота 2.4ГГц — это условное обозначение. На самом деле, имеется в виду диапазон частот, близкий к 2.4ГГц. nRF24L01+ работает на частотах 2.400-2.4835ГГц. Частота, на которой будут работать ваши модули, определяется номером канала. Каналы имеют шаг в 1МГц. То есть если Вы выбираете канал 0 — это частота 2.400ГГц, если канал 76 — 2.476ГГц. Разумеется, нужно выбирать свободную волну (канал) — иначе связь будет не стабильной или вообще отсутствовать.

Вы можете выбрать одну из трех скоростей передачи данных. Чем меньше скорость — тем больше чувствительность. То есть, при скорости 250kbps модули будут работать на большей дистанции, чем при более высоких скоростях.

На дальность работы модулей также влияет настройки выходной мощности модуля. Вы можете выбрать мощность в зависимости от приоритетов. То есть, если для вас важнее максимальная дальность, то надо выбрать максимальную мощность. Если приоритетной является экономичность, а дальность — несколько метров, разумно выбрать меньшую мощность сигнала. Интересное наблюдение в режиме приема данных (RX) модуль потребляет больший ток, чем в режиме передачи (TX).

Модуль nRF24L01+ в один момент времени может находиться в одном из режимов:

Power Down — выключен
Standby — спящий режим
RX Mode — режим ресивера (приемника)
TX Mode — режим трансмиттера (передатчика)

Диаграмма переходов из режима в режим изображенны на рисунке:

Информационный пакет, который передает модуль nRF24L01+ имеет следующий формат:

Preamble — Преамбула представляет собой последовательность битов и используется для синхронизации демодуляторов приемников.

Address — Адрес приемника. Адрес гарантирует, что пакет получит нужен приемник. Вы можете настроить длину адреса 3, 4 или 5 байт. Надо стараться чтобы адреса были уникальны. Но иногда Адреса могут быть одинаковые в нескольких nRF24L01+ если этого требуют Ваши задачи.

Packet Control Field — контрольное поле. Содержит: 6 бит, определяющих длину пакета (имеется в виду длина пакета полезных данных (от 0 до 32 байт)); 2 бита PID, используемые для определения является ли пакет новым или пересланным повторно; 1 бит — флаг NO_ACK.

Payload — полезный «груз». То есть данные, которые передает микроконтроллер. Может быть от 0 до 32 байт. Длину Payload можно настроить.

CRC — CRC является обязательным механизмом обнаружения ошибок в пакете. Длина CRC — 1 или 2 байта и зависит от общей длины пакета.

Для того, чтобы переданный пакет был принят нужным приемником, настройки приемника должны быть такими же, как и у передатчика. Если параметры пакета будут отличаться, приемник не сможет его обработать. Также надо корректно указывать адреса (об этом чуть ниже).

Если одновременно будут передавать несколько передатчиков, или возникнут другие препятствия, произойдет коллизия. Приемник не сможет получить пакет. Поэтому nRF24L01+ имеет настройку автоматической повторной отправки пакета (Aoto Retransmission (ART)). Эти настройки указывают с каким интервалом и сколько раз пытаться отправить пакет.

Как отмечалось в самом начале nRF24L01+ может работать на одном канале с 6-ю nRF24L01+. Для этого все модуля должны работать на одном канале, но каждый nRF24L01+ должен иметь уникальный адрес. Относительно адресации в документации приведена наглядная диаграмма:

Обратите внимание, что адреса для Data Pipe 1 — Pipe 5 отличаются друг от друга лишь последним байтом. Этого требует документация на nRF24L01+

На этой диаграмме модуль отмеченный как PRX прослушивает эфир для указанных адресов RX_ADDR_P0..RX_ADDR_P5. Каждый из PTX1..PTX6 отправляет пакеты на адреса TX_ADDR. Модуль, который работает как PRX тоже может отправлять модулям пакеты по их адресам.

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