Как стать автором
Обновить

Чем заняться в выходные: дистанционное управление домофоном, безбюджетный ремаппинг Nextion, разборки с Онлайм

Время на прочтение13 мин
Количество просмотров44K


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

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

Но обо всем (Arduino, банальные лайфхаки, телефонные склоки) по порядку.



Сим-сим, откройся!


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

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

Для обычных людей звучит довольно дико, но, как говорится, per aspera ad astra.

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

Впрочем, к домофонам. Вообще, автоматическое открытие домофона — штука не эксклюзивная. Например, здесь, на Geektimes, тов. Cluster еще в далеком 2013 году (когда доллар по 30) сделал не просто ДУ, но и автоответчик для гостей.

Это пока что самое крутое, что я видел в данном классе.

Но гораздо раньше посетители РадиоКота и множества других тематических форумов развлекались с устройствами типа «открывашка» — отпирающими домофон сразу же по звонку.

Ни то, ни другое повторять я не собирался. Первое — потому что сложно, и потому что у меня уже был работающий контроллер, который я планировал наделить новыми полномочиями. Второе по более очевидным причинам: слишком много деталей и слишком мало толка, прошу прощения, если обидел авторов.

Толка, конечно, для меня, а не вообще. То есть, мне категорически не нравится схема, которая гостеприимно открывает двери любому, кто набирает номер квартиры.

Отсюда основные требования к моей открывашке:

1) Использование центрального контроллера для управления через интернет и по радио
2) Минимальная защита от несанкционированного доступа
3) Минимальное вмешательство в интерьер

Начало



Начал я с того, что ознакомился с принципом работы домофона, который позаимствовал вот здесь:

Трубка работает очень просто: когда трубка уложена у неё сопротивление 50 Ом, когда трубка снята сопротивление ок. 400 Ом, когда нажата кнопка открывания замка сопротивление измеряется кило-Омами… Когда нет вызова нет и напряжения в линянии. Когда идёт вызов и трубка лежит ток большой и напряжение получается небольшое 5-7V, когда трубка отсутствует а на неё позвонили сопротивление бесконечность и напряжение максимальное ок. 15V, когда трубка снята напряжение ок 10V. Когда нажата кнопка напряжение максимальное ок. 15V — нажатие кнопки равно разрыву линии.


В случае с Цифралом это немного не так, поскольку в документации к трубке, а у меня оказалась KM-2НО (кстати, выражаю свою признательность Цифралу за публикацию схемы) указывается:

1. Ток потребления в режиме «Разговор» 18-22 мА
2. Напряжение в линии при установленной на корпус трубке 1,5–2,5 В
3. Напряжение в линии при поднятой трубке 5,8–6,5 В


Поэтому я более подробно ознакомился с принципиальной схемой своей трубки:



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

Обращаю внимание на тот факт, что моя модификация без светодиода. Но это оказалось в самый раз, поскольку данный факт позволяет очень просто передавать центральному контроллеру информацию о вызове.

Именно: звучит вызов, «горит» светодиод, включается оптрон, на пине контроллера имеем изменение уровня с высокого на низкий.

Так что вместо светодиода я поставил уже имеющийся у меня оптрон 4N35, выход которого направил прямиком к Arduino. По стандартной схеме из того же интернета:



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

При подключении к цифровому пину это выглядит так:

#define ringPin номер_пина

pinMode(ringPin, INPUT_PULLUP);


При подключении к аналоговому пину:

#define ringPin номер_пина

pinMode(ringPin, INPUT);
digitalWrite(ringPin, HIGH);


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

Что касается земли в приведенном выше примере, то надо понимать: хотя на схеме земля кажется общей это не так — на то, собственно и существует оптоэлектронная развязка. Ну и на то он и пример.

Отвяжись от меня!


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

Уж не знаю, как так вышло, но получилось, что замок работал кое-как. То «вполнакала», то вообще никак, и инсталляторы себе уже всю голову поломали. Но в конце концов предположили, что у них где-то случилось нежданное КЗ (или что-то вроде) в цепях управления. Конечно же, все проверили, конечно же, без особых успехов, поскольку ставили четко по инструкции.

Масла в огонь подливало и то, что точно такой же замок точно в такой же конфигурации, но на другом этаже работал просто великолепно.

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

В общем, разбирались довольно долго и нудно. И я не хотел повторения того же самого у себя дома.

Поэтому не стал экономить провода и подключил контакты реле самым простым способом:

1) Нормально замкнутые одного реле — последовательно с кнопкой подъема трубки SW1 (потому что эта кнопка в обычном состоянии замкнута)
2) Нормально разомкнутые другого реле — параллельно с кнопкой открывания двери SB1 (потому что эта кнопка в обычном состоянии разомкнута)

