Bug 16424

Summary: Не работает защита от обрыва датчика
Product: [Системы управления (Control Systems)] Театр Reporter: Олег Никулин <owl2>
Component: УправлениеAssignee: Олег Никулин <owl2>
Status: REOPENED --- QA Contact:
Severity: minor    
Priority: P4 CC: lav, pv
Version: не указана   
Target Milestone: ---   
Hardware: PC   
OS: Linux   
Whiteboard:
Заявки RT: Связано с:
Дата напоминания:
Attachments: Позиция и состояние двигателя
Диаграмма "от кого брать позицию и её статус"
Диаграмма "от кого брать позицию и её статус"
Диаграмма "от кого брать позицию и её статус"

Description Олег Никулин 2023-04-05 19:56:18 MSK
30.03.2023 в 11:10 Д47 ехал с отключенным датчиком. При этом ПЧ присылал высоту 3167 см (именно 3167, а не 31767). Контроллер шкафа присылал 65535 см.
Штанкет спокойно доехал до концевика, никаких защит не сработало. Статус D47_PositionStatus_AS = 3 (OutOfRange).
Тут всё логично: высота 3167 это просто выход за границы диапазона, но не поломка датчика, поэтому защита не сработала. (Хотя странно что ПЧ присылал именно 3167)

Из-за этого случая я пошел проверять то же самое на имитаторе. Если сымитировать обрыв датчика (высота становится = 31767 см), подключить двигатель и 
поехать, защита не срабатывает. И даже предупреждений нет.
 
В версии 3.1.21-alt1 были изменения в определение неисправности датчика высоты. Но на предыдущей версии 3.1.20-alt1 всё точно так же воспроизводится.
Comment 1 Олег Никулин 2023-04-05 20:08:38 MSK
Created attachment 5570 [details]
Позиция и состояние двигателя

Состояние переключилось в 3 (OutOfRange) в момент когда зашкалил контроллер шкафа. Двигатель еще не подключен.
А когда подключился, состояние переключилось в -1 (Unknown).
То есть во время движения состояние было всё-таки Unknown. Не ясно, почему не сработала защита (и должна была ли?).

Защита на станции была включена.
Театралы утверждают, что раньше не удавалось двигать штанкет с отключенным датчиком.
Comment 2 Олег Никулин 2023-04-06 19:31:14 MSK
Мой вердикт:
защита не срабатывает, потому что out_PositionStatus_fs = Unknown, если приходит некорректная высота и от ПЧ, и от КШ. При изменении статуса вызывается вот это https://gitlab.eterfund.ru/theatre/theatre/blob/master/src/Algorithms/Drive/DProt_Position_A.cc#L84
Но там не предусмотрен случай для статуса Unknown.

