dontsovcmc / waterius

Передача показаний воды по Wi-Fi. Watermeter Wi-Fi transmitter.
https://waterius.ru
GNU Lesser General Public License v3.0
555 stars 109 forks source link

Завышение показаний #200

Closed svpcom closed 1 year ago

svpcom commented 2 years ago

счетчики VLF-15U-I (ХВС и ГВС), подключены как сухой контакт (не НАМУР) Замечено, что переодически добаляются лишние импульсы. Общее время работы - около месяца. За первые две недели по ХВС была ошибка порядка +2 м3 После синхронизации (выставления точных значение через web ui) две недели назад: расход ГВС - 3.04, ХВС- 5.91 показания waterius'а : 5.914, 9.648 показания счетчиков: 5.853, 9.377 соотв. ошибки: +2%, +4.6%

дамп mqtt:

flat/water/ch0 5.914
flat/water/ch1 9.648
flat/water/delta0 90
flat/water/delta1 240
flat/water/voltage 3.060
flat/water/resets 3
flat/water/model 0
flat/water/boot 1
flat/water/good 1
flat/water/imp0 315
flat/water/imp1 615
flat/water/version 22
flat/water/version_esp 0.10.3
flat/water/voltage_low 0
flat/water/voltage_diff 0.008
flat/water/f1 10
flat/water/f0 10
flat/water/rssi -55
flat/water/waketime 5038
flat/water/setuptime 118004
flat/water/adc0 106
flat/water/adc1 106
flat/water/period_min 1440

это влияние помех, дребезг контактов в герконе или что-то еще?

dontsovcmc commented 2 years ago

Я видел большое завышение, если провода не зажаты в клеммниках - т.е. вытащатся, если потянуть с небольшим усилием или в пыли - тоже будет контакт плохой. Иногда бывает брак счетчиков с двойным импульсом. Это можно попробовать отловить прозвонкой, включив тонкой струйкой воду. Может партия бракованная, раз они оба врут. К Valtec не было претензий... Проверьте контакты и отпишите!

svpcom commented 2 years ago

