Что может быть общего между двумя этими объектами?

Идея
Однажды я задумал приучить кота к унитазу, с целью избавиться от неприятного запаха, исходящего от его лотка. Но приучить его ходить — это одно, а вот спускать за собой — задача почти невыполнимая. Поэтому я решил возложить это на электронные плечи, в роли которых выступает Arduino Nano.
Сценарий задумывался такой:
Котэ (тот, что на первой картинке) через минидверцу в двери санузла попадает внутрь, заставляя сработать датчик открытия, делает свои дела сколько ему угодно, и выходит. После второго срабатывания датчика включается вытяжка, спускается вода в унитазе и распыляется освежитель.
Оборудование и тесты
К плате были подключены сервомашинка Towerpro MG996R, Z-Wave реле Fibaro FGS221 и кнопка со светодиодом. Кнопку добавил в качестве бонуса параллельно реле и вывел ее на стену.

По факту сервомашинка питается от БП 5V 2A. От него же запитана плата по USB.
Схема подключения и код:

#include <Servo.h> // подключаем библиотеку Servo
Servo flush; // создаем объект для управления сервой
const int buttonPin = 2; // номер пина кнопки
const int led = 4; // номер пина светодиода
int buttonState = 0; // переменная для чтения статуса кнопки
int flag = 0; // флаг по умолчанию сброшен
unsigned long holdTime = 0; // время начала события
unsigned long blinkTime = 0; // время начала события
unsigned long loadTime = 0; // время начала события
void setup() {
pinMode(led, OUTPUT); // задаем пин светодиода как выход
pinMode(buttonPin, INPUT); // задаем пин кнопки как вход
flush.attach(3, 8, 140); // привязываем серву к пину 3 и задаем мин/макс угол
flush.write(8); // поворачиваем серву в положение по умолчанию
}
void loop(){
buttonState = digitalRead(buttonPin); // проверяем положение кнопки
if (buttonState == LOW && flag == 0) { // если кнопка не нажата и флаг не установлен
flush.write(8); // поворачиваем серву в положение по умолчанию
digitalWrite(led, LOW); // включаем светодиод
}
if (buttonState == HIGH && flag == 0) { // если кнопка нажата и флаг не установлен
delay(100); // защита от дребезга контактов кнопки
flush.write(140); // поворачиваем серву на заданный угол
flag = 1; // устанавливаем флаг
holdTime = millis(); // включаем таймер удержания кнопки
}
if (buttonState == HIGH && flag == 1 && millis()-holdTime > 200) { // если кнопка была нажата более X мс
flag = 0; // сбрасываем флаг
blinkTime = millis(); // включаем таймер мигания светодиода
do {
digitalWrite(led, LOW); // выключаем светодиод
delay(200);
digitalWrite(led, HIGH); // включаем светодиод
delay(200);
}
while (millis()-blinkTime < 5000); // мигаем светодиодом X мс
flush.write(8); // поворачиваем серву в положение по умолчанию
loadTime = millis(); // включаем таймер ожидания наполнения бачка
do {
digitalWrite(led, LOW); // выключаем светодиод
delay(200);
digitalWrite(led, HIGH); // включаем светодиод
delay(200);
}
while (millis()-loadTime < 54000); // мигаем светодиодом X мс (время полного наполнения бачка)
}
if (buttonState == LOW && flag == 1 && millis()-holdTime <= 200) { // если кнопка была нажата менее X мс
flag = 0; // сбрасываем флаг
blinkTime = millis(); // включаем таймер мигания светодиода
do {
digitalWrite(led, LOW); // выключаем светодиод
delay(200);
digitalWrite(led, HIGH); // включаем светодиод
delay(200);
}
while (millis()-blinkTime < 2000); // мигаем светодиодом X мс
flush.write(8); // поворачиваем серву в положение по умолчанию
loadTime = millis(); // включаем таймер ожидания наполнения бачка
do {
digitalWrite(led, LOW); // выключаем светодиод
delay(200);
digitalWrite(led, HIGH); // включаем светодиод
delay(200);
}
while (millis()-loadTime < 30000); // мигаем светодиодом X мс
}
}
Задержка равна периоду полной перезарядки бачка водой.
Реализация
Так как во время ремонта была установлена инсталляция от Geberit, то подключение тяги не составило большого труда. Сервомашинка поставлена враспор между бачком и алюминиевым профилем, прикручена и залита термоклеем. В качестве тяги был использован тросик с зажимами, который пропущен через отверстие в бачке. Гибкая тяга нужна была, чтобы не потерять возможность спуска воды кнопкой на бачке.

Электронная часть размещена в распаячных коробках за инсталляцией.

Ручное управление может осуществляться как кнопкой, так и через приложение для Fibaro HomeCenter.

Используется два режима спуска:
- При коротком нажатии (<200 мс) спускается половина воды.
- При удержании кнопки более 200 мс, бачок опустошается целиком.
Z-Wave реле настроено на второй режим.
Задержка срабатывания вызвана тем, что приложение работало в режиме удаленного доступа через сервера fibaro.
Заключение
К сожалению, котэ на видео не будет, так как он съехал, а желание реализовать задуманное у меня осталось.
Автор: sisaenkov