Управляющие контакты реле, разумеется, подключил к свободным (ура, они еще были) цифровым пинам микроконтроллера.

Всего, как легко представить, потребовалось шесть проводов: два на оптрон и еще четыре — для реле.

Прошу прощения за примитивизм иллюстрации:

Со стороны домофона




Со стороны Arduino




Реле здесь изображены исключительно схематично. Поскольку, повторюсь, я использовал уже готовые модули реле с полным фаршем — оптронами, транзисторами, диодами, и проч. Голые реле к Arduino подключать категорически не рекомендую.

… и не звони мне больше!


Уже на этом этапе я смог очень просто открывать домофон через интернет или локальную сеть с компьютера или смартфона по следующему принципу:

1) В момент звонка домофона контроллер на 40 секунд переходит в режим разрешения открывания двери. Время выбрано исходя из документации к домофону Цифрал, где указано, что длительность сигнала вызова именно 40 секунд.

Т.е. на большее время условно открытым оставаться нет смысла.

2) При получении команды открывания через интернет (HTTP POST) контроллер последовательно переключает реле. Сначала — размыкает реле трубки, чем имитирует ее подъем. Затем спустя небольшую паузу замыкает реле кнопки открывания, чем имитирует ее нажатие. После — «отпускает» кнопку и «кладет» трубку.

Тестовый стенд был примитивен донельзя:



На этом можно было бы и остановиться, если бы я, как гордый владелец КЦДВ-12-2 не был в курсе, насколько это неудобно — каждый раз бегать за пультом или телефоном, когда нужно что-то включить/выключить.

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



Короче, я по-быстрому (на самом деле — нет) добавил в метеостанцию самый обычный и пошлый передатчик на 433 МГц с амплитудной модуляцией, кои тоннами продают на Aliexpress за смешные деньги.

В результате метеостанция стала еще одной точкой управления домофоном, и поэтому если раздастся звонок, а ты сидишь рядом с ней, то нет смысла срываться к трубке, потому что прямо с экрана можно:

1) Открыть замок

2) Поднять трубку и уже неспешно (по документации длительность разговора 1,5 минуты против 40 секунд звонка) дойти до домофона, ответить и решить — открывать, или нет

3) «Отбить» звонок (контроллер «поднимает» и сразу «опускает» трубку)

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

Новенький интерфейс, к слову теперь совсем не похож на HAL. Теперь, все такое разноцветное и веселенькое, что просто обхохочешься. И ведь поди пойми: смузи не пил, хипстеры меня не кусали, ламберсеков в роду не было, а на стиль material тянет, как никогда в жизни:



Этот экран сменяет климатические данные, когда звонит домофон: в этот момент центральный контроллер выдает радиокоманду, на которую и реагирует метеодисплей.

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

Замок слева — открытие замка. Трубка справа — поднятие трубки для имитации начала разговора.

Экран сменяется на главный спустя 40 секунд от начала звонка, а не сразу по нажатию кнопки-пиктограммы. Это позволяет нажать несколько раз, если контроллер вдруг не «услышал» команду, что не редкость с учетом используемого типа радиоканала.

Алгоритмы


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

Но поигравшись пару дней понял, что стоять перед домофоном и тыкать в экран — довольно скучное занятие, и гораздо интереснее разрешить «отложенное» открытие, когда только подходишь к подъезду. Тогда останется только набрать номер квартиры на панели домофона и вуаля, дверь открыта.

Наконец, я подумал, что при таком раскладе, наверное, имеет смысл сделать и запрет открывания — вообще.

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

Во-вторых, по трезвому (а не как обычно) размышлению выходило, что особой разницы между открыванием по команде непосредственно в момент звонка или по команде данной заранее — тоже никакой.

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

Поэтому режим один и команда одна, а обработчиков два:

1) Если звонит домофон, то контроллер разрешает открывание в пределах 40 секунд с начала звонка

2) Если сначала поступает команда на открывание, то контроллер разрешает открывание и ждет звонка в пределах N минут с момента поступления команды (это чтобы подготовить домофон к открыванию по пути к дому)

Источников команды на открывание тоже может быть два:

1) HTTP POST-запрос через локальную сеть или интернет (например: myserver.com/?sim-sim-openup), т.е. открыть можно хоть из Куала-Лумпура

2) Радиокоманда от панелей или кнопок дома (в моей реализации — через библиотеку RC-Switch)

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

Внезапные бонусы


