Продолжаем разговор за бюджетный умный дом, в этой статье мы соберем простой модуль на Arduino Nano. Предыдущая статья, посвященная настройке кластера openHAB, находится тут.

Я выбрал Arduino Nano, потому что для него существует вот такой очень удобный шилд:

NANO IO Shield
NANO IO Shield

К такому шилду удобно подключать все что угодно при помощи кабельных наконечников НШВИ 0,5-8. А VCC и GND я подключаю через латунные шины, т.к. к ним надо подключать кучку проводов. Тоже получилось удобно. Собрал все в корпусе распределительной коробки.  Вот так это в итоге выглядит:

Это пример модуля для кухни. К нему подключены два реле, для управления светом, сенсорный выключатель, датчик движения, датчик открытия окна (геркон), два датчика протечки, датчик газа MQ2 (т.к. присутствует и печное отопление, хочу знать CO), датчик температуры. Для связи модуля с MQTT-брокером используется Ethernet модуль enc28j60.

Вместо схемы подключения, предлагаю Вам такую таблицу, по-моему тут все предельно понятно:

Arduino Pin 

Module Pin 

Module 

D2 

In 

Реле 1 

GND 

GND 

VCC 

VCC 

D7 

In 

Реле 2 

GND 

GND 

VCC 

VCC 

D3 

Датчик протечки 1 

GND 

VCC 

D4 

Датчик протечки 2 

 

 

GND 

VCC 

D5 

Желтый (DQ) 

Датчик температуры DS18b20

*нужен резистор на 4.7 кОм между DQ и VCC

GND 

Черный 

VCC 

Красный 

D6 

Out 

Инфракрасный датчик движения 

 

GND 

GND 

VCC 

VCC 

D8 

Датчик открытия 

GND 

D9 

SIG 

Сенсорный 

Выключатель 

GND 

GND 

VCC 

VCC 

A0 

Analog Out 

Датчик газа MQ2 

*цифровой выход не использую

GND 

GND 

VCC 

VCC 

3.3v 

VCC 

Модуль enc28j60 

*для UNO пин CS нужно подключать к D8

GND 

GND 

D10 

CS 

D11 

SI 

D12 

SO 

D13 

SCK 

Примеры, модулей (хотел разместить в таблице справа. но не получилось):

Реле
Реле
Датчик движения
Датчик движения
Датчик протечки
Датчик протечки
DS18b20
DS18b20
Датчик открытия
Датчик открытия
Сенсорный датчик
Сенсорный датчик
MQ2
MQ2
Модуль enc28j60
Модуль enc28j60

Подобных модулей умного дома у меня будет около десятка, все оснащены разными датчиками и исполнительными механизмами, т.к. это ардуино, то все очень быстро переписывается под разные нужды.
Я использую последнюю на данный момент Arduino IDE 2.3.2.

Чтобы собрать скетч, нужно установить некоторые библиотеки. В Arduino IDE идем в Tools->Manage Libraries.

Library manager
Library manager

И тут устанавливаем: 

OneWire 2.3.7; 

UIPEthernet 2.0.12; 

PubSubClient 2.7.0.

Целеком скетч можно посмотреть тут:

Hidden text
#include <avr/wdt.h>
#include <OneWire.h>
#include "PubSubClient.h"
#include <UIPEthernet.h>
#define DEBUG 1  // Debug output to serial console

const byte Relay1Pin = 2;
const byte w1Pin = 3;
const byte w2Pin = 4;
OneWire ds(5);
const byte md1Pin = 6;
const byte Relay2Pin = 7;
const byte Win1Pin = 8;
const byte Button1Pin = 9;
const byte MQ2pin = A0;

byte tmp = 0;
byte w1Value = 0;
byte w2Value = 0;
byte md1Value = 0;
byte win1Value = 0;
byte button1Value = 0;
byte l2Status = 0;

unsigned int gasValue = 0;
unsigned long mytime = 0;

const char* mqtt_server = "10.20.10.40";
const char* mqttUser = "arduino-kitchen-01";
const char* mqttPassword = "password123";

