В этой статье описан наш опыт выявления причин ошибки в расчете положения подъемного сосуда в шахтном стволе по сигналам с инкрементальных энкодеров, который может быть полезен другим разработчикам, наладчикам и инженерам АСУТП, работающим не только с подъемным оборудованием, но и с любым другим, где малые приращения используются для расчета больших величин.
Начнем с небольшого погружения в предметную область. Наша организация специализируется на наладке шахтных подъемных установок, это, выражаясь совсем простым языком, «как лифт, только для шахты». Принцип действия подъемной установки, в целом, как у лифта – привод вращает барабан, на который наматывается канат, на который подвешен подъемный сосуд - бадья, клеть или скип, в зависимости от производственной задачи – проходка ствола или тоннеля, добыча полезных ископаемых или подъем/спуск людей. Основная часть подъемной установки - подъемная машина, это барабан с редуктором и приводом (их может быть два), тормозная система, а также системы управ��ения, контроля и защиты.
На одной из таких подъемных машин, которую мы ввели в эксплуатацию и обслуживаем, положение подъемного сосуда для большей надежности контролируется одновременно двумя устройствами – САУ (Система автоматизированного управления) и АЗКД (Аппарат защиты и контроля движения). Для этого с каждого из двух датчиков углового положения вала – инкрементальных энкодеров, установленных на левом и правом редукторе (машина двухприводная), сигнал дублируется на счетные модули двух ПЛК (программируемых логических контроллеров), в САУ и в АЗКД, соответствующего канала, левого или правого. То есть, и в САУ, и в АЗКД установлено по два отдельных ПЛК, контролирующих так называемые левый и правый канал управления, относящиеся, соответственно, к левому и правому приводам подъемной машины, всего четыре ПЛК, из которых два ПЛК левого канала и в САУ, и в АЗКД получают данные с энкодера левого привода, а два ПЛК правого канала, соответственно, с правого.

Во время вращения вала подъемной машины, то есть, при подъеме или спуске, энкодеры передают счетным модулям ПЛК импульсы, по 10 000 за один полный оборот вала, количество которых за один программный цикл умножается на 3,14 (округленное до сотых число Пи) и на диаметр барабана с учетом текущего слоя навивки каната, и делится на количество импульсов за оборот, таким образом угловое приращение пересчитывается в линейное.
Формула расчета приращения пройденного пути за программный цикл (или за время по таймеру):

Данный алгоритм во всех ПЛК одинаковый, слой навивки каната, в зависимости от пройденного пути, тоже меняется во всех ПЛК синхронно. Различается только время программного цикла, в обоих ПЛК АЗКД оно, в среднем, составляет 10 мс, а в обоих ПЛК САУ – 30 мс, так как САУ обрабатывает намного больше входных и выходных сигналов, чем АЗКД. Следовательно, количество импульсов, полученных от энкодера за программный цикл, различается в том же соотношении. Положение подъемного сосуда – в данном случае, бадьи – считается в метрах и его долях, вверх и вниз от нуля – шахтной поверхности, соответственно, положительное или отрицательное. На экранах САУ и АЗКД оно округляется до сантиметров. Тип переменной, в которой оно хранится – Real (32 бит), собственно, это в итоге и оказалось причиной рассматриваемой проблемы.
Проблема начала проявляться при движении вниз на глубине -180 м – вычисляемое положение подъемного сосуда, отображаемое на экране АЗКД, с этого момента начинало изменяться быстрее, чем на экране САУ, расходясь с ним все больше и больше, это расхождение показывал и регистратор параметров – «бортовой самописец» (бирюзовый график на рисунке – разность положений, рассчитываемых по приращениям за программные циклы ПЛК САУ и ПЛК АЗКД). Машинистки не могли понять, какое из двух положений правильное, ведь у них нет никакой другой информации о положении бадьи в стволе, кроме этих показаний, как в том анекдоте – «видимость – ноль, иду по приборам». Но на отметке -256 м направление у этого расхождения менялось, теперь, наоборот, быстрее начинало изменяться положение на пульте управления – в САУ, в результате графики положений сходились, пересекались и расходились опять, на этот раз уже до остановки в крайней нижней отметки ствола, которая на тот момент была примерно на -500. При движении обратно, вверх, наблюдались эти же расхождения в обратной последовательности, зеркально. Расхождения выглядели одинаково в левом и правом каналах, ��то сразу отметало версию о неисправности одного из энкодеров, счетных модулей или ПЛК. На отметке -180 менялся слой навивки – диаметр, применяемый в формуле пересчета углового положения в линейное, уменьшался, но уменьшался одновременно, и на одну и ту же величину во всех четырех ПЛК, что само по себе не могло быть причиной расхождения. На отметке 256 не менялись никакие параметры, ограничения или режимы работы подъемной машины, поэтому причина расхождения, казалось, где-то в области мистики, хотя само число 256 так или иначе подталкивало к версии о переполнении какого-то буфера. Напомню, в расчетах приращений все было одинаково, кроме времени выполнения программного цикла, за которое считалось приращение, поэтому, после долгих поисков причины в алгоритмах и настройках ПЛК мы решили попробовать привести расчет приращения к одному периоду на всех ПЛК – 50 мс, по таймеру, и расхождение почти исчезло, в том числе и между приращением, рассчитанным по таймеру за 50 мс, и за программный цикл примерно 30 мс. Стало понятно, что на малых периодах (10 мс) приращение вычисляется неправильно. Также вычисление приращения по таймеру дало возможность построить в регистраторе параметров ровный и понятный график разницы приращений (синий график на рисунке – разность положений, рассчитываемых по приращениям за время по таймеру и за программный цикл ПЛК АЗКД), на котором стали заметны еще три точки преломления: -32 м, -64 м и -128 м, не настолько сильные, как на -256, не меняющие направление, но совершенно точно меняющие скорость расхождения, каждое - на следующей степени основания двоичной системы счисления.

