Идея: изготовить устройство, выводящее печатный текст и простую графику посредством светодиодной линейки, перемещаемой перед фотокамерой, выполняющей длительную экспозицию.
Для этого достаточно на короткое время включать те или иные светодиоды в соответствии с изображением букв и знаков, хранящихся в памяти контроллера. Воспроизведение строк запускается нажатием на одну из кнопок. Сами строки удобно хранить в ЭСППЗУ (EEPROM) контроллера, вводя их через последовательный интерфейс, без необходимости перепрограммирования контроллера целиком.
Для начала надо убедиться в работоспособности принципа (вернее в возможности его простой реализации, т.к. сам по себе он давно и успешно применяется в различных устройствах отображения информации). Для этого к контроллеру Arduino UNO (или любому его аналогу) подключаются десяток светодиодов и одна кнопка. Светодиоды LED1…LED10, через ограничивающие ток резисторы R1…R10, подключаются к портам Arduino D2…D11, а кнопка S1 — к D12.
Если собирать на макетной плате, получится примерно следующее:
Скетч для Arduino IDE — в архиве. В нем жестко прописан единственный воспроизводимый растр. Достаточно просто откомпилировать скетч и загрузить в контроллер. Более подробно код будет рассмотрен ниже.
Принцип вывода изображения следующий. Устройство с помощью линейки светодиодов последовательно воспроизводит отдельные столбцы растрового изображения символов. Этим реализуется «развертка по вертикали». Выглядит примерно так, как на анимации справа.
Перемещением камеры или самого устройства добавляем горизонтальную развертку. Если при этом снимать процесс фотоаппаратом с выдержкой в несколько секунд, то получится вполне читаемая строка.
А значит, идея рабочая и можно подумать над расширением возможностей устройства для создания надписей в технике «фризлайта» (freezelight).
Напрашивается увеличение количества светодиодов и кнопок, чтобы можно было выводить более «гладкие» символы, но при этом нежелательно вводить дополнительные электронные компоненты для коммутации или усиления, чтобы оставить возможность изучения работы устройства с помощью наборов на основе Arduino UNO (типа «Матрешек» Амперки, Sparkfun «Inventor’s Kit» и т.п.).
Не сильно выходя за пределы максимального выходного тока МК ATMega328 (200 мА), можно увеличить количество светодиодов до 16 и останутся еще выводы для 2-х кнопок. Количество кнопок можно сделать даже больше, если использовать идею коммутируемых делителей напряжения на входе АЦП, но пока ограничимся обычным цифровым вводом. Линии D0 и D1 тоже трогать не будем, т. к. они в рассматриваемых контроллерах намертво связаны с UARTом и, далее USB-портом, через который хочется загружать пользовательские строки.
Если же еще подумать над большей «портативностью», можно взять Arduino Nano или его аналог. Там используется тот же контроллер, но сама плата в несколько раз меньше, и имеет два дополнительных входа АЦП, на которые можно повесить еще две кнопки.
Итак, для «расширенной» версии понадобятся:
1. Контроллер Arduino Nano (UNO, Duemilanove и им подобные и совместимые).
2. 16 светодиодов.
3. 16 резисторов 220 Ом.
4. 4 (Nano) или 2 (для UNO/Duemilanove) тактовых кнопки.
5. 2 резистора 22 кОм (только для Nano при использовании четырех кнопок).
6. Макетная плата, проводники.
7. Источник питания 5 В или 7 — 15 В, 300 мА.
А также программные средства:
1. Среда Arduno IDE
2. Драйвер моста USB-serial (зависит от установленного на контроллере
моста, можно выяснить по маркировке чипа моста)
3. Терминальный клиент Putty или аналог (не обязателен, но рекомендуется)
Электрические соединения достаточно интуитивны:
— аноды светодиодов LED1…LED16 через резисторы R1…R16 подключаются к портам Ардуино D2…D13 и A0…A3 (светодиоды организуются в линейку, где «верхнему» соответствует порт D2, а «нижнему» — А3), катоды светодиодов соединяются с общим проводом схемы (GND).
— кнопки S1, S2 подключаются к портам A4, A5 (в случае Nano, также и S3* и S4* — к A6, A7) так, чтобы при нажатии кнопок порты замыкались на общий провод.
— (только для Nano) т.к. линии A6 и A7 не имеют встроенных резисторов подтяжки, они через резисторы R17* и R18* подтягиваются к линии питания 3,3 В.
— питание схемы осуществляется либо по USB-кабелю, либо от 9В батареи (GB1) или иного источника постоянного тока напряжением 7 — 12 В через линию Vin.
При конструировании, если схема собирается не на макетной плате с целью изучения, нужно обеспечить, чтобы светодиоды стояли в линейку с минимальным зазором, а кнопки было удобно нажимать, когда светодиоды повернуты к камере. Далеко не образец, а просто пример — ниже.
«Лишние» светодиоды, находящиеся на плате контроллера (индикатор питания и встроенный светодиод на D13) не должны попадать в поле зрения камеры. Если они на той же стороне, что и линейка, как в примере выше, их надо заклеить, отключить, обрезав нужную дорожку, а лучше всего — заключить устройство в корпус подходящей формы. Корпус должен быть черным и желательно матовым, это положительно скажется на качестве картинок.
Скетч для 16-ти светодиодов — здесь. Компилируется и загружается в контроллер с помощью Arduino IDE. Шрифт и таблица соответствия кодов и фигур символов хранится в отдельном файле font16.cpp. Это позволят менять файлы шрифта или кодировку символов, не боясь испортить программу.
Основные структуры и процедуры описаны в комментариях к коду. В знакогенераторе пока заполнены символы ASCII с кодами от 32, русский алфавит в кодировке CP1251 (изменением массива lktab можно реализовать любую) и несколько пробных символов-пиктограмм, размещенных на «непопулярных» кодах. Полный список того, что есть можно увидеть, изучив массивы stripe и lktab.
После включения или получения сигнала RESET (это происходит по нажатию на соответствующую кнопочку на контроллере, а также каждый раз при открытии и закрытии последовательного порта, связанного с USB), по линейке пробегает тестовая последовательность, зажигающая и гасящая все светодиоды, чтобы можно было убедиться в их работоспособности и правильности подключений.
Далее происходит чтение четырех сохраненных в энергонезависимой памяти строк, которые связываются с соответствующими кнопками. Длина каждой строки ограничена 60 символами для упрощения управления памятью.
При первом запуске строки оказываются или абракадаброй (если EEPROM ранее использовался в других проектах) или скучной полосой из букв «я» (код 0xFF). Следует задать собственные строки. Для этого:
- открыть «Монитор порта» в среде Arduino IDE;
- при этом контроллер получит сигнал сброса и через пару секунд по линейке побежит тестовая «змейка»;
- в это время нужно зажать первую кнопку устройства (требуется сделать низкий уровень на A4), контроллер перейдет в режим настройки;
- в «Мониторе порта» появится текст приглашающий ввести номер строки для изменения и ее новое содержимое, а также выведутся уже сохраненные строки;
- сообщение «Stored!» означает, что строка записана в EEPROM.
Теперь, отключив «палочку» от компьютера можно вызывать заданные строки нажатием на кнопки.
Когда устройство уже отлажено, работать с монитором порта Arduino IDE не очень удобно (особенно если его нет под рукой 😉 ). В качестве альтернативы для загрузки строк можно пользоваться популярным терминальным клиентом putty:
- подключить устройство к USB-порту компьютера, убедиться, что установлен драйвер моста USB-Serial и выяснить номер COM-порта, связанного с этим мостом;
- запустить putty, выбрать режим Serial, задать номер COM-порта, скорость 9600 bps (рис. 1); в настройке Terminal параметру Local echo задать Force on (рис. 2) (это делается, поскольку пока «терминальная часть» конфигуратора очень примитивна и даже, о, ужас, не реагирует на backspace 🙂 поэтому строки надо сразу вводить без исправлений); в настройке Translation выбрать кодировку Win1251 (рис. 3)(если нужно печатать кириллицей); чтобы не делать эти настройки каждый раз, полезно сохранить профиль подключения (рис. 4), который потом вызывать двойным щелчком;
- нажать Open, произойдет открытие порта и побежит тестовая змейка;
- дальнейшая процедура настройки аналогична описанной выше.
В конфигураторе нет никакого анализа вводимых строк, поэтому никаких тегов он не распознает. Для задания символов, которых нет на клавиатуре (и с которыми можно связать какие-нибудь собственные пиктограммы или спецэффекты), предлагается пользоваться комбинациями клавиш «левый Alt»+0ddd, где ddd — десятичный код символа, набранный на цифровой клавиатуре справа. Например, символ градуса «°» можно вызвать, зажав левый Alt и набрав 0176.
Создание собственных символов
В файле font16.cpp в массиве stripe содержатся битовые образы символов знакогенератора. Вот, например, заглавная «Q»:
... 0x0FC0, // 0172 - 0000111111000000 - Q 0x1020, // 0173 - 0001000000100000 0x2010, // 0174 - 0010000000010000 0x4008, // 0175 - 0100000000001000 0x4008, // 0176 - 0100000000001000 0x4028, // 0177 - 0100000000101000 0x4028, // 0178 - 0100000000101000 0x2010, // 0179 - 0010000000010000 0x1028, // 0180 - 0001000000101000 0x0FE8, // 0181 - 0000111111101000 0x0000, // 0182 - 0000000000000000 0x0000, // 0183 - 0000000000000000 - /Q ...
Первый элемент — шестнадцатеричное число, биты которого, «выталкиваемые» на нужные ноги контроллера, и определяют, как должен выглядеть отображаемый в данный момент столбец. Далее следует комментарий (то, что пропускается компилятором) с индексом элемента массива (это нам нужно, чтобы определить, где начинается и заканчивается символ) и двоичным представлением того, как должны светиться точки, чтобы получить нужную фигуру. Удобно использовать эту часть комментария как «графический редактор», не забыв отразить эти двоичные значения в числе в начале строки.
Далее в массиве lktab есть такой элемент:
... {172,183}, //81 - Q ...
Это как раз соответствие коду 81 символа буквы «Q», начальный столбец которой в нашем знакогенераторе имеет номер 172, а конечный — 183.
Массив lktab немного усложняет программу, но зато обеспечивает гибкость — разные буквы могут быть разной ширины (можно хоть полотна писать), быть расположены в любом порядке в знакогенераторе, а также один и тот же символ может отзываться на разные коды («русская» и «английская» «A«, например, хотя многие такое не одобряют). Однако здесь (из лени) похожие буквы также нарисованы только единожды. Массивы stripe и lktab хранятся в ПЗУ, так как разместить их в ОЗУ контроллера невозможно.
И теперь, если нужно «изобрести» какой-либо символ, потребуется:
- дополнить массив stripe числами, кодирующими столбцы этого символа;
- выбрать в массиве lktab позицию для кода этого символа и задать элементам на этой позиции значения начального и конечного столбцов;
- включить этот символ в отображаемую строку набрав его непосредственно или как «Alt-код».
Готово!
И еще одно видео, снятое при 270 к/с:
Вопросы, замечания, пожелания: sigma72@ya.ru