Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Не получили письмо с кодом активации?

Официальный форум Simple-Scada.

Автор Тема: Ошибка типа  (Прочитано 1115 раз)

B.B

  • Новичок
  • *
  • Сообщений: 19
    • Просмотр профиля
Ошибка типа
« : 08 Декабря 2021, 14:03:34 »
Возникла странная ошибка.

Есть внешняя переменная в OPC сервере тип DWord (4 байта)
В Simple-Scada тип LongWord.

Внутренней переменной типа Boolean присваивается младший бит
Код: (delphi)
// Состояние РКН
  PKH.Value:=Out2.Value and 1;

При очередном запуске проекта сервер начал ругаться в run-time

Ошибка в скрипте "MainCycle" в строке 15. Overflow while converting variant of type (Double) into type (Integer)

При этом "съедалось" содержимое тега (на OPC сервере смотрел)

Добавил явное приведение типа
Код: (delphi)
// Состояние РКН
  PKH.Value:=Out2.Value and LongWord(1);

Стало ругаться на строку 97 (до этого ошибку не показывало)
Ошибка в скрипте "MainCycle" в строке 97. Overflow while converting variant of type (Double) into type (Integer)

Поменял
Код: (delphi)
  // Включить вентиляторы
  if (Out2.Value and $3A000000) = 0 then Out2.Value:=Out2.Value or $3A000000;

на

Код: (delphi)
  // Включить вентиляторы
  if (Out2.asInt and $3A000000) = 0 then Out2.Value:=Out2.asInt or $3A000000;
Ошибка пропала.

Для проверки вернул Value вместо asInt - всё рабоатет...


ОС Win7 x64, Simple-Scada 2.5.13

Simple-Scada

  • Администратор
  • *****
  • Сообщений: 2996
    • Просмотр профиля
    • Simple-Scada
Re: Ошибка типа
« Ответ #1 : 08 Декабря 2021, 15:54:40 »
Здравствуйте.

Всё верно. Свойство Value переменной имеет тип данных Variant, потому при выполнении операций компилятор будет пытаться угадать тип данных в зависимости от выражения и текущего значения переменных. Кроме того, ничего не мешает OPC-серверу передать в скаду в переменную одного типа значение другого типа. Например, в переменную LongWord передать значение типа Double, в том случае, если адресация по OPC-сервере настроена неправильно, или выбран неправильный тип данных.
Когда Вы указали явное приведение к типу компилятор начал работать с конкретными значениями с правильными типами данных и ошибка исчезла. Только в Вашем случае правильнее было бы использовать приведение .AsInt64, так как максимальное значение переменной LongWord может быть выше максимального Integer значения.
Нужно также отметить, что если в момент выполнения приведённого Вами кода во всех переменных будут корректные значения соответствующего типа, то все варианты кода будут работать правильно. Например, на всех наших ПК приведённый Вами код работает без ошибок (мы в тестах используем OPC-сервер в котором на 100% значения переменных совпадают с типом переменных). Если испортить адреса переменных на OPC-сервере (чтобы в скаду попадали некорректные значения не соответствующие типу), то начинают возникать ошибки о которых Вы написали, что верно.   

Цитировать
При очередном запуске проекта сервер начал ругаться в run-time
Если до какого-то момента они не возникали и вдруг начали возникать, значит исходные данные изменились и нужно искать причину изменений и устранять её.

Если вышеописанное не подходит под Ваш случай, то просьба выслать текущую версию проекта (на support@simple-scada.com) и точные значения переменных в момент выполнения скрипта с ошибкой. Вывести значения переменных проще всего в лог-файл, так:
Код: (delphi)
Log_Add('vrOuterLongWord = ' + vrOuterLongWord.AsStr);
« Изменён: 08 Декабря 2021, 19:43:51 от Simple-Scada »

B.B

  • Новичок
  • *
  • Сообщений: 19
    • Просмотр профиля
Re: Ошибка типа
« Ответ #2 : 08 Декабря 2021, 18:07:58 »
Спасибо за оперативный ответ.

Кроме того, ничего не мешает OPC-серверу передать в скаду в переменную типа одного типа значение другого типа. Например, в переменную LongWord передать значение типа Double, в том случае, если адресация по OPC-сервере настроена неправильно, или выбран неправильный тип данных.
Когда Вы указали явное приведение к типу компилятор начал работать с конкретными значениями с правильными типами данных и ошибка исчезла. Только в Вашем случае правильнее было бы использовать приведение .AsInt64, так как максимальное значение переменной LongWord может быть выше максимального Integer значения.

