Товары из Китая

Автоматизация управления экраном домашнего проектора


Автоматизация управления экраном домашнего проектора

Очередная статья на муське про малую автоматизацию силами Arduino, теперь мой черед рассказать о своем опыте. Будем дружить проектор, экран и ресивер.

Disclaimer aka отмазка

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

Суть проблемы

Имеются проектор, моторизированный экран и ресивер. Даже при учете того, что источник изображения всегда включен, процесс начала просмотра все равно включает в себя много операций:

  • включить ресивер
  • включить проектор. Когда-то давно у меня была плазма, она по HDMI-CEC умела включаться сама. Текущий проектор не умеет
  • опустить (развернуть) экран

При завершении просмотра, соответственно, необходимо проделать операции в обратном порядке. В том числе и свернуть экран (не только производители экранов, но и любые другие специалисты настоятельно советуют это делать, чтобы ткань не растягивалась. Кто я такой, чтобы с ними спорить?) 🙂

В общем, процесс заметно раздражал даже меня, а жена вообще рычала. К экрану я еще вернусь чуть позже, сейчас же отмечу, что в документации ничего особого о способах управления сказано не было, однако на самом устройстве были многообещающие разъемы Trigger, RS-232 и IR. А раз так — то надо искать способ автоматизации всего этого. И вообще, лень, как известно, двигатель прогресса.

Концепция

(о том, чем я руководствовался при выборе решения, расписал под спойлером, т.к. не всем может быть интересно)
Погуглил, как обычно автоматизируют экраны. К сожалению, львиная доля топиков — про то, как добавить мотор к уже имеющемуся экрану. Но я-то благоразумно купил моторизированный! Нашлись советы и для таких счастливчиков, как я. Так, в ряде мест упоминалось, что на экранах обычно есть разъем Trigger (а у меня такой есть, ура!), такой же разъем бывает на проекторах. Принцип работы элементарный — с Trigger Out (такой должен быть у проектора) подается 12В, устройство с Trigger In (экран проектора) на это реагирует разворачиванием. При выключении проектора вместо +12 Вольт становится 0 и экран сворачивается обратно.

Итого всех расходов — кинуть провод от проектора до экрана, вот только оказалось, что разъема Trigger в моей модели проектора нет…

Зато такой разъем (даже два!) был в моем ресивере. Но только тут была еще одна проблема. Trigger на экране действует правильно, я проверил. Однако экран разматывается до конца, что мне не подходит, это слишком низко для моих стандартных потолков в 2.70. Нужен был способ останавливать экран при разворачивании на требуемую длину. Так что разъем Trigger пока отметаем…

Помимо мультимедийных разъемов имелся только RS-232. В инструкции к проектору нашлась довольно полная информация об управлении по COM. Отлично, значит, с проектором можно справиться, надо разбираться с разъемами на экране.

Экран у меня CACTUS SilverMotoExpert CS-PSSME-220X138-DG. Инструкция по эксплуатации вообще не рассказывает о назначении разъемов. Но я отдаленно припомнил, что когда-то, когда выбирал экран, смотрел модель какого-то другого производителя, где было рассказано про разъемы, а они были визуально похожи. Значит, подумал я, скорее всего это просто китайский OEM, который продается под разными брендами. Те подходят с разной степенью ответственности к переводу документации, но мне подойдет инструкция и от другого экрана, лишь бы она ответила на все мои вопросы.

Нашел визуально похожий экран от другого бренда, Digis, его инструкция куда как более полная. В частности, указана как распиновка, так и команды для взаимодействия.

Дальнейшие поиски показали, что у всех других экранов, которые я смог найти (не только в РФ, но и на Амазоне и прочих) с такими же разъемами, команды для управления индентичные, хотя вот распиновка иногда отличалась. Все это говорило в пользу того, что реальный разработчик электроники один, но, возможно, есть разные ревизии управляющей платы.

Кроме того, в инструкции к одному из экранов нашлась вот такая интересная штука.

