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

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

Обо мне

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

Немного предыстории

В 2016 году, примерно в июне, я переехал в новый дом в Lekki Gardens Phase 2. Lekki Gardens — это обслуживаемое и управляемое поместье. Однако вскоре я обнаружил, что «управляемый» не всегда и везде имеет одинаковое значение. В поместье есть центральный водопровод, но его катастрофически не хватает. Сначала вода была доступна с перерывами, поэтому нам приходилось наполнять наши ведра и большие контейнеры, когда вода готовилась до конца дня (или до конца следующих двух дней или одной недели), когда воды может не быть. Нам не разрешено бурить собственную скважину или колодец, а также устанавливать резервуары для хранения. С удачей и некоторым красноречием (ложь!), мы смогли убедить охрану позволить нам установить внешний резервуар для хранения. Это облегчило жизнь, так как все, что нам нужно было сделать, это открыть кран, и у нас есть вода (мы установили шаровые краны и обратные клапаны, чтобы нам никогда не приходилось беспокоиться о том, что бак полон или когда вода в поместье отключена). выключенный).

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

Наш бустерный насос значительно упростил задачу. Теперь мы могли заполнить наши резервуары менее чем за 45 минут с помощью нашего насоса высокого давления мощностью 1 л.с. (резервуар высокий, более 7 м от земли). Насос работал довольно хорошо, но была одна проблема. Предполагается, что насос автоматически отключается, когда давление становится слишком высоким (указывая на отсутствие открытых кранов или клапанов, следовательно, нет потока воды). Однако мы обнаружили, что наш трубопровод где-то протекает. Насколько нам известно, это могло быть где угодно вдоль 20-метрового подземного (под замками и бетонным полом) трубопровода, проходящего вокруг дома, но у нас было достаточно доказательств того, что он протекает. Таким образом, это означало, что нам приходилось включать и выключать насос вручную. Выключатель насоса был внизу и снаружи. В доме нет переднего забора и нет уединения, поэтому нам приходилось наряжаться, чтобы поставить или снять насос. Это было невероятно неудобно!

Тогда ко мне пришла мысль. Почему бы не разработать что-то, что позволило бы нам дистанционно включать и выключать насос? Я сказал жене, что могу построить для нее что-то, что позволит ей управлять помпой со своего телефона из любой точки мира. Она сначала насмехалась надо мной, потом поверила мне.

Познакомьтесь с Распупом

Raspump, как я его назвал (Raspberry Pump), представляет собой двухпозиционный переключатель на основе raspberry-pi. Это один из самых простых проектов Raspberry Pi, которые вы можете построить (после светодиодного переключателя). Однако все очень быстро усложнилось после того, как я решил, что хочу, чтобы приложение работало не только в нашем домашнем Wi-Fi, но и из любой точки мира. Оказалось, что включение насоса было самой простой частью проекта.

Raspump состоит из четырех (4) частей: удаленного сервера Raspump, локального сервера Raspump, Raspump Pi и приложения Raspump. В этой статье я сосредоточусь на Raspump Pi и окружающей его электронике.

Инструменты, которые я использовал

Я использовал модель Raspberry Pi 3, у которой много пригодных для использования контактов GPIO, намного больше, чем мне нужно (мне нужно было только два). Я намеревался купить Pi 3 для разработки и тестирования и Pi Zero W для конечного продукта. Однако получить Pi Zero и Zero W оказалось очень сложно.

Я также купил набор резисторов NPN (2N2222), набор металлопленочных резисторов, реле на 10 А, кнопочный переключатель, набор перемычек между штекерами и розетками и набор светодиодов. Я также купил инструмент для зачистки проводов и цифровой мультиметр, которые не требуются, но упрощают задачу. Я купил корпус Raspberry Pi Zewo (до того, как понял, что не могу купить Pi Zero W) и аккумулятор Pi (включая контроллер заряда и аккумулятор Li-Po емкостью 3800 мАч). У меня уже есть много зарядных устройств для телефонов на 5 В и еще больше кабелей USB-A — USB Micro-B.

Схема

Это принципиальная схема того, что я планировал.

