st-legal,
Teodor, извините, но вы сделали какой-то переполох на ровном месте и просто усложнили. Можно обойтись без секундного скрипта и лишних проверок.
Вопрос в следующем. При нажатии кнопок с некоторой задержкой все отрабатывает нормально, но стоит нажать 2 кнопки без паузы, отрабатывает только тот выход, кнопка которого была нажата последней. Кнопки привязаны к одному тегу, но через разные биты. В чем может быть проблема?
В данной ситуации нет никакого блокирования переменных и дело только в работе с битами одной и той же переменной. Всё очень просто. Присвоение внешних переменных происходит не моментально, а с какой-то задержкой. Вот последовательность шагов:
- переменная равна нулю;
- пользователь нажал кнопку;
- скада посылает OPC-серверу запрос на запись в тег единицы;
- OPC-сервер выполняет присвоение;
- скада получает результат (единицу).
Начиная с шага 2, до шага 5 сервер скады будет думать, что переменная равна нулю. И только на 5 шаге сервер получит значение, равное 1. Вот и всё.
Теперь конкретнее про биты. Есть две кнопки. Обе связаны с переменной vrBit. Первая кнопка работает с нулевым битом. Вторая кнопка - с первым. Тогда, если быстро кликнуть первую и вторую кнопку, может произойти следующая ситуация:
- сначала переменная vrBit, равна нулю (x0000);
- пользователь нажал кнопку 1. Скада берёт текущее значение vrBit, т.е. 0 (x0000), меняет в нём нулевой бит на 1 (x0001) и отправляет полученное значение на OPC-сервер, для присвоения. Сервер скады всё ещё хранит в vrBit значение 0 (x0000);
- пользователь нажал кнопку 2. Скада берёт текущее значение vrBit, т.е. 0 (x0000), меняет в нём первый бит на 1 (x0010) и отправляет полученное значение на OPC-сервер, для присвоения. Сервер скады всё ещё хранит в vrBit значение 0 (x0000);
- OPC-сервер получил два запроса, первый на присвоение x0001, второй на присвоение x0010. Он выполняет их последовательно и в переменной оказывается значение x0010, которое в результате передается скаде.
Для решения этого вопроса можно сделать синхронизацию через внутреннюю переменную. Т.е., дано: наша внешняя переменная в которой нужно менять биты. Она называется vrMy. Мы создаем ещё одну внутреннюю переменную с именем vrSync. Связываем обе кнопки с переменной vrSync. Также у этих кнопок в качестве доп. переменной выбираем vrMy. Пишем следующий универсальный скрипт:
begin
if not (Sender is TM_Object) then Exit;
with Sender as TM_Object do
if (Variable <> nil) and (VariableEx <> nil) then
VariableEx.Value := Value;
end.
Теперь ставим данный скрипт на событие OnDataChange у наших кнопок (причем этот скрипт подойдет для всех подобных кнопок в проекте). Готово. Теперь кнопки работают с внутренней переменной и присвоения выполняются моментально, поэтому проблемы с битами нет. При этом все изменения отправляются во внешнюю переменную.