Автоматизация управления экраном домашнего проектора

Стоит примерно 10000 — 12000 рублей, позволяет управлять экраном с любого проектора. Универсальность обеспечивается подходом — данное устройство с самим проектором никак не взаимодействует. По сути это розетка-мощемер, которая, при обнаружении нагрузки («проектор включился»), по радиоканалу пересылает команду дочерней плате, которая втыкается в разъем IR экрана.

Платить 10К было как-то неспортивно, плюс у производителя заявлена совместимость устройства только с экранами их производства. Визуально-то все похоже на мой, но кто знает, что там по этому IR будет отдаваться… Значит, будем изобретать велосипед.

Итак, мой велосипед мне виделся некой платой-контроллером, которая будет опрашивать статус проектора по RS-232 и, в зависимости от его состояния, сворачивать или разворачивать экран (опять же по RS-232). На обратную связь (вручную свернул экран — выключился проектор) рассчитывать не приходилось, так как экран команды умеет только принимать:

Автоматизация управления экраном домашнего проектора

Цена контроллера (в разумных рамках) не столь интересовала, но имеющуюся у меня апельсинку сразу отмел, т.к. она просит БП 10 Вт. Вспомнил об ардуинах. Одна ардуинка (нано) у меня даже валялась (осталась от проекта с AmbiLight), но ее тоже пришлось отмести, т.к. мне нужно было два порта RS-232. Гугление подсказало, что из одного COM-порта на ардуино можно сделать пару через библиотеку Software Serial, но мне не захотелось связываться со сложностями, которые сулило это программное разделение, плюс были подозрения, что получить два порта с разной скоростью передачи (9600 и 2400) не выйдет. Так что весь мой выбор свелся к Arduino Mega Pro, хотя остальные возможности платы мне, вроде как, не были нужны.

Я же обещал рассказывать о граблях? И вот первые из них. На самом деле (это уже после того, как я получил реальный опыт работы с Serial) работа с библиотекой Software Serial практически ничем не отличается от работы с аппаратным портом, разница буквально в пару строк (подключить библиотеку и инициализировать софтовый порт). Ну и так вышло, что вторую проблему (разная скорость интерфейсов) я тоже обошел, о чем расскажу чуть позже. Выходит, для моей задачи Mega Pro была не нужна, можно было обойтись любой ардуинкой. Тем не менее, купил-то я Mega Pro, поэтому и дальнейший рассказ будет о ней.

Ну и еще хочу заметить, что в Mega Pro три Serial-порта. Два для подключения устройств и один для отладки (вывода сообщений на компьютер по USB). Имея опыт работы с COM-портами на ПК, в том числе и с моим проектором (об этом чуть ниже), я был уверен, что задача «тут считал, сюда отправил» достаточно примитивная и три последовательных порта мне не нужны. К счастью, с двумя аппаратными портами ардуинок не нашлось, но теперь я могу сказать, что без дебага получить рабочее решение мало реалистично. Этих грабель я избежал, но лишь по случайности.

