Arduino, ESP8266 Lua, Raspberry Pi 2 && OpenHab. Умный дом: азы управления.

Тема в разделе "Глядите, что я сделал", создана пользователем ИгорьК, 12 май 2015.

  1. alp69

    alp69 Форумчанин

    Интересен сам код и правила. Намедни поставил устройство электричество считать по вспышкам счетчика. Все работает. В т.ч. онлайн установка через ОН начальных показаний. Возможность коррекции если что-то пошло не так. Вот только все никак не доберусь до компа.
    Бронирую номер 44. :D
     
    Последнее редактирование: 1 дек 2016
    ИгорьК нравится это.
  2. ИгорьК

    ИгорьК Гуру

    Добавил код в пост. Почему бета? Потому что пока не принял решение о конечной логике работы.
    Сейчас код отзывается на каждое замыкание геркона. Отправка идет сразу всей таблицы: горячая, холодная вода и напряжение батарейки.
    Возможно, сделаю передачу:
    • раз в час;
    • пропуск передачи, если за час ничего не изменилось.
    У меня в водоразборе электричества нет, поэтому надо экономить.
     
  3. alp69

    alp69 Форумчанин

    У меня логика передачи показаний несколько иная. Устройство знать не знает что там показывает счетчик. Его задача просто с определенной периодичностью передавать брокеру количество потребленной электроэнергии за некий интервал времени.
    Идея с отключением радиомодуля и его кратковременным включением на передачу понравилась. Можно рассматривать как дополнение к системе защиты радиосети. Элемент скрытности.

    P.S. Выход счетчиков заводской? Или потребовалась доработка? Была мечта и водосчетчики прикрутить. Только вот у них нет выходов. Кому-нибудь известен бесконтактный способ подключения?
     
    Последнее редактирование: 2 дек 2016
  4. ИгорьК

    ИгорьК Гуру

    Это хорошая мысль.
    Вместе с тем, я пытался размышлять шире над вопросом. Ведь много народа и без опенхаба. Можно задействовать открытый брокер и приложение на смартфоне. И у тебя всегда показания счетчика есть.
    Screenshot_20161202-104415.jpg
     
    Последнее редактирование: 2 дек 2016
  5. ИгорьК

    ИгорьК Гуру

    [​IMG]
     
    alp69 нравится это.
  6. alp69

    alp69 Форумчанин

    Суть ясна.
    Но в чем тут принципиальная разница? Приложение на телефоне выполняет роль ОН в контексте хранения данных. Если нет, то возникает вопрос - где хранить данные? В энергонезависимой памяти? На sd?
     
  7. ИгорьК

    ИгорьК Гуру

    Ответ здесь:
    Water4.jpg

    Последние данные хранятся на брокере постоянно. Каждый раз, когда телефон соединяется с брокером, он их получает.
     
  8. alp69

    alp69 Форумчанин

    Тогда не совсем понятен тезис:
    И в чем проиворечие с этим?
     
  9. ИгорьК

    ИгорьК Гуру

    Устройство должно передавать постоянно актуальную информацию об израсходованной воде, а не изменение потока воды на 10 литров.
    Эта информация и хранится на БЕСПЛАТНОМ НЕЗАВИСМОМ брокере - ее можно считать, подключившись к брокеру в любой момент.
     
  10. alp69

    alp69 Форумчанин

    Все, въехал. :) Таким образом инфа об общем потреблении хранится в устройстве и транслируется в брокер. Тогда в устройстве нужно организовывать энергонезависимое хранение данных на случай рестарта устройства.
    У меня общее потребление хранится на малине, а устройство передает расход за последние ... минут.
     
  11. ИгорьК

    ИгорьК Гуру

    Можно организовать, но устройство питается от батареек. Рестарт вряд ли возможeн. А когда батарейка сядет - запуск через MQTTSpy.
    Можно подумать на счет запроса из Опенхаба последней информации, кстати.
     
  12. SergeiL

    SergeiL Оракул Модератор

    Игорь, а сколько потребляет, в среднем?
     
  13. ИгорьК

    ИгорьК Гуру

    Посмотрим. Термометр от двух АА работает больше месяца. Здесь я вижу две самые толстые большие батарейки (не знаю как они назыаются).
    Возможно поставить и старый мотоциклетный аккумулятор с DC-DCS преобразователем.
    Но вопрос назрел и не только у меня.
    Не знаю ответа, практика покажет.
     
  14. alp69

    alp69 Форумчанин

    Тип ААА. По советской классификации - "элемент 373".
     
    Последнее редактирование: 2 дек 2016
  15. alp69

    alp69 Форумчанин

    Вот в этом то и грабли. MQTTSpy не всегда под рукой. Мое устройство тоже можно считать "бетой" т.к. в предстоящие выходные буду делать (если на работу не дернут) запрос отправку на устройство из Опенхаба последней информации. Алгоритм в голове уже сложился.
     
  16. ИгорьК

    ИгорьК Гуру

    Для смарфона их десяток. Они не такие удобные, но вполне рабочие и всегда под рукой.
     
  17. SergeiL

    SergeiL Оракул Модератор

    Наверное тип "D" - советский "373" ;-)
     
    alp69 нравится это.
  18. alp69

    alp69 Форумчанин

    Точно! :eek::)
     
  19. alp69

    alp69 Форумчанин

    44. Читаем счетчик расхода электричества.

    Принцип работы устройства давно известен и описан в Интернете на многих ресурсах. На нашем форуме беглый поиск по этой теме не выдал ничего.
    Итак, коротко.

    Теория:
    Множество моделей электросчетчиков имеют на лицевой панели мигающий светодиод (индикатор). Скорость его мигания зависит от количества потребляемой электроэнергии. Большинство бытовых счетчиков моргают с частотой 3200 импульсов на 1 кВт∙ч. Количество импульсов, которые счетчик выдает при расходовании 1 кВт∙ч можно узнать, разглядывая лицевую панель счетчика.

    Практика:
    Перед индикатором счетчика ставим фотоэлемент, который изменяет свое состояние при освещении его светом индикатора счетчика. Устройство считает зарегистрированные фотоэлементом вспышки индикатора.

    В опенхабе это выглядит так:
    shot_2016-12-02_20-14-40.png
    При нажатии на этот элемент переходим в на следующую страницу:

    shot_2016-12-02_20-18-51.png
    При нажатии на элемент «настройка» переходим на следующую страницу:
    shot_2016-12-02_20-18-09.png

    Собственно вся хитрость в последней странице.

    Устройство, висящее на счетчике, и считающие импульсы не знает, что там показывает счетчик. Ему это и не надо. Его задача отправить в опенхаб количество кВт∙ч, израсходованных за определенный интервал времени. Далее эти данные, поступив в опенхаб, плюсуются с предыдущими. Это все делается правилами (rules).
    Для того, чтобы установить первоначальные данные, (синхронизировать со счетчиком), нужно выставить показания счетчика на странице «настройка» (третий скриншот).
    Верхняя строка показывает то, что вы наберете ниже. Из нее же скорректированные вами данные фиксируются опенхабом. Следующие строки в режиме он-лайн корректируют эти показания. Строки сверху вниз:
    сотни тысяч (0ххххх,х);
    десятки тысяч (х0хххх,х);
    тысячи (хх0ххх,х);
    сотни (ххх0хх,х);
    десятки (хххх0х,х);
    единицы (ххххх0,х);
    десятые доли (хххххх,0).
    Просто набираем нужное значение. При рестарте опенхаба значения в этих строках будут отсутствовать. В этом случае нажимаем «сброс», тем самым установив нулевые значения.

    Если Вы обратите внимание, текущие показания счетчика (первый скриншот) превышают значение, отображаемое на странице «Настройка» (третий скриншот). Это нормально. На странице "Настройка" остались те значения, при которых устройство было поставлено в строй. Перезагрузок опенхаба пока не было.

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

    Железо:

    1. Донором для блока питания ~220/5v был 1-амперный зарядник от телефона.
    (фото не привожу)
    2. Далее 3,3 вольта получено от такого модуля:
    [​IMG]
    3. Датчик освещенности
    [​IMG]
    Фоторезистор был выпаян и припаян обратно через 20-сантиметровые провода. Это позволило вынести к счетчику не весь модуль, а крохотный фоторезистор.

    4. Модуль ESP-12E:
    [​IMG]


    5. Корпус (распредкоробка РК 75х75 (МРК 75х75) ОУ):
    [​IMG]

    Диагональные штырьки откусываются. В плате сверлится отверстие под центральный штырь.

    Схема:

    В связи с тем, что у меня на ноуте стоит WinXP, Fritzing с ходу в лоб установить не удалось. Поэтому красивостей не будет. Будет принципиальная схема с элементами графики ;):
    Для статьи схема.jpg
     
    Последнее редактирование: 3 дек 2016
    SergeiL и ИгорьК нравится это.
  20. alp69

    alp69 Форумчанин

    Код:
    Код (Lua):
    --Скрипт для трансляции расхода энергии. Устройство считывает количество световых импульсов
    --с табло счетчика электроэнергии.

    --Это можете изменить сами, если захотите:
    pin = 1     -- здесь датчик освещенности (gpio5)
    gpio.mode(pin, gpio.INPUT)
    imp_KWt_hour = 3200 -- импульсов на кВт ч (смотрим на счетчике)
    period_time = 60000 -- частота публикаций расхода за интервал времени (миллисекунды)
    freq_sample = 10 -- частота опроса состояния индикатора (миллисекунды)

    --Это менять не рекомендуется:
    period_rate = 0 -- переменная для хранения расхода за интервал времени
    old_state = 1 -- флаг состояния индикатора на счетчике ("индикатора")
      -- Если Ваш датчик реагирует на вспышку индикатора единицей, то old_state = 0
    state = nil -- переменная текущего состояния индикатора


    Broker = "АДРЕС_ВАШЕГО_БРОКЕРА"
    port = ПОРТ_ВАШЕГО_БРОКЕРА
    myClient = "Ваш_Клиент"
    name = myClient
    pass = "Ваш_Пароль"
    publish = false -- регулируем возможность публикаций

    m = mqtt.Client(myClient, 180, name, pass)
    m:lwt("/lwt", myClient, 0, 0)

    --###########################
    --### Функция подключения ###
    --###   (спасибо ИгорюК)  ###
    --###########################
    function connecting()
        print('Проверка (переподключение)...')
        publish = false
        function getConnect()
           if (wifi.sta.status() == 5) and (wifi.sta.getip() ~= nil) then
                print("Есть Wi-Fi!")
                m:connect(Broker, port, 0, 0,
                    function(conn)
                        tmr.stop(6)
                        print("Подключено!")
                        publish = true
                    end)
            end
        end
        getConnect()
        tmr.alarm(6, 90000, 1, function()
            getConnect()
        end)
    end

    m:on("offline", function(con)
        connecting()
    end)

    --#########################
    --## Работа со счетчиком ##
    --#########################

    tmr.alarm(0,freq_sample,1,function() -- считываем состояние индикатора каждые ... миллисек
        state = gpio.read(pin) -- переменная текущего состояния индикатора

    -- Если индикатор горит и ранее не горел, то:
    -- Если Ваш датчик реагирует на вспышку индикатора единицей, то в следующей строке вместо "state == 0" пишем "state == 1"
    if state == 0 and state ~=old_state then -- если индикатор горит, но перед этим не горел, то
        period_rate = period_rate + (1/imp_KWt_hour) -- и увеличиваем значение расхода за интервал времени
        old_state = state -- сообщаем текущее состояние индикатора временной переменной

        -- Если Ваш датчик реагирует на вспышку индикатора единицей, то в следующей строке вместо "state == 1" пишем "state == 0"
    elseif state == 1 then -- если индикатор не горит, то
        old_state = state -- сообщаем текущее состояние индикатора временной переменной
    end
    end)

    tmr.alarm(1,period_time,1,function() -- отправка расхода энергии
        m:publish("/myhome/Mur_power_count1",period_rate,0,0) -- за период
    print("За период "..period_rate.." кВт")
        period_rate = 0 -- сбрасываем значения счетчика расхода за период
    end)

    connecting()
    Item:
    Код ( (Unknown Language)):
    Number    Mur_power_count    "Израсходовано [%.1f кВт•ч]"    <el_count> { mqtt="<[mosquitto:/myhome/Mur_power_count:state:default]" }
    Number    Mur_power_count1    "кВт•ч [%.5f кВт•ч]"    <el_count>  { mqtt="<[mosquitto:/myhome/Mur_power_count1:state:default]" }
    Number    Mur_power_count_set    "Счетчик [%.1f кВт•ч]"
    Number    Mur_power_count_a    "0ххххх,х [%d]"
    Number    Mur_power_count_b    "х0хххх,х [%d]"
    Number    Mur_power_count_c    "хх0ххх,х [%d]"
    Number    Mur_power_count_d    "ххх0хх,х [%d]"
    Number    Mur_power_count_e    "хххх0х,х [%d]"
    Number    Mur_power_count_f    "ххххх0,х [%d]"
    Number    Mur_power_count_g    "хххххх,0 [%.1f]"
    Switch    Mur_power_count_switch "Сброс"    <switch>
    Number    Mur_power_count_period    ""

    Sitemap:

    Код ( (Unknown Language)):
    Frame label="Электросчетчик"  {

    Group item=Mur_power_count icon="el_count" {
                Switch item=Mur_power_count_period mappings=[0="Ч", 1="Д", 2="Н", 3="2Н", 4="М", 5="2М", 6="4М", 7="Г"]      
                Chart item=Mur_power_count1 period=h refresh=60000 visibility=[Mur_power_count_period==0, Mur_power_count_period==Uninitialized]            
                Chart item=Mur_power_count1 period=d refresh=600000 visibility=[Mur_power_count_period==1]      
                Chart item=Mur_power_count1 period=W refresh=600000 visibility=[Mur_power_count_period==2]    
                Chart item=Mur_power_count1 period=2W refresh=6000000 visibility=[Mur_power_count_period==3]
                Chart item=Mur_power_count1 period=M refresh=60000000 visibility=[Mur_power_count_period==4]    
                Chart item=Mur_power_count1 period=2M refresh=600000000 visibility=[Mur_power_count_period==5]    
                Chart item=Mur_power_count1 period=4M refresh=600000000 visibility=[Mur_power_count_period==6]    
                Chart item=Mur_power_count1 period=Y refresh=600000000 visibility=[Mur_power_count_period==7]    
            Text item=Mur_power_count1 label="За минуту [%.5f кВт•ч]"
     
            Group label="Настройка" icon="settings"  {
                Text item=Mur_power_count_set      
                Setpoint item=Mur_power_count_a minValue=0 maxValue=900000 step=100000      
                Setpoint item=Mur_power_count_b minValue=0 maxValue=90000 step=10000      
                Setpoint item=Mur_power_count_c minValue=0 maxValue=9000 step=1000      
                Setpoint item=Mur_power_count_d minValue=0 maxValue=900 step=100      
                Setpoint item=Mur_power_count_e minValue=0 maxValue=90 step=10      
                Setpoint item=Mur_power_count_f minValue=0 maxValue=9 step=1      
                Setpoint item=Mur_power_count_g minValue=0 maxValue=0.9 step=0.1
                Switch item=Mur_power_count_switch icon="crosscircle"
            }
            }    
        }
     

    Rules:

    Код (C++):
    rule "Mur_power_count corrective"
    when
        Item Mur_power_count_a changed or
        Item Mur_power_count_b changed or
        Item Mur_power_count_c changed or
        Item Mur_power_count_d changed or
        Item Mur_power_count_e changed or
        Item Mur_power_count_f changed or
        Item Mur_power_count_g changed
    then
        var Number a = Mur_power_count_a.state
        var Number b = Mur_power_count_b.state
        var Number c = Mur_power_count_c.state
        var Number d = Mur_power_count_d.state
        var Number e = Mur_power_count_e.state
        var Number f = Mur_power_count_f.state
        var Number g = Mur_power_count_g.state
        var Number count_set = a + b + c + d + e + f + g ;
        postUpdate(Mur_power_count_set, count_set)
        postUpdate(Mur_power_count, count_set)
    end


    rule "Mur_power_count reset"
    when
        Item Mur_power_count_switch received command
    then
        if(receivedCommand==ON)
        postUpdate(Mur_power_count_a, 0)
        postUpdate(Mur_power_count_b, 0)
        postUpdate(Mur_power_count_c, 0)
        postUpdate(Mur_power_count_d, 0)
        postUpdate(Mur_power_count_e, 0)
        postUpdate(Mur_power_count_f, 0)
        postUpdate(Mur_power_count_g, 0.0)
        postUpdate(Mur_power_count_switch, OFF)
    end


    rule "Mur_power_count Update"
    when
      Item Mur_power_count1 received update
    then
        var Number Power_count_old = Mur_power_count.state
        var Number Power_count_new = Mur_power_count1.state
        var Number Power_count = Power_count_old + Power_count_new ;
        postUpdate(Mur_power_count, Power_count)
    end
     
     

    Вложения:

    Последнее редактирование: 3 дек 2016
    ИгорьК нравится это.