Дозиметрический контроль пространства комнаты
Реализация системы контроля и управления ионизирующего облучателя.
Основными интересными моментами данного программного продукта являются:
- Интеграция в систему с контроллером Premium (Schneider Electric) белорусской системы дозиметрического контроля компании “Атомтех” “SARKtech” по нестандартному протоколу
- Вывод текущей информации из системы на светодиодные панели MIGRA
Схема настройки интеграции системы дозиметрического контроля “Атомтех” “SARKtech” с Premium была следующей… Сначала все собрали в соответствии с заводскими схемами и заставили работать систему так, как она поставлялась с завода. Затем, разъединив соединение между панелью и самой собранной системой, стали сниферить протокол обмена и наблюдать, какие телеграммы посылает компьютерная программа в панель (запросы), и какие присылает сама панель (ответы). Описание протокола было, но оно не имело большой ценности, так как кое-что в нем не соответствовало текущему состоянию дел.
В итоге принесли радионуклидный излучатель-тестер и стали проводить испытания, вводя поочередно в “зашкал” каждый из приборов.
Был создан ютуб ролик: https://www.youtube.com/embed/VCzWNrKBb_s
Оказалось, что переменные типа REAL или Float имеют достаточно странный формат, состоящий всего из трех байт. Никакие стандартные способы конвертации данных в формат данных REAL не годились, пришлось обращаться к помощи знатоков и вот какое решение получилось:
Код С, работает без ошибок (так создано в панели):
//собирает float из трех байт
float R3toR4(BYTE a, BYTE b, BYTE c)
{
float ret;
void* pv = &ret;
WORD e;
BYTE s = a & 0x80;
if((a|b|c)==0)return (float)0.0;
a &= 0x7F;
e = (WORD)( a + (BYTE)0x3e)<<7;
((BYTE*)pv)[3] = (HIBYTE(e)) | s;
s = (b & 0x7f) | LOBYTE(e);
((BYTE*)pv)[2] = s;
((BYTE*)pv)[1] = c;
((BYTE*)pv)[0] = 0;
return ret;
}
С-код работает идеально, а вот в Unity Pro XL(ST) получалось не важно.
Контрольные примеры:
Input: 18317 14080 / 478D 3700
C-Value: 70.607422 / 428D3700
U-Value: 91.78
Input: 18137 20480 / 46D9 5000
C-Value: 54.328125 / 42595000
U-Value: 52.21
Input: 18137 5376 / 46D9 1500
C-Value: 54.270508 / 42591500
U-Value: 37.46
Input: 18136 62976 / 46D8 F600
C-Value: 54.240234 / 4258F600
U-Value: 123.4219
Код, который работает правильно в контроллере Premium (Schneider Electric):
WORD_AS_BYTE (IN := UINT_TO_WORD(FIRST),LOW => b,HIGH => a);
WORD_AS_BYTE (IN := UINT_TO_WORD(SECOND),LOW => d,HIGH =>c );
tmp_WORD := INT_TO_WORD((BYTE_TO_INT(a AND 16#7F)+62)*128);
(* выделили порядок, сместили к стандарту, сдвиг влево на 7 бит – в мл.байте остается мл.бит порядка *)
tmp_BYTE := WORD_TO_BYTE(SHR(IN :=tmp_WORD, N := 8)) OR (a AND 16#80);
(* в байт порядка возвращается бит знака *)
tmp_BYTE1 := (b AND 16#7F) OR WORD_TO_BYTE(tmp_WORD AND 16#FF); (* старший байт мантисы *)
(* в старший байт мантиссы, в котором отбросили старший бит (в стандарте IEE он всегда нехранимая 1) *)
(* вписывается младший бит порядка *)
First_WORD:= BYTE_AS_WORD (HIGH := tmp_BYTE, LOW := tmp_BYTE1);
Second_WORD:= BYTE_AS_WORD (HIGH := c, LOW := 0);
If (a=0) And (b=0) And (c=0) Then
ret1 := 0.0;
Else
ret1 := WORD_AS_REAL (HIGH := First_WORD, LOW := Second_WORD);
End_If;
С панелями (их было несколько) тоже пришлось повозиться, выбрав изначально неправильный путь развития ситуации. Стал мучить панели посимвольным выводом ASCII кодов. Да, как оказалось, так тоже можно выводить, но правильный путь другой – заготавливать в программе панели готовые шаблоны сообщений и выводить их по коду команды из контроллера, наподобие программы работы с принтером (последовательности).
#Интеграциястороннихпротоколов, #ШнайдерЭлектрик, #цифроваяпанель, #SARK
23.10.2021