Передаём данные с помощью ИК

Как передать данные без проводов? На слуху у каждого современного человека два современных высокотехнологичных способа, которыми мы пользуемся каждый день: wifi и bluetooth. Оба этих способа используют для передачи радиоволны. Но есть еще один, наверное даже более распространенный вариант — передача данных с помощью инфракрасного света. И о нём мало кто задумывается при создании своих DIY проектов.

Система инфракрасной (ИК) связи повсеместно используется для управления бытовой техникой: телевизорами, кондиционерами, люстрами и пр. А было время, когда с помощью ИК сотовые телефоны и ноутбуки могли передавать друг другу данные. Кстати, до сих пор, в некоторых смартфонах есть ИК-порт для управления бытовыми приборами.

Что касается самой технологии, то она не стоит на месте. ИК-спектр нечувствителен к радиопомехам, а значит всегда будет востребован в наше насыщенное радиошумом время. Современные атмосферные ИК системы могут передавать данные со скоростями до умопомрачительных 4 Тбит/с.

На этом уроке мы создадим приёмник и передатчик инфракрасной связи, с помощью которых будем обмениваться данными между двумя платами Ардуино Уно. Попробуем реализовать передачу, используя последовательный протокол (класс Serial). А в завершении реализуем дальнобойную лазерную связь.

Этот урок посвящен основам ИК связи, а для тех, кто ищет информацию о применении ИК-приемника VS1838 и пультов с протоколом NEC рекомендуем этот урок: Ардуино: инфракрасный пульт и приемник

ИК передатчик

Для передачи сигнала нам нужен источник излучения в инфракрасном спектре, мы же делаем ИК связь, как никак. Инфракрасное излучение — это невидимый глазу свет, длина волны которого больше видимого красного света и меньше длины микроволнового излучения.

Почему именно инфракрасный? У инфракрасного спектра есть два плюса:

  • во-первых, он позволяет избежать влияние (хотя и не полностью) множества источников естественного и искусственного света на качество связи;
  • во-вторых, инфракрасное излучение не видно человеческому глазу, а значит такие передатчики не будут создавать паразитную засветку; плюс, канал ИК связи будет обладать некоторой скрытностью.

Самый доступный источник инфракрасного излучения — ИК светодиод. Встречаются ИК светодиоды с разной длиной волны: 740 нм, 850 нм, 880 нм, 940 нм и т.п. Для выбора подходящего светодиода, мы должны рассматривать сразу пару: излучатель и приемник. Надежный канал ИК связи подразумевает, что приёмник хорошо чувствителен к длине волны излучателя.

Подключаются ИК-светодиоды также как обычные их собратья — последовательно с токозадающим резистором. Для единичного ИК-светодиода подойдет резистор 100-200 Ом.

ИК связь на Arduino. ИК фотодиод

ИК приёмник

Теперь, когда есть излучатель, нам нужно создать приёмник этого излучения. Некий прибор, который будет улавливать инфракрасный свет и генерировать на выходе сигнал, пригодный для Ардуино: высокий уровень напряжения (HIGH) либо низкий уровень (LOW).

Такой прибор проще всего сделать с помощью фотодиода или фототранзистора. Существует несколько популярных схем детектора ИК-излучения с этими приборами, используем такую:

Детектор ИК излучения на фотодиоде и транзисторе

В схеме используется фотодиод, чувствительный к длине волны излучателя. Биполярный транзистор, например 2N2222 и три резистора. Работает схема следующим образом.

Когда на фотодиод не падает свет, он работает как обычный диод — не пропускает ток в обратном направлении. Следовательно, на базе транзистора будет низкий потенциал — транзистор окажется закрытым. Ток от источник питания +5В потечет прямиком на 3-й контакт платы Ардуино, ведь через транзистор ему путь заказан.

Если на фотодиод падает свет, то у него появляется обратный ток — от катода к аноду. Следовательно, на базе транзистора появится высокий потенциал и он откроется. Ток от источника питания потечет через транзистор на землю, и не потечет на контакт микроконтроллера.

Таким образом, схема детектора работает в инверсной логике: когда детектор видит излучение, то на контакте контроллера появляется низкий уровень (LOW), в противном случае — будет высокий уровень (HIGH).

И небольшое пояснение по резисторам. R4 — защищает схему от КЗ через транзистор, R5 — защищает базу транзистора от чрезмерного тока (хотя он особо тут не нужен), R6 — нивелирует насыщение фотодиода паразитной засветкой (солнце).

