Рано или поздно, в создаваемых проектах Arduino появится необходимость дистанционного управления. Одним из самых бюджетных решений является использование радиоприемника и радиопередатчика, такими являются WL101-341 и WL102-341. Подключаются WL101-341 и WL102-341 к Arduino очень просто, библиотеки уже существуют (к примеру RadioHead), так что не составит большого труда обмениваться данными между ардуинками. Простейший пример их использования вы найдете в данной статье, а дальше все зависит только от ваших нужд и фантазии.
- 1 Установка библиотеки RadioHead
- 2 Описание методов класса RH_ASK
- 2.1 RH_ASK ()
- 2.2 virtual bool init()
- 2.3 virtual bool available()
- 2.4 virtual bool recv (uint8_t *buf, uint8_t *len)
- 2.5 virtual bool send(const uint8_t *data, uint8_t len)
- 2.6 virtual uint8_t maxMessageLength()
- 2.7 void setModeIdle()
- 2.8 void setModeRx()
- 2.9 void setModeTx()
- 2.10 void handleTimerInterrupt()
- 2.11 uint16_t speed()
- 3 Подключение WL101-341 и WL102-341 к Arduino
- 4 Пример передачи данных рандомной длины
- 5 Материалы
- 6 Похожие записи
Установка библиотеки RadioHead
RadioHead Packet Radio — это библиотека для встроенных микропроцессоров. RadioHead предоставляет полную объектно-ориентированную библиотеку для отправки и получения пакетированных сообщений через различные распространенные радиопередачи данных и другие виды транспорта на ряде встроенных микропроцессоров/микроконтроллеров. Установить библиотеки можно следующим образом:
- Скачиваем библиотеку с сайта RadioHead, на данный момент последняя версия: RadioHead-1.89.zip;
- Распаковываем архив в
\Documents\Arduino\libraries
;
- Библиотека установлена.
Описание методов класса RH_ASK
Для работы с данными радиомодулями будет использован класс RH_ASK. RH_ASK работает с рядом недорогих РЧ трансиверов ASK (амплитудная манипуляция), таких как RX-B1 (также известный как ST-RX04-ASK); Передатчик TX-C1 и приемопередатчик DR3100; Приемопередатчик FS1000A / XY-MK-5V; HopeRF RFM83C / RFM85. Поддерживает ASK (OOK).
RH_ASK ()
Конструктор. В настоящее время поддерживается только один экземпляр RH_ASK на скетч.
RH_ASK::RH_ASK (uint16_t speed = 2000, uint8_t rxPin = 11, uint8_t txPin = 12, uint8_t pttPin = 10, bool pttInverted = false )
Параметры:
speed
— Желаемая скорость в битах в секунду
rxPin
— Пин, который используется для получения данных от приемника
txPin
— Пин, который используется для отправки данных на передатчик
pttPin
— Пин, который подключен к EN передатчика. Будет установлено ВЫСОКОЕ состояние, чтобы включить передатчик (по умолчания pttInverted = true).
pttInverted
— true, если вы хотите, чтобы pttin был инвертирован, чтобы НИСКОЕ состояние включило передатчик.
virtual bool init()
Инициализирует драйвер. Убедитесь, что драйвер настроен правильно перед вызовом init()
.
bool RH_ASK::init()
Возвращает:
истина, если инициализация прошла успешно.
virtual bool available()
Проверяет, доступно ли новое сообщение из драйвера. Также переводит драйвер в режим RHModeRx до тех пор, пока сообщение не будет фактически получено транспортом, когда оно будет возвращено в RHModeIdle. Это может быть вызвано несколько раз в цикле ожидания.
bool RH_ASK::available()
Возвращает:
true, если новое, полное, безошибочное несобранное сообщение доступно для извлечения с помощью recv()
.
virtual bool recv (uint8_t *buf, uint8_t *len)
Включает приемник, если он еще не включен. Если доступно допустимое сообщение, копирует его в buf
и возвращает true
, иначе возвращает false
. Если сообщение копируется, *len
устанавливается длина (Внимание, сообщения 0 длины разрешены). Вы должны вызывать эту функцию достаточно часто, чтобы не пропустить ни одного сообщения. Рекомендуется вызывать ее в основном цикле.
bool RH_ASK::recv(uint8_t * buf, uint8_t * len)
Параметры:
buf
— место для копирования полученного сообщения
len
— указатель на доступное пространство в буфере. Устанавливает фактическое количество скопированных октетов.
Возвращает:
true
, если действительное сообщение было скопировано в buf
.
virtual bool send(const uint8_t *data, uint8_t len)
Ожидание завершения передачи любого предыдущего передаваемого пакета с помощью waitPacketSent()
. Затем загружает сообщение в передатчик и запускает передатчик. Обратите внимание, что длина сообщения 0 НЕ допускается.
bool RH_ASK::send(const uint8_t * data, uint8_t len)
Параметры:
data
— массив данных для отправки
len
— Количество байтов данных для отправки (> 0)
Возвращает:
истина, если длина сообщения была правильной, и оно была правильно поставлена в очередь для передачи
virtual uint8_t maxMessageLength()
Возвращает максимальную длину сообщения, доступную в этом драйвере.
uint8_t RH_ASK::maxMessageLength()
Возвращает:
Максимальная допустимая длина сообщения
void setModeIdle()
Если текущий режим — Rx или Tx, он переключается в режим ожидания. Если передатчик или приемник работает, отключает их.
void INTERRUPT_ATTR RH_ASK::setModeIdle()
void setModeRx()
Если текущий режим Tx или Idle, изменяет его на Rx. Запускает приемник в RF69.
void RH_ASK::setModeRx()
void setModeTx()
Если текущий режим Rx или Idle, изменяет его на Rx. F Запускает передатчик в RF69.
void RH_ASK::setModeTx()
void handleTimerInterrupt()
не вызывайте этот метод, он используется обработчиком прерываний
uint16_t speed()
Возвращает текущую скорость в битах в секунду.
uint16_t RH_ASK::speed()
Возвращает:
Текущая скорость в битах в секунду
Подключение WL101-341 и WL102-341 к Arduino
Схема подключения WL101-341 к Arduino
Arduino | WL101-341 |
---|---|
3.3В | Vin |
GND | GND |
11 | DO |
Пример скетча для приёмника
Приёмник будет получать числа от 0 до 255 по нарастающей. Если ожидаемое число получено не будет, тогда выводим в терминал ‘*’.
/* Добавляем необходимые библиотеки */ #include <RH_ASK.h> #define SPEED (uint16_t)1200 #define RX_PIN (uint8_t)11 #define TX_PIN (uint8_t)12 #define PTT_PIN (uint8_t)10 #define PTT_INVERTED false /* Создаём экземпляр класса RH_ASK приёмника */ RH_ASK driver(SPEED, RX_PIN, TX_PIN, PTT_PIN, PTT_INVERTED); void setup() { /* задаем скорость общения с компьютером */ Serial.begin(115200); /* Инициализируем приёмник */ if (! driver.init()) { Serial.println(F("RF init failed!")); while (true) { delay(1); } } /* Настройка встроенного светодиода */ pinMode(LED_BUILTIN, OUTPUT); } void loop() { static uint8_t estdata; uint8_t data; uint8_t buflen = sizeof(data); /* Проверяем наличие новых данных */ if (driver.recv((uint8_t*)&data, &buflen)) { /* Гасим светодиод */ digitalWrite(LED_BUILTIN, LOW); /* Выводим в терминал '*' если полученные данные не совпадают с ожидаемыми */ if (data != estdata) { Serial.print('*'); } /* Выводим в терминал полученные данные */ Serial.print("RX: "); Serial.println(data); /* Инкрементируем значение */ estdata = data + 1; /* Включаем светодиод */ digitalWrite(LED_BUILTIN, HIGH); } }
Схема подключения WL102-341 к Arduino
Вывод данных WL102-341 не толерантный к 5 вольтам поэтому, если вы используете пятивольтовую arduino, то подать 3.3 вольта можно через резистивный делитель (R1 = 1к, R2 = 2к).
На данном модуле линия EN неактивна, так как на плате установлена перемычка, соединяющая 1-й вывод микросхемы (EN) с линией питания, то есть модуль постоянно работал при подаче питания. Можно отпаять перемычку, чтобы иметь возможность управления передатчиком.
Arduino | WL102-341 |
---|---|
GND | GND / — |
3.3В | Vin / + |
DAT | 12 |
EN | 10 |
Пример скетча для передатчика
Передатчик будет отправлять числа от 0 до 255 по нарастающей.
/* Добавляем необходимые библиотеки */ #include <RH_ASK.h> #define SPEED (uint16_t)1200 #define RX_PIN (uint8_t)11 #define TX_PIN (uint8_t)12 #define PTT_PIN (uint8_t)10 #define PTT_INVERTED false /* Создаём экземпляр класса RH_ASK передатчика */ RH_ASK driver(SPEED, RX_PIN, TX_PIN, PTT_PIN, PTT_INVERTED); void setup() { /* задаем скорость общения с компьютером */ Serial.begin(115200); /* Инициализируем передатчик */ if (!driver.init()) { Serial.println(F("RF init failed!")); while (true) { delay(1); } } /* Настройка встроенного светодиода */ pinMode(LED_BUILTIN, OUTPUT); } void loop() { static uint8_t data = 0; /* Гасим светодиод */ digitalWrite(LED_BUILTIN, LOW); /* Передаём данные */ driver.send((uint8_t*)&data, sizeof(data)); /* Ждем пока передача будет окончена */ driver.waitPacketSent(); /* Выводим в терминал отправленные данные */ Serial.print("TX: "); Serial.println(data); /* Инкрементируем значение */ ++data; /* Включаем светодиод */ digitalWrite(LED_BUILTIN, HIGH); /* Ждём */ delay(100); }
Результат
Пример передачи данных рандомной длины
Для большего понимания принципа работы библиотеки, создал ещё один пример обмена данными между ардуинками. Передатчик будет отправлять массив данных uint8_t data[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
с интервалом в одну секунду. Количество отправленных байт будет неизвестно, потому что применяется функция random(1, 10)
. Принимающая сторона принимает эти данные и выводит их и их количество в терминал.
Скетч для передатчика
/* Добавляем необходимые библиотеки */ #include <RH_ASK.h> #define SPEED (uint16_t)2000 #define RX_PIN (uint8_t)11 #define TX_PIN (uint8_t)12 #define PTT_PIN (uint8_t)10 #define PTT_INVERTED false /* Создаём экземпляр класса RH_ASK передатчика */ RH_ASK driver(SPEED, RX_PIN, TX_PIN, PTT_PIN, PTT_INVERTED); void setup() { /* задаем скорость общения с компьютером */ Serial.begin(115200); /* Инициализируем передатчик */ if (! driver.init()) { Serial.println(F("RF init failed!")); while (true) { delay(1); } } /* Настройка встроенного светодиода */ pinMode(LED_BUILTIN, OUTPUT); } void loop() { /* Буфер данных для отправки */ uint8_t data[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; /* Гасим светодиод */ digitalWrite(LED_BUILTIN, LOW); /* Передаём массив данных случайной длины (от 1 до 10) */ driver.send(data, random(1, 10)); /* Ждем пока передача будет окончена */ driver.waitPacketSent(); /* Включаем светодиод */ digitalWrite(LED_BUILTIN, HIGH); /* Ждём секунду */ delay(1000); }
Скетч для приёмника
/* Добавляем необходимые библиотеки */ #include <RH_ASK.h> #define SPEED (uint16_t)2000 #define RX_PIN (uint8_t)11 #define TX_PIN (uint8_t)12 #define PTT_PIN (uint8_t)10 #define PTT_INVERTED false /* Создаём экземпляр класса RH_ASK приёмника */ RH_ASK driver(SPEED, RX_PIN, TX_PIN, PTT_PIN, PTT_INVERTED); void setup() { /* задаем скорость общения с компьютером */ Serial.begin(115200); /* Инициализируем передатчик */ if (! driver.init()) { Serial.println(F("RF init failed!")); while (true) { delay(1); } } /* Настройка встроенного светодиода */ pinMode(LED_BUILTIN, OUTPUT); } void loop() { /* Буфер полученных данных */ uint8_t data[16]; /* Размер полученных данных */ uint8_t buflen = sizeof(data); uint8_t i; /* Проверяем наличие новых данных */ if (driver.recv(data, &buflen)) { /* Гасим светодиод */ digitalWrite(LED_BUILTIN, LOW); /* Выводим в терминал полученные данные */ Serial.print("Size: "); Serial.print(buflen); Serial.println(); Serial.print("Data: "); for (i = 0; i < buflen; i++) { Serial.print((char)data[i]); Serial.print(' '); } Serial.println(); /* Включаем светодиод */ digitalWrite(LED_BUILTIN, HIGH); } }
Результат
Материалы
WL101-341 и WL102-341 — Обзор супергетеродинного приемника и передатчика
VirtualWire
RadioHead
RF 433 MHz модули SYN115/SYN480R и WL101-341/WL102-341
Спасибо за статью! Не подскажите как подобрать скорость в бит/сек? поставил 1250 вместо 2000, работает лучше.
Ознакомьтесь с полным процессом регистрации некоммерческой организации – кликните и узнайте больше
https://registracia-nko.ru/ — форма регистрации некоммерческой организации
Узнайте, как зарегистрировать НКО с минимальными затратами и временными издержками
https://registracia-nko.ru/ — заявление на регистрацию нко