Итак, что я закупил для проекта? Внимание: далеко не все из этого нужно, поэтому, если вы хотите воспроизвести мой проект, не стоит всё бездумно покупать, читайте и описания тоже!!! Ссылки давал на те вещи, что покупал лично я, но, как всегда, перед заказом рекомендую проверить цены — возможно, вы найдете более выгодные предложения.

  1. 1. Собственно, Arduino Mega Pro Mini. Как я и писал выше, функциональность этой платы в итоге оказалась излишней и подошел бы более дешевый вариант. Сейчас вообще есть много действительно копеечных контроллеров типа STM*, если в каком-то из них есть последовательный порт, то пошли бы и они. Мне отдельные чипы не подходили. Во-первых, к ним всегда нужна простейшая обвязка, а у меня дома нет резисторов-емкостей-конденсаторов, т.е. надо еще и их покупать, а штучно они выходят довольно дорогими). Во-вторых, все это надо куда-то паять, т.е. нужно проектировать свои платы, плюс иметь шанс все это перегреть при пайке (повторюсь, я не электронщик). В общем, мой выбор — готовые платы производителей, которые будут работать из коробки и исключат кривые руки при сборке. Отличие Mini от обычной версии исключительно в форм-факторе пинов
  2. 2. Две платы RS-232 To TTL converter. Докупались позже (объясню, почему), пригодилась в итоге только одна.
  3. 3. Voltage Sensor. Вообще о таком не думал, но когда искал ардуинку, в рекомендациях алиэкспресса такой модуль всплыл. А что, подумал я, ведь разъем Trigger есть у меня в ресивере! Возьму на всякий случай, вдруг пригодится? И таки пригодился. Думаю, что надо еще раз заметить: вот уж конкретно этот модуль (хотя и все остальные, используемые мной в этом проекте, тоже) совсем примитивный и собрать такое на коленке несложно. Но и обошелся он мне в 20 рублей, а соображения про отсутствие компонентов и сомнения в прямизне рук я описал в пункте 1.
  4. 4. 16-тиканальный мультиплексер CD74HC4067. И вновь напомню свои размышления о рассыпухе. Так-то тут стандартный чип и пара дополнительных элементов всего. Но разводить все это «на коленке» я б замучался. Важно отметить, что хватило бы мультиплексера на 4 канала (но таких в виде платы вроде как не бывает) и, тем более, на 8 каналов. Платы на 8 каналов бывают (74HC4051), но я обходился тем, что в наличии в локальных магазинах, т.к. необходимость мультиплексера всплыла на последних этапах. Так-то рекомендую покупать именно на 8 каналов, они более компактные. Например, вот .
  5. 5. Два гнезда RJ-9 (4P4C). Как-то особо не задумывался, почему выбрал именно такой тип разъема. По работе часто сталкиваюсь с COM в стандарте RJ-11/RJ-45, на экране, опять же, оно (правда, RJ-11 6P6C). Плюс сам разъем механически довольно надежный (джек защелкивается в разъеме, не выдернуть случайно, если ковыряться в ТВ-стойке). В общем, на тот момент мне казалось это логичным. Минус всплыл позже — гнезда довольно высокие, поэтому бутерброд из ардуино и платы с разъемами не влез в корпус. Если бы я собирал второе такое устройство, я бы уже использовал разъемы 3.5 мм 4-pin, они гораздо более компактные.
  6. 6. Собственно, корпус. Корпус я подбирал под габариты ардуинки и она туда так идеально подходила… Более того, все остальное тоже отлично разместилось под размер этого корпуса… В общем, не мог не упомянуть корпус, он мне понравился своим удобством. Опять же, можно говорить «да за что такие деньги?!», но для цен чип-и-дипа корпус довольно бюджетный. На али похожих по габаритам и конструктиву найти не смог (не утверждаю, что их не бывает). Тем не менее, я воспользоваться корпусом не смог из-за пункта 5. Не совершайте моих ошибок — или другие разъемы, или другой корпус (своим решением я поделюсь).
  7. 7. Разъем 3.5 мм. Данный конкретный выбирал из-за его ширины (тогда я еще не знал, что корпус мне не подойдет, так что имел ограничения по ширине). Почему 3.5 мм тогда, а не более компактный 2.5 мм? Потому что Trigger в ресивере (а разъем будет использоваться для него) именно 3.5 мм, так что я могу использовать самый обычный AUX-кабель, которых у меня дома много. На тот момент я просто решил, что подключу Trigger к вольтметру, а далее использовать пока не буду. В настоящий момент Trigger с ресивера я вовсю использую, но об этом расскажу в части про код.
  8. 8. Монтажная плата (текстолит с отверстиями стандартного шага 2.54 мм). Ссылку не приведу, т.к. такая у меня давно валялась дома. Плюс моя плата, когда настал ее звездный час, подвела. Металлизация при пайке начала отваливаться. Вроде бы и паяльником водил не усердно, и температура была не как в жерле вулкана, однако вот. В половине случаев пришлось припаиваться непосредственно к ножкам. На возраст списать не могу (данной конкретной плате было лет 10, но был опыт пайки техники еще родом из СССР, и там ничего никуда не отваливалось).
  9. 9. Набор разноцветных проводов. Провода как провода, но цветов в наборе могло бы быть и больше. Повезло, что у меня дома еще других цветов были (от всяких древних компьютерных корпусов).
  10. 10.Макетная плата. Опционально, но упрощает жизнь. Я сначала пошел по хардкору и перепаивал проводки, но мне это довольно быстро надоело (болью поделюсь), так что приобрел для себя. Если не лень паять по сто раз — можно сэкономить.
  11. 11. Кабель 3.5 мм — 3.5 мм, для подключения к ресиверу. У меня такие валялись, так что не покупал.
  12. 12. Телефонные кабели необходимой длины (от устройства до проектора и до экрана). Был соблазн использовать витую пару (просто потому, что имеется), но она слишком толстая, плюс стандартного мышиного цвета. Для экрана (он белый и на белой стене) взял белый, для проектора — черный. Брал сразу готовые (обжатые и в заводской упаковке) на ближайшем строительном рынке. Смотрите только, чтобы там было 4 провода. Разумеется, если где-то найдете по погонным метрам, то это будет выгоднее. Мне вот к проектору надо было 8 метров. 7.5 не хватало, а 10 перебор, пришлось укорачивать.
  13. 13. Джеки RJ-9 4p4c для подключения к контроллеру. Если последуете моему совету и замените на 4-pin 3.5 мм, то, соответственно, и коннекторы нужны того же стандарта.
  14. 14. Джек RJ-11 6p6с для подключения к экрану. Я тут было обрадовался сначала, когда купил телефонный кабель, потом радость стихла — там с двух концов были коннекторы RJ-11 6p4c (фишка на 6 контактов, но обжато всего лишь 4). Мне одного купленного джека не хватило, т.к. проводов в кабеле всего 4, а распиновку я в итоге использовал другую (расскажу ниже). Но покупал я всего один, так что при отладке пришлось нарукопопить из RJ-45, с помощью дремеля. Потом, на постоянку, переобжал на нормальный 6p6с. В общем, это я к тому, что не скупитесь, возьмите коннекторов чуть больше
  15. 15. Коннектор mini-DIN 3-pin. В таком разъеме присутствует RS-232 в моем проекторе. Соответственно, у вас может быть что-то другое, тогда подбирать то, что требуется. По разъему по ссылке замечу, что, с одной стороны, розничная цена на него в чип-и-дипе соответствует цене (с доставкой) с алиэкспресса. С другой — пластик данного коннектора ведет при малейшем нагреве контактов, а сами контакты с обычной сосновой канифолью лудятся очень неохотно. Так что мне пришлось потом купить еще один такой же коннектор, который я паял уже при помощи кислоты. И даже так штырьки немного повело, но все удалось выгнуть обратно
  16. 16. Гребенка 2.54 мм — использовалась для крепежа модулей на монтажную плату