#define MACADDRESS 0x00, 0x01, 0x02, 0x03, 0x04, 0x05
#define MYIPADDR 10, 20, 10, 50
#define MYIPMASK 255, 255, 255, 0
#define MYDNS 10, 20, 10, 10
#define MYGW 10, 20, 10, 10

char buf[10];                // Buffer to store the sensor value
int updateInterval = 10000;  // Interval in milliseconds
EthernetClient espClient;
PubSubClient client(espClient);

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    #ifdef DEBUG
    Serial.print(F("MQTT connection..."));
    #endif
    wdt_disable();
    // Attempt to connect
    if (client.connect("arduino-KITCHEN-01", mqttUser, mqttPassword)) {
      #ifdef DEBUG
      Serial.println("connected");
      #endif
      w1Value = digitalRead(w1Pin);
      pubw1();
      w2Value = digitalRead(w2Pin);
      pubw2();
      md1Value = digitalRead(md1Pin);
      pubmd1();
      win1Value = digitalRead(Win1Pin);
      pubwin1();
      client.subscribe("oh/kitchen/l1");
      client.subscribe("oh/kitchen/l2");
      wdt_enable(WDTO_8S);
    } else {
      #ifdef DEBUG
      Serial.print(F("failed, rc="));
      Serial.print(client.state());
      Serial.println(F(" try again in 5s"));
      #endif
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void sensors() {
  byte data_t[2];
  ds.reset();      // Начинаем взаимодействие со сброса всех предыдущих команд и параметров
  ds.write(0xCC);  // Даем датчику DS18b20 команду пропустить поиск по адресу. В нашем случае только одно устрйоство
  ds.write(0x44);  // Даем датчику DS18b20 команду измерить температуру. Само значение температуры мы еще не получаем - датчик его положит во внутреннюю память
  delay(1500);
  ds.reset();  // Теперь готовимся получить значение измеренной температуры
  ds.write(0xCC);
  ds.write(0xBE);  // Просим передать нам значение регистров со значением температуры
  // Получаем и считываем ответ
  data_t[0] = ds.read();  // Читаем младший байт значения температуры
  data_t[1] = ds.read();  // А теперь старший
  float temperature = ((data_t[1] << 8) | data_t[0]) * 0.0625;

  dtostrf(temperature, 4, 1, buf);
  #ifdef DEBUG
  Serial.print("Temp: ");
  Serial.println(buf);
  #endif
  client.publish("oh/kitchen/temp", buf);

  gasValue = analogRead(MQ2pin);
  dtostrf(gasValue, 4, 1, buf);
  #ifdef DEBUG
  Serial.print("gasValue: ");
  Serial.println(buf);
  #endif
  client.publish("oh/kitchen/gas", buf);
}

void callback(char* topic, byte* message, unsigned int length) {
  #ifdef DEBUG
  Serial.print(F("Msg arrived on topic: "));
  Serial.print(topic);
  Serial.print(". Msg: ");
  #endif
  String messageTemp;

  for (int i = 0; i < length; i++) {
    #ifdef DEBUG
    Serial.print((char)message[i]);
    #endif
    messageTemp += (char)message[i];
  }
  #ifdef DEBUG
  Serial.println();
  #endif
 
  if (String(topic) == "oh/kitchen/l2") {
    if (String(messageTemp) == "1") {
      l2Status = 1;
      digitalWrite(Relay1Pin, 0);
    }
    if (String(messageTemp) == "0") {
      l2Status = 0;
      digitalWrite(Relay1Pin, 1);
    }
  }

  if (String(topic) == "oh/kitchen/l1") {
    if (String(messageTemp) == "1") {

      digitalWrite(Relay2Pin, 0);
    }
    if (String(messageTemp) == "0") {

      digitalWrite(Relay2Pin, 1);
    }
  }
}

void setup() {
  wdt_disable();
  digitalWrite(Relay1Pin, 1);
  digitalWrite(Relay2Pin, 1);
  pinMode(Relay1Pin, OUTPUT);
  pinMode(Relay2Pin, OUTPUT);
  pinMode(w1Pin, INPUT_PULLUP);
  pinMode(w2Pin, INPUT_PULLUP);
  pinMode(md1Pin, INPUT_PULLUP);
  pinMode(Win1Pin, INPUT_PULLUP);
  pinMode(Button1Pin, INPUT_PULLUP);
  #ifdef DEBUG
  Serial.begin(9600);
  #endif
  uint8_t mac[6] = { MACADDRESS };
  uint8_t myIP[4] = { MYIPADDR };
  uint8_t myMASK[4] = { MYIPMASK };
  uint8_t myDNS[4] = { MYDNS };
  uint8_t myGW[4] = { MYGW };
  Ethernet.begin(mac, myIP, myDNS, myGW, myMASK);
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  #ifdef DEBUG
  Serial.println(F("\nStart!"));
  #endif
}

void pubw1() {
  client.publish("oh/kitchen/w1", itoa(w1Value, buf, 2));
  #ifdef DEBUG
  Serial.print("W1: ");
  Serial.println(w1Value);
  #endif
}

void pubw2() {
  client.publish("oh/kitchen/w2", itoa(w2Value, buf, 2));
  #ifdef DEBUG
  Serial.print("W2: ");
  Serial.println(w2Value);
  #endif
}

void pubmd1() {
  client.publish("oh/kitchen/md1", itoa(md1Value, buf, 2));
  #ifdef DEBUG
  Serial.print("md1: ");
  Serial.println(md1Value);
  #endif
}

void pubwin1() {
  client.publish("oh/kitchen/win1", itoa(win1Value, buf, 2));
  #ifdef DEBUG
  Serial.print("win1: ");
  Serial.println(win1Value);
  #endif
}

void loop() {
  wdt_reset();
  if (!client.connected()) { reconnect(); }
  client.loop();
  if (millis() - mytime > updateInterval) {
    mytime = millis();
    sensors();
  }

  tmp = digitalRead(w1Pin);
  if (tmp != w1Value) {
    w1Value = tmp;
    pubw1();
  }
  tmp = digitalRead(w2Pin);
  if (tmp != w2Value) {
    w2Value = tmp;
    pubw2();
  }
  tmp = digitalRead(md1Pin);
  if (tmp != md1Value) {
    md1Value = tmp;
    pubmd1();
  }
  tmp = digitalRead(Win1Pin);
  if (tmp != win1Value) {
    win1Value = tmp;
    pubwin1();
  }

  if (digitalRead(Button1Pin) == 0 && button1Value == 0) {
    char* tmp = "0";
    if (l2Status == 0) {
      tmp = "1";
    }
    client.publish("oh/kitchen/l2", tmp);
    button1Value = 1;
    digitalWrite(Relay1Pin, 0);
  } else if (digitalRead(Button1Pin) == 1) {
    button1Value = 0;
  }
}

Опишу подробнее, упустив однотипные куски кода и отладку.

Указываем пины ардуины для наших датчиков и реле: 

const byte Relay1Pin = 2; //реле 1 
const byte w1Pin = 3;     //датчик протечки 1 
const byte w2Pin = 4;     //датчик протечки 2 
OneWire ds(5);            //датчик DS18b20 
const byte md1Pin = 6;    //датчик движения 
const byte Relay2Pin = 7; //реле 2 
const byte Win1Pin = 8;   //датчик открытия окна 
const byte Button1Pin = 9;//сенсорный ввыключатель 
const byte MQ2pin = A0;   //датчик газа 

Укажим параметры соединения для MQTT: 

const char* mqtt_server = "10.20.10.40"; 
const char* mqttUser = "arduino-kitchen-01"; 
const char* mqttPassword = "password123"; 

Так же укажем сетевые настройки:  

#define MACADDRESS 0x00,0x01,0x02,0x03,0x04,0x05 
#define MYIPADDR 10,20,10,50 
#define MYIPMASK 255,255,255,0 
#define MYDNS 10,20,10,10 
#define MYGW 10,20,10,10 

Не забывем менять MACADDRESS и MYIPADD для каждого подобного устройства. Инициализация:

void setup(){
//выключаем watchdog 
wdt_disable();
//инициализируем GPIO, для входных линий указываем использовать подтягиваюший резистор (INPUT_PULLUP)); 
digitalWrite(Relay1Pin, 1); 
pinMode(Relay1Pin, OUTPUT); 
pinMode(w1Pin, INPUT_PULLUP); 

//инициализация Ethernet 
uint8_t mac[6] = {MACADDRESS}; 
uint8_t myIP[4] = {MYIPADDR}; 
uint8_t myMASK[4] = {MYIPMASK}; 
uint8_t myDNS[4] = {MYDNS}; 
uint8_t myGW[4] = {MYGW}; 
Ethernet.begin(mac,myIP,myDNS,myGW,myMASK); 

//инициализация библиотеки MQTT 
client.setServer(mqtt_server, 1883); 
client.setCallback(callback);
}

 Тут “callback” это функция, которая вызывается если в топик, на который мы подписаны, прилетает какое-то значение. Вот эта функция (в сокращении):

void callback(char* topic, byte* message, unsigned int length) { 
  String messageTemp; 
  for (int i = 0; i < length; i++) { 
    messageTemp += (char)message[i]; 
  } 
if (String(topic) == "oh/kitchen/l2") { 
  if (String(messageTemp) == "1") { 
    l2Status = 1; 
    digitalWrite(Relay1Pin, 0); 
  } 

  if (String(messageTemp) == "0") { 
    l2Status = 0; 
    digitalWrite(Relay1Pin, 1); 
  }
}
}

т.е. тут мы из канала "oh/kitchen/l2" получаем или 0 или 1, тем самым включаем или выключаем реле. Периодически из основного цикла вызывается функция опроса датчиков:

void sensors() { 
  byte data_t[2]; 
  ds.reset(); 
  ds.write(0xCC); 
  ds.write(0x44);
  delay (1500); 
  ds.reset(); 
  ds.write(0xCC);  
  ds.write(0xBE); 
  data_t[0] = ds.read(); 
  data_t[1] = ds.read(); 
  float temperature = ((data_t[1] << 8) | data_t[0]) * 0.0625; 
  dtostrf(temperature,4, 1, buf); 
  client.publish("oh/kitchen/temp", buf); 
  gasValue = analogRead(MQ2pin); 
  dtostrf(gasValue,4, 1, buf); 
  client.publish("oh/kitchen/gas", buf); 
} 

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

void loop(){ 
  wdt_reset(); //сбрасываем watchdog таймер 
  //если соединение c mqtt не установлено, то устанавливаем 
  if (!client.connected()) { reconnect(); } 
    client.loop(); 
  //время от времени дергаем опрос датчиков 
  if (millis()-mytime>updateInterval){ 
    mytime=millis();  
    sensors(); 
  } 

  //обработаем сенсорную кнопку 
  if (digitalRead(Button1Pin) == 0 && button1Value == 0) { 
    char* tmp = "0"; 
    if (l2Status == 0) {tmp = "1";} 
    client.publish("oh/kitchen/l2", tmp); 
    button1Value = 1; 
    digitalWrite(Relay1Pin, 0); 
  } else if (digitalRead(Button1Pin) == 1) { 
    button1Value = 0; 
  } 

  //остальные датчики 
  tmp = digitalRead(w1Pin); 
  if (tmp != w1Value) { 
    w1Value = tmp; 
    pubw1(); 
  } 
} 

Прямо тут обрабатываются все простые датчики и пишутся в соответствующие каналы, но через определенную функцию, для примера тут pubw1(), сделано для экономии памяти, т.к. эта функция вызывается еще из reconnect(), для того чтобы при старте передать актуальные значения всех датчиков, вот эта функция:

void reconnect() { 
  while (!client.connected()) { 
  //выключаем watchdog, т.к. соединение может устанавливаться более 8 секунд, а либа его не сбрасывает 
  wdt_disable(); 
  // Attempt to connect 
  if (client.connect("arduino-KITCHEN-01", mqttUser, mqttPassword)) { 
    w1Value = digitalRead(w1Pin); 
    pubw1(); 
    w2Value = digitalRead(w2Pin); 
    pubw2(); 
    md1Value = digitalRead(md1Pin); 
    pubmd1(); 
    win1Value = digitalRead(Win1Pin); 
    pubwin1(); 
  //тут же подписываемся на необходимые топики 
  client.subscribe("oh/kitchen/l2"); 
  //и включаем watchdog 
  wdt_enable(WDTO_8S); 
 } 
 } 
}

Вот и весь скетч. Приведу еще конфиг openHAB с моими item’ами:

[root@srv-oh-01 ~]# cat /etc/openhab/items/pleshki.items

Hidden text
Group           Home                        "Плешки"            <house>                                           ["Building"]
Group           GF                          "Первый этаж"       <groundfloor>     (Home)                          ["GroundFloor"]
Group           OU                          "За домом"          <garden>          (Home)                          ["Outdoor"]
Group           AT                          "Второй этаж"       <attic>           (Home)                          ["Attic"]
Group           GF_FamilyRoom               "Гостиная"          <parents_2_4>     (Home, GF)                      ["Room"]
Group           GF_Kitchen                  "Кухня"             <kitchen>         (Home, GF)                      ["Kitchen"]
Group           OU_Toilet                   "Туалет"            <toilet>          (Home, OU)                      ["Bathroom"]
Group           AT_StorageRoom              "Кладовка"          <suitcase>        (Home, AT)                      ["Room"]
Switch          Security                    "Охрана"         <security>           (Home,house,GF_FamilyRoom)             ["Security", "Switchable"]
Number          OU_Temperature              "Температура"       <temperature>     (OU, garden, gTemperature)      ["Temperature"]
Number          OU_Humidity                 "Влажность [%.2f]%unit%"         <Humidity>        (OU, garden, gHumidity)      ["Humidity"]
Number          OU_Pressure                 "Атмосферное давление [%.1f]%unit%"         <Pressure>        (OU, garden, gPressure)      ["Pressure"]
Number          OU_windDir_Num              "Направление ветра [%s] градусы"                    <wind>            (OU, garden, gWeather)
String          OU_windDir                  "Направление ветра [%s]"                    <wind>            (OU, garden, gWeather)
Dimmer          GF_FamilyRoom_Light         "Освещение"         <light>           (GF_FamilyRoom, gLight)         ["Light"]
Rollershutter   GF_FamilyRoom_Shutter_1     "Шторы 1"             <rollershutter>   (GF_FamilyRoom, gShutter)       ["Rollershutter"]
Rollershutter   GF_FamilyRoom_Shutter_2     "Шторы 2"             <rollershutter>   (GF_FamilyRoom, gShutter)       ["Rollershutter"]
Rollershutter   GF_FamilyRoom_Shutter_3     "Шторы 3"             <rollershutter>   (GF_FamilyRoom, gShutter)       ["Rollershutter"]
Rollershutter   GF_FamilyRoom_Shutter_4     "Шторы 4"             <rollershutter>   (GF_FamilyRoom, gShutter)       ["Rollershutter"]
Number          GF_FamilyRoom_Temperature   "Температура"       <temperature>     (GF_FamilyRoom, gTemperature)   ["Temperature"]                    
Contact         GF_FamilyRoom_Motion        "Датчик движения в гостиной"   <motion>          (GF_FamilyRoom, gMotion)        ["MotionDetector", "Switchable"]   
Number          GF_FamilyRoom_Gas           "Содержание CO [%.1f]%unit%"       <gas>     (GF_FamilyRoom, gGas)      ["Gas"]
Number          GF_FamilyRoom_Humidity      "Влажность"       <Humidity>     (GF_FamilyRoom, gHumidity)      ["Humidity"]
Switch          GF_Kitchen_Light_1          "Освещение общее"         <light>           (GF_Kitchen, gLight)            ["Light", "Switchable"]
Switch          GF_Kitchen_Light_2          "Освещение рабочей зоны"  <light>           (GF_Kitchen, gLight)            ["Light", "Switchable"]
Rollershutter   GF_Kitchen_Shutter_1        "Шторы 1"             <rollershutter>   (GF_Kitchen, gShutter)          ["Rollershutter"]
Rollershutter   GF_Kitchen_Shutter_2        "Шторы 2"             <rollershutter>   (GF_Kitchen, gShutter)          ["Rollershutter"]
Rollershutter   GF_Kitchen_Shutter_3        "Шторы 3"             <rollershutter>   (GF_Kitchen, gShutter)          ["Rollershutter"]
Number          GF_Kitchen_Temperature      "Температура"       <temperature>     (GF_Kitchen, gTemperature)      ["Temperature"]
Number          GF_Kitchen_Gas              "Содержание CO [%.1f]%unit%"       <gas>     (GF_Kitchen, gGas)      ["Gas"]
Contact         GF_Kitchen_Water_1          "Датчик протечки - раковина"        <water>   (GF_Kitchen, gWater)    ["Water"]
Contact         GF_Kitchen_Water_2          "Датчик протечки - стиралка"        <water>   (GF_Kitchen, gWater)    ["Water"]
Contact         GF_Kitchen_Motion           "Датчик движения на кухне"   <motion>          (GF_Kitchen, gMotion)           ["MotionDetector"]
Switch          OU_Toilet_Light             "Освещение"         <light>           (OU_Toilet, gLight)             ["Light", "Switchable"]
Contact         AT_StorageRoom_Motion       "Датчик движения"   <motion>          (AT_StorageRoom, gMotion)       ["MotionDetector", "Switchable"]
Contact         GF_Kitchen_Window_1         "Окно 1 на кухне"   <window>          (GF_Kitchen, gWindow)           ["Window"]
Contact         GF_Kitchen_Door_1           "Дверь 1 на кухне"  <door>          (GF_Kitchen, gDoor)           ["Door"]
Contact         GF_Kitchen_Button_1         "Кнопка у плиты"   <switch>          (GF_Kitchen, gButton)           ["Button"]
Group:Switch:OR(ON, OFF)           gLight        "Освещение"         <light>           (Home)   ["Light", "Switchable"]
Group:Rollershutter:OR(UP, DOWN)   gShutter      "Шторы"             <rollershutter>   (Home)   ["Rollershutter"]
Group:Number:AVG                   gTemperature  "Температура"       <temperature>     (Home)   ["Temperature"]
Group:Number:AVG                   gGas          "Содержание CO"     <gas>             (Home)   ["Gas"]
Group:Number:AVG                   gHumidity     "Влажность"     <humidity>            (Home)   ["Humidity"]
Group:Contact:OR(OPEN, CLOSED)          gMotion  "Датчик движения"   <motion>      (Home)   ["MotionDetector"]
Group:Contact:OR(OPEN, CLOSED)          gWater   "Датчик протечки"   <water>       (Home)   ["Water"]
Group:Contact:OR(OPEN, CLOSED)          gWindow  "Окно"   <window>                (Home)   ["Window"]
Group:Contact:OR(OPEN, CLOSED)          gDoor    "Дверь"   <door>                   (Home)   ["Door"]
DateTime Date "Дата [%1$td.%1$tm.%1$tY]" <calendar> { channel="ntp:ntp:ourhome:dateTime" }
DateTime CurTime "Время [%1$tR]" <clock> { channel="ntp:ntp:ourhome:dateTime" }
DateTime         Sunrise_Time       "Sunrise [%1$tH:%1$tM]"                   { channel="astro:sun:local:rise#start" }
DateTime         Sunset_Time        "Sunset [%1$tH:%1$tM]"                    { channel="astro:sun:local:set#start" }
Number  Day     "Day [%d]"      <day>   (Home)
String VoiceCommand

В интерфейсе openHAB это все выглядит так:

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

rule "Light on kitten work zone"
when
    Item GF_Kitchen_Motion changed
then
    if (Day.state == 0){
        if (GF_Kitchen_Motion.state == OPEN){
            if (GF_Kitchen_Light_2.state == OFF){
                logInfo("pleshki.rules", "GF_Kitchen_Motion is: " + GF_Kitchen_Motion.state )
                sendCommand(GF_Kitchen_Light_2, ON)
            }
        }
    }
    if (GF_Kitchen_Motion.state == CLOSED){
            if (GF_Kitchen_Light_2.state == ON){
                logInfo("pleshki.rules", "GF_Kitchen_Motion is: " + GF_Kitchen_Motion.state )
                sendCommand(GF_Kitchen_Light_2, OFF)
    }
    }
end

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

Комментарии (12)


  1. Speccyfan Автор
    09.04.2024 10:39

    А на самом деле примерно так и есть, на фото в левом верхнем углу - БП, к нему подключены латунные шины, а от них к модулям. Где-то тоже ставлю стабилизатор LM2596S. Там, где надо получить опорное напряжение очень стабильное.


    1. pav18
      09.04.2024 10:39
      +1

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


      1. Speccyfan Автор
        09.04.2024 10:39

        Согласен, так здорово. Возможно, в будущем, тоже так сделаю


  1. pav18
    09.04.2024 10:39

    Сразу скажу. Питалово заводите отдельно. У меня идет 12В от отдельного блока питания и перед каждым датчиком стоит стабилизатор на 5 или 3.3В Ардуина не потянет такие большие нагрузки.


  1. suprimex
    09.04.2024 10:39

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


    1. Speccyfan Автор
      09.04.2024 10:39

      Сам OpenHAB более года, а ардуины я постоянно что-то дергал и переделывал, поэтому более месяца аптайма нет.


    1. pav18
      09.04.2024 10:39

      Majordomo arduino esp8266 uptime 10 лет


    1. Albert2009Zi
      09.04.2024 10:39

      Меня больше смущает отстутсвие провода PE (заземляющего) во всей этой конструкции... Хотя автор делал все сам и для себя, соответственно априори выключит автомат в электрощитке перед тем, как лезть в своё изделие. А так за статью респект.


  1. Vilos
    09.04.2024 10:39

    В этом всём "умном" (или "полоумном" уж не знаю) доме всегда огорчает наличие кучи всяких проводов для релюшек, питания, передачи данных и прочее...присматривался ко всяким ZigBee и аналогам, однако питание все равно никуда не денешь, электричество пока только по проводам гуляет...а ковырять ремонт ради "сомнительного удобства", так себе...буду руками свет включать пока. Для академического интереса - да, можно побаловаться, поэкспериментировать...и дааа, как и 20 лет назад бОльшая часть задач решается обычными датчиками с проводами (реле времени, датчики света и проч), абсолютно без микроконтроллера; просто имея припой, паяльник и горстку компонентов. Пока не вижу ни одного, по-настоящему умного дома.

    В моем понимании умный дом этот не только куча датчиков и исполнительных механизмов, умный он станет тогда, когда он сможет сам обучаться и делать сценарии; начиная от того что в пятницу хозяин приходит домой обычно позже (но не всегда), он смотрит положение моего телефона на карте и знает, что сейчас я ближайшие 2 часа дома не буду - а значит топить котел не нужно, однако увидев что я поехал домой он он понимает что нужно подготовить комфортную температуру дома. Либо другой кейс я ночью встаю в туалет и он понимает что яркий свет мне не нужен, и тихонечко плавно включает свет по мере моего перемещения по дому, однако если при этом же сценарии он видит что гуляет по дому не хозяин, а кот (собака/хомячок)..., то эти ребята и без света обойдутся. Третий кейс - ребенок не засыпает или плохо засыпает, дом включает тихонько шум дождя в его комнате, делает прохладной температуру и организм сам стремится под тепленькое уютное одеялко...Всех сценариев в жизни не предусмотришь, однако умный дом на то и умный, что бы понимать, что происходит и создавать скрипты как ему действовать в той или иной ситуации, а пока умных домов нет, есть дома с датчиками и механизмами...как и 20-30 лет назад.


    1. Speccyfan Автор
      09.04.2024 10:39

      Все это вполне реализуемо сейчас. Я постепенно к этому и иду. К модулям,
      где не нужно 220В, тяну только витую пару, работает по PoE. Все беспроводное
      только там, где слишком неудобно и далеко тянуть кабель, т.к. не
      надежно. На реле времени, то что вы описали не построить, поэтому нужен
      OpenHAB, Home Assistant, etc, который и будет логику всю выполнять, уже и
      искусственный интеллект можно прикрутить, так что все будет.


  1. ZK413
    09.04.2024 10:39

    Я вот не как не пойму нескольких вещей:

    1. Что мешает использовать переменный ток? 12-24 переменки, меньше просадок, а если "оборудование" понимает толь DC, есть диодный мост.

    2. По какой причине не использовать КСВВнг(А)-LS (используется например в ОПС, САУЭ,..)? Он тонкий и дешевый, а главное безопасный.

    3. Для чего тащить 100500 реле? Умный дом подразумевает отсутсвие распред.коробок. Тянем люстру и выключатель в щит. На люстру ВВГнг(А)-ls 3х1,5, на розетки ВВГнг(А)-ls 3x2,5, на все выключатели и датчики КСВВнг(А)-LS. Это безопасно, и не противоречит ПУЭ, ГОСТам, и СНИПам.

    4. Что мешает использовать программируемое реле, промышленного типа (да ардуинка это программируемое реле, и не надо тешить себя фантазиями) например тот же овен пр200? Он имеет корпус, крепление на динрейку, и штатные расширения. Тот же ардуино, только со всеми разрешениями (им можно управлять шкафами автоматики энергоснабжения, пожаротушения, газовыми установками и т.д.), тестыми, гарантией на отказоустойчивость. В общем не хрень которая сегодня работает, завтра нет. А нормальное решение.

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

      Я не спорю, ардуинка с али + десяток говнодатчиков, и того 1500 вместе с доставкой. Тот же пр200 стоит больше 10к. НО! Мы используем нано для управления подцветкой (адресная лента) и светосигналами в серверных шкафах. Больше года, живут 5 из 10. То есть, это лотырея. Мало того, нано это почти самая слабая из семейства. И на полноценное управление просто светом, на однушку студию, их надо десяток. С модулями, таже беда.

      Как говорится - Можно сделать из говна конфету. Только конфета говняная будет...


  1. Speccyfan Автор
    09.04.2024 10:39

    1. Где в моем случае, Вы видите применение переменному току 12-24В ? Куда его тянуть? Все мои модули питаются или ~220 (внутри стоит БП на 5В), либо через PoE. Не представляю, зачем может понадобиться ~12В? Приведите пример.

    2. Я вообще тут не описывал применяемые типы кабелей, но в целом я согласен с применением 2.5кв на розетки и 1.5кв на люстру (хотя и много по современным меркам). А вот КСВВнг(А)-LS хоть и очеь хорош, но дешевле витую пару протянуть, для сигналов тоже подходит.

    3. Я не вижу смысла тянуть все лампочки, розетки, датчики и все остальное в шкаф, а тут дорогими контроллерами и реле отключать каждую розетку, это просто развод людей на деньги. В моем случае, две такие коробочки ставятся на комнату, все к ним подключено, все близко. А в шкафу только автоматы и может будут потом несколько серьезных реле для включения бойлера например.

    4. Зачем превозмогания? Потому что это DIY, причем совсем не сложный уровень, поверьте времени было затрачено, чтобы сделать первый модуль, заставить работать MQTT, а все остальное под копирку. И дешевле такое решение на порядки. А если вдруг помрет эта ардуина, то она на панельке, вынул, другую вставил, все.

    И на полноценное управление просто светом, на однушку студию, их надо десяток

    Вы про 74HC595 слышали? Да 100 лампочек можно легко подключить на нее.