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 в список мониторинга для фиксирования результатов обработки запросов
    • AMon – объект в котором будет вызываться метод VarUp при положительном ответе на запрос обновления и метод VarErr при ошибке
  • DelMon – удаляет объект из мониторинга
    • AMon – объект, который будет удален

Класс TKRVariabels

Родительский класс TKRComponentCollection

TKRVariabels – коллекция переменных TKRVariable. Виртуальный класс

Свойства класса TKRVariabels
  • ReactionTime – время реакции в миллисекундах. Минимальное значение 1. После получения результата запроса для синхронизации используется таймер. Время реакции – это время работы этого таймера.
Методы класса TKRVariabels
  • updateAllVariabels – вызывает метод UpdateValue у всех переменных, которых интервал равен нулю
  • updateAllWaitingVariabels – вызывает метод UpdateValue у всех переменных, которых включено свойство WaitForUpdates
 
Поделиться:
0
Дмитрий Понкратьев
27.03.2021 07:17
 
Добрый день Руслан. Можешь пояснить логику работы обработчика события OnValUpdated.
Для клиентов, с которых я только считываю информацию каждые 100 мс, обновление происходит каждые 100 мс, а для клиентов в которые я должен писать с периодичностью 100 мс, обновление происходит каждые 200 мс. Наверное это связано с тем, что клиент тратит 1 интервал на запись данных в устройство?
Скажи а как можно заставить этот клиент не тратить время на чтение, а только записывать? Или уменьшить интервал для этого клиента до 50 мс?
Спасибо.

P.S. Поменял Interval на 50. Странно, но периодичность осталась таже 200 мс.
Показать полностью
13
Руслан Кандирал
27.03.2021 09:17
Дмитрий Понкратьев
 
Если при 50мс у вас запись проходит каждые 200мс, значит на саму запись тратится 200мс и наверняка у вас переполняется очередь сообщений.

UpAftWrite включено по умолчанию. Для увеличения скорости его лучше выключить, так как это дополнительный запрос.

Для максимальной скорости записи лучше использовать KRModbusMaster. Код ниже проводит запись на максимально возможной скорости

И если вы используете компоненты 2020 года, то там есть дополнительные задержки в коде. Лучше перейти на последнюю версию.
Показать полностью
0
Дмитрий Понкратьев
27.03.2021 16:20
Руслан Кандирал
 
Спасибо за столь развернутый ответ. Я попробовал вариант с этой функцией WriteHoldingRegisters. Только вызывал ее из отдельного потока с периодом в 100 мс. Перед вызовом проверял флаг ответа от клиента. В свойствах регистра клиента установил Interval = 0 и UpAftWrite = false.
Получается я запретил чтение этого регистра с данного устройства.
Так я вызываю функцию из отдельного потока:
Это калбэк функция:
Теперь у меня попутный вопрос. Для удобства тестирования выходов модуля и использовал TKRVCheckBox-ы и TKRBLField. Само собой раз чтение состояния регистра отключено, то и галочки не отображаются. Если принудительно записывать в adr24_mb0050_word.Value число которое я отправил в функции выше не вызовет ли это повторный запрос на запись в клиент?
Показать полностью
13
Руслан Кандирал
27.03.2021 17:21
Дмитрий Понкратьев
 
Да, код ниже отправит запрос записи
Учтите, что функция WriteHoldingRegister ни как не повлияет на значение adr24_mb0050_word.Value до обновления через интервал или функцией adr24_mb0050_word.UpdateValue

Можно интервал (mainformDozatorSM.adr24_mb0050_word.Interval) выставить в секунду (1000) или 500мс. Этого будет достаточно для обновления данных в визуальных компонентах. Будет отправляться запрос чтения и вы будете наверняка знать текущее значение.
Показать полностью
0
Дмитрий Понкратьев
27.03.2021 18:22
Руслан Кандирал
 
Моя задумка провалилась)
Хотел проверить функцию WriteHoldingRegister так сказать не выходя из дома)
1. При помощи этой функции отправляю в устройство по адресу 24 число 2
2. Установил (на время тестирования) interval = 100 и UpAftWrite = true
3. По идее мастер должен сам формировать запросы на чтение с периодом 100 мс и считать с устройства то число, которое мы отправили в п.1. (т.к. в устройстве в нужном регистре должно быть записано число 2)
4. В поле KRBLField должно отобразится число считанное с устройства, но там 0.
Может быть, я что-то не так делаю?
Может быть на работу функции WriteHoldingRegister могут влиять другие клиенты, которые тоже работают с этим мастером (мастер то 1)?
У меня три клиента модбас и 1 мастер.
Показать полностью
13
Руслан Кандирал
27.03.2021 18:28
Дмитрий Понкратьев
 
Какой тип у adr24_mb0050_word.MCVarType ?
Показать полностью
0
Дмитрий Понкратьев
27.03.2021 18:37
Руслан Кандирал
 
MCT_WORD
Показать полностью
13
Руслан Кандирал
27.03.2021 18:55
Дмитрий Понкратьев
 
