Вся суть состоит в том, что на экран выводятся квадраты, которые могут быть окрашены в белый, либо чёрный цвет, то есть иметь два состояния. Как биты. И их восемь штук. Как байт.
Чем отличается чёрный цвет от белого? Забавно, но не цветом, а яркостью, интенсивностью света. Интенсивность белого много больше интенсивности чёрного. В качестве регистратора интенсивности я использовал самое простое специально предназначенное для этого устройство — фоторезистор. Фоторезисторами называют полупроводниковые приборы, проводимость которых меняется под действием света. В моём случае проводимость затемнённого фоторезистора много меньше проводимости освещённого. Подключение фоторезистора к микроконтроллеру выбрал самое простое — между пином и землёй, включив встроенную подтяжку к питанию. Проверил напряжение, которое получает АЦП МК ATMega8: слева фоторезистор смотрит на белый фон, справа на чёрный. Напряжение в вольтах.
Да, да — Arduino IDE. Потому-что там я могу быстро набросать код и сразу залить его в плату нажатием одной кнопки, использовать обкатанные и растолкованные до безумия библиотеки.
Как видно, при считывании в цифровом режиме, мы получим 0 на белом и 1 на чёрном, что несколько идёт в разрез с моими шаблонами (чёрный ноль и белая единица), зададим чёрную единицу в программе на ПК.
Для вывода информации на монитор в необходимом нам представлении была написана простая программа на Си — Opto_Байт. Написал её по моей просьбе сосед по общежитию — kinetik161, за что ему большое спасибо и литр
Использовал микроконтроллер ATMega8, который в DIP28 корпусе имеет два полноценных (8 битных) порта — порт B и порт D. На порте B висит кварцевый резонатор, на D — UART. В итоге, я использовал безумную солянку портов, из которых потом составлял один байт. Подключение фоторезисторов от старшего разряда к младшему, слева направо: PC3, PC2, PC1, PC0, PB2, PB1, PB0, PD7.
Быстренько собрал всё на макетной плате и окончательно проверив работу с отправкой данных обратно по com-порту, я решил подключить знакосинтезирующий ЖК экран для вывода информации. Прилагаю код для Arduino IDE.
#include <Wire.h> // Подключаем библиотеки
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x20, 4, 5, 6, 0, 1, 2, 3, 7, NEGATIVE); // Настройка подключения дисплея(есть разные)
int led = 2; // Указываем пин светодиода
byte data = 0; // Полученный байт
byte dataold = 170; // Предыдущий байт
byte k=0; // Переменная для красивого форматирования байта на LCD
void setup() {
lcd.begin (16,2); // Инициализация экрана
lcd.setBacklight(1); // Включить подсветку
lcd.print("Hello, Geektimes"); // Приветствие
lcd.setCursor(2, 1); // Сдвиг курсора
lcd.print("from NikitosZs");
// Serial.begin(9600); // Инициализация UART
DDRC = DDRC & 0b11110000; // Задаём порты ввода/вывода
DDRB = DDRB & 0b11111000;
DDRD = DDRD & 0b01111111;
PORTC = PORTC | 0b00001111; // Включаем подтяжку фоторезисторов
PORTB = PORTB | 0b00000111;
PORTD = PORTD | 0b10000000;
pinMode(led, OUTPUT); // Индикатор приветствия
digitalWrite(led, 1);
delay(2000); // Держим приветствие на экране
lcd.clear(); // Очищаем экран
digitalWrite(led, 0); // Индикатор приветствия выключен
}
void loop() {
data = get(); // Присваиваем переменной data текущий байт
if(data!=dataold) // Перерисовываем информацию на экране, если байт изменился
{
// Serial.println(data); // Отправляем байт в терминал
lcd.setCursor(1, 0);
lcd.print("DEC:");
lcd.setCursor(6, 0);
lcd.print(" "); // Очищаем локальную область
lcd.setCursor(6, 0);
lcd.print(data);
lcd.setCursor(1, 1);
lcd.print("BIN:");
lcd.setCursor(6, 1);
lcd.print("00000000"); // Создаём правильную подложку
if(data>127) k=0; // Определяем старший бит для сдвига
else if(data>63) k=1;
else if(data>31) k=2;
else if(data>15) k=3;
else if(data>7) k=4;
else if(data>3) k=5;
else if(data>1) k=6;
else k=7;
lcd.setCursor(6+k, 1);
lcd.print(data, BIN);
dataold=data; // Присваеваем значение байта переменной хранящей предыдущее значение
}
}
byte get(){
byte raw=1, rawold=0; // Локальные переменные raw и rawold
while(raw != rawold) // Выполняется, пока не равны (для устойчивости значения)
{
rawold = raw; // Сохраняем старое значение
byte data1 = 0b10000000 & PIND; // Считываем солянку из пинов
byte data2 = 0b00000111 & PINB;
byte data3 = 0b00001111 & PINC;
raw = data3 << 4; // Сдвигаем, создаём целый байт
raw = raw + (data2 << 1);
raw = raw + (data1 >> 7);
}
return raw; // Возвращаем готовый байт
}
Выполним проверку правильной адресации фоторезисторов с битами, закрывая источник света пальцем. Должно получиться следующее:
И так-как всё получилось, то можно прислонять макетную плату с фоторезисторами к экрану компьютера. Длинноногие фоторезисторы, воткнутые в макетную плату, нехотя, но всё же согласились никуда не убегать на время съёмки видео, хотя позиционировать их было не очень просто.
Теперь немного занудства… По сути монитор это управляемый транспарант (матрица световых вентилей, возбуждаемых некоторыми внешними сигналами: электрическими, акустическими, оптическими, магнитными). Каждый квадратик — бит — занимает площадь 60*60 пикселей (50 — сторона квадрата и 10 — промежуток). Я имею монитор с разрешением 1920*1080 пикс, частота 60Гц. 1920/60=32 квадрата по ширине, 1080/60=18 квадратов по высоте, 32*18=576 бит на кадр. Не вдаваясь в тонкости, в секунду мы сможем рисовать 60 кадров, а это 576*60=34560 бит/с или 4320 Байта/с. Сократив размер квадратов до 30 пикселей по стороне, получим четырёхкратный прирост скорости (17280Б/с). К сожалению, если уменьшать дальше, то наши каналы будут засвечивать друг друга.
Конечно же я не собираюсь использовать этот оптоэлектронный канал связи, так-как есть куда более удобные, быстрые и менее затратные способы коммуникации, не занимающие рабочее место на мониторе. Однако, не стоит забывать, что самые обыденные вещи можно использовать совсем непривычным для нас способом.
Программа Opto_Байт на Я.Диске
Комментарии (13)
dcoder_mm
08.04.2015 13:20+5А еще в качестве приемника можно использовать не фотодиод, а светодиод. Или даже сегмент индикатора. И подключать к МК как обычно, без промежуточных усилителей и тд. Раз уж мы начали заниматься фигней, к делу надо подходить основательно :) www.youtube.com/watch?v=g2XmBdOXa-U
fundorin
08.04.2015 13:43Эта идея уже давно лежит в основе маски для осознанных сновидений Remee. Именно через два квадрата на экране компьютера или планшета передаются в маску настройки.
Alexeyslav
09.04.2015 08:17Надо было 9 каналов делать. 8 бит + синхронизация.
Да, кстати на яркости монитора меньше 50%(на разных мониторах по разному) могут начаться проблемы — подсветка начинает ШИМ-ироваться с частотой в 200Гц...XкГц(зависит от монитора) а фоторезисторы приборы быстродействующие…
Maccimo
09.04.2015 11:50Привет из далёкого 1992:
http://zhurnalko.net/=sam/junyj-tehnik/1992-04-05--num75
http://zhurnalko.net/=sam/junyj-tehnik/1992-04-05--num76
http://zhurnalko.net/=sam/junyj-tehnik/1992-04-05--num77
http://zhurnalko.net/=sam/junyj-tehnik/1992-04-05--num78
Ардуин тогда, правда, не было и сигнал с датчиков предлагалось подавать напрямую на оконечное устройство через согласующую схему.
kAIST
Эмм, а зачем 8 фотодиодов, если можно обойтись одним, а приложением просто моргать. Такой способ уже используется кстати в некоторых девайсах
NikitosZs Автор
8 фоторезисторов выбрал для простоты и наглядности (видно на анимации). Тут заморочек нет совсем — просто считываем порты. Никакой работы с временем, старт\стоп сигналами, синхронизацией.
roller
Не то, чтобы в устройствах, но прошивки так сливали и с фотоаппаратов, и (звуковым бибиканием) с приставок, и даже с телефонов кажется.