KRVariables.pas
Типы данных
- TVarUpdateType – метод обновления значения переменной
- vutBefore – перед отправкой значения
- vutAfter – после отправки значения
- vutAftUpdate – после обновления. То есть после отправки запроса чтения и получения результата с текущим значением
- TVarType – тип значения переменной
- VT_BYTE – беззнаковый целочисленный байт
- VT_WORD – беззнаковое 16-битное целочисленное значение
- VT_DWORD – беззнаковое 32-битное целочисленное значение
- VT_SMALLINT – 16-битное целочисленное значение
- VT_INT – 32-битное целочисленное значение
- VT_SINGLE – 32-битное значение с плавающей точкой
- VT_STRING – строка
- VT_INT64 – 64-битное целочисленное значение
- VT_DOUBLE – 64-битное значение с плавающей точкой
- VT_UINT64 – беззнаковое 64-битное целочисленное значение
- TValUpdate – событие обновления значения
- Sender – указатель на TKRVariable
- Variable – обновленная переменная
Интерфейсы
Интерфейс IKRVarUp
IKRVarUp – интерфейс мониторинга за результатами запросов переменной
Методы интерфейса IKRVarUp
- VarUp – вызывается при положительном ответе от удаленного устройства на запрос получения текущего значения переменной
- AVar – переменная, значение которой обновилось
- VarErr – вызывается при ошибке выполнения запроса
- AVar – переменная, в которой возникла ошибка
Классы
Класс TKRVariable
Родительский класс TKRComponentCollectionItem
Интерфейсы: IKRCfgParam
TKRVariable – переменная удаленного устройства. Виртуальный класс
Свойства класса TKRVariable
- ErrorMsg – последнее сообщение об ошибке
- Error – код последней ошибки
- Value – значение переменной
- VarType – тип переменный TVarType
- Interval – интервал обновления значения в миллисекундах. Если установлено значение больше нуля, то будут отправляться запросы обновления с заданной периодичностью
- CfgInterval – конфигурационный параметр типа TKRIniCfgParam, для хранения значения свойства Interval
- CfgValue – конфигурационный параметр для сохранения значения переменной
- UpdateType – метод обновления значения переменной TVarUpdateType
- UpAftWrite – если опция включена, то после положительного ответа устройства на запрос записи, посылается запрос чтения
- UserError – включение пользовательской ошибки(симуляция ошибки)
- UserErrorMsg – сообщение об ошибке при включенной пользовательской ошибке
- ValUpdated – индикатор обновления значения. Только чтения. Значение актуально только когда свойство Interval равно нулю. При отправке запроса чтения с помощью метода UpdateValue сбрасывается в False, а после получения положительного ответа переходит в True
- WaitForUpdates – ожидание обновления значения. Актуально только когда Interval равен нулю. Если свойство включено, то после первого вызова метода UpdateValue, он будет повторно вызываться пока не будет получено значение переменной. То есть если по запросу чтения получена ошибка или не получено ни чего(таймаут), то запрос чтения будет отправляться повторно пока не придёт положительный ответ.
- ErrorCount – количество подряд пришедших ошибок для установки состояния переменной в ошибку. Например, если установить значение этому свойству 3, то одна или две подряд пришедшие ошибки не будут влиять на визуальные компоненты (например KRField цвет фона менять не будет) и событие OnError вызываться не будет
События класса TKRVariable
- OnValUpdated – событие вызывается после положительного ответа на запрос чтения значения с удаленного устройства
- OnError – вызывается если не удалось получить ответ от устройства или ответ содержит ошибку
- OnRuntimeError – вызывается при возникновении исключения в компоненте
Методы класса TKRVariable
- UpdateValue – посылает запрос чтения значения в удаленное устройство. Если свойство Interval больше нуля, то данный метод не работает
- AddMon – добавляет объект соответствующий интерфейсу IKRVarUp в список мониторинга для фиксирования результатов обработки запросов
- DelMon – удаляет объект из мониторинга
- AMon – объект, который будет удален
Класс TKRVariabels
Родительский класс TKRComponentCollection
TKRVariabels – коллекция переменных TKRVariable. Виртуальный класс
Свойства класса TKRVariabels
- ReactionTime – время реакции в миллисекундах. Минимальное значение 1. После получения результата запроса для синхронизации используется таймер. Время реакции – это время работы этого таймера.
Методы класса TKRVariabels
- updateAllVariabels – вызывает метод UpdateValue у всех переменных, которых интервал равен нулю
- updateAllWaitingVariabels – вызывает метод UpdateValue у всех переменных, которых включено свойство WaitForUpdates
Для клиентов, с которых я только считываю информацию каждые 100 мс, обновление происходит каждые 100 мс, а для клиентов в которые я должен писать с периодичностью 100 мс, обновление происходит каждые 200 мс. Наверное это связано с тем, что клиент тратит 1 интервал на запись данных в устройство?
Скажи а как можно заставить этот клиент не тратить время на чтение, а только записывать? Или уменьшить интервал для этого клиента до 50 мс?
Спасибо.
P.S. Поменял Interval на 50. Странно, но периодичность осталась таже 200 мс.
UpAftWrite включено по умолчанию. Для увеличения скорости его лучше выключить, так как это дополнительный запрос.
Для максимальной скорости записи лучше использовать KRModbusMaster. Код ниже проводит запись на максимально возможной скорости
И если вы используете компоненты 2020 года, то там есть дополнительные задержки в коде. Лучше перейти на последнюю версию.
Получается я запретил чтение этого регистра с данного устройства.
Так я вызываю функцию из отдельного потока:
Это калбэк функция:
Теперь у меня попутный вопрос. Для удобства тестирования выходов модуля и использовал TKRVCheckBox-ы и TKRBLField. Само собой раз чтение состояния регистра отключено, то и галочки не отображаются. Если принудительно записывать в adr24_mb0050_word.Value число которое я отправил в функции выше не вызовет ли это повторный запрос на запись в клиент?
Учтите, что функция WriteHoldingRegister ни как не повлияет на значение adr24_mb0050_word.Value до обновления через интервал или функцией adr24_mb0050_word.UpdateValue
Можно интервал (mainformDozatorSM.adr24_mb0050_word.Interval) выставить в секунду (1000) или 500мс. Этого будет достаточно для обновления данных в визуальных компонентах. Будет отправляться запрос чтения и вы будете наверняка знать текущее значение.
Хотел проверить функцию WriteHoldingRegister так сказать не выходя из дома)
1. При помощи этой функции отправляю в устройство по адресу 24 число 2
2. Установил (на время тестирования) interval = 100 и UpAftWrite = true
3. По идее мастер должен сам формировать запросы на чтение с периодом 100 мс и считать с устройства то число, которое мы отправили в п.1. (т.к. в устройстве в нужном регистре должно быть записано число 2)
4. В поле KRBLField должно отобразится число считанное с устройства, но там 0.
Может быть, я что-то не так делаю?
Может быть на работу функции WriteHoldingRegister могут влиять другие клиенты, которые тоже работают с этим мастером (мастер то 1)?
У меня три клиента модбас и 1 мастер.
AData здесь типа Word вроде, я думал, что не нужно массив делать.
Руслан добрый день!
Есть такой интересный вопрос. После отправки запроса на запись с помощью функции WriteHoldingRegisters, в случае если устройство не ответило или ошибка в ответе событие OnError сработает?
Дело в том, что я не отправляю новый запрос пока не отработает callback в функции WriteHoldingRegisters. Однажды так получилось, что callback не сработал и повторного запроса не было и модуль выходов перестал работать.
Потом я решил еще раз перепроверить функцию WriteHoldingRegister, которая в качестве параметра ADate принимала Word. Оказалось, что действительно эта функция не срабатывает. А вот WriteHoldingRegisters с параметром AData типа TKRRegisters для которого надо создавать массив и элементу массива уже присваивать то что хочешь отправить - действительно работает.
В общем, Руслан, спасибо тебе больше за твой труд, за твою работу.
Как я могу отблагодарить тебя? Напиши номер своей карты, я переведу тебе хоть немного денег. От души!
Функция WriteHoldingRegisters и ваша переменная adr24_mb0050_word ни как не связаны. То есть при вызове WriteHoldingRegisters результат отправляется в
callback, а при обновлении adr24_mb0050_word вызываются события OnVarUpdate или OnError
callback должен отработать в любом случае. Единственный вариант это переполнение исходящей очереди коннектора. Есть визуальный компонент KRConnectorQueueBar для отображения заполнения очередей коннектора
KRConnectorQueueBar.Connector - сюда коннектор
KRConnectorQueueBar.StackOut - какая именно очередь мониторится, false - входящая, true - исходящая
KRConnectorQueueBar.Timer - KRTimer для обновления показаний
Нужно поставить два таких компонента для входящей и исходящей очередей.
По сути KRConnectorQueueBar - это ProgressBar где максимальное значение равно CE_QUEUE_MAX_ITEMS, а текущая позиция берется из свойств коннектора QueueCount или QueueOutCount, это показатели текущего заполнения очередей
При большом объеме запросов нужно контролировать заполнение очередей.
Есть еще очередь в KRModbusMaster и компонент для ее мониторинга KRMBQueueBar, но тут вряд ли может случится переполнение.
При переполнении очереди KRModbusMaster и входящей очереди коннектора все равно будет вызван callback но с соответствующей ошибкой в параметре AError, а вот при переполнение исходящей очереди коннектора callback не вызовется.
По очередям коннектора есть статья
Поставил я два компонента KRConnectorQueueBar и один KRMBQueueBar.
Все компоненты показывают 0%. Только 1 компонент KRConnectorQueueBar с StackOut = false иногда меняется на 1%, потом опять 0%. Получается очереди вообще не переполняются?
Тут, скорее всего нужна логика работы интервала обновления. При обновлении по интервалу используется обычный таймер, но только интервал у таймера не статичный, то есть не 100мс, а 100 минус время затраченное на обработку предыдущего запроса. Что касается OnValUpdated, то это событие вызывается каждый раз при удачном обновлении значения из клиента. Теоретически код ниже должен записывать значение каждые 100мс
Но, нужно учитывать тот факт, что сообщения для одной переменной обрабатываются последовательно, то есть пока мы не получим ответ (от клиента) на предыдущее сообщение, текущее отправляться не будет. И в таком случае, если отправка значения будет проходить более 100мс, мы можем получить переполнение очереди сообщений.
В данном случае нахватает события сигнализирующего об успешной записи (возможно в будущем я его добавлю). Но есть свойство UpAftWrite, при включении которого, после успешной записи отправляется запрос на чтение. Используя это свойство можно сделать так: