WB-MSW v3: Провал показаний температуры (остальные показания не пропадают)

А вот за это - наша благодарность. Да, такой момент тоже нужно описать, возможно нам кажется это очевидным и “глаз замыливается”.

Так модуль первые две секунды после включения ждет в загрузчике.
Ну и процедура описана https://wirenboard.com/wiki/

Такс. Запустил первый тест: беру температуру из регистра 0 и отдаю её на график синей линией без обработки (делю на 10, и всё). Ждём пару часов, чтобы график заполнился - и отпишусь тут.
Пойду жечь вонилки, чтобы измучить VOC.

Про загрузчик и про обновление прошивки прочитал. ЭТО СТРАШНО! И МУТНО. Везде какие-то ужасные командные строки, прошивка тулзой из командной строки… ужасть!

Про инструкции. Да, пишите. Правда, ну посмотрите на то, какие инструкции у ОВЕНа. Они тоже российская фирма, тоже сами всё разрабатывают. И вот их можно взять за образец. Вот например от модуля IO (https://owen.ru/product/moduli_diskretnogo_vvoda_s_interfejsom_rs_485/documentation_and_software) инструкция: https://owen.ru/uploads/215/re_mv110-x.16d_dn__m01__1-ru-34143-1.16_a4.pdf - там показано и как крепить, и как провода подключать, и как клеммную колодку снимать, и вся инфа про ModBus собрана разом. Скачал - распечатал - пользуешься. Удобно же. Или даже в ERP-CRM систему этот файл с инструкцией прицепил, и он там всегда лежит (у меня так).

А вот картинка с их сайта, где показан монтаж их датчика. Нарисована даже неказисто, но понятно:


Обратите внимание, что на картинке даже показаны ВИТЫЕ пары. Скрученные. Вот так надо делать!

3 лайка

Итак, беглые результаты первого теста, потому что по ним кое-что видно.


Смотрим на график температур. На нём показано вот что:

  • Зелёная линия = температура с регистра #4, которая проваливается, зато более точная (х100)
  • Тёмно-синяя линия = температура с регистра #0, который якобы стандартный для всех датчиков. К ней прибавлено +15, чтобы она НЕ накладывалась на зелёную линию и было видно, какое из значений пропадает. Значение БЕЗ фильтрации. Если будет 0 или 0xFFFF, то график так и улетит в ноль или в небеса.
  • Тонкая фиолетовая линия внизу = просто число, которое записано так: если не было отвала связи с модулем или ошибок ModBus - то выставить в 10. Если была хоть одна ошибка - выставить в 45. То есть, если линия будет прыгать (как в начале графика - это я значения перепутал, пока тестил), то будем видеть что были отвалы связи с датчиком.
  • Тёмно-красная линия = Всё те же показания с ОВЕНского датчика, который висит на том же канале связи.

ИТОГО, что видно:

  • Глючат только зелёные показания;
  • Отвала или ошибок ModBus НЕТ (фиолетовая линия как была ровная внизу, так и не подскакивала);
  • Эта хрень непонятно как зависит от VOC. А может и не зависит. Пики VOC/CO2/Влажности - это я надышал на датчики специально. Но это было в районе 1ч45мин по времени графика, а глюкалово было раньше - от 1ч30мин до 1ч45мин.

Ну и - ДА, датчик, блин, ТОРМОЗНОЙ в плане активности, если вы (Wiren) действительно можете это подтвердить официально, а не строчкой про

То есть, я о чём? Опять должна быть ИНСТРУКЦИЯ, в которой будет сказано не только про монтаж, а про ограничения вида “минимальная частота запросов на чтение = хх мсек, на запись = yyy мсек”. А вот откуда я знаю, тормозит датчик или нет? Почему я про это узнаю на практике?
С временем запросов я ещё повеселюсь. Что мне тесты одного датчика, если их у меня будет 8? А если 32 (максимум интерфейса)?
Спрашиваю зло, да, прям в открытую. Вот датчик позиционируется как крутой, и с возможностью и диодами мигать, и ИК-команды посылать. Вот ща на объекте, про который я говорю (и заказчик читает эту тему), у нас будет 8 датчиков, пять из которых будут рулить пятью кондеями.
И как быть, если следовать тому, что можно прочитать на Wiki (я про витую пару, чёрт её побери, а не специальный кабель ModBus) и тому, что я тут услышал про скорость опроса?
Типа, заказчик ткнул кнопку в WEB-интерфейсе “Врубить кондей”, и через MM времени (ща рассчитаем) эта команда дошла до датчика?
Я могу ошибаться, но подсчитаю, беря синтетический пример (не считая других устройств на том же канале ModBus).
8 штук датчиков
Из-за кривой карты регистров уложиться в один запрос на чтение всего и на один запрос на запись всего мы не можем. Значит подсчитаем запросы, если всё-таки опрашивать по парочке соседних регистров, открывая карту:

    1. Чтение регистров 0-1 (худший случай, так как регистр 3 глючит);
    1. Чтение регистров 3-4-5 (шум, температура, влажность точные);
    1. Чтение регистров 8-9-10-11 (CO2, освещённость, VOC);
    1. Запись Coils 0 (пищалка);
    1. Запись Coils 10-11 (зелёный и красный диод, которые в карте перепутаны нахер);
    1. Запись Coils 5100-5180 (воспроизведение ИК-команд);
  • (иногда) 7. Запись Coils 5300-5380 (обучние ИК-команд).

Итого 6 штук запросов. Так как инфы о том, через сколько датчик надо опрашивать, нету, а оказывается что 100 мсек - это типа много, берём 500 мсек и 1 сек.
Далее мы знаем, что все устройства разом опросить нельзя, потому что в силу работы протокола ModBus Master может посылать запрос и получать ответ только от одного Slave в один момент времени.
Также мы знаем, что внутри ядра ПЛК обмен с одним устройством ModBus производится один раз за цикл программы, который я могу накрутить на 10-30 мсек. Берём 10 мсек, чтобы сделать идеальные условия.
Итак, получаем следующие данные для нашего мутного прикидочного расчёта:
Один датчик требует 6 штук запросов, интервал каждого из которых будет составлять 500 мсек или 1 секунду. То есть 6 х 0,5 сек = 3 сек, 6 х 1 сек = 6 сек на опрос ОДНОГО датчика.
Далее. Датчиков у нас 8 штук. Значит 3 сек х 8 = 24 сек или 6 сек х 8 = 40 сек.
Далее вспоминаем, что ядро ПЛК делает промежутки между опросами в 10 мсек на каждый датчик. То есть 10 х 8 = 80 мсек. Ну, это в ключе СЕКУНД не страшно.

И вот вопрос. Он не провокационный, а зло ироничный. Что же это за такой продукт, который не получится использовать так, как он задуман? Вот реально, подумайте, если следовать устным рекомендациям типа “что-то 100 мсек дофига, датчик тормозит”, то получается что из-за кучи запросов моя команда включения кондея дойдёт до датчика через 24 или 40 секунд, что ли?

А теперь вспомним, что на этой линии у меня ещё и 11 термостатов тёплых полов. Которые, правда, не тормозят и которые я гонял аж на 10 мсек ради прикола (отдельно, в тепличных условиях - и он не отваливался).
Представим, что термостаты я опрашиваю раз в 100 мсек. Значит 11 х 0,1 сек = 1,1 секунда. Карллл!! Все мои термостаты опросятся за 1,1 секунду.

Блин. Это что? РЕАЛЬНО ваши датчики НЕЛЬЗЯ на 100 мсек гонять? а как же ИК-командами-то пользоваться? Что за фигня?

На практике: С момента нажатия кнопки
Screenshot from 2020-08-25 15-40-09
в меню, ну или отправки в mqtt команды проходит много меньше секунды до начала воспроизведения записанной ИК-команды.
Просто потому что все coil мы не пишем. Потребовалось записать - записали.

Реально каждый раз гонять все команды? То есть писать туда нули, поверх нулей? Но зачем? Это просто пустой трафик! То есть 80*(8+6) байт, плюс стоп-биты Это просто нагрев воздуха и занятие шины. Ну нелогично же. Не надо так.

Есть хорошая статья на хабре. Именно про скорость. Нельзя пытаться передать по шине больше чем она способна пропустить. Какое бы устройство не было. 9600 - это меньше 1200 байт/сек.
Если уж с одним устройством при холостой записи удалось занять всю ширину канала.

Но чтение температуры-влажности раз (и даже 5 раз) в секунду успешно работает. Проверил. Потому что запрос регистра (одного) занимает разумное время. Мне нужен один (два, три, пять) регистр - я их запрашиваю.

Опять же с точки зрения практики: ну нету потребности знать температуру даже раз в секунду.

Реально у нас работает на 10 мсек

В том-то и дело что если НЕ надо передавать команду, то и записывать “0” не нужно.
Это как (аналогия)

  • Петров!
  • Я!
  • Не нужен, свободен.
  • Сидоров!
  • Я!
  • Не нужен, свободен.
  • Васечкин, включи команду!
  • Есть!
  • Баранкин!
  • Я!
  • Не нужен, свободен.

…мать-перемать!
Первое. Я писал ВЫШЕ, что у меня сейчас ОДИН КАНАЛ RS-485. Одна. Штука. Канала. На канале всего два устройства. И сейчас пишется только три штуки Coiloв раз в 100 мсек.
Это что? Много? Прям вот офигеть как много?
Второе. Я считал худший случай. Когда мне надо использовать все 80 ИК-команд. На полную. Датчик же это может? Может. Почему я не могу?
Третье. Все эти рисуночки мне ни о чём не сказали. Мне нужны тесты на живой магистрали из, скажем, 20 штук штук таких датчиков. Вот на такой магистрали и надо замерять время реакции на разные команды по Coils.
Четвёртое. Зачем цеплять за температуру-то? Про температуру речь не идёт. Речь идёт, ещё раз, о следующем

  • Из-за идиотской карты регистров, про которую не подумали, применить один групповой запрос на запись и один групповой запрос на чтение не получается
  • Тормозит реакция датчика на работу по Coils. На другие вещи НЕ тормозит. Какого чёрта я нажимаю на кнопку, и мой бризер-кондей реагирует через 10 секунд-то?
  • В инструкции (а точнее, в неких Wiki) на датчик НЕ указана максимальная частота опроса.

Пятое. Что касается “статьи на хабре”. Она короткая. Я напишу потом позже свою и длиннее. И про все эти нюансы.
Шестое. Что касается других ядер. Опять же, в инструкции и Wiki НЕТ надписи “датчик корректно работает только с WirenBoard версии не ниже хх”. Значит я могу его пихать в любой ПЛК. Даже в такой, ядро которого по умолчанию пишет всё подряд.
Конечно же я могу сделать запись в Coils по запросу. Ща пойду и сделаю. И… грожу пальцем если и это будет тормозить - вот тогда мы и посмотрим, у кого какой ModBus.

Какое?

Почему бы не написать в документации следующие характеристики:

  • максимальное время ответа на команду чтения (для каждой функции 1-4, если отличается)
  • максимальное время ответа на команду записи (для каждой функции 5, 6, 15, 16, если отличается)
  • минимальный интервал между запросами к одному устройтсву (если есть)

и не только для датчиков MSW, а для всех modbus-устройств вашего производства?

Я согласен, что отправлять команды на запись нужно только при изменении состояния. Но знать эти характеристики было бы очень полезно, например, для выставления таймаутов, или при работе через собственное ПО без драйвера wb-mqtt-serial или вообще без контроллера WB.

1 лайк

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

Пока измерений и формального куска в документации нет, могу дать оценку:

  • максимальное время ответа на команду чтения или записи - ~10мс
  • к coil-ам, управляющим ИК, это не относится, там может быть и больше
  • минимального интервала между запросами нет
  • надо помнить, что по стандарту Modbus между любыми фреймами должно быть 3.5 байта тишины, а мы стандарт соблюдаем. Так что отправка ответа раньше 3.5 байт после запроса, или повторный запрос раньше, чем через 3.5 байта после ответа - это нарушение стандарта и наши датчики такое будут считать шумом и обрабатывать не будут.
2 лайка

Мы сейчас постараемся воспроизвести то, что вы написали, но это займёт какое-то время.

У меня есть смутное подозрение, что проблемы могут быть как раз из-за постоянной записи coil-ов связанных с ИК: они привязаны к аппаратно затратной операции чтения огромных кусков из флеша, они реализованы внутри отдельным образом, и в них никто никогда раньше не писал нули в цикле просто так.

Блин! Позвоните мне уже кто-то из WB. Мне хочется обмареить вас (справедливо) за ублюдочные программные косяки, а тут я не могу этого сделать. А мне ОЧЕНЬ хочется.
И я попробую, даже если меня забанят. Похер. Буду действовать жёстко, но без переходов на личность. Буду критиковать только стиль программирования.

Итак, эта вот херня подтверждается:

А теперь у меня вопрос. Все мы начинали с AtMega8 или PIC. И все мы писали в их EEPROM всякие штучки. И все мы помним, что операция чтения или записи из EEPROM ОЧЕНЬ затратная по времени. Настолько, мать её, затратная, что её обычно выносят в обработку по прерыванию, чтобы не рушить скорость основного цикла программы.
Нет понимания, куда я клоню? Я хотел завернуть что-то зло-ядовитое, но не вышло.
Поясняю на пальцах. Что будет, если мы будем постоянно нашу AtMega заставлять читать-писать EEPROM? Да она просто не будет успевать этого делать, пытаясь отдавать какие-то там байты из него. Но полностью операция никогда не завершится, потому что мы будем пихать всё новые запросы записи-чтения, которые будут заставлять всё начинаться с начала.
Так вот тут вы мне (как производители) описали ту же херовину. И я не могу не материться, правда. Я на чужом ресурсе, я ОЧЕНЬ стараюсь этого не делать. Но вот я же говорил? Говорил, что прежде чем что-то делать - ПОСОВЕТУЙТЕСЬ СО СПЕЦАМИ, вашу мать!!!
Я - не совсем спец в новых STM32, я не адский спец по МК. есть и другие люди. Но любой из них (если не говорить о поверхностных ардуинщиках), скажет вам, что такие жирные операции надо делать по принципу КОНЕЧНОГО АВТОМАТА!!! (мать его прародителя всех МК и жену его печатную плату)!!!
А все эти посылки “ой, а мы никогда не пробовали так писать и не думали про это” - это признак недоработанности алгоритмов.

Надо сделать конечный автомат флагов на выполнение команд. В сложном варианте - с очередью, в простом - без очереди. Который активирует команду по ФРОНТУ, мать его, а не по уровню!
Хотя, о чём мы говорим? Какого хера флеш вообще читается, если мы засылаем в Colis 0, по которому никакой IF не не должен даже доходить до операции чтения команды её посыла?

Короче, что надо:

  1. Битовый (или как удобно) флаг (глобальная переменная) с названием (условным) “IRBusy”, по которому смотрится: передаётся ли на ИК-излучатель какая-то команда или нет?
  2. Массив битовых флагов с названием “IRCommandsState” - текущие состояния работы команд (1 = надо выполнить, 0 = не надо);

Алгоритм должен по Colis ставить флаги, отслеживая как у нормальных людей - фронты. ФРОНТЫ, а не уровни!!! То есть, пробую расписать на словах:

  • Функция, которая смотрит полученные значения от Coils и сравнивает их с текущими в IRCommandsRequest. Если полученное значение по Coils отличается от сохранённого - то ОДИН РАЗ меняется значение флага в IRCommandsRequest.
    Этот момент можно доработать так как удобно. Можно даже настройку в регистре по ModBus сделать. Если мы хотим, чтобы команда бесконечно повторялась, пока по Colis не придёт 0 - то оставляем как есть. Если же хотим, чтобы команда выполнялась всегда один раз (даже если по Colis всегда торчит 1) - то добавляем ещё один массив флагов, где смотрим на выполненные команды. Если надо - могу расписать. Ща идею не сформировал, дописал по ходу.
  • Отдельная функция, которая сканит флаги IRCommandsRequest и спокойно, с её доступной скоростью определяет те команды, которые надо выполнить. В полрядке очереди.
  • Функция, которая выполняет одну команду, защищая сама себя от повторных вызовов флагом IRBusy. В начале она ставит этот флаг, в конце - скидывает. Она получает в качестве параметра банк (да хоть указатель на адрес) того, что надо передать.
    Пока флаг IRBusy установлен, никакие другие ИК-команды не должны работать.

То есть, нам надо сделать следующее: флаги команд на исполнение и флаги “команда уже исполняется” и “ИК занят”. И на них, на простых битовых фагах, построить логику, которая будет блочить бесконечную передачу команд по записи Colis по сто раз. То есть, чтобы вся фигня работала строго по фронтам и спадам: если Colis ОДИН раз перешли из 0 в 1 - передаём. Если Colis ОДИН раз перешли из 1 в 0 - перестали передавать. Для этого мы сравниваем их текущие и предыдущие значения через массивы флагов. А чтобы одновременно не выполнялось несколько команд - мы не даём работать нескольким вызовам передачи команды (и чтения флешки) одновременно.

Тут должна быть защита от дурака. Щас-то как себя датчик поведёт, если я возьму все 80 Colis и бахну в них 1? А? Ща проверю!!!
UPDATE: БУГАГАГА!! АХАХАХАХААААА!!! ДАТЧИК ЛЁГ В ДАУН СРАЗУ ЖЕ НАПРОЧЬ!!! Ура!! Мы нашли не баг, а кривые руки и кривые мозги в прошивке!!!
Обожаю это наивное программистское “Ну, тут никогда не может быть нулевой указатель”, “Да эта функция всегда будет получать параметр, не надо ничего сверять”. 0xDEADC0DE вам в глотку! =)) Вместе с 0xDEADBEEF!!