Даже если не пользоваться функцией открывания двери, теперь получается, что контроллер регулярно уведомляет о том, что кто-то скребется в дверь подъезда посредством домофона. Мне, как человеку любопытному, эта информация небезынтересна — и теперь я ее получаю регулярно.

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

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

И ландшафтный дизайн


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



В итоге я решил, что протянуть шлейф за дверной коробкой и закрыть его фрагменты отпечатанными на 3D-принтере декоративными панелями будет лучше, чем занимать еще одну розетку блоком питания, непонятно как тянуть его провод к трубке домофона и городить радиоканал между трубкой и контроллером.



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

Ремаппинг Nextion


Рассказывая про настольный метеодисплей (метеостанцию, если хотите), я упоминал, что в процессе доводки корпуса успел повредить основной компонент — собственно сенсорный экран Nextion.

Поломка не сказалась на работе его бортового микроконтроллера и отображении данных, но вот сенсорная панель практически отказала. Однако опытным путем я выяснил, что если даже не слишком сильно надавить на плату Nextion в определенном месте, то таким образом можно восстановить чувствительность левой (примерно) половины экрана.

Работает этот трюк нестабильно и не всегда, но достаточно часто, чтобы я смог с этим смириться, размышляя о заказе нового экрана.

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

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

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

Было:



Стало:



Попутно, правда, пришлось убить в себе перфекциониста и переделать оригинальный экран управления домофоном на минимально рабочий:



Вживую




Когда техническая поддержка «не але»


Казалось бы, на всех этих взлетах и падениях можно было бы и закончить, если бы не одна деталь: я внезапно обнаружил, что домофон (а за ним и вся остальная автоматика) перестал управляться при доступе из внешних сетей.

То есть, все команды безупречно отрабатывали при подключении к интернету через домашнюю сеть и по внешним адресам (а не по внутренним вида 192.xxx.xxx.xxx), но столь же безупречно отказывались исполняться из сетей других операторов (я пробовал двух).

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

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

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

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

Оператор для целей предотвращения несанкционированного доступа к оборудованию абонентов блокирует во входящем абонентском трафике следующие порты:
TCP/25 – предотвращение спам-активности;
TCP/135-139, TCP/445 и UDP/135-139 – Обеспечение безопасности систем, работающих под ОС MS Windows;
TCP/23, TCP/161, UDP/69 и UDP/161– Защита клиентского оборудования.

Все остальные порты, включая названый, не блокируются.


Я, в свою очередь настаивал, что мой порт а) не попадает в данный диапазон, б) не работает, как положено и в) я ничего не менял.

Как об стену горох.

Ну что делать, тогда я вежливо объяснил, что хотя понимаю, что мои несчастные 450 рублей в месяц погоды им не сделают, но от такого пофигизма я пойду искать пусть такой же пофигизм, но хотя бы работающий.

В ответ снова пробормотали, что IP они мне предоставляют, а дальше все мои проблемы. Ну мои, решил я, значит мои. И волевым решением сначала проверил работоспособность системы на другом порту (на единичку сместил) — работает. А потом сделал гибкую настройку номера порта в Tasker, через который, собственно и рулю автоматикой.

Собственно, к чему я описываю свои страдания: мне объективно очень хотелось понять, кто в такой ситуации неправ. Потому что чувствую себя полным идиотом — и маршрутизатор перезагружал, и настройки проверял (причем по своей инициативе, а не по подсказке «специалистов»), и все равно меня посылали куда подальше, намекая на мои кривые руки.

За кадром


В заключение о том, что я использовал для стройки века:

1) КЦДВ-12-2 — 1 шт.
2) Трубка домофона Цифрал КМ-2НО — 1 шт.
3) Оптрон 4N35 — 1 шт.
4) Кабель плоский 10 жил (использовал шесть, но положил все — на всякий случай) — 3 м.
5) Разъемы к кабелю — по 2 шт. пап и мам
6) Самодельный метеодисплей с сенсорным экраном Nextion — 1 шт.
7) Передатчик 433 МГц (из комплекта вроде такого) для модификации метеодисплея — 1 шт.
8) Резистор 1 кОм для оптрона — 1 шт.

Опции:

Обновленный интерфейс для Nextion

Тестовый код (до интеграции с КЦДВ-12-2 и полного букета сервисных функций, только для понимания хода мысли)
#include <RCSwitch.h> //   http://code.google.com/p/rc-switch/