Далее удалось найти и связь неточности с «волшебными числами» – проблема заключалась в ограничении длины значимой части числа для типа Real (32 бит). Об этой особенности данного типа написано много статей, в т ч и на Хабре, поэтому постараемся коротко изложить причину проблемы, применительно к нашему случаю. Значимая часть числа (мантисса) для типа Real, в соответствии со стандартом IEEE 754, имеет размер 23 бита (плюс один подразумевающийся старший бит, значение которого всегда равно единице), что соответствует 7-8 десятичным разрядам. Приращение положения, вычисляемое за программный цикл 10 мс на четвертом слое навивки каната (на этом слое бадья проходит отметку 0 м) при скорости 2 м/с, составляет 0,018636402 м – уже на первом его прибавлении все 8 десятичных разрядов оказываются заняты ненулевыми значениями. Далее, по мере увеличения положения до десятых и целых частей метра, а затем десятков и сотен метров необходима запись в старшие разряды, при этом младшие отбрасываются, как менее значимые, и минимально допустимый шаг приращения увеличивается, становясь больше самого приращения, в результате чего оно округляется до ближайшего возможного значения в большую или меньшую сторону. Например, при положении более 1 метра минимальный шаг приращения равен 0,0000001192 м (2 в минус 23 степени), более 32 м – 0,0000038147 м (2 в минус 18 степени), а более 256 м – 0,0000305176 м (2 в минус 15 степени), с каждым пересечением степени основания двоичной системы увеличиваясь примерно вдвое, так как хранение данных и, соответственно, сдвиг разрядов происходят в этой системе счисления.


Чтобы проверить, действительно ли данная особенность типа Real стала причиной возникшей проблемы, мы вычислили по приведенной выше формуле приращение на каждом из пронумерованных участков графиков между точками излома, по количеству импульсов за программные циклы АЗКД и САУ, а также за время по таймеру. И на каждом участке округлили каждое из этих приращений до ближайшего минимального шага, изменяющегося в связи со сдвигом разрядов.
Участков, в данном случае, семь:
Путь от датчика синхронизации положения (желтый график дискретного сигнала внизу - значение 1) до выхода из зоны ограничения скорости и разгона до максимально разрешенной (серая линия);
Путь от разгона до отметки -32 (зеленая линия с указанием соответствующего значения);
Путь от отметки -32 до отметки -64 (зеленая линия с указанием соответствующего значения);
Путь от отметки -64 до отметки -128 (зеленая линия с указанием соответствующего значения);
Путь от отметки -128 до перехода на следующий слой навивки каната и, соответственно, уменьшения диаметра (фиолетовая линия);
Путь от перехода на следующий слой до отметки -256 (зеленая линия с указанием соответствующего значения);
Путь от отметки -256 до остановки перед полком (серая линия).
Результаты вычислений позволили нам сопоставить разности приращений, приведенные в таблице, с направлениями и углами излома обоих графиков, и убедиться, что на каждом из участков они соответствуют.
Разность между приращениями пройденного пути, рассчитанного за программные циклы ПЛК АЗКД и САУ, и за время по таймеру, с округлением до минимально допустимого приращения на каждом участке:

При прохождении данных участков, с увеличением минимального шага и более грубым округлением, прибавляемое приращение все сильнее отличается от фактического, на -32, -64 и -128 это не так заметно, а на -256 это уже меняет направление расхождения. Кроме того, чем меньше приращение, тем большую его часть составляет минимально допустимый шаг на каждом этапе, и тем заметнее будет расхождение, поэтому оно практически незаметно при программном цикле 30 мс и, тем более, при периоде по таймеру 50 мс. По этой же причине на отметке -180, при смене слоя навивки каната, уменьшенное приращение вызывает большее расхождение, видимое на графике, а также расхождение увеличивается на малых скоростях. Планируемая глубина шахтного ствола на этом объекте – 1350 м, поэтому после прохождения отметок -512 м и -1024 м отклонение может достигнуть 0,5 м и более, что, в свою очередь, может вызвать ложное срабатывание, или, наоборот, несрабатывание защит и блокировок, необходимых для обеспечения безопасной работы.
Таким образом была выявлена причина расхождений вычисляемого положения с реальным, и, совместно с разработчиками программного обеспечения подъемной машины, принято решение изменить тип данных для вычисления положения на Double (число с плавающей запятой двойной точности, 64 бит), где на мантиссу отводится уже 52 бита, что обеспечивает требуемую точность.