Какие вижу варианты исправления:
-Добавить новую причину срабатывания защиты - "Неизвестное положение"
-Переделать выставление статуса out_PositionStatus_fs. Например вообще не смотреть на КШ, если двигатель подключен, а брать только статус позиции ПЧ.
Comment 3 Олег Никулин 2023-04-06 19:35:21 MSK
(Ответ Олег Никулин на комментарий #2)
> -Переделать выставление статуса out_PositionStatus_fs. Например вообще не
> смотреть на КШ, если двигатель подключен, а брать только статус позиции ПЧ.
В этом случае тоже надо предусмотреть какое-то действие если статус окажется Unknown.
Comment 4 Олег Никулин 2023-04-06 19:55:41 MSK
Ну и попутно к этой баге, оказалось что статусы датчиков высоты, которые должен присылать контроллер шкафа, на имитаторе всегда = 0. Это важно, потому что extPosInfo.status выставляется именно по этим статусам.

Добавил
https://gitlab.eterfund.ru/theatre/theatre/merge_requests/544
Comment 5 Олег Никулин 2023-04-07 22:55:01 MSK
Были небольшие сложности с проверкой на имитаторе, потому что высота двигателя обновляется только когда он подключен, или если имитируется самоход. Из-за этого не обновляется высота от КШ, если имитируется обрыв датчика или неисправность канала.
Это я поправил. 


Еще один баг обнаружился: неправильно интерпретируются статусы, которые присылает КШ.

Значения статусов КШ в его прошивке:
#define STATUS_OK 0
#define STATUS_SHORT_CIRCUIT_WIRE_1 1
#define STATUS_SHORT_CIRCUIT_WIRE_2 2 //этот статус никогда не выводится
#define STATUS_BREAK_WIRE_1 3
#define STATUS_BREAK_WIRE_2 4

И в программе театра:
enum class Status : int
{
	Unknown = -1,  // неизвестен (нет связи)
	OK = 0,	  // OK
	KZ = 1,   // КЗ
	Break = 2 // Обрыв
};

Исправил.



Немного переделал алгоритм определения обобщенного статуса out_PositionStatus_fs. В частности, теперь если статусы ПЧ и КШ != ok, но статусы совпадают, то в out_PositionStatus_fs записывается этот статус. Раньше в таком случае было unknown - мне кажется нелогично, т.к. ПЧ и КШ единогласно говорят об одном статусе, и это не unknown

И на мой взгляд странно было сделано с определением статуса КШ (extPosInfo.status). Там мог выставиться OutOfRange, даже если статус полученный от КШ говорит о другой неисправности. Переделал, чтобы OutOfRange мог ставиться только если от КШ приходит ok (сам КШ не определяет OutOfRange).

На имитаторе посмотрел. Вроде бы всё правильно работает. По крайней мере теперь есть реакция на обрыв датчика, и каких-то явных проблем я не нашел. Но надо будет еще раз внимательно перепроверить, потому что нет 100% уверенности что всё правильно сделано
Пока что все изменения в моей мусорной экспериментальной ветке https://gitlab.eterfund.ru/theatre/theatre/commits/owl2-experimental
Comment 6 Олег Никулин 2023-04-07 23:00:59 MSK
Created attachment 5576 [details]
Диаграмма "от кого брать позицию и её статус"

Получилась такая логика.
И еще у нас таблица https://wiki.office.etersoft.ru/%D0%A2%D0%B5%D0%B0%D1%82%D1%80-%D0%92%D1%8B%D1%81%D0%BE%D1%82%D0%B0
Ей тоже соответствует
Comment 7 Олег Никулин 2023-04-11 22:28:05 MSK
Поменял логику определения статуса out_PositionStatus_fs в случае если одновременно ПЧ != ok и КШ != ok:
-Если статусы совпадают, то берём этот статус.
-Если у одного статус unknown, то берём от другого.
-Если у ПЧ сбой канала, берём от КШ
-В иных случаях (ПЧ и КШ говорят о разных поломках датчика) берём статус UnknownFault

В моем понимании out_PositionStatus_fs относится именно к датчику двигателя, а не к ПЧ. Поэтому сбой канала ПЧ трактуется как проблема с ПЧ, и статус датчика двигателя берется от КШ.

UnknownFault - это я сделал новый статус. Отличие от простого Unknown в том, что при UnknownFault срабатывает защита.
Т.е. Unknown - мы не знаем текущую высоту
UnknownFault - мы знаем, что с датчиком высоты есть проблема, но не ясно какая именно.

Также добавил срабатывание защиты при КЗ датчика.

Всё, что удалось в полной мере протестировать, работает. Но удалось не всё, потому что при имитации аварий на стенде, они применяются одновременно к ПЧ и КШ. Хотелось бы проверить ситуацию когда, например, у КШ всё ок, а у ПЧ сбой канала измерения.
К тому же, автоматическое тестирование не проходит MeasuringChannelFailure. Предполагаю, что проблема как раз в имитации сбоя канала, но до конца не разобрался еще.
Comment 8 Олег Никулин 2023-04-11 22:29:09 MSK
Created attachment 5583 [details]
Диаграмма "от кого брать позицию и её статус"

По сути эта диаграмма описывает функцию RSDrive::calcPosition()
Comment 9 Олег Никулин 2023-04-13 21:44:44 MSK
(Ответ Олег Никулин на комментарий #7)
> К тому же, автоматическое тестирование не проходит MeasuringChannelFailure.
Проблема была в имитации сбоя канала. Сделал, чтобы она влияла только на высоту от ПЧ. Теперь тесты проходят нормально.

И еще доработал имитатор:
-Поменял значение позиции при обрыве датчика с 31767см на 3176см
-Снизил порог определения обрыва датчика у КШ. Было 4000см, стало 3100см
-Добавил имитацию PositionOutOfRange при отключенном двигателе
-Добавил имитацию КЗ

Доделал срабатывание защит по датчику позиции. Защиты от обрыва и от КЗ работают даже при отключенном двигателе. Двигатель переходит в состояние защиты, и восстановить можно только после устранения обрыва/кз, или если отключить защиты. Т.е. здесь мы верим КШ и не даём подключить двигатель с неисправным датчиком.

Есть баг: если произойдет авария датчика (например обрыв) когда защита отключена, то после её включения перестает работать защита от аварий датчика. Судя по всему не доходят сообщения до DProt_Position_A, но пока не смог починить
Comment 10 Олег Никулин 2023-04-14 20:18:34 MSK
(Ответ Олег Никулин на комментарий #9)
> Есть баг: если произойдет авария датчика (например обрыв) когда защита
> отключена, то после её включения перестает работать защита от аварий
> датчика. Судя по всему не доходят сообщения до DProt_Position_A, но пока не
> смог починить
Так происходит, если не нажимать восстановление защиты.
Дело в том, что есть разные акторы для двигателя: Drive_A и DProt_Position_A. При отключенной защите Drive_A не переходит в состояние st_protection. Но DProt_Position_A всё равно переходит в st_sensor_failure, где и остается, пока не будет сброшена защита.
Сделал, чтобы st_sensor_failure работал как и st_protection: эти состояния активируются только при включенной защите.

Заметил, что статус датчика OutOfRange сделан только предупреждением, без аварии. Но при этом высота (out_Position_as) перестает обновляться. Получается ситуация, что мы не отключаем двигатель, но перестаем обновлять высоту. Сделал, чтобы продолжало обновляться и отображаться.

Чтобы не путаться, сделал таблицу по которой определяется обобщенный статус датчика высоты, и сама высота.
https://wiki.office.etersoft.ru/%D0%A2%D0%B5%D0%B0%D1%82%D1%80-%D0%92%D1%8B%D1%81%D0%BE%D1%82%D0%B0
(вторая таблица)
Comment 11 Олег Никулин 2023-04-14 22:59:04 MSK
Created attachment 5588 [details]
Диаграмма "от кого брать позицию и её статус"
Comment 12 Олег Никулин 2023-04-17 20:36:59 MSK
Сделал еще исправление, чтобы авария, вызванная неисправностью датчика отключенного двигателя, не сбрасывалась после реинициализации.
Теперь кажется всё. На имитаторе погонял, работает как задумано.
https://gitlab.eterfund.ru/theatre/theatre/merge_requests/545
Comment 13 Олег Никулин 2023-06-05 21:25:08 MSK
Еще раз всё внимательно протестировал. Нашелся баг:
Сымитировать обрыв датчика, сделать станцию резервной, убрать имитацию обрыва, снова сделать станцию главной. После этого перестает работать защита от неисправностей датчика у отключенных двигателей
Причина в том, что после обрыва DProt_ActiveBase_A переходит в состояние st_sensor_failure, и так и остается в нём, несмотря на то что обрыв пропал. А для работы защит нужно состояние st_disabled

Исправил так, что в preinit выходим из состояния st_sensor_failure, а когда preinit заканчивается, смотрим на датчик, и если он неисправен, снова переходим в st_sensor_failure.

st_sensor_failure и st_preinit в разных классах, и я пока не додумался как вызывать st_sensor_failure.activate() из другого класса. Поэтому для этого посылаю специальный тип сообщений, но мне такая реализация не очень нравится. Постараюсь потом переделать
Comment 14 Олег Никулин 2023-06-30 18:17:16 MSK
Все изменения в релизе 3.2.23
Поставил обновление в театре, проверил.
Защита от обрыва работает. У отключенных двигателей тоже работает.

Не получилось вызывать срабатывание защиты от КЗ. Замыкаю датчик, выводится "значение высоты вышло за пределы нормального", но защита не срабатывает. Проблема в том что КШ не выставляет флаг КЗ. Скорее всего надо будет у него в прошивке подкорректировать порог определения КЗ.

Пишет что у Д61 обрыв датчика. Это какая-то аппаратная проблема. Напряжение на одном из проводов датчика плавает относительно общей земли (измерял на плате КШ). На работу это не влияет, потому что Д61 выключен (disabled).

Больше проблем не обнаружилось.
Comment 15 Олег Никулин 2023-07-07 18:07:41 MSK
(Ответ Олег Никулин на комментарий #14)
> Пишет что у Д61 обрыв датчика. Это какая-то аппаратная проблема. Напряжение
> на одном из проводов датчика плавает относительно общей земли (измерял на
> плате КШ)
На плате, где расположены источники тока для датчиков высоты, была разорвана одна дорожка. Запаял. Стало нормально измеряться, без обрывов.
Comment 16 Олег Никулин 2024-07-16 18:39:19 MSK
Случайно обнаружил на имитаторе, что появилась ошибка в работе защит от КЗ и обрыва датчика. В момент обрыва/КЗ подключенные двигатели не отключаются и по ним не выводится сообщения в журнале.
Пока выяснил что сломалось в коммите bf18197e
Comment 17 Олег Никулин 2024-07-18 16:48:31 MSK
(Ответ Олег Никулин на комментарий #16)
> Случайно обнаружил на имитаторе, что появилась ошибка в работе защит от КЗ и
> обрыва датчика. В момент обрыва/КЗ подключенные двигатели не отключаются и
> по ним не выводится сообщения в журнале.
> Пока выяснил что сломалось в коммите bf18197e
В коммите bf18197e перестала работать только защита от обрыва у подключенных двигателей. И это баг только по части имитатора (перестал выставляться статус КШ).
Защита от КЗ же, судя по всему, никогда не срабатывала у подключенного двигателя. Причина в том, что у нас отсутствует проверка на КЗ значения высоты, полученного от ПЧ. Следовательно, у КШ выставляется статус "КЗ", а у ПЧ остается статус "ОК". А если у ПЧ "ОК", то данные считается что проблемы с датчиком нет.

На имитаторе при имитации КЗ выставляется высота = 0. Надо выяснить что будет присылать реальный ПЧ в случае КЗ датчика. Есть подозрение, что будет меньше нуля (т.е. переполнится переменная) и сработает какая-то другая защита (например по сбою канала измерения)