#define ringTimeOut 40000 // максиамальное время сигнала вызова домофона Цифрал 2094
#define openTimeOut 300000 // время действия флага allowOpen для моментального открывания по сети во время вызова
#define handsetPin A3 // реле поднятия трубки 0
#define openPin A4 // реле кнопки открывания (1)
#define ringPin 7 // индикатор вызова (3)
#define ringCode 360500 // код для дублирования сигнала вызова на беспроводных панелях
#define doorBell 3395840 // код для повторения сигнала вызова дверным звонком
#define openCode 255899 // код для открывания по радио
#define openDelay 1500 // задержка нажатия на кнопку
#define handsetDelay 2500 // задержка после поднятия трубки
#define txPin 8

unsigned long ringTime, openTime; // счетчик длительности сигнала вызова
boolean ring = false;
boolean ringRepeat = false; // разрешение на повтор сигнала вызова дверным звонком
boolean allowOpen = false; // разрешение на открытие по сети

RCSwitch mySwitch = RCSwitch();

// ОТКРЫВАНИЕ двери
void openDoor() {
    
    digitalWrite(handsetPin, LOW);
    delay(handsetDelay);
    digitalWrite(openPin, LOW);
    delay(openDelay);
    digitalWrite(openPin, HIGH);
    digitalWrite(handsetPin, HIGH);
    ring = false; // сброс признака звонка
    allowOpen = false; // сброс разрешения на открытие через сеть
    // sendMail(37); // отправка уведомления о дистанционном открытии замка     
}


void setup() {
  Serial.begin(9600);
  mySwitch.enableTransmit(txPin); // разрешение передачи
  mySwitch.enableReceive(0); // разрешение приема
  pinMode(handsetPin, OUTPUT); // инициализация пинов и реле
  pinMode(openPin, OUTPUT);
  pinMode(ringPin, INPUT_PULLUP  );
  digitalWrite(handsetPin, HIGH); // реле обесточено
  digitalWrite(openPin, HIGH);
  Serial.println("Ready");
}

void loop() {
  
  if (digitalRead(ringPin) == LOW && ring == false) { // если сработал индикатор вызова и если не в ожидании таймаута сигнала вызова
    ring = true; // блокировка повторого определения вызова
    ringTime = millis();
    // sendMail(36); // отправка уведомления о сигнале вызова
    mySwitch.send(ringCode, 24);
    Serial.println("Sent ringCode");
    if (ringRepeat == true) { // если разрешен повтор вызова дверным звонком
      mySwitch.send(doorBell, 24);
      Serial.println("DoorBell repeat");
    }
    Serial.println("Ring-ring!");
  }

if ((millis() - ringTime) > ringTimeOut && ring == true) { // если прошло 40 секунд (по документации к домофону) с начала сигнала вызова
  ring = false; // сброс признака вызова
  Serial.println("Ring reset");
  // sendMail(38); // отправка уведомления о таймауте вызова 
}

// открытие по сети
if (ring == true && allowOpen == true) {
  openDoor(); // открытие двери
  Serial.println("Door opened via net");
}

if (ring == false && allowOpen == true) { // отмена "автоматического" открытия по сети
  if ((millis() - openTime) > openTimeOut) { // сколько времени ждать сигнала на открытие 
   allowOpen = false; 
   // sendMail(39); // отправка уведомления о таймауте открывания
  }
  
}

// открытие по радио

if (mySwitch.available()) { //
    int value = mySwitch.getReceivedValue();
    if (value != 0) {
      Serial.println(mySwitch.getReceivedValue());
      switch (mySwitch.getReceivedValue()) {
        
        case openCode: // сигнал открытия двери
          if (ring == true) {
            mySwitch.disableReceive();
            openDoor(); // открытие двери
            Serial.println("Door opened via radio");
            mySwitch.enableReceive(0); // разрешение приема 
          }
          break;
    }
    mySwitch.resetAvailable();
  }

// конец тестового кода
}

}






Картиночки для интерфейса взял на замечательном сайте Pixabay.
Теги:
Хабы:
Всего голосов 22: ↑21 и ↓1+20
Комментарии17

Публикации

Истории

Ближайшие события

19 августа – 20 октября
RuCode.Финал. Чемпионат по алгоритмическому программированию и ИИ
МоскваНижний НовгородЕкатеринбургСтавропольНовосибрискКалининградПермьВладивостокЧитаКраснорскТомскИжевскПетрозаводскКазаньКурскТюменьВолгоградУфаМурманскБишкекСочиУльяновскСаратовИркутскДолгопрудныйОнлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн
10 – 11 октября
HR IT & Team Lead конференция «Битва за IT-таланты»
МоскваОнлайн
25 октября
Конференция по росту продуктов EGC’24
МоскваОнлайн
7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн
7 – 8 ноября
Конференция «Матемаркетинг»
МоскваОнлайн
15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
25 – 26 апреля
IT-конференция Merge Innopolis 2025
Иннополис