Рейтинг@Mail.ru
Радио приёмник XY-MK-5V и передатчик  FS1000A
Радио приёмник XY-MK-5V и передатчик FS1000A

Подключение радиомодуля XY-MK-5V / FS1000A к Arduino

автор:
2 comments Arduino
Print Friendly, PDF & Email

Сегодня мы займёмся подключением радиомодуля, а точнее, двух модулей – приёмника XY-MK-5V и передатчика FS1000A – к Arduino. Тоже к двум.

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

  • компьютер с установленной Arduino IDE или другой средой разработки;
  • 2 платы Arduino UNO или другой модификации (недорого купить можно на этом сайте);
  • радиопередатчик FS1000A и радиоприёмник XY-MK-5V, приобретаются здесь;
  • соединительные провода (рекомендую вот такой набор, в котором есть все комбинации «мама-мама», «папа-папа», «папа-мама»).

1Описание радиопередатчика FS1000A и приёмника XY-MK-5V

Эта пара отличается очень низкой стоимостью, при этом имеет весьма неплохой радиус передачи (около 50-ти метров в условиях города). Радиопередатчик FS1000A и радиоприёмник XY-MK-5V должны работать на одной частоте. «Из коробки» они настроены на несущую частоту 433 МГц. Это распространённая частота для радиосвязи. Например, она используется для связи домашней метеостанцией типа Oregon Scientific с выносными метеодатчиками (мы к ним ещё вернёмся), в некоторых системах автоматического управления воротами, и в других «умных» приборах и системах, передающих данные «по воздуху».

Внешний вид приёмника XY-MK-5V и передатчика FS1000A
Внешний вид приёмника XY-MK-5V и передатчика FS1000A

2Подключение к Arduino радиопередатчика FS1000A и приёмника XY-MK-5V

Прежде чем подключать передатчик FS1000A к Arduino, необходимо к контактной площадке, обозначенной на плате ANT, припаять отрезок провода сечением примерно 0,25…0,5 мм и длиной 17,3 см. Это будет антенной.

Частоте 433 МГц соответствует длина волны, равная примерно 69 см. При длине антенны, равной 1/4 от длины волны, волновой вибратор (антенна) находится в резонансе с длиной волны, и её эффективность максимальна. Отсюда число 17,3 см (= 69 / 4).

Передатчик FS1000A можно запитать напряжением от 3,3 до 12 В. В зависимости от поданного напряжения дальность передачи может несколько меняться: при большем напряжении – большая дальность. Мы подадим на передатчик напряжение 5 В, и остальные выводы подключим согласно схеме.

Схема подключения передатчика FS1000A к Arduino
Схема подключения передатчика FS1000A к Arduino

Приёмник XY-MK-5V подключается тоже просто. Вывод "DATA" на модуле сдвоен, можно подключаться к любой из двух ножек. Питание также подадим 5 В от платы Arduino.

Схема подключения приёмника XY-MK-5V к Arduino
Схема подключения приёмника XY-MK-5V к Arduino

3Пример простейшей передачи данных по радиоканалу с помощью Arduino

Особенностью радиопередачи является то, что длительные сигналы одного уровня передавать невозможно, передача будет срываться. Для более-менее устойчивой передачи необходимо передавать переменный сигнал. Причём необходимо каким-то образом выделять полезный сигнал из шума, который всегда присутствует в радиоэфире.

Для первого эксперимента возьмём стандартный скетч мигания светодиодом Blink и немного модифицируем его: каждые 5 секунд будем посылать команду с одного Arduino (передатчика) к другому (приёмнику). По принятии команды приёмник будет либо зажигать светодиод, если он погашен, либо гасить. То есть каждые 5 секунд приёмник будет менять своё состояние по принятой команде. Сделать это немного сложнее, чем кажется, ведь нам нужно выделить команду из постоянно присутствующего в эфире шума.

Первый скетч – для передатчика. Он довольно простой.

#define prd 4 // пин DATA передатчика FS1000A 
#define ledPin 13 // вывод встроенного светодиода Arduino

void setup() {
  pinMode(ledPin, OUTPUT); 
  pinMode(prd, OUTPUT); 
}

void loop() {
  sendCommand(); // отправляем команду
  delay(5000); // делаем задержку на 5 сек
}