Это достаточно простая электрическая схема. Важно отметить, что реле представляет собой единую цепь, имеющую 3 контакта цепи (GND, Vcc, IN) и 3 контакта с высокой нагрузкой (NO, NC, COM). Транзистор и диод являются частью этой схемы.

  • L1 — светодиод питания. Он указывает, когда система включена (обратите внимание, что это произойдет, когда Pi включен, а не когда он готов).
  • L2 — это светодиод состояния. Он показывает, когда насос включен.
  • GPIO19 подключен к контакту GPIO19.
  • GPIO12 подключен к контакту GPIO12.
  • S1 — это физический переключатель для включения/выключения помпы, когда это более удобно.
  • R1 составляет 70 Ом. R5 составляет 60 Ом. R2 составляет 100 Ом. Q2 — 2N2222 NPN.
  • Каждый второй резистор 1 кОм.

Однако когда я протестировал эту схему, то был очень неприятно удивлен. Случилось так, что реле, которое я купил, было реле LOW TRIGGER. То есть реле включается, когда сигнальный контакт подключен к земле, а не к Vcc. Я должен был спроектировать это (так горжусь собой), используя свое небольшое понимание электроники. Это то, с чем я закончил.

Единственная разница между этой и оригинальной конструкцией заключается во введении дополнительного транзистора и поддерживающих резисторов. R7 (10 кОм) — подтягивающий резистор. То есть, когда транзистор открыт (через транзистор нет тока), сигнал, поступающий на реле, становится равным Vcc (реле будет выключено). Когда есть сигнал с вывода GPIO, транзистор закрывается, и начинает течь ток. Поскольку R8 (1 кОм) меньше, чем R7, напряжение, поступающее на реле (~ +0,45 В), настолько близко к GND, что реле интерпретирует его как GND и срабатывает. В более чувствительном приложении мы бы либо уменьшили R8, либо увеличили R7, чтобы сделать напряжение намного ближе к GND.

Теперь, когда я подаю сигнал на GPIO19, включается L2, и реле замыкается, включая насос. Что ж, это было достаточно просто.

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

Архитектура

Ниже приведены различные части, которые составляют этот проект.

  • Raspump Pi — это драйвер Raspberry pi. Это программное обеспечение, которое установлено внутри самого Pi, чтобы заставить его работать.
  • Raspump Remote — это удаленный сервер, размещенный в Интернете. Это сервер, который гарантирует, что Pi можно будет контролировать из любой точки мира.
  • Raspump Local — это локальный сервер (находится на моем компьютере :D). Это основной управляющий сервер. Этот сервер синхронизируется с удаленным сервером.
  • Приложение Raspump — это пользовательское приложение, которое используется для управления помпой. Я преобразовал его в приложение Cordova для более удобного доступа, но также разместил его в Интернете на случай, если окажусь без телефона.

Распамп Пи

Теперь к интересным вещам. Подключение Pi оказалось самой простой и наименее трудоемкой частью всего проекта.



Raspump Pi, как я его назвал, — это компонент Raspberry pi управляющего программного обеспечения, состоящего из 4 частей. Он работает на Node.js v8. Я выбрал Typescript для проекта, потому что я влюбился в Typescript. В первый раз, когда я использовал Typescript в проекте, я задавался вопросом, как я смог использовать простой JS без проверки типов.

Я не пытаюсь объяснить каждую строку кода. Я упомяну только важные из них и те, которые нуждаются в объяснении. Вы можете просмотреть весь код в репозитории Github, указанном выше.

Технический стек