Соберем приёмник на макетной плате и подключим к Ардуино. Теперь, когда у нас есть обе части линии связи, приступим к программированию.

Программа

Проверим связь с помощью двух простых программ.

Пусть передатчик просто мигает светодиодом: 500 миллисекунд горит, другие 500 — не горит.

const byte ledPin = 2;

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

void loop(){
  digitalWrite(ledPin, HIGH);
  delay(500);
  digitalWrite(ledPin, LOW);
  delay(500);
}

Ардуино на стороне приёмника будет каждые 100 мс считывать сигнал от ИК-детектора и передавать в последовательный порт на компьютер слово «received» если сигнал есть и «-» если его нет.

const byte photoPin = 3;

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

void loop() {
  byte v = digitalRead(photoPin); // считываем данные с детектора
  if(v == LOW){ // проверяем, что детектор выдает LOW
      Serial.println("received");
  } else {
      Serial.println("-");
  }
  delay(100);
}

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

ИК связь на Arduino

Затем открываем монитор последовательного порта приёмника и проверяем, приходит ли сигнал. В случае успеха, картина будет такая:

...
received
-
-
-
received
received
received
-
-
...

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

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

Другая плохая ситуация, когда приемник постоянно выдает «received», хотя должен делать это с периодом 1 сек. Если схемы собраны правильно, то вероятнее всего детектор засвечен паразитным ИК излучением.

В данной ситуации можно попробовать две вещи:

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

На текущем этапе уже можно передавать с помощью ИК линии связи простые сигналы. Например, управлять включением и выключением какого-то устройства или робота. Чтобы обеспечить обмен текстом и числами, используем стандартную библиотеку и класс Serial. Об этом далее.

UART через ИК

Класс Serial, который есть в стандартной библиотеке Arduino IDE, умеет передавать данные через аппаратный интерфейс UART (он же последовательный порт). На плате семейства Ардуино контакты 0 (RX) и 1 (TX) как раз привязаны к аппаратному UART, а значит мы сможем их использовать для наших целей.

Схема излучателя у нас останется прежней, кроме контакта Ардуино, к которому она подключается. Мы передаем данные, значит используем контакт №1 (он же TX).

Программа передатчика будет каждую секунду отправлять в последовательный порт текст «ping».

void setup() {
  Serial.begin(4800);
}

void loop() {
  Serial.println("ping");
  delay(200);
}

Готово. Теперь сделаем приёмник.

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

Таким образом, для создания приёмника нам необходимо, чтобы контроллер имел два UART интерфейса, причём с возможностью менять логику. Надо ли говорить, что у Ардуино Уно UART только один и логика там не меняется. Хмм.

Как вариант, можно вместо Уно использовать версию Мега, у которой есть несколько UART. Проблему с инверсной логикой можно решить переделав схему детектора и заменив транзистор на PNP. А можно всё оставить как есть и использовать программный UART интерфейс. Благо, в среде Arduino IDE есть специальная библиотека SoftwareSerial, которая как раз для таких целей и нужна.

Как и в большинстве случаев, при использовании разного рода библиотек, нам потребуется в самом начале программы создать объект класса SoftwareSerial. Пишем:

SoftwareSerial Photo(10, 11, 1);

здесь первый аргумент 10 — контакт, на котором будет RX канал; второй аргумент 11 — контакт TX канала; 1 — означает инверсию сигнала, это нам и нужно!

Программа приёмника данных будет выглядеть так.

#include <SoftwareSerial.h>

SoftwareSerial Photo (10, 11, 1);

void setup() {
  Serial.begin(9600);
  Photo.begin(4800);
}

void loop() {
  while( Photo.available() ){
    char v = Photo.read();
    Serial.write(v);
  }
}

Загружаем программы, выставляем излучатель и детектор на линии и подаем питание. Если при этом открыть монитор последовательного порта, то там будут появляться слова «ping».

В данном примере мы использовали скорость передачи 4800 бод. Откуда именно такая скорость? Дело в том, что скорость работы нашей ИК системы сильно проседает из-за программного UART. Если от него избавиться, то линию связи вполне можно разогнать до куда более высоких скоростей.

Подобную систему связи уже можно применить для передачи сообщений в плотной среде роевых роботов. При такой скученности радиосвязь работает плохо, а вот передача данных ИК-светом ближайшим соседям вполне подойдет.

В следующей главе посмотрим как сделать оптическую линию еще надежнее и быстрее.

Лазерная связь

Увеличить дистанцию приёма можно разными способами, один из них — использовать мощный излучатель. Например, можно заменить светодиод на лазер.