Предположу, что все необходимое для пайки, ножницы и надфили (для подгонки монтажной платы), MicroUSB-кабель для отладки и блок питания от старого телефона у вас уже имеются.

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

Проектор

Проектор — это первое, над чем я начал работы. Еще до покупки ардуинки я провел тестирование (proof of concept, если хотите). С ноутбука, с помощью нормального USB-to-COM убедился, что могу проектор включать и выключать. «Нормальный» в моем понимании тот, который брендовый и работает автоматически (винда автоматом ставит драйверы Prolific, т.е. это не китайский клон, прикидывающийся PL2303)

В документации к проектору все команды представлены в виде двух типов: как ASCII (символьная) и HEX (шестнадцатеричная) последовательности.

Автоматизация управления экраном домашнего проектора

С ASCII на компьютере я не добился взаимности, начал пробовать HEX. На удивление, PuTTY так не умеет (по крайней мере, я не нашел, а на разных форумах утверждается, что нельзя), надо искать другие решения. Вот тут уже был первый звоночек, что бороться с проектором мне придется долго…

Люди с форумов рекомендовали для отправки Hex программу Teraterm. Таких отзывов встречалось большое число, так что, видимо, как-то оно работать должно, но я добиться взаимности не смог. Вторым попробовал близкий мне Powershell, но нужного не получил. Простые технологии самые надежные — смог подружиться с проектором через обычный cmd.exe