Видос ща будет. Кривой, с рук, но мы ж тестим! Да, если Colis писать по фронту - то становится веселее. Ура. Признали один грёбаный глюк. Офигеть.

Теперь, кстати, я жду признавания глюка провалов температуры в регистре

Вот вы кода не видели, причину проблем (если они есть) не знаете. А уже наделали выводов на три экрана. Естественно, мы знаем и про время операций работы с флешем (которая кстати не EEPROM в наших МК), и про конечные аквтоматы, и про флажочки. Странно думать, что можно сделать продукт такой сложности как WB-MSW v.3 и не столкнуться с такими базовыми вещами.

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

Хм, но ведь то же самое можно сказать и про алгоритм на ПЛК? Писать флаги по ФРОНТАМ, а не уровням, как у нормальных людей, чтобы экономить ценные ресурсы МК и пропускную способность шины.

Должна быть, если есть проблема - то исправим. Но, как вы наверное понимаете, не существует реальной задачи, где нужно слать 80 coil-ов с единичками, так что “защита от дурака” в этом случаке непонятно что и от кого должна защищать.

Напишите пожалуйста подробнее, что всё-таки произошло и что значит эта фраза. Может датчик терпеливо отправляет 80 ИК команд подряд по вашей команде?

Вот НЕ соглашусь. ЖЁСТКО не соглашусь. Разрабы, которые говорят “да никто никогда не будет писать сразу 80 команд” - это плохие разрабы. Просто ЖЕСТЬ какие плохие. Так делать НЕЛЬЗЯ, и это очень, это ужасно плохо. Прям настолько плохо, что если диалог будет и дальше идти в стиле “этого не должно случаться”, то его можно не продолжать. Либо просьба меня вывести на контакты главного разработчика, и я буду разговаривать уже с ним, а не с форумом.
Защита должна не давать работать командам передачи одновременно разом. Вот что будет, если я запишу 80 Coilов? Вот проглючило у меня цикл, например. Дурак я, плохо программу составил, просмотрел. Что? Датчик сбесится?
Выводы про код и программирование я сделал на основании той цитаты, которую получил - о том, что дескать даже при записи нулей в Coil выполняется чтение из флеша и это отжирает много времени. И от этого я офигел и начал ругаться, как сделал бы любой мало-мальский спец. На такие-то решения.
Если это не так - то просьба сначала нормально разбираться в происходядем, а потом уже отвечать здесь. Чтобы не получалось таких неприятностей, как с этим случаем.
Касательно “писать надо по фронтам” я могу ответить в таком же наивном стиле: “Да я как-то с 2016 года так писал, и ни разу не думал, что кому-то придёт в голову от этого тормозить”.
Если ответить серьёзно, то есть два способа записи, которые я применяю:
а) Запись для модулей IO внутри щита, где требуется максимум быстродействия. Я использую модули дискретного IO от ОВЕНа на 16 или 32 канала (целиком или все входы или все выходы), в которых модуль умеет отдавать ВСЕ свои каналы в одном (для 16ти) или двух (для 32х) регистрах. Поэтому у меня запрос на вечное чтение из модуля - это один или два регистра читать на 115 200.
Вечные чтения и записи мне в этом случае требуются для максимального быстродействия системы: значения с одного и того же модуля (тот самый регистр-битовая маска) разбираются на части и могут использоваться в нескольких задачах ПЛК одновременно. Писать по изменению тут нет смысла.
б) А вот все внешние интерфейсы у меня были те, которые не используют Coils. Я НИ РАЗУ В ЖИЗНИ до вашего датчика не писал Coils (потому что все, даже AliExpress, юзают регистры).
И в 99,9% случаев из внешних интерфейсов у меня было только чтение, а не запись. А уж читать постоянно (раз в 1-2 секунды) температуры - это-то и так должно быть циклично.
Я ясно пояснил свой опыт? Моё объяснение снимает вопросы на тему “писать надо по изменению”?

Значится, по фактам:

  1. Я не получил инфы, почему у меня температура из 3го регистра валится в нули, при этом связь и другая температура с регистра 0 не отваливаются. А меж тем это как было, так и продолжается.
  2. ЛЮБАЯ постоянная запись ЛЮБОГО значения в ЛЮБОЙ (не ИК) Coil работает с тормозами.
  3. Запись в Coilы ИК-команд нулей (какие нафиг попытки передать ИК-команды-то) отваливает датчик по ModBus напрочь. Он что-то успевает изредка ответить, а большее время не отвечает.
  4. Запись по фронту в Coil работает с задержкой около 1-2 секунды, которая обусловлена уже тем, что на шине ещё два несуществующих устройства, до которых ПЛК (с таймаутом 1-2 секунды) пытается достучаться.

Выложил видео. Вот прямая ссылка на мой хостинг как на файл: https://cs-cs.net/ExxChange/WBVideo.avi
Просьба кому надо видео скачать, так как через пару-тройку недель я его оттуда удалю. Сейчас на хостинге есть проблемы, поэтому если сразу ссыль не сработает, просьба попытаться несколько раз.

Это сайт техподдержки, он у нас принципиально публичный. Руковожу разработчиками прошивок лично я, так что уже никого позвать не получится :slight_smile: Придётся продолжать со мной и здесь.

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