Так оно и есть... работает ОРС сервер со специализированным оборудованием, в старших разрядах "резервные" биты. Состояние их не определено.
Обычно они нулевые, но иногда там единички (когда памяти устройству не хватило).

Сразу вопрос (наверно глупо спрашивать, приложение-то 32 битное...) - тип Integer в Simple-Scada двухбайтный?

Simple_Scada

  • Администратор
  • *****
  • Сообщений: 1165
    • Просмотр профиля
Re: Ошибка типа
« Ответ #3 : 08 Декабря 2021, 19:38:08 »
Цитировать
тип Integer в Simple-Scada двухбайтный?
Описание типов данных можно найти по ссылке.

Цитировать
работает ОРС сервер со специализированным оборудованием, в старших разрядах "резервные" биты. Состояние их не определено.
Обычно они нулевые, но иногда там единички (когда памяти устройству не хватило).
В теории OPC-сервер (являясь, по сути, драйвером к устройству) должен учитывать это и правильно извлекать значения из устройства. Но на самом деле, к сожалению, может быть по-другому.
« Изменён: 08 Декабря 2021, 19:51:53 от Simple-Scada »

B.B

  • Новичок
  • *
  • Сообщений: 19
    • Просмотр профиля
Re: Ошибка типа
« Ответ #4 : 09 Декабря 2021, 11:05:41 »
По ссылке получается, что оба типа имеют одинаковую разрядность,
но разный тип (аналог из С uint/int).


Тип          | Разрядность| Знаковый/Беззнаковый         | Диапазон чисел
-------------+------------+------------------------------+-------------------------------
Integer      | 32 бита    | Целые числа со знаком        | -2147483648…2147483647
LongWord     | 32 бита    | Положительные целые числа    | 0…4294967295


Т.е. перевод делается не бит_в_бит, когда $80 равно
128   для типа Byte
-128  для типа ShortInt
А       для типа Сhar

Можете дать ссылку (или тут описать)  какие правила преобразования типов  использует  Simple-Scada?

Simple-Scada

  • Администратор
  • *****
  • Сообщений: 2996
    • Просмотр профиля
    • Simple-Scada
Re: Ошибка типа
« Ответ #5 : 09 Декабря 2021, 12:01:30 »
Цитировать
По ссылке получается, что оба типа имеют одинаковую разрядность, но разный тип (аналог из С uint/int).
Да, именно так, в этом суть типов данных, каждый тип представляет разный диапазон чисел.

Цитировать
Т.е. перевод делается не бит_в_бит, когда $80 равно
Перевод всегда делается бит в бит, меняется только представление данных (то, как они интерпретируются). В ином случае скада просто портила бы оригинальные данные и не могла бы нормально работать.

Цитировать
Можете дать ссылку (или тут описать)  какие правила преобразования типов  использует  Simple-Scada?
В Simple-Scada нет каких-либо особых правил преобразования типов, мы используем самый стандартный компилятор Object Pascal, правила преобразования те же, что и у других компиляторов, например у компилятора Delphi/Pascal (отличия есть, но принцип работы тот же в 99% случаев). Те биты, которые OPC-сервер передал в скаду берутся в неизменном виде, никаких доп. операций с ними не выполняется и не может выполняться, ведь это привело бы к искажению данных и невозможности написать стабильно работающую программу. Представление данных зависит тот типа данных и если значение переменной одного типа данных записать в переменную другого типа данных, то значение может выглядеть по-другому, что логично. Т.е. если записать значение 128 в переменную типа Byte, то оно отобразится как 128, ведь диапазон Byte = 0..255. Если записать 128 в ShortInt, то значение отобразится как -128, ведь диапазон ShortInt = -128..127 и число 128 в этот диапазон не входит. Поэтому двоичное 10000000 = -128 для ShortInt (восьмой бит используется для знака), а для Byte двоичное 10000000 = 128.
Данный вопрос касается больше программирования, чем тех. поддержки по скада-системе. Всю необходимую информацию по типам данных (включая тип Variant) и принципам работы компилятора можно найти в интернете используя запросы связанные с Delphi/Pascal, т.к. в Simple-Scada используется компилятор Object Pascal.
« Изменён: 09 Декабря 2021, 12:15:22 от Simple-Scada »