Кому интересно, то вот информация о том, как через встроенную утилиту certutil превратить команды в HEX и отправить их в COM. В таком виде оно работало, если вбивать данные в консоль, но часто сбоило, если пытаться управлять проектором с помощью CMD-файлов, содержащих тот же самый текст. Тем не менее, было очевидно, что это какие-то проблемы именно cmd.exe (я как-то не так делаю батники), так что проекту был дан старт и я заказал на алиэкспрессе ардуинку с вольтметром, а пока они идут — покупаю разъемы, кабели и корпус.

Пришла ардуинка, я подключаю ее к проектору и пишу простейший скетч, который должен переслать последовательность для включения проектора (такую же, как я уже умею выполнять с ПК) и… И не работает!

Множественные танцы с бубном, попытки отправки последовательности в HEX (тут есть как минимум два варианта, или массив значений, или построчно передаем каждую из hex-пар символов) вместо ASCII, перепроверка распиновки по сто раз… Ничего не помогает, проектор игнорирует меня.

Напоминаю, что я собирался делиться граблями, и вот крупнейшие из них.

Гугление навело меня на статью, где человек испытывал те же проблемы, и ему посоветовали схему подключения к Arduino через адаптер RS-232 to TTL.

Собственно, я и раньше знал, что COM — COMу рознь. Что, во-первых, на стандартном разъеме DB-9 могут быть разведены не только стандартные Rx/Tx, но и ряд дополнительных (а могут и не быть разведены), а, во-вторых, уровень сигнала может быть как 5В, так и 12В, но сами сигналы при этом одинаковые, что создает нехилую путаницу. Так что термины COM / UART / TTL / RS-232 в быту часто считаются синонимами, но фактически разница может быть.

Однако одно дело знать, другое дело сообразить. Я с такой проблемой ранее никогда не сталкивался, но совет на форуме звучал разумно, поэтому я купил сразу два конвертера (у меня же еще экран есть!).

Итак, адаптеры получены, подключаю один к ардуино и… Опять не работает! Более того, сам адаптер нехило греется. Палец держать можно, но с трудом, и это на открытом воздухе. А что же будет в тесном корпусе?

Гуглю. Нахожу, что это особенность китайских микросхем MAX3232, они, мол, действительно склонны к перегреву, в отличие от оригинальных. На том же форуме (ссылку я не сохранил) указывается, что родные чипы могут работать на напряжении и 3V, но владельцам китайских клонов остается только страдать.

Без особой надежды подключаю питание 3В вместо 5В, но устройство при этом делает вид, что работает (мигает светодиодами RX/TX), и не греется. В общем, чудеса. На всех схемах плату подключают к 5В, но подключать надо к 3В. К счастью, микросхема не сгорела.