Насколько я вижу по коду и истории в репозитории и трекере, осознанного решения про “никто не будет писать 80 coil-ов” мы не принимали. Если бы приняли, то сделали бы так, как вы написали: ограничили бы на уровне Modbus, внесли бы пометку в документацию.

Так что хорошие у нас разработчики, зря вы так.

В этом случае моя мотивация была следующая: воспроизвести у нас займёт не меньше дня, код посмотреть - ну тоже не сразу. Но из общих представлений об архитектуре наших прошивок, я могу сделать предположение о том, что можно проверить вам. Я об этом ровно так и написал - как о предположении. Мне кажется, что это достаточно полезно: вдруг у вас прямо сейчас есть 10 минут времени, чтобы этот рецепт проверить? Так вы получите работающую систему гораздо раньше, чем если будете ждать, пока мы всё воспроизведём, разберёмся и напишем идеально проверенный рецепт.

С чтениями - да, тут всё логично: цикл опроса. Но как связано быстродействие и запись coil-ов в каждом цикле опроса, даже если они не менялись?

У нас исторически немного другое отношение: модулей быстрого параллельного вывода у нас нет (мы ограничены временем срабатывания реле например), тем более такого нет в датчиках. Задачи с быстрым параллельным выводом, по нашему опыту, тоже бывают исключительно редко. И мы сами, и большинство заказчиков делают запись coil-ов именно по событиям, т.е. вклиниваются в цикл чтения параметров с командой записи какого-то одного coil-а, когда нужно. Логика в ПЛК там ровно такая, как вы выше описали для ИК: флажки, автоматы и т.д.

