Навигация:
<< >> Оглавление Указатель

Описание пользователя

Глава 3. Использование стандартных модулей автокомпиляции

§3.6. Принципы создания автокомпилируемых моделей блоков

§3.6.3. Работа с динамическими переменными

§3.6.3.3. Динамические переменные сложных типов

Рассматривается работа с динамическими переменными сложных типов – структурами, матрицами и т.п.

В примерах в §3.6.3.1 и §3.6.3.2 модели блоков работали с простыми динамическими переменными вещественного типа double. Динамическая переменная может быть любого типа, допустимого в RDS: структурой, матрицей, матрицей структур и т.п. В автокомпилируемых моделях обращение к таким сложным переменным производится по стандартным для языка C правилам: индексы массивов записываются в квадратных скобках, имена полей структур отделяются от имен самих переменных точкой. Фактически, во фрагментах программ, вводимых пользователем в редактор модели, обращение к динамической переменной ничем не отличается от обращения к статической.

В §3.6.3.2 были рассмотрены блоки, обеспечивающие схему значением температуры окружающей среды, которая передавалась через вещественную динамическую переменную «AmbientTemperature». Пусть блокам в этой схеме нужна не только температура среды, но и влажность и атмосферное давление. Можно было бы завести еще пару вещественных динамических переменных и записывать эти значения в них, но при этом в блоках, присваивающих значения переменным, потребовалось бы три вызова функции NotifySubscribers для уведомления остальных блоков об изменении значения – по одному вызову для каждой переменной. Вероятнее всего, все три этих значения будут изменяться одновременно, в момент считывания параметров окружающей среды или расчета динамики их изменения каким-либо блоком. Удобнее будет создать структуру, полями которой будут температура, влажность и давление, и динамическую переменную такого типа. Блок, вычисливший или получивший новые параметры окружающей среды, будет записывать их в поля структуры и делать единственный вызов NotifySubscribers.

Назовем структуру, в которой буду храниться параметры среды, «Ambience», а ее поля для температуры, влажности и давления – «Temperature», «Humidity» и «Pressure» соответственно. Для добавления в RDS этой структуры нужно выполнить следующие шаги:

Структура Ambience в окне редактирования структуры

Рис. 398. Структура «Ambience» в окне редактирования структуры

Как и в примере из §3.6.3.2, создадим блоки с автокомпилируемыми моделями, одна из которых будет создавать динамическую структуру типа «Ambience» и записывать в ее поля значения входов блока, а другая – считывать поля структуры и выдавать их на свои выходы. Динамическую переменную назовем точно так же, как и тип структуры – «Ambience».

Начнем с блока, записывающего свои входы в динамическую переменную. У него будет три входа: «H» – для влажности, «T» – для температуры, и «P» – для давления. Структура его переменных будет такой:

Имя Тип Вход/выход Пуск Начальное значение
Start Сигнал Вход 1
Ready Сигнал Выход 0
H double Вход 0
T double Вход 0
P double Вход 0

Модель блока будет запускаться при самом первом запуске расчета (у сигнала «Start» единичное начальное значение) и при поступлении нового значения на входы «H», «T» и «P» (у них установлен флажок «пуск»). Создадим новый блок с автокомпилируемой моделью, зададим для него запуск по сигналу и введем в редакторе модели его структуру переменных. Чтобы наш блок создавал динамическую структуру, выполним следующие шаги:

На вкладке «модель» окна редактора введем следующий текст:

  // Запись входов в поля структуры
  Ambience.Temperature=T;
  Ambience.Humidity=H;
  Ambience.Pressure=P;
  // Уведомление подписчиков об изменении данных
  Ambience.();

Здесь мы по очереди записываем в поля структуры входы блока, соответствующие этим полям по смыслу – имя поля (например, Humidity) отделяется от имени переменной (Ambience) точкой. В последней строчке программы мы, как и в предыдущих примерах, вызываем у динамической переменной функцию-член NotifySubscribers, которая уведомляет все блоки, подписавшиеся на эту переменную, о том, что мы записали в нее новые значения (при этом в моделях этих блоков вызывается реакция на изменение динамической переменной).