Для эксперимента подойдет обычный лазерный модуль мощностью 5 мВт со встроенным токозадающим резистором. Полупроводниковый лазер по устройству очень похож на светодиод, и подключается он точно так же: катод — к земле, анод — к контакту Ардуино №2. Собираем всё схемы, загружаем программы, подаем питание.

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

Модуляция

Еще один способ увеличить дистанцию — модуляция сигнала. Это значит, что передатчик должен генерировать несущую частоту и модулировать её полезным цифровым сигналом. Полученный сигнал передается в эфир. Приёмник же должен обеспечить демодуляцию полезного сигнала.

Сделать такую систему можно из доступных каждому DIY-щику деталей. В передатчике катод ИК-светодиода подключаем не к земле, а к ещё одному контакту Ардуино. Программа приемника должна формировать на этом контакте прямоугольный сигнал частотой 38 кГц. Например так:

TCCR2A = _BV(COM2A0) | _BV(WGM21);
TCCR2B = _BV(CS20);
OCR2A = 209;

Для приёма модулированного сигнала используется стандартный ИК-приёмник на 38 кГц, например, vs1838. Этот прибор сам производит демодуляцию сигнала.

Над учитывать, что чем выше несущая частота, тем больше пропускная способность такого канала. С несущей частотой 38 кГц можно добиться скорость передачи до 2400 бод.


Изменено:

Передаём данные с помощью ИК: 2 комментария

  1. #include
    #include

    const int buttonPin = 5; // Кнопка на пине 5
    IRsend irsend;
    IRrecv irrecv(2, 4); // ИК-приемник подключен к пину 2, с дополнительным буфером 4
    boolean isTransmitting = true; // Флаг для определения режима работы (true — передача, false — прием)

    File dataFile; // Глобальная переменная для хранения файла из SD-карты

    void setup() {
    Serial.begin(9600);
    pinMode(buttonPin, INPUT_PULLUP);
    irsend.begin(3); // Передатчик подключен к пину 3
    if (!irrecv.enableIRIn()) {
    Serial.println(«Unable to start receiver»);
    }
    if (!SD.begin(10)) {
    Serial.println(«SD initialization failed!»);
    while (1); // Остановить выполнение, если инициализация SD-карты не удалась
    }
    pinMode(10, OUTPUT); // Устанавливаем пин 10 как выход для SD-карты (CS)

    // Установка пинов SCK, MOSI, MISO не требуется, они устанавливаются автоматически при инициализации SD
    }

    void loop() {
    if (digitalRead(buttonPin) == LOW) {
    delay(50); // Для устранения дребезга контактов
    if (isTransmitting) {
    transmitData();
    } else {
    receiveData();
    }
    }
    }

    void transmitData() {
    dataFile = SD.open(«music.mp3», FILE_READ); // Открываем файл mp3 для чтения
    if (dataFile) {
    while (dataFile.available()) {
    irsend.sendSony(dataFile.read(), 8); // Отправляем данные (байты файла mp3) через ИК-передатчик
    delay(50);
    }
    dataFile.close();
    isTransmitting = false; // Переключаем режим на прием
    digitalWrite(6, HIGH); // Зажигаем светодиод на пине 6, чтобы показать, что передача завершена
    } else {
    Serial.println(«error opening file»);
    }
    }

    void receiveData() {
    decode_results results;
    if (irrecv.decode(&results)) {
    irrecv.resume(); // Продолжаем прием ИК-сигналов
    byte receivedData = results.value & 0xFF; // Получаем принятый байт данных

    dataFile = SD.open(«music_received.mp3», FILE_WRITE); // Открываем файл для записи
    if (dataFile) {
    dataFile.write(receivedData); // Записываем принятый байт в файл
    dataFile.close();
    isTransmitting = true; // Переключаем режим на передачу, чтобы готовиться к следующей передаче
    digitalWrite(6, LOW); // Выключаем светодиод на пине 6
    } else {
    Serial.println(«error opening file»);
    }
    }
    }
    /*
    pinMode(10, OUTPUT); // Устанавливаем пин 10 как выход для SD-карты (CS)
    pinMode(13, OUTPUT); // Установка пина 13 (SCK) и 11 (MOSI) включается автоматически при инициализации SD
    pinMode(12, INPUT); // MISO используется только для чтения, обычно устанавливается как входной
    SCK (Serial Clock) — пин 13
    MOSI (Master Out Slave In) — пин 11
    MISO (Master In Slave Out) — пин 12
    CS (Chip Select) — пин 10
    */

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.