// посылает команду в эфир 
void sendCommand() {
  digitalWrite(ledPin, HIGH); // на время отправки команды зажигаем встроенный светодиод
  // команда представляет собой три импульса наподобие «тире-точка-тире»
  digitalWrite(prd, HIGH);
  delay(100); 
  digitalWrite(prd, LOW);
  delay(50); 
  digitalWrite(prd, HIGH);
  delay(50); 
  digitalWrite(prd, LOW);
  delay(50); 
  digitalWrite(prd, HIGH);
  delay(100); 
  digitalWrite(prd, LOW);
  delay(50); 
  digitalWrite(ledPin, LOW);  // по окончании передачи команды гасим светодиод
}

Временная диаграмма команды приведена на рисунке:

Передаваемая в радиоэфир команда
Передаваемая в радиоэфир команда
Временная диаграмма двух идущих подряд команд
Временная диаграмма двух идущих подряд команд

Скетч для приёмника, ввиду описанных выше причин, сложнее. Поэтому для начала давайте просто периодически читать данные на входе приёмника и выводить то, что принимаем, в последовательный порт.

#define prm 2 // пин DATA приёмника XY-MK-5V
#define ledPin 13 // встроенный светодиод

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  int data = digitalRead(prm); // читаем данные с входа приёмника
  Serial.println(data);
  delay(10);
}

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

Данные+шум на входе приёмника
Данные+шум на входе приёмника

Как видно, на входе приёмника постоянно присутствует шумовой сигнал. Моменты, когда излучает передатчик, легко отслеживаются на глаз (на рисунке они выделены синими пунктирными рамками). После окончания передачи ненадолго устанавливается нулевой уровень, но затем система автоматической регулировки усиления снова усиливает шумы, и на входе приёмника появляется хаотичная смена логических уровней.

Однако, выделение полезного сигнала из шума с помощью аппаратуры не так просто, как на глаз.

Существует т.н. теорема Котельникова, которая говорит о том, что при дискретизации аналогового сигнала потерь информации не будет только в том случае, если частота полезного сигнала равна половине или меньше частоты дискретизации (т.н. «частоты Найквиста»).

Для простоты возьмём период опроса данных (период дискретизации) со входа приёмника 50 мс – это число равно длительности самой короткой части команды, которую мы каждые 5 секунд отправляем передатчиком в радиоэфир. Снимая по одному отсчёту за 50 мс мы, конечно же, нарушаем теорему Котельникова (период дискретизации надо брать хотя бы 25 мс или меньше). Но для максимального упрощения примера оставим так и посмотрим, сможем ли выделить из шума в радиоэфире нашу команду.

Длительность логических уровней передаваемой команды
Длительность логических уровней передаваемой команды

Опрашивая данные с приёмника каждые 50 мс (зелёные вертикальные штрихи на рисунке – моменты опроса приёмника), мы должны увидеть последовательность "110101100". При этом вероятность ложных срабатываний нашего детектора будет достаточно высока, т.к. есть немалый шанс, что в моменты считывания данных с приёмника случайный шумовой сигнал будут иметь точно такие же значения. К счастью, в конце последовательности имеется большое число нулей. Так что будем искать последовательность, скажем, "11010110000000".

Если взять больше нулей, то вероятность ложных срабатываний уменьшится. Но надо понимать, что поиск совпадения большего по размерности массива будет занимать больше времени, и 50 мс станут уже не 50-тью, а несколько больше. Из-за этого постепенно будут сдвигаться моменты, в которые мы опрашиваем приёмник («убегание» частоты). Кроме того, мы не можем гарантировать, что в моменты, когда мы ожидаем прихода нулей, на входе приёмника не возникнет какой-то случайный всплеск, и мы не распознаем пришедшую команду. То есть, получим пропуск искомой последовательности. Здесь надо добиться компромисса между числом ложных срабатываний и числом пропусков – оба эти условия нас не устраивают.

const int prm = 2; // пин входа приёмника XY-MK-5V
const int ledPin = 13; // пин встроенного светодиода Arduino
const int len = 14; // длина массивов