Теперь займемся блоком, который будет выдавать значения полей динамической структуры на выходы. Назовем выходы блока так же, как и поля структуры: «Temperature» (температура), «Humidity» (влажность) и «Pressure» (давление):

Имя Тип Вход/выход Пуск Начальное значение
Start Сигнал Вход 1
Ready Сигнал Выход 0
Temperature double Выход 0
Humidity double Выход 0
Pressure double Выход 0

Создадим новый блок с автокомпилируемой моделью, зададим для него запуск по сигналу, введем в модель приведенную выше структуру переменных и добавим подписку на переменную «Ambience». Для этого:

На вкладке «модель» редактора мы не будем ничего вводить – наша модель не выполняет вычислений в такте расчета. Вместо этого мы добавим в нее реакцию на изменение динамической переменной, в которую введем следующий текст программы:

  // Запись полей структуры в выходы
  Temperature=Ambience.Temperature;
  Humidity=Ambience.Humidity;
  Pressure=Ambience.Pressure;
  Ready=1;  // Выходные связи должны сработать

В этой реакции мы переписываем значения из полей динамической переменной Ambience в соответствующие этим полям выходы блока и взводим сигнал Ready, чтобы выходные связи блока сработали в следующем такте расчета.

Для проверки этих моделей соберем схему, изображенную на рис. 399. В этой схеме слева расположен блок с моделью, записывающий входы в динамическую структуру, а справа – блок, подающий поля этой структуры на выходы. Запустив расчет и изменяя значения в полях ввода левого блока, можно увидеть, что значения на индикаторах правого блока изменяются синхронно.

Тестирование блоков, работающих с динамической структурой

Рис. 399. Тестирование блоков, работающих с динамической структурой

В рассмотренном примере у нас было три отдельных вещественных входа, которые мы записывали в поля структуры, и три отдельных вещественных выхода, на которые мы подавали эти же поля в другом блоке. Это позволило показать, как в тексте программы осуществляется обращение к отдельным полям сложной динамической переменой, но, в данном простом примере, такое решение не оптимально. Если бы мы сделали у левого блока вход типа «Ambience», а у правого – выход того же типа, в каждой из моделей можно было бы обойтись одним единственным оператором присваивания. Пусть вход левого блока называется «X», а выход правого – «Y», оба они – структуры типа «Ambience». В этом случае модель левого блока выглядела бы так:

  // Копирование структуры-входа в динамическую структуру
  Ambience=X;
  // Уведомление подписчиков об изменении данных
  Ambience.();

Модель правого блока содержала бы обратный оператор присваивания:

  // Копирование динамической структуры в выход
  Y=Ambience;
  Ready=1;  // Выходные связи должны сработать

В объектах, создаваемых модулем автокомпиляции для доступа к статическим и динамическим переменным, переопределен оператор присваивания, поэтому приведенная выше запись допустима. В схеме с новой моделью поля ввода и индикаторы нужно было бы подключать уже не к отдельным входам и выходам, а к полям переменных «X» и «Y» (рис. 400).

Блоки, работающие с динамической структурой, входы и выходы которых – тоже структуры

Рис. 400. Блоки, работающие с динамической структурой,
входы и выходы которых – тоже структуры

Работа с динамическими массивами, матрицами и строками производится аналогичным образом: все операторы, применяемые к статическим переменным этих типов, могут применяться и к динамическим. Например, если DynArray – динамический массив, то к его i-му элементу можно обратиться оператором «DynArray[i]». Функции NotifySubscribers, GetLink и CheckLink при этом всегда применяются к самой динамической переменной, а не к ее отдельным элементам: например, для динамического массива DynArray нужно записывать DynArray.NotifySubscribers().


<< >> Оглавление Указатель