Данные для отправки формируете так ?
Показать полностью
0
Дмитрий Понкратьев
27.03.2021 19:00
Руслан Кандирал
 
Нет, я использую функцию:
AData здесь типа Word вроде, я думал, что не нужно массив делать.
Показать полностью
13
Руслан Кандирал
27.03.2021 19:07
Дмитрий Понкратьев
 
Когда отправляете функцию записи нужно указать какие данные записываете

Показать полностью
0
Дмитрий Понкратьев
29.03.2021 11:55
Руслан Кандирал
 
Упс, ниже я ответил на свой комментарий)
Руслан добрый день!
Есть такой интересный вопрос. После отправки запроса на запись с помощью функции WriteHoldingRegisters, в случае если устройство не ответило или ошибка в ответе событие OnError сработает?
Дело в том, что я не отправляю новый запрос пока не отработает callback в функции WriteHoldingRegisters. Однажды так получилось, что callback не сработал и повторного запроса не было и модуль выходов перестал работать.
Показать полностью
0
Дмитрий Понкратьев
27.03.2021 21:48
Руслан Кандирал
 
Долго проверял свой код и обнаружил, что в одном таймере случайно обнулялось значение, которое я в устройство отправлял. Вот я и подумал, что функция не работает)
Потом я решил еще раз перепроверить функцию WriteHoldingRegister, которая в качестве параметра ADate принимала Word. Оказалось, что действительно эта функция не срабатывает. А вот WriteHoldingRegisters с параметром AData типа TKRRegisters для которого надо создавать массив и элементу массива уже присваивать то что хочешь отправить - действительно работает.
В общем, Руслан, спасибо тебе больше за твой труд, за твою работу.
Как я могу отблагодарить тебя? Напиши номер своей карты, я переведу тебе хоть немного денег. От души!
Показать полностью
Комментарий удален
13
Руслан Кандирал
29.03.2021 11:55
Дмитрий Понкратьев
 
Здравствуйте, Дмитрий

Функция 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 не вызовется.

По очередям коннектора есть статья
https://kandiral.ru/delphi/princip_rabot...
Показать полностью
0
Дмитрий Понкратьев
29.03.2021 12:50
Руслан Кандирал
 
Спасибо за ответ Руслан.
Поставил я два компонента KRConnectorQueueBar и один KRMBQueueBar.
Все компоненты показывают 0%. Только 1 компонент KRConnectorQueueBar с StackOut = false иногда меняется на 1%, потом опять 0%. Получается очереди вообще не переполняются?
Показать полностью
13
Руслан Кандирал
29.03.2021 13:12
Дмитрий Понкратьев
 
Получается, что да. По крайней мере за то время когда вы наблюдали за процессом
Показать полностью
13
Руслан Кандирал
27.03.2021 08:49
Дмитрий Понкратьев
 
Здравствуйте!
Тут, скорее всего нужна логика работы интервала обновления. При обновлении по интервалу используется обычный таймер, но только интервал у таймера не статичный, то есть не 100мс, а 100 минус время затраченное на обработку предыдущего запроса. Что касается OnValUpdated, то это событие вызывается каждый раз при удачном обновлении значения из клиента. Теоретически код ниже должен записывать значение каждые 100мс
Но, нужно учитывать тот факт, что сообщения для одной переменной обрабатываются последовательно, то есть пока мы не получим ответ (от клиента) на предыдущее сообщение, текущее отправляться не будет. И в таком случае, если отправка значения будет проходить более 100мс, мы можем получить переполнение очереди сообщений.

В данном случае нахватает события сигнализирующего об успешной записи (возможно в будущем я его добавлю). Но есть свойство UpAftWrite, при включении которого, после успешной записи отправляется запрос на чтение. Используя это свойство можно сделать так:
Показать полностью

Новости сайта

18.07.2021 14:30
Новая статья по экспорту Google Sheet в MS Excel
Экспорт таблиц Google Sheets в файл MS Excel с помощью Google Script, а также сохранение на Google Drive и отправка на e-mail
30.03.2021 14:53
Обновлен набор компонентов для Delphi
Пакет компонентов для Delphi обновлен до версии от 30.03.2021 г.
14.03.2021 04:54
Обновлен скрипт экспорта Google таблиц в PDF
Добавлены новые возможности при экспорте Google таблиц в PDF файл
22.01.2021 11:45
Обновлен пакет компонентов для Delphi
В пакет компонентов для Delphi было внесено большое количество изменений, касающиеся протокола Modbus и мультиязычности

Популярные статьи

Modbus Slave на Arduino
Реализация клиентской части протокола Modbus RTU и Modbus ASCII для контроллеров Arduino
Экспорт таблиц Google Sheets в PDF файл, на email и на Google диск
Экспорт таблиц Google Sheets в PDF файл с помощью Google Script с последующим скачиванием или сохранением на Google Drive или отправкой на почту
Инструкция по установке компонентов на Delphi
Подробная инструкция по установке компонентов на Delphi с видео обзором
Пример передачи данных по протоколу Modbus на Delphi
Пример передачи данных с контроллера ОВЕН ПЛК100 в программу на Delphi по протоколу Modbus