Проблема в том, что при испытаниях (что тестером, что waterius'ом) путем открывания крана все работает - счетчики честно выдают 1 импульс на 10 литров при одном и том же положении мадшего (литрового) разряда. У меня подозрения в том, что проблемы возникают при очень малом потреблении из-за дребезга контактов и/или когда счетчик останавливается на включенном герконе. (У меня есть обратноосмотический фильтр воды, который умеет как раз давать такое микропотребление для ХВС). Возможно нужно ставить на входе конденсатор, который будет заряжаться через резистор и триггер шмидта, который будет срабатывать от разных уровней напряжения на этом конденсаторе чтобы отфильтровать дребезг контактов. https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B8%D0%B3%D0%B3%D0%B5%D1%80_%D0%A8%D0%BC%D0%B8%D1%82%D1%82%D0%B0#/media/%D0%A4%D0%B0%D0%B9%D0%BB:TS_contact_bounce_filter.svg

svpcom commented 2 years ago

Контакты я естественно проверял - они облужены и крепко зажаты в клемник

dontsovcmc commented 2 years ago

У Ватериуса софтовое устранение дребезка - для него импульс - это замыкание + 750 мс размыкание. https://github.com/dontsovcmc/waterius/blob/master/Attiny85/src/counter.h#L70

svpcom commented 2 years ago

Переключил счетчики в режим НАМУР - посмотрим, поможет ли, что на входе не будет висеть длинный провод, при разомкнутом герконе

svpcom commented 2 years ago

А как устроена подтяжка входов к питанию - через втроенные резисторы attiny? Они всегда включены или включаются только при выходе контроллера из сна? Если включаются, то есть ли задержка считывания значение входа, позволяющая входу зарядится (имеется ввиду, что длинные провода могут иметь емкость, которая через слабый резистор подтяжки может заряжаться ненулевое время). Я не специалист по AVR, но вот например в stm32f1 у ADC есть настройка времени конверсии которое можно увеличить если вход имеет большое внутренне сопротивление, чтобы внутренние конденсаторы ADC успели от него зарядиться. Как это устроено у AVR?

svpcom commented 2 years ago

@dontsovcmc По даташиту attiny сопротивление внутреннего подтягивающего резистора нахожится в пределах 20 - 50 кОм, в то время как ADC требует выход с сопротивлением не более 10 кОм https://electronics.stackexchange.com/questions/107741/required-output-impedance-for-adc-input. https://github.com/dontsovcmc/waterius/blob/1816e56ca21b2f08f4d675c4b5dc35241a237dc2/Attiny85/src/counter.h#L53 Мне кажется, что тут надо после включения подтягивающего резистора поставить некоторую задержку и потом в цикле проверят значение adc, пока оно не стабилизируется

dontsovcmc commented 2 years ago

@svpcom Cпасибо за матчасть, любопытно, что раньше не думали про это. Не уверен, что это является причиной завышения у вас показаний - ведь достаточно много счетчиков valtec работают практически без погрешности. У вас прям сильно большая погрешность. А есть возможность обновить прошивку и протестировать с новым кодом adc? Можно digitalRead сделать и тоже проверить. Вопрос - у нас же analogRead очень частый - успевает ли конденсатор разрядится? Насколько актуальна эта задержка в нашем случае.

svpcom commented 2 years ago

В прошивке один ADC переключается между двумя входами. Возможно проблема есть, когда один вход в "0", а другой "1" . Холодная вода как раз на втором входе и возможно ADC не хватало времени перезарядить конденсатор с 0 до 1 и код считал это завершением импульса. Но это только мое преположение.

Я обновил прошивку - за пару дней пока лишних импульсов не набежало. Подожду неделю - две и будет видно - помогло или нет

svpcom commented 2 years ago

А какая обычно погрешность подсчета - то есть сколько лишних или недостающих импульсов получается по отношению в общему показанию счетчика при длительном сроке изменени (недели/месяцы)?

dontsovcmc commented 2 years ago

Я встречал у кого 0% была через год. У меня самого где то 5 импульсов за полгода. Опрос не проводили среди пользователей =(.

dontsovcmc commented 2 years ago

@svpcom "Возможно проблема есть, когда один вход в "0", а другой "1" " - Любопытная гипотеза! Пошёл за попкорном, что получится. Но картина у всех пользователей схожая...

dontsovcmc commented 2 years ago

@svpcom как успехи тестирования?

svpcom commented 2 years ago

Провел испытания: Новые показания счетчиков: хвс: 11.477, гвс: 7.405 waterius: хвс: 11.777, гвс: 7.484

погрешность хвс: (11.777 - 11.477) / (11.477 - 9.377) = 14.2 % погрешность гвс: (7.484 - 7.405) / (7.484 - 5.914) = 5%

судя по тому, что показания всегда завышаются, то где-то не компенсируется дребезг контактов. Также так как гвс опрашивается первым (ch0), то возможно взаимное влияние их друг на друга. Я думаю, что надо поправить процедуру проверки импульса - добавить условие, что начало импульса это не любое замыкание контактов, а только то, что длится более некоторого количества времени (как это сделано с размыканием)

svpcom commented 2 years ago

@dontsovcmc А в чем смысл замены attiny85 на attiny45? Это привело к тому, что сейчас осталось всего свободно 44 байта для нового кода.

dontsovcmc commented 2 years ago

@dontsovcmc А в чем смысл замены attiny85 на attiny45? Это привело к тому, что сейчас осталось всего свободно 44 байта для нового кода.

В мире кризис микроконтроллеров, поэтому чем больше выбор, тем проще найти их у поставщиков =).

svpcom commented 2 years ago

@dontsovcmc Поправил pull-request. Теперь вроде точно все считает

dontsovcmc commented 2 years ago

@svpcom обнаружил 2-х пользователей у кого 1л/имп и пропускают показания. при 1л/имп очень быстро проходит импульс.

define TRIES_OPEN 24 - не подойдёт =(.

ощущение, что нужно на прерывания переходить + проверка дребезга. что думаете?

svpcom commented 2 years ago

@dontsovcmc Мне кажется тут надо ставить внешнюю подтяжку и включать ее полевым транзистором по команде с МК (когда он просывается). Но тут потребуется другой МК, так как у attiny ноги уже закончились. Без нее namur помехоустойчиво не получится считать. Ну и придется сделать в прошивке выбор типа счетчика: namur/dry contacts и 1/10 литров на импульс для выбора допустимых границ напряжений и задержек. Так как без этого точно считать не получится. Вообще я бы перешел с attiny на stm32f0/f1 - там памяти сильно больше, сильно лучше переферия и его можно удаленно препрошивать через загрузчик.

dontsovcmc commented 2 years ago

@svpcom namur/dry тоже можно автоматически + ручной ввод сделать, по уровню во время настройки... наверно мне стоит собрать статистику по корректности показаний у кого Намур и тогда можно сделать вывод о необходимости в этом. А помехоустойчивость хардварно не улучшить? (кроме внешней подтяжки) Еще есть вариант перейти на OneWire.... )

svpcom commented 2 years ago

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

dontsovcmc commented 2 years ago

@svpcom Подтяжка, кстати 30к где-то. Геркон даёт 110 при замыкании (а там 3к3 резистор стоит).

OneWire между attiny и esp.

А шумы будут при герконе или намуре?

neitri commented 2 years ago

Мне кажется алгоритм "анти дребезга" несколько не правильный. Когда напряжение падает ниже уровня LIMIT_CLOSED или LIMIT_NAMUR_CLOSED на время одного цикла счета. Инициируется таймер значением 3. Возрастании напряжения на входе. В течении 3 циклов считает таймер и по истечению времени увеличивает счетчик. На мой взгляд отсутствует гистерезис. Меньше 170 контакт замкнут, А больше 170 уже инициируем счетчик и ждем подсчета импульсов. детектор разомкнутого состояния должен быть несколько иной. Разомкнут если больше LIMIT_OPEN ( 800) иначе если больше LIMIT_NAMUR_OPEN (допустим 400) разомкнут намур. Сам же подсчет импульсов можно отвязать от статусов и если напряжение меньше LIMIT_NAMUR_CLOSED (200) считаем таймер анти дребезга. А если напряжение больше LIMIT_NAMUR_OPEN (400) взводим таймер.

dontsovcmc commented 2 years ago

@dontsovcmc По даташиту attiny сопротивление внутреннего подтягивающего резистора нахожится в пределах 20 - 50 кОм, в то время как ADC требует выход с сопротивлением не более 10 кОм https://electronics.stackexchange.com/questions/107741/required-output-impedance-for-adc-input.

https://github.com/dontsovcmc/waterius/blob/1816e56ca21b2f08f4d675c4b5dc35241a237dc2/Attiny85/src/counter.h#L53

Мне кажется, что тут надо после включения подтягивающего резистора поставить некоторую задержку и потом в цикле проверят значение adc, пока оно не стабилизируется

Занялся адпейдом прошивки и внимательнее изучил вопрос. Не хочется мне "с запасом" добавлять 1мс, т.к. там потребление 800мкА, что дает в сутки эквивалент 350мА*1сек. По ссылке: With R = 100 kΩ and C = 14 pF, the RC time constant (TC) is 1.4 μsec. У нас 40кОм - 0.5 мкс. Т.е. 1000мкс выглядят лишними. У вас есть возможность убрать эту задержку и проверить точность подсчета?

Далее я подумал вставить delayMicroseconds, но в файле обнаружил:

// for the 1 MHz internal clock (default settings for common AVR microcontrollers)
    // the overhead of the function calls is 14 (16) cycles
    if (us <= 16) return; //= 3 cycles, (4 when true)
    if (us <= 25) return; //= 3 cycles, (4 when true), (must be at least 25 if we want to subtract 22)

    // compensate for the time taken by the preceding and next commands (about 22 cycles)
    us -= 22; // = 2 cycles
    // the following loop takes 4 microseconds (4 cycles)
    // per iteration, so execute it us/4 times
    // us is at least 4, divided by 4 gives us 1 (no zero delay bug)
    us >>= 2; // us div 4, = 4 cycles

выходит что вход в функцию analogRead уже больше микросекунды.

кстати, любопытный вопрос: а не уменьшиться ли потребление, если attiny запускать на 8Мгц...

svpcom commented 2 years ago

Тут надо с осцилографом и генератором сигналов отлаживать. В теории analogRead() отрабатывает за 0.1ms.

svpcom commented 2 years ago

Возможности поменять прошивку сейчас у меня нет

svpcom commented 2 years ago

Мне кажется что фундаментальная проблема тут другая:

 // Возвращаем текущее состояние входа
    enum CounterState_e value2state(uint16_t value)
    {
        if (value < LIMIT_CLOSED) {
            return CounterState_e::CLOSE;
        } else if (value < LIMIT_NAMUR_CLOSED) {
            return CounterState_e::NAMUR_CLOSE;
        } else if (value < LIMIT_NAMUR_OPEN) {
            return CounterState_e::NAMUR_OPEN;
        } else {
            return CounterState_e::OPEN;
        }
    }

данная функция не имеет запрещенных состояний. То есть любое напряжение на входе конвертируется в состояние входа. Поидее ее надо переписать так:

так как иначе любая помеха начинает отсчитывать таймер

Мне кажется алгоритм "анти дребезга" несколько не правильный. Когда напряжение падает ниже уровня LIMIT_CLOSED или LIMIT_NAMUR_CLOSED на время одного цикла счета. Инициируется таймер значением 3. Возрастании напряжения на входе. В течении 3 циклов считает таймер и по истечению времени увеличивает счетчик. На мой взгляд отсутствует гистерезис. Меньше 170 контакт замкнут, А больше 170 уже инициируем счетчик и ждем подсчета импульсов. детектор разомкнутого состояния должен быть несколько иной. Разомкнут если больше LIMIT_OPEN ( 800) иначе если больше LIMIT_NAMUR_OPEN (допустим 400) разомкнут намур. Сам же подсчет импульсов можно отвязать от статусов и если напряжение меньше LIMIT_NAMUR_CLOSED (200) считаем таймер анти дребезга. А если напряжение больше LIMIT_NAMUR_OPEN (400) взводим таймер.

wrewolf commented 2 years ago

Подпишусь, у меня такая же проблема

dontsovcmc commented 1 year ago

Подпишусь, у меня такая же проблема

А какой марки у вас счетчики? Пока таких проблем больше не встречал. Но встречал счетчики с "двойными" импульсами — может как-то магнит там дефектно установлен.

dontsovcmc commented 1 year ago

Закрою задачу. Это какой-то редкий кейс. Да, в ветке universal код теперь есть возможность по изменению уровня считать импульсы. Может в вашем случае это подойдет?

wrewolf commented 1 year ago

Я как раз 2 недели как обновил прошивку, наблюдаю

dontsovcmc commented 1 year ago

Я как раз 2 недели как обновил прошивку, наблюдаю

в dev/master старый код. не должно быть никакой разницы. а у вас какой чип attiny? 45 или 85?

wrewolf commented 1 year ago

У меня 45, а прошивка была 0.10.5

Сейчас version: 25 version_esp: 0.11.3