И это печально, как мне кажется. Есть прекрасный инструмент в стандарте, все возможные ПЛК и софт его поддерживают, но вместо этого разработчики оборудования не могут дочитать стандарт дальше третьей страницы и пытаются эмулировать coil-ы и discrete-ы поверх регистров хранения.

Сейчас пытаемся воспроизвести у себя, пока не получается. Я правильно понимаю, что это чтение именно нуля (0x0000) из регистра температуры?

Это пока даже начать воспроизвести не можем. Тормоза - это что? Устройство не отвечает на очередную команду записи? Или устройство отвечает с задержкой?

Т.к. у нас нет под рукой ПЛК конкурентов, да и вашей программы тоже нет, то нам это сложно угадать. Очень поможет, если вы сделайте какой-то минимальный пример, воспроизводящий проблему.

Это уже более понятно. Датчик не отвечает на сами команды записи coil-ов?

Ну это, кажется, с нами вообще никак не связано.

Я вот сейчас смотрю видео, у меня есть вопросы:

  • вы можете просто отключить вообще совсем опрос отсутствующих устройств в Codesys и посмотреть, как будет пищалка работать?

  • зачем там везде таймауты по 1000мс? Для наших устройств 20-100мс достаточно, в зависимости от того, как Codesys считает таймаут.

  • время в 100/500мс - это что значит и как соотносится с общей периодичностью задачи в 30мс? Вы уверены, что рантайм Codesys в этом случае вызывает запись действительно каждые 500мс, или это умножается на количество параметров или устройств?

  • есть какая-то в Codesys отладка на уровне Modbus? Т.е. можете ли вы увидеть, что именно и когда отправляет рантайм Codesys-а, какие ответы приходят и какие не приходят?

    В видео вы ориентируетесь на “красный треугольничек в кодесисе”, но нам это мало что говорит, к сожалению.

    В части про запись по фронтам тоже слышно, что пищалка не выключилась. Но что это было на уровне Modbus мне не понятно: Codesys не отправил команду? Отправил, но в ответ пришла ошибка? Отправил, но ничего не получил в ответ?

    Если рантайм делает запись по фронту, но игнорирует ошибку и не пытается повторить запись - то это какое-то странное поведение рантайма. В таком случае лучше действительно в Codesys использовать постоянную запись, потому что мы-то прошивку исправим, если в ней проблема, но что будет, если там помеха по линии прилетит?