Собственно, по тому, как я пишу, понятно, что помогло переключение на 3В, но тогда я этого еще не знал, ведь переключение не решило всех проблем. Количество проблем при подключении к проектору просто зашкаливало. Перечислю их:

  • не то напряжение питания модуля
  • были и проблемы с Rx из-за плохих контактов на отладочной плате
  • когда предыдущие шаги были устранены, все равно проектор не реагировал на посылаемые команды, а в ответ выдавал какой-то мусор. Тут роль сыграл вот этот тред. Были приведены куски кода, которые у человека отрабатывали не всегда корректно. В моем случае этот код не работал вообще. Вероятно, я бы застрял на этом шаге, если бы не додумался заменить команду на ту, которая проектор включает. Команда успешно отработала. Отработал и ряд других команд, что я пробовал.

    Т.е. из примерно пары десятков команд, что я попробовал, только одна (та, что использовал автор топика) не работала у меня. Да, я везунчик 100 lvl. Долбился в стену, хотя рядом была открыта дверь

Итого, после многочисленных экспериментов и гуглежа я смог с ардуины включать и выключать проектор, а также отслеживать его состояние. Заняло это где-то 4 вечера, что я считаю просто дикой тратой времени (реализация включения-выключения под cmd.exe заняла не более 10 минут).

И да, одна из функций с листинга по ссылке выше (recvWithEndMarker) осталась в моем коде, за что автору топика спасибо.

А еще в этом разделе я считаю важным отметить, что мой проектор меняет статус далеко не сразу. Только когда проектор выходит в рабочий режим (т.е. отображает уже не лого производителя, а картинку с видеовхода), он отдает статус «включено». С выключением аналогично. Забегая вперед: это означает, что лаг между включением/выключением проектора и управлением экраном составляет секунд 20-30. В реальной жизни никак не раздражает, но было бы приятнее, если бы экран приходил в движение параллельно с проектором

Экран

Проектором мне удалось поуправлять с компьютера, поэтому все те разы, когда у меня не получалось сделать этого с ардуино, я просто знал, что я делаю что-то не так. С экраном же ситуация другая, я не смог управлять им и с ПК.

С ардуино, несмотря на конвертеры RS 232 в TTL, я тоже потерпел фиаско. Пробовал разные распиновки, но все бесполезно. Предположу, что дело не в интерфейсе, а в командах. Т.е. HEX-последовательности для управления моему экрану нужны другие (напомню, в инструкции об этом вообще ни слова). Логически контакты все же куда-то скоммутированы. Более того, на них видно 5В (смотрел мультиметром, не осциллографом), т.е., вроде бы, похоже на TTL

Если проблему не удается решить, ее надо обойти, подумал я и воткнул в разъем коннектор 6p6c, обжатый под витую пару (чтобы задействовать все контакты, ведь в моем телефонном кабеле их было всего 4).

Тем самым я убедился, что документация от модели-близнеца не врет: 4 оставшихся контакта тоже используются для управления движением экрана, достаточно просто их замыкать. Один общий контакт и три контакта управляющих: вверх / вниз / стоп.

Отлично, новый квест: как замыкать контакты с ардуины. Первое, что приходит в голову — реле. Все бы хорошо, но:

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

В качестве альтернатив реле нашел варианты управления через N-транзистор, но так и не понял, как мне это применить в моем случае. На сколько я смог разобраться, управлялся сигнал, который брался с выхода самой Arduino. Мне же надо было закорачивать сигнал с экрана. Соединять общий провод с экрана и минус на ардуино мне тоже показалось плохой идеей (контроллер и экран разнесены, плюс разные розетки — все это попахивало возможным выгоранием арудинки)

И тут я наткнулся на совет использовать мультиплексер. Суть его в том, что по цифровым сигналам с ардуино (в моем случае каналов 16, поэтому пинов задействуется 4) микросхемой мультиплексера происходит коммутация одного из 16 каналов на определенный канал (логически это может быть как вход, так и выход, микросхеме не столь важно). Можно сказать, что это некий аналог галетного переключателя

Повторюсь, 16 каналов мне не требовалось, хватило бы и 4, но брал то, что было в наличии.

С мультиплексером тоже все взлетело не сразу, так как умудрился слегка запутаться в распиновке, но, в итоге, все заработало как надо. Соответственно, вторая плата RS232 to TTL осталась без нужды

Ресивер

