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

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

Трудно переоценить удобство беспроводной связи. Можно управлять самодельными роботами, передавать на расстоянии звук, да и вообще любую информацию, и все это безо всяких идиотских проводов! В мире Arduino существует множество устройств беспроводной связи, вспомнить хотя бы XBee, APC220 / APC230, а также всевозможные Bluetooth и Wi-Fi модули. Но сегодня мы рассмотрим, пожалуй, одно из самых дешевых и широко распространенных решений на базе чипа NRF24L01.

Немного теории

NRF24L01 является полудуплексным устройством. В один момент времени оно может либо передавать, либо принимать информацию. Чтобы обеспечить двухстороннюю связь, нужно постоянно переключаться из одного режима в другой. Чип передает данные на частоте от 2.400 до 2.525 ГГц в зависимости от выбранного канала, которых в NRF24L01 доступно 126 (см ISM диапазон). То есть, шаг между соседними каналами составляет 1 МГц. Используется модуляция GFSK GFSK.

В устройстве реализованы контрольные суммы, подтверждение передачи пакетов и повторная посылка. Все это можно гибко настраивать. Например, можно указать, сколько раз и с какой частотой совершать повторную посылку, или изменить размер контрольной суммы. Используя один канал, устройство позволяет строить сети типа звезда 1:6. С микроконтроллером устройство общается по протоколу SPI.

Как ни странно, купить NRF24L01 проще в виде готового модуля, чем отдельного чипа. Модули эти выглядят как-то так:


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

По центру находится модуль с разъемом RP-SMA и антенной к нему. Многие Wi-Fi роутеры используют такие же разъемы и антенны. Модуль несколько дороже и более громоздок, зато (в теории) способен передавать данные на расстояние до одного километра.

Наконец, справа — адаптер для модулей NRF24L01. Этот адаптер главным образом состоит из стабилизатора напряжения AMS1117-3.3. Дело в том, что NRF24L01 нужно 3.3 В стабилизированного напряжения. При этом он потребляет достаточно большой ток, который не может выдать гнездо Arduino на 3.3 В. В интернете есть много советов на тему как обойтись без этого адаптера — припаять к модулю конденсатор, использовать отдельный источник питания, обмотать модуль фольгой, и так далее. Я все это перепробовал, и пришел к следующему вердикту. Без стабилизатора напряжения у вас скорее всего ничего не заработает.

Перечисленные модули продаются во многих интернет-магазинах. Выше по тексту я привел ссылки на iarduino.ru, так как сам покупал в нем. На самом деле, все эти модули производятся в Китае, поэтому на AliExpress их можно купить намного дешевле. Но и доставка займет больше времени. Посылки из Китая в Россию идут около двух месяцев.

Дополнение: Как оказалось, существуют также модули NRF24L01 Mini (Chipster.ruAliExpress), предназначенные для пайки на плату.

Практика

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

  • IRQ — в данном посте не пригодится. Вообще может использоваться для прерываний;
  • VCC — к плюсу. Притом, поскольку это контакт стабилизатора, подключаем к 5 В, а не 3.3 В;
  • GND — земля;
  • SCK — к цифровому пину 13;
  • MISO, MOSI, CSN, CE — к пинам 12, 11, 10 и 9 соответственно;

Заметьте, что подключение MOSI, MISO и SCK приведено для Arduino Uno. На других версиях Arduino они могут подключаться иначе.

Fun fact! Хотя NRF24L01 и питается от 3.3 В, он понимает и корректно обрабатывает подачу на сигнальные пины напряжения в 5 В. Сделано так специально для удобства взаимодействия с микроконтроллером.

Для работы с NRF24L01 существует несколько готовых библиотек. Наиболее популярной и активно поддерживаемой, по всей видимости, является библиотека RF24 от TMRh20. Она основана на более ранней и ныне, похоже, заброшенной, одноименной библиотеки от maniacbug. Будьте внимательны, не возьмите по ошибке более старую библиотеку.

Пример использования библиотеки RF24 от TMRh20:

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

RF24 radio(9, 10);

const int role_pin = A4;
const int led_pin = 2;
const int button_pin = led_pin;
const uint64_t addresses[] = { 0xAF1510009001LL, 0xAF1510009002LL };

bool isMaster = false;
uint8_t last_btn_state = HIGH;

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

  pinMode(role_pin, INPUT);
  // enable internal pull-up resistor. keep this!
  digitalWrite(role_pin, HIGH);
  isMaster = (bool)digitalRead(role_pin);

  radio.begin();
  radio.setChannel(108);
  radio.setPALevel(RF24_PA_LOW);
  radio.setDataRate(RF24_250KBPS);

  if (isMaster)
  {
    radio.openWritingPipe(addresses[1]);
    // radio.openReadingPipe(1, addresses[0]); // not used yet

    pinMode(button_pin,INPUT);
  }
  else
  {
    // radio.openWritingPipe(addresses[0]); // not used yet
    radio.openReadingPipe(1, addresses[1]);

    radio.startListening();
    pinMode(led_pin,OUTPUT);
    digitalWrite(led_pin, HIGH);
  }
}

void loop(void)
{
  uint8_t state;

  delay(10);

  if (isMaster)
  {
    state = digitalRead(button_pin);

    if(state != last_btn_state)
    {
      Serial.println("Sending state: " + String(state));
      bool ok = radio.write( &state, sizeof(uint8_t) );
      if(ok) Serial.println("OK");
      else Serial.println("Failed!");
      last_btn_state = state;
    }
  }
  else
  {
    if(radio.available())
    {
      Serial.println("Data available, reading...");
      radio.read( &state, sizeof(state) );

      Serial.println("Received: " + String(state));
      digitalWrite(led_pin, state);
    }
  }
}

Этот код обеспечивает взаимодействие двух Arduino, первая из которых выглядит таким образом:

Вторая Arduino выглядит точно так же, только без провода между гнездом A4 и землей, а вместо светодиода к ней подключена кнопка. Если A4 ни к чему не подключен, устройство считается управляющим (мастером), а если подключен к земле — управляемым. Когда кнопка на мастере нажата, светодиод на втором устройстве гаснет. Если кнопка отпущена, светодиод горит.

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

Заключение

Все исходники к этой заметке вы найдете в этом репозитории на GitHub.

Много интересного по теме NRF24L01 вы найдете на GitHub’е уже упомянутого TMRh20. Помимо документации к библиотеке RF24 и дополнительных примеров ее использования там есть, например, наработки по передаче при помощи NRF24L01 звука, создании с его помощью сетей типа ZigBee, и не только.

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

А какие устройства беспроводной связи в это время суток предпочитаете вы?

Материал позаимствован с сайта eax.me