Li-Fi (Light Fidelity – «Световое качество») – это перспективная технология, которая позволяет передавать данные с помощью оптической связи, используя в качестве переносчика сигнала обычный свет. Данные в технологии Li-Fi передаются при помощи света, излучаемого каким-либо устройством (например, светодиодом), а на приемной стороне принимаются каким-либо светочувствительным элементом, например, фоторезистором или фотодиодом. Скорость передачи данных в технологии Li-Fi может быть до 100 раз выше чем в технологии Wi-Fi, поскольку частотная емкость оптического диапазона значительно больше, чем частотная емкость радиодиапазона.
В данном проекте мы осуществим Li-Fi связь между двумя платами Arduino. Мы будем передавать текстовые данные с помощью светодиода и клавиатуры (клавишной панели) 4×4. На приемной стороне мы будем декодировать эти сигналы с помощью фоторезистора (LDR).
Необходимые компоненты
- Плата Arduino Uno (купить на AliExpress).
- Плата Arduino Nano (купить на AliExpress).
- Фоторезистор (LDR) (купить на AliExpress).
- Клавиатура (Keypad, клавишная панель) 4×4 (купить на AliExpress).
- ЖК дисплей 16х2 с модулем интерфейса I2C для него (купить на AliExpress).
- Светодиод 5 mm (купить на AliExpress).
- Макетная плата.
- Соединительные провода.
Реклама: ООО «АЛИБАБА.КОМ (РУ)» ИНН: 7703380158
Краткое введение в технологию Li-Fi
Как уже упоминалось, Li-Fi является достаточно прогрессивной технологией и с ее помощью можно обеспечить связь в 100 раз более быструю, чем с помощью технологии Wi-Fi. Данные в технологии Li-Fi передаются с помощью света. Есть даже проекты организации высокоскоростного интернета с помощью технологии Li-Fi – представляет каким скоростным его можно было бы сделать.
Технология Li-Fi использует видимый свет в качестве среды переноса данных. Светодиод может выступать в качестве источника света, а фотодиод (фоторезистор) – в качестве приемника света. Управляя импульсами света на передающей стороне, мы можем передавать уникальные образцы данных. Эти процессы можно осуществлять на очень высокой скорости и на частотах света, невидимого человеческому глазу.
Передающая часть Li-Fi на основе платы Arduino
Структурная схема передающей части Li-Fi на основе платы Arduino представлена на следующем рисунке.
Как показано на рисунке, в качестве устройства ввода информации используется клавиатура (клавишная панель) 4х4 – то есть текст для передачи мы будем набирать на ней. Информация с клавиатуры поступает в управляющее устройство (control unit), роль которого в нашем проекте выполняет плата Arduino. Данная плата преобразует информацию, поступающую от клавиатуры, в бинарные (двоичные) импульсы, которые подаются на светодиод для их последующей передачи в виде импульсов света.
Схема передающей части Li-Fi на основе платы Arduino представлена на следующем рисунке.
Приемная часть Li-Fi на основе платы Arduino
На приемной стороне фоторезистор (LDR) принимает импульсы света от передающей стороны и преобразует их в электрические импульсы, которые затем подаются в плату Arduino (Control unit). Плата Arduino отображает полученные данные на экране ЖК дисплея 16×2.
Схема приемной части Li-Fi на основе платы Arduino представлена на следующем рисунке.
Объяснение программы для Arduino
Полный код программы приведен в конце статьи, здесь же мы кратко рассмотрим его основные фрагменты. Рассмотрим последовательно фрагмента кода для передающей и приемной частей нашего проекта.
Объяснение программы для передающей части Li-Fi
В передающей части плата Arduino Nano взаимодействует с клавиатурой 4×4 и светодиодом. Первым делом нам необходимо скачать по следующей ссылке и установить в Arduino IDE библиотеку для работы с клавиатурой 4х4. Более подробно о подключении подобной клавиатуры к плате Arduino можно прочитать в этой статье. Далее подключим в программе заголовочный файл этой библиотеки.
1 |
#include <Keypad.h> |
После успешной установки библиотеки укажем число столбцов и число строк в используемой нами клавиатуре.
1 2 3 4 5 6 7 8 |
const byte ROW = 4; const byte COL = 4; char keyscode[ROW][COL] = { {'1', '2', '3', 'A'}, {'4', '5', '6', 'B'}, {'7', '8', '9', 'C'}, {'*', '0', '#', 'D'} }; |
Далее укажем к каким контактам платы Arduino подключены контакты строк и столбцов клавиатуры (клавишной панели). В нашем случае мы использовали контакты A5, A4, A3 и A2 для подключения к контактам R1, R2, R3, R4 клавиатуры, и контакты A1, A0, 12, 11 для подключения к контактам C1, C2, C3 и C4 клавиатуры соответственно.
1 2 3 |
byte rowPin[ROW] = {A5, A4, A3, A2}; byte colPin[COL] = {A1, A0, 12, 11}; Keypad customKeypad = Keypad( makeKeymap(keyscode), rowPin, colPin, ROW, COL); |
Внутри функции setup() для контакта 8 (к которому подключен светодиод) устанавливается режим работы на вывод данных и на него затем подается напряжение низкого уровня (светодиод выключен).
1 2 3 4 5 |
void setup() { pinMode(8,OUTPUT); digitalWrite(8,LOW); } |
Внутри функции loop с помощью функции customKeypad.getKey() происходит считывание значений, поступающих с клавиатуры и далее с помощью операторов if формируются условия, позволяющие сформировать уникальный набор световых импульсов для каждой нажатой клавиши. Для формирования уникальных импульсов мы использовали различные временные интервалы действия импульсов.
1 2 3 4 5 6 7 8 |
char customKey = customKeypad.getKey(); if (customKey) { if (customKey == '1') { digitalWrite(8,HIGH); delay(10); digitalWrite(8,LOW); } |
Объяснение программы для приемной части Li-Fi
На приемной стороне к плате Arduino подключены фоторезистор и ЖК дисплей. Фоторезистор соединен последовательно с обычным резистором, таким образом они образуют схему делителя напряжения. Аналоговое напряжение с выхода делителя напряжения подается на плату Arduino в качестве входного сигнала. В нашем проекте мы используем модуль интерфейса I2C для подключения ЖК дисплея чтобы уменьшить число контактов платы Arduino, используемых для подключения ЖК дисплея – в нашем случае мы используем только 2 контакта для передачи данных (SCL/SDA) и 2 контакта для подачи питания.
Первым делом в программе необходимо подключить используемые библиотеки: Wire.h для связи по интерфейсу I2C, LiquidCrystal_I2C.h – для управления ЖК дисплеем по интерфейсу I2C. Эти библиотеки по умолчанию присутствуют в Arduino IDE, поэтому скачивать и устанавливать их не нужно.
1 2 |
#include <Wire.h> #include <LiquidCrystal_I2C.h> |
Для управления ЖК дисплеем с помощью модуля I2C объявим объект класса LiquidCrystal_I2C. Для этого объекта необходимо указать адрес, число столбцов и строк дисплея, в нашем случае эти параметры будут равны 0x3f, 16 и 2 соответственно.
1 |
LiquidCrystal_I2C lcd(0x3f, 16, 2); |
Внутри функции setup() зададим режим работы для контакта, с которого будем считывать принимаемый сигнал. Также покажем на экране дисплея приветственное сообщение.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
void setup() { pinMode(8, INPUT); Serial.begin(9600); lcd.init(); lcd.backlight(); lcd.setCursor(0, 0); lcd.print(" WELCOME TO "); lcd.setCursor(0, 1); lcd.print(" CIRCUIT DIGEST "); delay(2000); lcd.clear(); } |
Внутри функции loop мы будем определять длительность импульса, поступающего от фоторезистора, с помощью функции pulseIn. Тип импульса в нашем случае будет LOW. Значение длительности импульса будет выводиться в окно монитора последовательной связи для целей отладки.
1 2 |
unsigned long duration = pulseIn(8, HIGH); Serial.println(duration); |
В нашем случае мы будем иметь 16 различных длительностей импульса (число клавиш на нашей клавиатуре). Сравнивая полученную длительность импульса с различными временными интервалами (возможными диапазонами длительности импульсов) мы сможем определить какой символ передавался. Фрагмент кода для приема клавиши 1 в этом случае будет выглядеть следующим образом:
1 2 3 4 5 |
if (duration > 10000 && duration < 17000) { lcd.setCursor(0, 0); lcd.print("Received: 1 "); } |
Тестирование работы проекта
После сборки аппаратной части проекта и загрузки кодов программы в обе платы Arduino вы можете приступить к тестированию работы проекта. Нажимайте произвольные клавиши на клавиатуре в передающей части проекта и вы увидите как нажатые символы (клавиши) будут высвечиваться на экране ЖК дисплея 16×2 в приемной части проекта. Более подробно эти процессы можно посмотреть в видео, приведенном в конце статьи.
Исходный код программы (скетча)
Код программы для передающей части
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
//Transmitter Side: #include <Keypad.h> const byte ROW = 4; const byte COL = 4; char keyscode[ROW][COL] = { {'1', '2', '3', 'A'}, {'4', '5', '6', 'B'}, {'7', '8', '9', 'C'}, {'*', '0', '#', 'D'} }; byte rowPin[ROW] = {A5, A4, A3, A2}; byte colPin[COL] = {A1, A0, 12, 11}; Keypad customKeypad = Keypad( makeKeymap(keyscode), rowPin, colPin, ROW, COL); char keycount = 0; char code[5]; void setup() { Serial.begin(9600); pinMode(8,OUTPUT); digitalWrite(8,LOW); } void loop() { char customKey = customKeypad.getKey(); if (customKey) { Serial.println(customKey); if (customKey == '1') { digitalWrite(8,HIGH); delay(10); digitalWrite(8,LOW); } else if (customKey == '2') { digitalWrite(8,HIGH); delay(20); digitalWrite(8,LOW); } else if (customKey == '3') { digitalWrite(8,HIGH); delay(30); digitalWrite(8,LOW); } else if (customKey == '4') { digitalWrite(8,HIGH); delay(40); digitalWrite(8,LOW); } else if (customKey == '5') { digitalWrite(8,HIGH); delay(50); digitalWrite(8,LOW); } else if (customKey == '6') { digitalWrite(8,HIGH); delay(60); digitalWrite(8,LOW); } else if (customKey == '7') { digitalWrite(8,HIGH); delay(70); digitalWrite(8,LOW); } else if (customKey == '8') { digitalWrite(8,HIGH); delay(80); digitalWrite(8,LOW); } else if (customKey == '9') { digitalWrite(8,HIGH); delay(90); digitalWrite(8,LOW); } else if (customKey == '*') { digitalWrite(8,HIGH); delay(100); digitalWrite(8,LOW); } else if (customKey == '0') { digitalWrite(8,HIGH); delay(110); digitalWrite(8,LOW); } else if (customKey == '#') { digitalWrite(8,HIGH); delay(120); digitalWrite(8,LOW); } else if (customKey == 'A') { digitalWrite(8,HIGH); delay(130); digitalWrite(8,LOW); } else if (customKey == 'B') { digitalWrite(8,HIGH); delay(140); digitalWrite(8,LOW); } else if (customKey == 'C') { digitalWrite(8,HIGH); delay(150); digitalWrite(8,LOW); } else if (customKey == 'D') { digitalWrite(8,HIGH); delay(160); digitalWrite(8,LOW); } else; } } |
Код программы для приемной части
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
//Receiver Side: #include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); #include <SoftwareSerial.h> #include <Keypad.h> void setup() { pinMode(8, INPUT); Serial.begin(9600); lcd.init(); lcd.backlight(); //lcd.backlight(); lcd.setCursor(0, 0); lcd.print(" WELCOME TO "); lcd.setCursor(0, 1); lcd.print(" CIRCUIT DIGEST "); delay(2000); lcd.clear(); } void loop() { unsigned long duration = pulseIn(8, HIGH); Serial.println(duration); if (duration > 10000 && duration < 17000) { lcd.setCursor(0, 0); lcd.print("Received: 1 "); } else if (duration > 20000 && duration < 27000) { lcd.setCursor(0, 0); lcd.print("Received: 2 "); } else if (duration > 30000 && duration < 37000) { lcd.setCursor(0, 0); lcd.print("Received: 3 "); } else if (duration > 40000 && duration < 47000) { lcd.setCursor(0, 0); lcd.print("Received: 4 "); } else if (duration > 50000 && duration < 57000) { lcd.setCursor(0, 0); lcd.print("Received: 5 "); } else if (duration > 60000 && duration < 67000) { lcd.setCursor(0, 0); lcd.print("Received: 6 "); } else if (duration > 70000 && duration < 77000) { lcd.setCursor(0, 0); lcd.print("Received: 7 "); } else if (duration > 80000 && duration < 87000) { lcd.setCursor(0, 0); lcd.print("Received: 8 "); } else if (duration > 90000 && duration < 97000) { lcd.setCursor(0, 0); lcd.print("Received: 9 "); } else if (duration > 100000 && duration < 107000) { lcd.setCursor(0, 0); lcd.print("Received: * "); } else if (duration > 110000 && duration < 117000) { lcd.setCursor(0, 0); lcd.print("Received: 0 "); } else if (duration > 120000 && duration < 127000) { lcd.setCursor(0, 0); lcd.print("Received: # "); } else if (duration > 130000 && duration < 137000) { lcd.setCursor(0, 0); lcd.print("Received: A "); } else if (duration > 140000 && duration < 147000) { lcd.setCursor(0, 0); lcd.print("Received: B "); } else if (duration > 150000 && duration < 157000) { lcd.setCursor(0, 0); lcd.print("Received: C "); } else if (duration > 160000 && duration < 167000) { lcd.setCursor(0, 0); lcd.print("Received: D "); } } |
2 ответа к “Передача текста с помощью Arduino и технологии Li-Fi”
Здравствуйте! Можно ли использовать лазерный модуль ky-008 или Лазерный диод (RCK353000), чтобы увеличить расстояние приема?
Добрый вечер. Да, конечно можно если плата Ардуино потянет по току управление ими со своего контакта — мы же не делаем здесь какой то хитрой модуляции, а просто включаем и выключаем светодиод. Если не потянет, то можно через MOSFET попробовать подключить, или через обычный транзистор если высокие скорости не нужны.