bool state = false; // текущее состояние светодиода
int pattern[len] = {1,1,0,1,0,1,1,0,0,0,0,0,0,0}; // эталонный массив - маска команды, которую нужно «словить»
int testReg[len] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // тестовый регистр - массив оцифрованных значений с входа приёмника

void setup() {
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
}

void loop() {
  int data = digitalRead(prm); // читаем значение на входе приёмника
  ShiftReg(data, testReg); // вдвигаем полученное число в тестовый регистр
  if (IsCommandDetected) { // проверяем, нет ли в тестовом регистре искомой последовательности
    state = !state; // если есть, меняем состояние светодиода
    digitalWrite(ledPin, state);
  }
  delay(50); 
}

// вдвигает в тестовый регистр новое значение
void ShiftReg(int newVal, int *arr) {
  for (int i=0; i<len; i++) {
    arr[i] = testReg[i+1]; // смещаем значения в регистре на 1 позицию
  }
  arr[len-1] = newVal; // последнюю позицию заменяем только что принятым измерением
}

// проверяет, обнаружена ли команда на входе приёмника
bool IsCommandDetected() {
  for (int i=0; i<len; i++) {
    if (testReg[i] != pattern[i]) { // почленно сравниваем 2 массива
      return false;
    }
  }
  return true;
}

Функция ShiftReg() получает на вход два аргумента: текущее содержимое тестового регистра и последнее полученное со входа приёмника значение. Она сдвигает все значения в регистре на 1 позицию, а в младший разряд регистра помещает текущее принятое значение. Таким образом, в регистре постоянно хранятся 16 (в данном конкретном случае) последних считанных с приёмника значений. Если мы посмотрим как меняется содержимое регистра, которое формируется функцией ShiftReg(), то увидим примерно следующее:

0000000000000000
0000000000000001
0000000000000010
0000000000000100
0000000000001000
0000000000010000
0000000000100001
0000000001000010
0000000010000101
0000000100001010
0000001000010101
0000010000101010
0000100001010101
0001000010101010
0010000101010100
0100001010101001
1000010101010010
0000101010100101
0001010101001010
0010101010010101
0101010100101010
1010101001010101
0101010010101011
1010100101010110
0101001010101101
1010010101011010
0100101010110101
1001010101101010
0010101011010101
0101010110101010
1010101101010101
0101011010101011
1010110101010110
0101101010101101
1011010101011010
0110101010110101
1101010101101010
1010101011010101
0101010110101010
1010101101010100
0101011010101000
1010110101010000
0101101010100001
1011010101000010
0110101010000101
1101010100001010
1010101000010101
0101010000101010
1010100001010101
0101000010101010
1010000101010100
0100001010101001
1000010101010010
...и т.д.

Функция IsCommandDetected() почленно сравнивает два массива – эталонный массив (искомая последовательность) и содержимое тестового регистра (массив полученных с приёмника значений), и если массивы одинаковы, значит мы «поймали» команду. В таком случае меняем состояние встроенного светодиода.

Выводы

На практике, полученный детектор довольно хорошо справляется с поставленной задачей. Светодиод на плате Arduino, к которой подсоединён приёмник, каждые 5 секунд ожидаемо меняет своё состояние. Это от него и требовалось.

Однако в реальности, как правило, возникают более сложные задачи, а именно – передавать какие-то осмысленные данные. В следующей статье, посвящённой работе с модулями XY-MK-5V и FS1000A, я детально рассмотрел возможность передачи данных по радиоканалу. Идея ориентирована на передачу между двумя компьютерами с помощью модулей UART. Но Arduino также имеет линии Rx и Tx, относящиеся к UART. Так что адаптировать идею к использованию с Arduino, уверен, не составит большого труда.

Демонстрация подключения радиомодулей XY-MK-5V и FS1000A к Arduino
Last modified onПятница, 22 Ноябрь 2019 18:53 Read 27882 times
Ключевые слова: :

Поблагодарить автора:

Поделиться

Print Friendly, PDF & Email

2 comments

Leave a comment

  1. Arduino это...
  2. Arduino это...
  3. Arduino это...
Отличный способ начать знакомство с электроникой, микроконтроллерами и программированием!
Замечательное средство для создания собственных электронных устройств, которые пригодятся в быту или для развлечения!
Уникальный конструктор, для которого разработаны десятки совместимых датчиков и модулей!
next
prev