С ним все было просто — в настройках самого ресивера задействовал триггер, повесив его на изменение статуса питания (вкл-выкл) самого ресивера

Ну и плата вольтметра подключилась, на удивление, без проблем.

Повторюсь, сначала вообще не планировал использовать ресивер (размышлял следующим образом: «а вдруг я просто радио захочу послушать? А тут сразу и проектор, и экран»), однако в текущей версии триггер я проверяю. Сработала банальная логика «так ли часто тебе надо послушать радио по сравнению с частотой просмотра фильмов»

Скетч

Логика кода довольно простая. Ардуино отслеживает состояние триггера с ресивера. Если на триггере 12 вольт, то значит, что ресивер включен (и наоборот)

По состоянию триггера ардуино делает и статус проектора — посылает ему сигналы вкл или выкл. Состояние проектора мы запоминаем, поэтому сигналы посылаются только в том случае, если статус проектора и ресивера различаются (одно включено, другое нет)

Экран на триггер никак не завязан, исключительно на проектор. Логика работы такая:

-если статус непонятен — то просто его игнорируем. При том же включении / выключении проектора в статусе пробегает много странного, ничего собственно о состоянии проектора не сообщающего. Кроме того, даже верный статус иногда бьется при передаче. Вместо OK0 может доехать K0 или OK. Уже на следующей итерации все будет ОК, поэтому и принял решение отбрасывать неизвестное

-если на предыдущем шаге статус был один, а сейчас другой — проектор сменил свое состояние (из выкл во вкл или наоборот). Соответствующим образом разворачиваем или сворачиваем экран

-при разворачивании экрана отправляем две команды. Сначала — на разворачивание. Потом, через заданный интервал, на остановку. Сделано это для того, чтобы экран разворачивался не полностью. Родная инструкция вообще не предоставляет никаких альтернатив. Инструкция от экрана Digis (приводил выше) говорит, что есть некий подстроечный винт, регулирующий длину развёртывания. Однако в своем проекторе я такой винт не нашел. Поэтому с секундомером выяснил интервал между командами «вниз» и «стоп», что и реализовал в коде. Для сворачивания экрана достаточно отправить одну команду, далее экран по концевикам отключится сам

Итого при включении всё срабатывает так:

1. Включается ресивер (теперь управлять можно только им)

2. Контроллер считывает +12 Вольт на триггере и отсылает команду для включения проектора

3. После окончания загрузки проектора (примерно 20 секунд) начинает разворачиваться экран, что занимает еще 19.5 секунд (в моем случае)

При выключении все аналогично.

Экран не завязан на триггер ресивера принципиально — эту часть можно закомментировать (собственно, какое-то время я так и пользовался), тогда экран по-прежнему будет слушаться только проектора (тут ни строчки менять не надо), а вот проектор перестанет реагировать на ресивер; можно включать последний для прослушивания радио и прочего, не требующего работы проектора

Собственно, сам код:

Сверну под спойлер, чтобы уменьшить и без того немалую длину текста


//define multiplexor pins

#define EN 7 // D7 pin

#define S0 2 // D2 pin

#define S1 3 // D3 pin

#define S2 4 // D4 pin

#define S3 5 // D5 pin

// define screen mode directions

#define STOP 0 // multiplexer C0 pin

#define DOWN 1 // multiplexer C1 pin

#define UP 2 // multiplexer C0 pin

// define analog pin for voltage sensor

#define VSensor A0 // A0 pin

// AV-receiver low and high limits for a trigger

const int TriggerLow = 3; // if voltage is lower than the value, then the trigger is OFF

const int TriggerHigh = 7; // if voltage is higher than the value, then the trigger is ON

// projector serial connection variables

const byte numChars = 32;

char receivedChars[numChars]; //an array to store the received data

// projector state variables

boolean newData = false;

String ProjectorPowerState;

String ProjectorPreviousPowerState;

//screen constants

const int PullUpTime = 25000; // full time from lower to upper position, milliseconds

