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

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

  1. ИгорьК

    ИгорьК Гуру

    Сглаживание данных, которые "болтает" по сути явления. Датчики влажности когда больше 90%, прерывистый ветер...
    Суть - усредняются последние N значений. N можно устанавливать.
     
  2. alp69

    alp69 Форумчанин

    Где? Есть мануал? Или примеры?
     
  3. ИгорьК

    ИгорьК Гуру

    Explorer... он и есть Explorer. Хорошо что он есть, но все комментарии нужно удалять когда гонишь код.
     
  4. ИгорьК

    ИгорьК Гуру

    Раскомментируйте 3 и 4 строчку и устанавливайте N.
    Код (Javascript):
    size = 20 -- размер буфера. Можно без этой и следующей строк.
    aver.bufsize(size) -- установить размер буфера, не обязательно. 10 по умолчанию
     
     
  5. alp69

    alp69 Форумчанин

    А я все пилю перезагрузчик роутера. Пока в тесте. Шлифую. Наверное на следующей неделе покажу. Логика несколько иная, но основной упор сделан на устойчивость коннекта при различных вариантах дисконнекта.
    Дело в том, что в некоторых имеющихся в теме примерах, содержащих enduser_setup() нашел "дырку", при попадании в которую модуль самостоятельно к брокеру уже не сможет подключиться никогда. Это касается не только перезагрузчика. И ситуация может стать патовой, если до модуля не добраться (забыл где он, вмуровали в стену, и т.д.).
    Это не связано с качеством кода. Скорее в алгоритме просто эта "дырка" не учтена. Тем не менее я в нее попал при тесте прототипа.
     
    Последнее редактирование: 28 фев 2017
  6. alp69

    alp69 Форумчанин

    Ясности не добавилось, но хвостик есть - дальше сам распутаю ;)
     
  7. ИгорьК

    ИгорьК Гуру

    хм... я месяц минимум тестировал. Или больше. :(
     
  8. ИгорьК

    ИгорьК Гуру

    Суть. Постоянно берутся последние N данных и усредняются. Все просто.
     
    alp69 нравится это.
  9. alp69

    alp69 Форумчанин

    Забыл уточнить. Это касается использования enduser_setup(). Т.к. Вы не сторонник этого - грусть отменяется! :)
     
  10. alp69

    alp69 Форумчанин

    Поправил пост, относительно уточнения по enduser_setup.
    Это важно. Т.к. enduser_setup часто впихивают в модули, о которых планируетя "забыть".
     
  11. ИгорьК

    ИгорьК Гуру

    У меня две сети на даче. Одна слишком не устойчивая, чтобы пытаться дублировать соединение. Тем не менее, я бы посмотрел в эту строну, чем в странное "enduser setup". Единственное, где реализовал enduser_setup - датчик СО2 - его иногда просят знакомые.
     
  12. alp69

    alp69 Форумчанин

    Пока не буду вдаваться в суть моего кода. Пока он в тесте. Вас он вряд ли удивит, но пообсуждать, надеюсь, будет что. Последний месяц посвящен именно устойчивости соединения и автономному принятию решения в отсутствие хозяина.
     
  13. SergeiL

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

    Штука полезная! Тоже пользуюсь циклическими буферами для усреднения информации от датчиков, и АЦП.
    С усреднением, измеряемые значения, по крайней мере, не прыгают по причине ошибок преобразования.
     
  14. ИгорьК

    ИгорьК Гуру

    Все никак фильтр Калмана на сделаю. Тоже полезная штука.
     
    Последнее редактирование: 28 фев 2017
  15. ИгорьК

    ИгорьК Гуру

    51. Фильтр Калмана.
    Присвоить коду название kalmanm.lua
    Код (Lua):
    local M = {}
    M.Pc = 0.0
    M.G = 0.0
    M.P = 1.0
    M.Xp = 0.0
    M.Zp = 0.0
    M.Xe = 0.0
    M.variance = 0
    M.varProcess = 0

    M.set = function(variance, varProcess)
        M.variance = variance or 1.12184278324081/100000
        M.varProcess = varProcess or 1/100000000
        print("variance = ", M.variance)
        print("varProcess = ", M.varProcess)
    end

    M.update = function(vol)
        M.Pc = M.P + M.varProcess
        M.G = M.Pc/(M.Pc + M.variance)
        M.P = (1-M.G)*M.Pc
        M.Xp = M.Xe
        M.Zp = M.Xp
        M.Xe = M.G*(vol-M.Zp) + M.Xp
        return M.Xe
    end

    return M

    Применять так:
    Код (Lua):
    do
    local data -- Это данные
    local kdata -- Это отфильтрованнные данные
    av = require("kalmanm")
    av.set()
    -- или av.set(variance, varProcess) -- читаем wiki
    tmr.alarm(0, 3000, 1, function()
        data = math.random(10) -- добываем данные как умеем
        print("Got data = ", data)
        kdata = av.update(data) -- фильтруем данные
        print("Kalman Data = ", kdata)
    end)
    end
    Выход:
    kalman.jpg
    Как видно, поскольку рандом установлен в пределах 10, отфильтрованное значение держится посредине - около 5.

    А также см. пример.

    А также для нескольких потоков.
     
    Последнее редактирование: 1 мар 2017
  16. SergeiL

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

    Я тут тоже, в процессе создания дачного контроллера для мониторинга и управления питанием устройств от двух аккумуляторных батарей, озадачился вопросом надежности восстановления соединения с брокером находящимся дома. Как выяснилось, Leonardo ETH, иногда, по крайней мере после загрузки кода через USB, может перестать подключаться по IP. После выключения / включения питания все начинает работать, и работает нормально неделями, при этом, возможны отключения / подключения Ethernet. Причина - в момент загрузки данных по USB, chip W5500 может схватить произвольные данные от ATmega. А вход ресет от W5500 не заведен на выходы ATmega. Он заведен только на общий аппаратный Reset, параллельный Reset на ATmega.
    Поэтому помогает: либо нажать кнопку Reset, либо отключить/включить питание, либо подать "0" на вход Reset платы.

    Вот я и озадачился внешним WatchDog-ом.

    После изучения ассортимента готовых WatchDog-ов, не нашел ничего, с таймаутом до сброса в районе 20-30 секунд. Стандарт - 1,6 сек. Это не подходит по причине долгой заливки ПО в Arduino IDE.
    От таймера 555 отказался по причине большого кол-ва элементов обвязки.

    В общем, внешний WatchDog был сделан на ATtiny13.
    (контроллер 8 ног, из них задействовано 5: питание, земля, вход импульсов от Leonardo ETH, выход на ресет Leonardo ETH и дополнительно, выход на реле, отключающее питание Leonardo ETH на 10 секунд - это перебор, но уж по максимум :) ).

    Алгоритм - простейший: Если импульсы 0/1/0 не поступают на вход более 25 секунд, на выходе формируется нулевой импульс, продолжительностью 0,5 сек. Так повторяется 5 раз, потом реле включается на 20 секунд, отключая питание с Leonardo ETH через НЗ контакты реле.

    Программу для ATtiny13 писал на Си для ICCAVR v7.20, заливал через AVRISP mkII, если кому-то нужно - выложу.
     
    ИгорьК нравится это.
  17. ИгорьК

    ИгорьК Гуру

    Здесь устройство мониторит WiFi и ping и перегружает с разной степенью интенсивности роутер и модем.
    Я уже как-то сильно убежал от ардуино разных мастей...
    http://bit.ly/2jkrQGk
    А то что на esp-8266 и iskra js как-то и не зависает.
     
    Последнее редактирование: 28 фев 2017
  18. SergeiL

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

    Это понятно, просто иногда подвисает чип, так сказать "встроенного Ethernet шилда", и попытки перезапуска роутера уже не помогают. Приходится перезапустить "себя", причем аппаратно. Что и делаю, программно заблокировав выдачу импульсов на внешний watchdog из контроллера.
    Leonardo ETH - это потому, что WiFi в бетонный подвал не добивает, LAN все равно приходит на видео регистратор, требуется 4 аналоговых входа на два 12В аккумулятора. Два на напряжение, два на ток через датчик тока ACS712. Плюс выходы на управление на реле, включая реле управляющее питанием LTE роутера.
     
    ИгорьК нравится это.
  19. ИгорьК

    ИгорьК Гуру

    WiFi в подвал не идёт, точно. Идёт 433 МГЦ - HC-12.
     
  20. ИгорьК

    ИгорьК Гуру

    Два фильтра работают вместе:
    Код (Lua):
    do
    aver = require("buffm") -- инициируем кольцевой буфер
    size = 20 -- размер кольцевого буфера
    aver.bufsize(size) -- установить размер буфера, не обязательно. 10 по умолчанию

    av = require("kalmanm") -- инициируем фильтр Калмана
    av.set() -- установки по умолчанию

    tmr.alarm(0, 3000, 1, function()
        local data = math.random(10) -- Добыли данные
        print("Got = "..data)
        local avr = aver.add(data) -- кольцевой фильтр
        local kdata = av.update(data) -- фильтр Калмана
        kdata = string.format("%.2f", kdata)
        avr =  string.format("%.2f", avr)
        print("Filtered = "..avr, "  Kalman = "..kdata)

    end)
    end
    circandkalmn.jpg