Дело (еще) в том что это поведение документировано но для непустых банков команд

Как и в случае работы с регистрами постоянного хранения, в каждый момент времени можно выполнять только одну операцию только над одним сигналом. Так как во время выполнения любой операции в один из регистров флагов ставится 1, а после завершения операции туда же ставится 0, в каждый момент времени среди всех регистров флагов, относящихся к ИК-приёмопередатчику, только один регистр может быть установлен в единицу. Попытка записи 1 в регистры флагов, связанных с ИК, при уже имеющейся единице приведёт к ошибке BUSY
Но для пустых - сейчас проверяю.

Такс. Я сейчас вырубил опрос всех лишних устройств и апгрейдил свой график. Набираю 5 часов. Вот завтра по утру выложу всё сюда, чтобы было ясно, что там с регистром температуры.
И завтра же будем мутить тесты с Coils на CodeSys. Сделаю я пример, где буду дёргать один Coil на одной линии постоянной записью. И его же, потом, записью по фронтам.

Про CodeSys и их работу с ModBus. Кратко так:

  • ПЛК многозадачен. Многозадачность - вытесняющая. Каждая задача имеет своё время, через которое ПЛК её вызывает и даёт ей процессорное время. Задача должна выполняться за время меньшее, чем интервал вызова в ПЛК.
    Например, мне нужна задача опроса кнопок. Самая быстрая. Я могу её вызывать раз в 30 мсек. А другую задачу регулирования радиаторов отопления по температуре в комнате с датчиков, могу вообще раз в минуту вызывать.
  • Работа с ModBus в данном ядре может или привязываться к какой-то конкретной задаче (могу сказать “Вот этот канал опрашивай с таким же временем, как и эта задача крутится”), или привязываться к тем задачам, которые используют переменные с устройство этого канала (лайтовый вариант: мы в одной из задач строим график, используя данные с датчика - ПЛК будет читать эти данные в этой же задаче вывода на экран).
    Если никто ничего не назначил специально (то, к какой задаче привязать опрос), то по умолчанию используется самая быстрая задача.
  • В пределах одного вызова задачи опрашивается одно устройство и все его параметры разом, если позволяет канал.