const int PushDownTime = 19500; // time that requred to push down the screen to a working position; milliseconds

void setup() {

// set digital pins mode

pinMode(S0, OUTPUT);

pinMode(S1, OUTPUT);

pinMode(S2, OUTPUT);

pinMode(S3, OUTPUT);

pinMode(EN, OUTPUT);

// initialize the multiplexer

digitalWrite(S0, LOW);

digitalWrite(S1, LOW);

digitalWrite(S2, LOW);

digitalWrite(S3, LOW);

digitalWrite(EN, HIGH);

Serial.begin(9600); // console output for debug

Serial1.begin(9600); // projector serial connection

ProjectorPreviousPowerState = "Unknown";

}

void loop() {

int volt = analogRead(VSensor); // read the input

int voltage = map(volt,0,1023, 0, 2500); // input voltage in centivolts. i.e. 3V = 300 cV

Serial.println((String)"Trigger voltage in centivolts: " + voltage);

if (Serial1.available()) {

Serial.println("Projector serial connection is available, we need to check it state");

recvWithEndMarker();

// we need to get current projector state variable from the serial output

if (newData == true) { // only if we have a new data, we need to check the state

newData = false; // reset the new data flag

ProjectorPowerState = String(receivedChars); // convert array to a sting

ProjectorPowerState.trim(); // remove rn

Serial.println((String)"Projector current state is '" + ProjectorPowerState + "'");

}

// now we are ready to control the projector and screen

if (ProjectorPowerState == "OK0") {

Serial.println("The projector is OFF now. We need to check the screen state");

if (ProjectorPreviousPowerState == "OK1") { // we need to pull up the screen

Serial.println("The projector was powered off, we need to pull up the screen");

ScreenControl(UP); // pull up the screen

delay(PullUpTime); // we need to wait a few seconds while screen will be pulled up

}

else {

Serial.println((String)"Previous projector power state was '" + ProjectorPreviousPowerState + "', nothing to do");

}

ProjectorPreviousPowerState = ProjectorPowerState;

//if projector is OFF, but the trigger is ON, we need to power on the projector

if (voltage > (TriggerHigh*100)) {

Serial.println("Trigger is ON now, so we need to power on the projector too");

Serial1.print("~0000 1r"); //power on

}

}

else if (ProjectorPowerState == "OK1") {

Serial.println("The projector is ON now. We need to check the screen state");

if (ProjectorPreviousPowerState == "OK0") { // we need to push down the screen

Serial.println("The projector was powered off, we need to push down the screen");

ScreenControl(DOWN); // push down the screen

delay(PushDownTime); // wait for a proper length

ScreenControl(STOP); // and stop

}

else {

Serial.println((String)"Previous projector power state was '" + ProjectorPreviousPowerState + "', nothing to do");

}

ProjectorPreviousPowerState = ProjectorPowerState;

//if projector is ON, but the trigger is OFF

if (voltage < (TriggerLow*100)) {

Serial.println("Trigger is off, so we need to power off the projector too");

Serial1.print("~0000 0r"); //power off

}

}

else {

Serial.println("The projector state is Unknown. Nothing to do");

}

}

else {

Serial.println("Projector serial connection is not available");

}

//initial request to projector, if it not send anything

Serial1.print("~00124 1r"); // powerstate query. OK0 if powered down, OK1 if powered on

Serial.println("");

delay(1000);

}

void recvWithEndMarker() { //thanks to https://forum.arduino.cc/t/problem-sending-serial-commands-to-a-video-projector/481406/4

static byte ndx = 0;

char endMarker = 'r';

char rc;

while (Serial1.available() > 0 && newData == false) {

rc = Serial1.read();

if (rc != endMarker) {

receivedChars[ndx] = rc;

ndx++;

if (ndx >= numChars) {

ndx = numChars - 1;

}

}

else {

receivedChars[ndx] = '


СМОТРИ ТАКЖЕ

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

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