Raspump использует Socket.io для сигнализации в реальном времени и onoff (https://www.npmjs.com/package/onoff) для обнаружения прерываний (это важно для обнаружения нажатия кнопки). Изначально я хотел обойтись без библиотеки, но мне нужно было обнаруживать прерывания, которые невозможно обнаружить с помощью одного только JavaScript, поэтому вместо этого пришлось использовать onoff.

Принцип работы

Есть только две вещи, которые приложение когда-либо должно делать.

  1. Определите, когда насос был включен (включен или выключен), и действуйте соответственно.
  2. Определите, когда была нажата физическая кнопка включения / выключения, и действуйте соответственно.

Подключение

Когда драйвер запускается, он пытается одновременно подключиться к локальному и удаленному серверам. Если он установит контакт с локальным сервером, он отключит удаленный сервер.

Серверы написаны так, чтобы быть в некоторой степени безопасными и масштабируемыми. Поэтому при установлении контакта приложение сначала должно пройти аутентификацию на сервере. Он отправит событие «auth» с именем пользователя и паролем (см. метод login в src/socket.ts).

Если аутентификация пойдет не так, нам действительно больше нечего делать. Убиваем приложение.

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

Обнаружение дистанционного управления

Когда помпа переключается удаленно, один из серверов посылает сигнал драйверу помпы. Код, управляющий подключением к серверу, можно найти в src/socket.ts. Когда в приложении происходят изменения, серверы отправляют сигнал драйверу Pi.

При изменении вызывается pump.switchPump с новым статусом и датой переключения (код, управляющий насосом, находится в src/pump.ts). Дата важна, так как она гарантирует, что в случае сетевой задержки обрабатывается последний сигнал (и, следовательно, самый последний и, вероятно, правильный). Если дата предшествует дате последнего переключения, изменение не применяется.

Обнаружение нажатия кнопки

Когда физическая кнопка нажата, сигнал отправляется через контакт 12 GPIO. Это изменение определяется как прерывание с использованием onoff и запускает событие.

Насос переключается (строка 8 выше), и отправляется событие pushButton, которое обнаруживается (в src/index.ts), и событие сокета отправляется на сервер (socket.setStatus(deviceId, status);). При этом обновляются серверы и все остальные наблюдатели (включая все управляющие приложения).

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

Самая простая часть всего этого — включение насоса. Включить насос так же просто, как записать «1» в файл /sys/class/gpio/gpio19/value. Отключить его так же просто, как записать «0» в тот же файл.

Настройка Raspberry Pi

Это не все plug and play. Нам нужно сделать одну или две вещи, чтобы наш pi заработал.

Сначала я установил Raspbian на SD-карту. Я подключил Pi к своему телевизору через HDMI для настройки сети (вы также можете использовать порт Ethernet для прямого подключения к сети, если вам некуда подключить Pi). Настройка сети позволила мне подключиться к Pi по SSH и выполнить остальные настройки там. Мне также нужно было настроить Pi, чтобы в первую очередь разрешить SSH. Лень менять пароль по умолчанию (и запоминать новый пароль), я просто отключил вход по паролю через SSH. Все это выходит за рамки данной статьи. Простой поиск в Google даст много результатов по настройке Pi для доступа по SSH.

Я установил Node.js. Обратите внимание, что загрузка Node.js с домашней страницы узла не работает. Вам необходимо специально загрузить сборки ARMv7 для Node.js. Вы можете найти его на https://nodejs.org/en/download/current/.

Я клонировал код в /home/pi/raspump-pi и запустил npm install --prod для установки зависимостей. Вам нужно будет запустить эту команду на Pi с установленной конкретной версией узла. Если вы устанавливаете другую версию узла, вам нужно будет снова npm install --prod (поскольку onoff необходимо скомпилировать Epoll для конкретной версии узла).

Делаем контакты GPIO доступными для узла

Прежде чем вы сможете получить доступ к контактам GPIO, вам необходимо экспортировать контакты. Поскольку нашему приложению нужны GPIO19 и GPIO12, нам нужно экспортировать эти два контакта. Для этого мы записываем 19 и 12 в /sys/class/gpio/export:

echo '12' > /sys/class/gpio/export
echo '19' > /sys/class/gpio/export

Обратите внимание, что это не обычные файлы. Это специальные файлы. Итак, вы не можете, например, запустить cat /sys/class/gpio/export. Вы получите ошибку ввода-вывода.

Запуск драйвера при старте системы

Поскольку это Нигерия, и нет гарантии электричества, даже с резервной батареей, темнота может быть достаточно долго, чтобы батарея разрядилась, мне нужно было найти способ запустить службу после загрузки системы. Это довольно легко. Есть много способов добиться этого, но я решил использовать crontab. В терминале я запустил crontab -e, чтобы вызвать редактор crontab. Я написал следующую строку:

@reboot /usr/local/bin/node /home/pi/raspump-pi/src/index.js > /home/pi/raspump-pi/raspump.log

Это записывает весь вывод в raspump.log.

Это все, что составляет первую часть приложения. Во 2 части статьи я напишу о серверах и управляющем приложении.