Итого получается так: каждый вызов задачи ПЛК (к которой привязан канал ModBus) вызывает опрос одного устройства подряд в цикле (1-2-3-1-2-3 и так далее для трёх устройств).
Те времена, которые можно задать для опроса переменных, нужны для того, чтобы сделать запросы к ним реже, чем вызывается задача опроса. То есть:

  • Если задача опроса работает раз в 10 мсек, а мы выставили время опроса регистра раз в 500 мсек - то он так раз в 500 мсек и будет опрашиваться. В остальное время задача опроса будет вызываться, но ничего не делать и трафика по шине не создавать;
  • Если задача опроса работает раз в 100 мсек, а мы (дураки) поставил опрос регистра раз в 20 мсек - то это ошибка, и ничего работать не будет, так как вызовы задачи будут реже, чем время опроса регистра.

В нашем случае нам надо знать то, что на время работы самой задачи наплевать, потому что я всегда использую первый случай: задача вызывается чаще (10-30 мсек), чем опрос регистров канала (15-1000 мсек для разных переменных).
И для нашего случая возможны такие ситуации:
а) Все переменные опрашиваются (читаются, пишутся) точно так как указано по их времени в настройке каналов в устройстве;
б) Какое-то устройство физически тупит, не отвечая на посылки на уровне протокола (не своих функций), и ПЛК ждёт указанный таймаут. В этом случае вся шина встаёт на таймаут. Таймауты в 100 мсек ставятся по умолчанию. Я их в данном случае не менял, так как не думал, что с датчиком будет такой треш (а думал, что я его дня три погоняю, к пятнице отсниму видео, сделаю фотки монтажа кабелей, задамся вопросом на тему кому верить в плане точности и бумаг - и выложу пост).
в) При наличии ошибок ModBus (любых: устройство ответило не то, устройство не ответило, таймаут), у устройства выставляется булевый флаг bError, который в дереве устройств и показывается этим “красным треугольничком” для наглядности.
Также можно достать код последней ошибки из ModBus-шины. Более глубоких средств отладки нету. Есть блее жёсткий вариант: взять штатную библиотеку и написать Modbus самому на уровне “открыть порт, послать, принять, сверить, закрыть порт”.

