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

Суммарный ток нагрузки .
Мощность, рассеиваемая стабилизатором:
Тепловое сопротивление кристалл-окружающая среда для AMS1117 в корпусе SOT-223 при минимальной площади меди: .
Перегрев кристалла:
При максимальной температуре внутри шкафа температура кристалла составит , что значительно ниже предельно допустимой . Режим работы безопасен.
Схема: подтягивающий резистор подключен к +5 В, второй конец – к аналоговому входу A0. Электроды датчика включены между A0 и GND.
Сопротивление воды образует делитель:
Сухое состояние: , .
Проводящая вода (водопроводная, дождевая): .
Устанавливаем порог обнаружения при :
Программная логика: – протечка; гистерезис ±0.2 В (возврат при ).
Последовательный резистор не влияет на коэффициент деления, так как входное сопротивление АЦП превышает 100 МОм.
Мощность на стабилитроне:
Фильтр эффективно подавляет высокочастотные промышленные помехи.
| Обозначение | Компонент | Модель / корпус | Цена, руб. |
|---|---|---|---|
| A1 | Arduino Nano (клон) | ATmega328P, microUSB | 200 |
| R1 | Резистор 100 кОм, 1% | 0805 SMD | 2 |
| R2 | Резистор 1 кОм, 1% | 0805 SMD | 2 |
| R5 | Резистор 220 Ом, 1% | 0805 SMD | 2 |
| D1 | Стабилитрон BZX55C5V1 | SOD-80 | 5 |
| C1, C2 | Конденсатор 0.1 мкФ, 50 В | 0805 X7R | 2×2 |
| C4 | Конденсатор 100 нФ (керамика) | 0805 | 2 |
| HL1 | Светодиод красный 5 мм | Выводной | 5 |
| U2 | USB-изолятор | Модуль на ADuM3160 | 250 |
| Электроды | Винт М4×20 нерж., гайка, шайба | A2 | 30 |
| Корпус | Заглушка сантехническая, гермоввод, эпоксидка | – | 50 |
| Прочее | Монтажная плата 30×50 мм, клеммники, кабель USB A–B 1 м | – | 150 |
| Итого | ~700 |
"OK" – сухо (напряжение на A0 > порога возврата)."ALARM" – протечка (напряжение ниже порога срабатывания)."ADC: 820".#include <Arduino.h>
#include <ArduinoJson.h>
// ==================== КОНФИГУРАЦИЯ ====================
#define SENSOR_PIN A0 // Аналоговый вход датчика протечки
#define BUILTIN_LED 13 // Встроенный светодиод на плате (L)
// Пороговое значение АЦП, ниже которого считаем, что есть протечка
// При сухом датчике напруга ~4.5В -> АЦП ~920
// При мокром (10к) напруга ~0.45В -> АЦП ~92
// Ставим порог 500 (примерно 2.5В) для надежности
#define ALARM_THRESHOLD 500
// Период опроса и отправки данных (миллисекунды)
#define SEND_INTERVAL 1000
// ==================== ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ ====================
unsigned long lastSendTime = 0;
int sensorValue = 0;
bool leakDetected = false;
bool prevLeakDetected = false;
void setup() {
// Инициализация последовательного порта (USB)
Serial.begin(9600);
// Ждем стабилизации питания и порта (важно для неттопов с медленной инициализацией)
delay(1000);
pinMode(BUILTIN_LED, OUTPUT);
digitalWrite(BUILTIN_LED, LOW);
// Вывод приветственного сообщения в Serial
Serial.println(F("{\"status\":\"startup\", \"msg\":\"Leak Sensor Ready\"}"));
}
void loop() {
// 1. Чтение данных с аналогового входа
// Усреднение для подавления помех (читаем 10 раз и усредняем)
long sum = 0;
for (int i = 0; i < 10; i++) {
sum += analogRead(SENSOR_PIN);
delay(1); // Небольшая задержка между семплами
}
sensorValue = sum / 10;
// 2. Логика обнаружения протечки
// Сигнал инверсный: Мокро = малое сопротивление = низкое напряжение = низкое число АЦП
if (sensorValue < ALARM_THRESHOLD) {
leakDetected = true;
digitalWrite(BUILTIN_LED, HIGH); // Зажечь встроенный светодиод при аварии
} else {
leakDetected = false;
digitalWrite(BUILTIN_LED, LOW);
}
// 3. Отправка данных по расписанию (или немедленно при смене состояния)
unsigned long now = millis();
bool stateChanged = (leakDetected != prevLeakDetected);
if ((now - lastSendTime >= SEND_INTERVAL) || stateChanged) {
lastSendTime = now;
prevLeakDetected = leakDetected;
// Создаем JSON документ
StaticJsonDocument<128> doc;
doc["raw"] = sensorValue;
doc["leak"] = leakDetected ? 1 : 0;
doc["msg"] = leakDetected ? "ALARM: Water detected!" : "OK: Dry";
// Сериализуем в строку и отправляем
serializeJson(doc, Serial);
Serial.println(); // Перенос строки для парсера на неттопе
// Дополнительная диагностика: если подозрение на обрыв (слишком высокое сопротивление)
// > 1000 обычно значит, что висит в воздухе (обрыв датчика), но 1023 - это штатное "сухо" для нашей схемы
if (sensorValue > 1010) {
Serial.println(F("{\"warning\":\"Sensor might be disconnected (air)\"}"));
}
}
// 4. Обработка входящих команд (базовая)
if (Serial.available()) {
String cmd = Serial.readStringUntil('\n');
cmd.trim();
if (cmd == "STATUS") {
// Принудительная отправка статуса
lastSendTime = 0; // Сброс таймера, чтобы отправить в следующем цикле
}
else if (cmd == "RESET") {
// Программный сброс
asm volatile ("jmp 0");
}
}
}