Более точно по временам:

  • Задача вызывается раз в 30 мсек. Я тестирую датчик на готовом проекте квартиры и на отлаженном щите и отлаженном железе под ОВЕНские датчики. Я просто добавил ваш датчик ещё одним устройством, чтобы не писать отдельно тестовую программу;
  • Если запись регистра стоит раз в 500 мсек - значит задача несколько раз прокрутится вхолостую, пока не наступят 500 мсек;
  • Когда наступит 500 мсек, то все запросы на обмен, у которых будет указано это время, будут сгруппированы, и ПЛК инициирует обмен с устройством;
  • Если обмен пройдёт неудачно, ПЛК будет повторять обмен в течение таймаута и, если это будет снова неудачным, выставит флаг bError у этого устройства.
  • Дальше всё повторяется циклически.

Пока что просьба не ммм… не гнать на CodeSys. Проблема не в таймаутах и не в таймингах, а в том, что когда я постоянно пишу Coils - начинается хрень.
Можете ли вы проверить это у себя на контроллере? Забацать задачу, которая в бесконечном цикле раз в 100-500 мсек будет посылать значение какого-нибудь DI (1 или 0) в Coil для пищалки - и на этом проверить, как будет вести себя датчик?

вот это бы было полезно. Можете попробовать?

УРА!! Докладываю результаты тестов. Ночь оно простояло с выключенным опросом всех несуществующих устройств и записью в Coils по фронтам (без постоянной записи в них).
Пока полёт нормальный по температуре (на уровне шума 1 = дождь пошёл, 2 = проснулся):


Про код ошибки ModBus. Сейчас перепишу программу так:
а) Нехай выводит код ошибки на экран, если он не ноль. То есть в переменной на экране будет торчать последний код ошибки.
б) Воткну переключатель, который врубает или вырубает опрос двух несуществующих датчиков. Будем баловаться и смотреть, влияет ли это на показания температуры.
в) Потестю два варианта с постоянным опросом Coils и без него.

Всё, тесты запустил. Вечером будут результаты.
Полдня погоняю без Colis, вторую половину дня буду над Coils издеваться.
У меня аж вся работа встала из-за этого датчика. Третий день уже как.

Докладываю.

  1. Тесты затянулись до завтра.
  2. Код ошибки Modbus, который иногда возвращает датчик - это 0xA1 - RESPONSE_TIMEOUT.
  3. Прикол в том, что в этот момент проваливается ТОЛЬКО температура из регистра 3. Остальные параметры в норме. У вас там этот регистр 3 обрабатывается без костылей? По идее это ж долно быть то же, что в регистре 0, но с другой точностью.
  4. Ща на ночь врубил опрос несуществующих устройств и запись в Coils постоянно по 100 мсек. Посмотрим, что будет.

ЗЫ. Датчик VOC угарный. Я тут спиртом одну железку протирал - так VOC больше 2000 взлетел. Надо будет попробовать вина напиться и посмотреть, сколько покажет.
ЗЫ2. Я на тесты этого датчика про…протерял три дня. Блин, а кто мне их компенсирует? У меня уже исследование на тему “Ой… а мы никогда этот датчик в другие ПЛК не пихали, а как это там он постоянно значения пишет”?

Это уже интереснее. Датчик, естественно, никакой 0xA1 не возвращает. Это, видимо, внутренне обозначение Codesys-а для отсутствия ответа в течение заданного таймаута. Если рантайм не получил ответ от датчика на команду чтения регистра 3 в очередной цикл опроса, то что у вас будет на графичке температуры? Варианты, которые приходят в голову:

  • отсутствие точки
  • значение, которое было 100мс (цикл опроса) назад
  • ноль

Мы ничего похожего так воспроизвести и не смогли, хотя продолжаем пытаться. Очень осложняет жизнь, что совершенно непонятно что и когда шлёт рантайм в шину, и какие ответы получает. Codesys это точно не умеет? Может быть у вас под рукой есть логический анализатор или просто какой-нибудь USB-RS485 переходник?

Ну из проблем, с которыми вы столкнулись, уже две, предположительно, были вызваны неудачной настройкой ПЛК: тормозная пищалка, которая на самом деле не тормозила; и коилы, которые на самом деле взводили ERROR_BUSY в соответствии с документацией. Так что как минимум за один день из трёх компенсации не будет :slight_smile:

Добрый день!

Проверили скорость реакции пищалки при постоянной записи coil - датчик отреагировал мгновенно:

Сам скрипт и его вывод:
test_coils.sh (826 Байт) result.txt (28.4 КБ)
Думаю, для дальнейших исследований вам нужно делать что-то из этого:

чтобы отделить “особенности” работы CODESYS и ОВЕН от реальных ответов WB-MSW v.3.