48673

Модель регулятора уровня жидкости

Курсовая

Коммуникация, связь, радиоэлектроника и цифровые приборы

Подводящая и отводящая труба – объекты одного класса TTube. Верхний и нижний датчик – объекты одного класса TSensor. Поэтому вводится понятие модели объект Relity класса TRelity. При этом отпадает необходимость в наличии класса TSignl.

Русский

2013-12-22

99 KB

2 чел.

1. ФОРМУЛИРОВКА ЗАДАЧИ

Модель регулятора уровня жидкости

Выполнить наглядное моделирование процесса регулирования уровня жидкости в емкости. В ёмкость через трубу сверху поступает жидкость, и через трубу снизу жидкость отводится. В отводящей трубе установлена заслонка. В ёмкости установлены два датчика уровня. Первый датчик подаёт сигнал “открыть заслонку”, если он погружён в жидкость. Второй датчик вырабатывает сигнал “закрыть заслонку”, если он не погружён в жидкость. Пользователю предлагается возможность изменять высоту расположения датчика и производительность потока из подводящей трубы. Во время эксперимента в цифровой форме отображается производительность потока жидкости и количество жидкости в ёмкости.

2. СИСТЕМНЫЙ АНАЛИЗ

2.1. Составление словаря системной области.

2.1.1. Перечислим факты, характеризующие системную область:

  1.  В ёмкость поступает жидкость.
  2.  Жидкость поступает через трубу сверху.
  3.  Жидкость отводится через трубу снизу.
  4.  В отводящей трубе установлена заслонка.
  5.  В ёмкости установлены два датчика уровня.
  6.  Первый датчик подаёт сигнал, если он погружен в жидкость.
  7.  Второй датчик подает сигнал, если он не погружён в жидкость.
  8.  Первый датчик подаёт сигнал “открыть заслонку”.
  9.  Второй датчик подаёт сигнал “закрыть заслонку”.
  10.  Пользователь может изменять высоту расположения датчиков и производительность потока из подводящей трубы.
  11.  В цифровой форме отображается производительность потока жидкости и количество жидкости в ёмкости.

2.1.2. Перечислим все объекты (существительные) с указанием фактов, в которых они упоминаются.

  1.  Ёмкость (1, 5, 11).
  2.  Жидкость (1, 2, 3, 6, 7, 11).
  3.  Подводящая труба (2, 10).
  4.  Отводящая труба (3, 4).
  5.  Заслонка (4, 8, 9).
  6.  Верхний датчик (5, 6, 8, 10).
  7.  Нижний датчик (5, 7, 9, 10).
  8.  Сигнал открыть заслонку” (6, 8).
  9.  Сигнал закрыть заслонку” (7, 9).
  10.  Производительность потока из подводящей трубы (10, 11).
  11.  Количество жидкости в ёмкости (11).


2.1.3. Разделим факты, относящиеся к каждому объекту, на три группы: “атрибуты”, ”поведение” и ”сообщения другим объектам”. В результате получим словарь системной области.

  •  Модель. (TReality)
  •  Атрибуты

Регулятор. (Regulator)

  •  Действия

Начать моделирование. (Run)

  •  Регулятор. (TRegulator)
  •  Атрибуты

Ёмкость (Vessel)

Подводящая труба (InTube).

Отводящая труба (OutTube).

Верхний датчик (HiSensor).

Нижний датчик (LoSensor).

  •  Действия

Изменить высоту датчика (ChangeHeight).

Изменить производительность потока (ChangePressure).

  •  Ёмкость. (TVessel)
  •  Атрибуты

Количество жидкости (LiquidAmount).

  •  Действия

Сообщить количество жидкости. (GetLiquidAmount)

Изменить количество жидкости. (ChangeLiquidAmount).

  •  Труба. (TTube)
  •  Атрибуты

Производительность. (Pressure)

Состояние. (State)

  •  Действия

Сообщить текущую производительность потока. (GetPressure)

Изменить производительность потока. (ChangePressure)

Закрыть / открыть заслонку (SetState)

  •  Сообщения другим объектам

Изменить количество жидкости. (MoveLiquid)

  •  Датчик. (TSensor)
  •  Атрибуты

Высота. (Height)

Вырабатываемый сигнал. (Signal)

Тип датчика. (SensorType)

  •  Действия

Сообщить высоту датчика. (GetHeight)

Установить высоту датчика. (SetHeight)

  •  Сообщения другим объектам

Подать сигнал.

  •  Сигнал. (TSignal)
  •  Атрибуты

Содержание. (What)

2.1.4. Примечания к словарю системной области.

  •  Подводящая и отводящая труба – объекты одного класса TTube. Верхний и нижний датчик – объекты одного класса TSensor. Это сделано для простоты, чтобы не усложнять схему наследования классов. Поведение этих объектов полностью определяется их атрибутами, общими для всех объектов, поэтому использовать наследование нецелесообразно.
  •  На моделируемый регулятор уровня жидкости оказывается воздействие со стороны внешнего источника (команды – изменить производительность потока, изменить высоту датчика). Поэтому вводится понятие модели (объект Reality класса TReality). Этот объект генерирует внешние события и воздействует на моделируемый регулятор (Run).

2.2. Техническое задание на проектирование

2.2.1. Функции системы.

  •  Отображение на экране монитора работы регулятора уровня жидкости в сосуде.
  •  Жидкость поступает в ёмкость по трубе сверху, имеется возможность изменить производительность потока этой трубы.
  •  Жидкость отводится из трубы снизу. У этой трубы - два состояния (открыто/закрыто), которые переключаются по сигналам от датчиков, установленных в ёмкости.
  •  В ёмкости установлены два датчика – верхний и нижний. Верхний подаёт сигнал открыть” отводящей трубе, если он погружен в жидкость. Нижний подаёт сигнал “закрыть” отводящей трубе, если он не погружён в жидкость. Имеется возможность регулировать высоту датчиков.
  •  На экране в цифровой форме отображается производительность верхней трубы и количество жидкости в ёмкости.
  •  Управление моделированием осуществляется при помощи команд, подаваемых с клавиатуры: изменить высоту датчика (клавиши , , , ), изменить производительность верхней трубы (клавиши +, - ), завершить работу программы (клавиша “Q”).

2.2.2. Эксплуатационные требования.

  •  Технические средства – ПЭВМ IBM PC;
  •  Операционная система – MS DOS;
  •  Процесс моделирования управляется одним оператором.

2.2.3. Ограничения на процесс разработки.

  •  Срок выполнения проекта – 24 мая 1999 года.

2.2.4. Диаграммы классов и объектов на стадии анализа приведены в Приложении 1.

3. ПРОЕКТИРОВАНИЕ

3.1. Идентификация классов и объектов

 

  •  По отношению к программной системе должны возникать внешние события: сигнал изменения высоты датчика, сигнал изменения производительности потока, сигнал начала моделирования. Кроме того, необходимо предусмотреть дополнительное событие - сигнал об окончании работы программной системы. Поэтому синтезируем класс "событие" (TEvent). При этом отпадает необходимость в наличии класса TSignal.
  •  Реальные объекты существуют в реальном времени, а для моделирования должно быть введено модельное время. Здесь могут быть реализованы различные механизмы. Первый вариант - проектирование процессов реального времени, при котором сигнал об изменении времени поступает извне программной системы, например, от таймера. Другой вариант - имитация времени самой программной системой. В данной курсовой работе реализуем первый вариант. Функцию генерации события наступления моментов времени возложим на объект класса "таймер" (TTimer).
  •  Проектируемая система должна обеспечивать отображение моделируемых объектов в виде графических фигур на экране дисплея. Каждый объект привязывается к определенной точке экрана. Поэтому вводим класс "точка" (TPiont) и класс "фигура" (TFigure), последний обобщает графические свойства всех графических объектов.

3.2. Идентификация содержания классов

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

Класс TPoint. Положение точки определяется координатами X и Y, которые являются атрибутами. Реальные объекты и их графические образы имеют разные линейные размеры и системы координат, поэтому для рассматриваемого класса следовало бы ввести еще один атрибут – масштаб. Для простоты будем считать что размеры всех графических объектов измеряются в единицах экранных координат.

Класс TFigure. Графические объекты в целом характеризуются своим положением на экране, поэтому атрибутом класса TFigure являются координаты левого верхнего угла прямоугольника, в котором располагается фигура (Origin). Графический объект при создании должен сразу располагаться в каком-то месте, поэтому для него требуется соответствующий конструктор. При моделировании изменения состояния фигур требуется убирать их изображения и перерисовывать, поэтому вводятся соответствующие правила Hide и Show. Введём также метод Draw, который будет отвечать за прорисовку объекта, и в зависимости от значения параметра Visible будет либо показывать, либо скрывать объект.

Класс TEvent. Событие характеризуется некоторым значением, по которому одно событие отличается от другого. Для хранения такого значения вводим общедоступный атрибут What.

Класс TTimer. Характеристиками таймера является длительность периода Interval между генерируемыми событиями и текущее значение счетчика CurTime. При создании соответствующего объекта следует установить его в начальное состояние и запомнить длительность периода генерации событий, для чего и вводится конструктор. Кроме того, основным назначением таймера является генерация событий и передача потребителю, что реализуется методом HandleEvent.

Далее рассмотрим классы, которые были "открыты" на стадии системного анализа.

Класс TVessel. Атрибутом данного класса является количество жидкости (LiquidAmount). Для получения / установки значения этого атрибута введём соответственно методы GetLiquidAmount и ChangeLiquidAmount. Переопределим для данного класса метод Draw, который будет рисовать частично заполненную ёмкость, при этом степень заполненности зависит от значения атрибута LiquidAmount.

Класс TTube. Атрибутами данного класса являются: тип трубы (TubeType), производительность потока (Pressure), состояние заслонки (State). Определим метод MoveLiquid, возвращающий значение изменения объёма жидкости в единицу времени (в зависимости от значений атрибутов Pressure и State). Переопределим для класса метод Draw, который будет рисовать трубу, направленную вниз или вверх (в зависимости от атрибута TubeType), частично, полностью или совсем не заполненную водой (в зависимости от атрибутов State и Pressure), с открытой или закрытой заслонкой (атрибут State). Для получения / изменения значения атрибута Pressure определим соответственно методы GetPressure и ChangePressure. Для установки состояния заслонки (атрибут State) введём метод SetState.

Класс TSensor. Определим для данного класса следующие атрибуты – тип (SensorType), высота (Height) и вырабатываемый сигнал (Signal). Определим методы GetHeight и ChangeHeight для доступа к полю Height, метод Show для прорисовки датчика в зависимости от значения атрибутов Height и Signal, и метод GetSignal для получения текущего состояния датчика (наличие/отсутствие сигнала).

Класс TRegulator. Для данного класса определим следующие атрибуты: Vessel – объект типа TVessel; InTube и OutTube – объекты типа TTube; HiSensor и LoSensor – объекты типа TSensor. Внешние события должны восприниматься объектом класса TRegulator, поэтому необходимо ввести соответствующий метод HandleEvent. Кроме того, необходимо предусмотреть метод Update, который изменяет состояние всех составных частей объекта класса TRegulator так, как будто прошел интервал времени еденичной длины. Определим дополнительный атрибут ActiveSensor, содержащий указатель на датчик, высота которого изменяется пользователем в данный момент.

Класс TReality. Объект данного класса содержит в себе в качестве атрибутов объект класса TRegulator и объект класса TTimer.

3.3. Идентификация связей между классами и объектами

  •  Обработка внешних событий ведется методами HandleEvent объектов типа TReality (приём событий от таймера и оператора, передача событий объекту типа TRegulator) и TRegulator (обработка событий).
  •  Метод Update объекта TRegulator изменяет состояние объектов InTube, OutTube, Vessel, UpSensor, DownSensor и вызывает перерисовку всех объектов системы.
  •  Сигнал, вырабатываемый датчиком, реализуется с помощью специального атрибута Signal класса TSensor. Метод Update класса TRegulator постоянно анализирует состояние этого атрибута, и при необходимости изменяет состояние объекта OutTube

3.4. Реализация классов и объектов

Все разработанные классы и выявленные объекты должны быть включены в проект. Уточненные диаграммы классов и объектов показаны в Приложении 1. Для диаграммы объектов составлена диаграмма взаимодействия, иллюстрирующая порядок взаимодействия кометы с другими объектами.

Относительно универсальные классы TPoint и TFigure, могут быть использованы в любой графической программной системе. Они составят модуль Figures. Оставшиеся классы относятся к изучаемой предметной области и будут входить в модуль LLReg (Liquid Level Regulator). Кроме того, для графического изображения простейших фигур необходимо использовать стандартный модуль графики Graphics. Головная программа main в данном случае является единственной и содержит инициализацию, выполнение и уничтожение единственного объекта класса TReality. Вся программная система реализуется одним процессом, поэтому нет необходимости составлять диаграмму процессов.

4. ПРОГРАММИРОВАНИЕ

Программирование выполняется на языке С++, что определено общими требованиями к курсовой работе. Основу для программирования составляют диаграммы и спецификации этапа проектирования. Необходимые детали разъясняются комментариями в тексте программы в Приложении 2.

5. ТЕСТИРОВАНИЕ


П
риложение 1 (рисунки)

Приложение 2 (текст программы)

// events.h - описание класса TEvent и констант событий

#ifndef events_h

#define events_h

// константы событий

enum TEvConstant

{

evNothing,           // событий нет

evTick,              // событие от таймера

evQuit,              // завершение работы программы

evIncreasePressure,  // увеличить давление

evDecreasePressure,  // уменьшить давление

evIncreaseHeight,    // увеличить высоту датчика

evDecreaseHeight,    // уменьшить высоту датчика

evLeftSensor,        // изменить высоту левого датчика

evRightSensor        // изменить высоту правого датчика

};

// Описание класса TEvent

class TEvent

{

public:

 TEvConstant What;   // тип события

};

#endif// figures.h - Интерфейс модуля графических фигур

#ifndef figures_h

#define figures_h

// Описание класса TPoint

class TPoint

{

public:

 int X,Y;         // экранные координаты точки

};

// Описание класса TFigure

class TFigure

{

protected:

 TPoint Origin;  // координаты левого верхнего угла фигуры

public:

 TFigure(int X, int Y);                 // конструктор

 virtual void Draw(int Visible) = 0;    // прорисовка объекта

 virtual void Show();

 virtual void Hide();

 TPoint GetOrigin();                    // методы для доступа к полю Origin

 void SetOrigin(TPoint Point);           

};

#endif

// figures.cpp - Реализация модуля графических фигур

#include "figures.h"

#include <graphics.h>

// Методы класса TFigure

TFigure::TFigure(int X, int Y)

{

TPoint tmp;   

tmp.X = X;

tmp.Y = Y;

Origin = tmp;    // Инициализация объекта Origin параметрами конструктора

};

void TFigure::Show()

{

Draw(1);         // Нарисовать фигуру

};

void TFigure::Hide()

{

Draw(0);         // Спрятать фигуру (закрасить черным)

};

TPoint TFigure::GetOrigin()

{

return Origin;   // возвращает координаты фигуры

};

void TFigure::SetOrigin(TPoint Point)

{

Origin = Point;  // изменение координат фигуры

};

// regparts.h - интерфейс модуля regparts (Классы TVessel, TTube, TSensor)

#ifndef regparts_h

#define regparts_h

#include "figures.h"

enum TTubeTypes {tInTube, tOutTube};             // типы труб

enum TTubeStates {stClosed, stOpen};             // состояния трубы

enum TSensorTypes {tHiSensor, tLoSensor};        // типы датчиков

enum TSensorSignal {sigNone, sigClose, sigOpen}; // типы сигналов датчиков

// Описание класса TVessel (емкость)

class TVessel : public TFigure

{

private:

 float LiquidAmount;    // Количество жидкости

 float Capacity;        // Максимальный объем жидкости

public:

 TVessel(float parCap, int parX, int parY);

 void Draw(int Visible);            // переопределенный метод для прорисовки

 float GetLiquidAmount();           // методы для доступа к полю LiquidAmount

 void ChangeLiquidAmount(float Delta);

};

// Описание класса TTube (труба)

class TTube : public TFigure

{

private:

 TTubeTypes TubeType;   // Тип трубы (входящая/отводящая)

 TTubeStates State;     // Состояние трубы (открыто/закрыто)

 float Pressure;        // Производительность (давление)

public:

 TTube(TTubeTypes parType, float parPressure, int parX, int ParY);

 void Draw(int Visible);               // переопределение метода для прорисовки

 float GetPressure();                  // методы для доступа к полю Pressure

 void ChangePressure(float Delta);

 void SetState(TTubeStates NewState);  // установка состояния трубы

 float MoveLiquid(); // возвращает количество жидкости, перенесенной трубой

                     // в единицу времени (с учетом давления и состояния)                

};

// Описание класса TSensor (датчик)

class TSensor : public TFigure

{

private:

 TSensorTypes SensorType; // тип датчика (верхний/нижний)

 TSensorSignal Signal;    // текущий сигнал датчика

 int Height;              // высота на которой расположен датчик

public:

 TSensor(TSensorTypes parType, int parHeight, int parX, int parY);

 void Draw(int Visible);       // переопределение метода для прорисовки

 int GetHeight();              // методы для доступа к полю Height

 void ChangeHeight(int Delta);

 TSensorSignal GetSignal(int Level); // возвращает сигнал датчика

};

#endif// regparts.cpp - реализация модуля regparts (классы TVessel, TTube, TSensor)

#include <graphics.h>

#include "regparts.h"

// Методы класса TVessel

TVessel::TVessel(float parCap, int parX, int parY) : TFigure(parX, parY)

{

Capacity = parCap;     // инициализация полей

LiquidAmount = 0;

};

void TVessel::Draw(int Visible)

{

int X1 = Origin.X;

int Y1 = Origin.Y;

if (!Visible)                      // реализация закрашивания (Hide)

{

 setcolor(BLACK);

 setfillstyle(SOLID_FILL,BLACK);

 bar(X1,Y1,X1+202,Y1+402);

 return;

};

setcolor(WHITE);                   // прорисовка объекта (Show)

line(X1,Y1,X1+202,Y1);

line(X1+202,Y1,X1+202,Y1+402);

line(X1+202,Y1+402,X1,Y1+402);

line(X1,Y1+11,X1,Y1+391);

setfillstyle(SOLID_FILL,BLACK);

bar(X1+1,Y1+1,X1+201,Y1+401-LiquidAmount);

setfillstyle(SOLID_FILL,BLUE);

bar(X1+1,Y1+401-LiquidAmount,X1+201,Y1+401);

};

float TVessel::GetLiquidAmount() // возвращает текущее количество жидкости

{

return LiquidAmount;

};

void TVessel::ChangeLiquidAmount(float Delta)

{

 // изменение количества жидкости на Delta (с учетом макс. емкости сосуда)

if (Delta == 0) return;

float testLA = LiquidAmount + Delta;

if (testLA > Capacity) LiquidAmount = Capacity;

else if (testLA < 0) LiquidAmount = 0;

     else LiquidAmount = testLA;

setfillstyle(SOLID_FILL,BLACK); // закрашиваем поле для вывода нового

bar(525,120,640,130);           //  количества жидкости

};

// Методы объекта TTube

TTube::TTube(TTubeTypes parType, float parPressure, int parX, int parY)

: TFigure(parX, parY)

{

TubeType = parType;      // Инициализация полей

Pressure = parPressure;

if (TubeType == tInTube) State = stOpen;

else State = stClosed;

};

void TTube::Draw(int Visible)

{

int X1 = Origin.X;

int Y1 = Origin.Y;

if(!Visible)                      // Закрашивание черным цветом (Hide)

{

 setfillstyle(SOLID_FILL,BLACK);

 bar(X1,Y1,X1+100,Y1+10);

 return;

};

setcolor(WHITE);                  // Прорисовка в зависимости от текущего

line(X1,Y1,X1+100,Y1);            //  состояния трубы

line(X1,Y1+10,X1+100,Y1+10);

int col1 = BLUE, col2 = BLUE;

if (State == stClosed)

{

 if (TubeType == tOutTube) col1 = BLACK;

 else col2 = BLACK;

};

if ((Pressure == 0)&&(TubeType == tInTube))

 col1 = BLACK, col2 = BLACK;

setfillstyle(SOLID_FILL,col1);

bar(X1,Y1+1,X1+50,Y1+9);

setfillstyle(SOLID_FILL,col2);

bar(X1+51,Y1+1,X1+100,Y1+9);

if (State == stClosed) line(X1+50,Y1,X1+50,Y1+10);

};

float TTube::GetPressure()   // возвращает текущую производительность трубы

{

return Pressure;

};

void TTube::ChangePressure(float Delta) // изменение давления на Delta

{

float testP = Pressure + Delta;

if (testP < 0) Pressure = 0;

else if (testP > 10) Pressure = 10;

     else Pressure = testP;

setfillstyle(SOLID_FILL,BLACK);        // закрашиваем поле для вывода

bar(525,100,640,110);                  //  нового значения давления

};

void TTube::SetState(TTubeStates NewState)  // Установка состояния трубы

{

State = NewState;

};

float TTube::MoveLiquid()

{

 // Метод возвращает количество жидкости, перенесенной трубой

 //  в единицу времени с учетом типа трубы и состояния заслонки

int sign = (TubeType == tInTube) ? +1 : -1;

if (State == stClosed) sign = 0;

return Pressure * sign;

};

// Методы класса TSensor

TSensor::TSensor(TSensorTypes parType, int parHeight, int parX, int parY) :

TFigure(parX, parY)

{

SensorType = parType;   // Иницицализация полей

Signal = sigNone;

Height = parHeight;

};

void TSensor::Draw(int Visible)

{

  // Реализация прорисовки в зависимости от состояния датчика

int X1 = Origin.X;

int Y1 = Origin.Y - Height;

int col = (Signal == sigNone) ? (LIGHTGREEN):(LIGHTRED);

if (Visible) setcolor(col);

 else setcolor (BLACK);

line(X1-9,Y1,X1+9,Y1);

};

int TSensor::GetHeight()

{

return Height;  // возвращает текущую высоту датчика

};

void TSensor::ChangeHeight(int Delta) // изменение высоты датчика на Delta

{

Hide();

int testH = Height + Delta;

if (testH > 389) testH = 389;

else if (testH < 11) testH = 11;

Height = testH;

Show();

};

TSensorSignal TSensor::GetSignal(int Level)

{

 // Возвращает сигнал в зависимости от уровня жидкости, высоты и типа датчика

Signal = sigNone;

switch (SensorType)

{

 case tLoSensor:

   if (Level < Height) Signal = sigClose; break;

 case tHiSensor:

   if (Level > Height) Signal = sigOpen;  break;

};

return Signal;

};

// reg.h - Заголовок модуля Reg (Описание класса TRegulator)

#ifndef reg_h

#define reg_h

#include "regparts.h"

#include "events.h"

class TRegulator

{

private:

 TVessel *Vessel;          // Поля класса - емкость, входная и выходная трубы,

 TTube *InTube, *OutTube;  // верхний и нижний датчики, текущий датчик

 TSensor *LoSensor, *HiSensor, *ActiveSensor;

public:

 TRegulator();

 ~TRegulator();

 void HandleEvent(TEvent *Event); // Метод обработки событий

 void Update();                   // Обновление всех компонентов регулятора

 void ShowAll();                  // Вывод на экран всех компонентов

 void ShowParams();               // Вывод текущих параметров регулятора

};

#endif

// reg.cpp - Реализация модуля Reg (Класс TRegulator)

#include "reg.h"

#include <graphics.h>

#include <stdio.h>

TRegulator::TRegulator()

{

Vessel = new TVessel(400,100,25);              // Создание всех компонентов

InTube = new TTube(tInTube,9,0,25);

OutTube = new TTube(tOutTube,10,0,417);

LoSensor = new TSensor(tLoSensor,100,90,425);

HiSensor = new TSensor(tHiSensor,300,312,425);

ActiveSensor = LoSensor;  // Делаем текущим нижний датчик

};

TRegulator::~TRegulator()

{

delete HiSensor;   // Удаление из памяти всех компонентов

delete LoSensor;

delete OutTube;

delete InTube;

delete Vessel;

};

void TRegulator::HandleEvent(TEvent *Event)

{

// Определим макрос - конец обработки события в операторе switch

#define END_OF_EVENT Event->What = evNothing; \

                    break

// Обработка событий

switch (Event->What)

{

 case evTick:

   Update(); END_OF_EVENT;

 case evIncreasePressure:

   InTube->ChangePressure(+1);     END_OF_EVENT;

 case evDecreasePressure:

   InTube->ChangePressure(-1);     END_OF_EVENT;

 case evIncreaseHeight:

   if ((HiSensor->GetHeight() - LoSensor->GetHeight()) > 1)

    ActiveSensor->ChangeHeight(+1);

   else if (ActiveSensor == HiSensor)

    ActiveSensor->ChangeHeight(+1);END_OF_EVENT;

 case evDecreaseHeight:

   if ((HiSensor->GetHeight() - LoSensor->GetHeight()) > 1)

    ActiveSensor->ChangeHeight(-1);

   else if (ActiveSensor == LoSensor)

    ActiveSensor->ChangeHeight(-1);END_OF_EVENT;

 case evLeftSensor:

   ActiveSensor = LoSensor;        END_OF_EVENT;

 case evRightSensor:

   ActiveSensor = HiSensor;        END_OF_EVENT;

};

#undef END_OF_EVENT     // отмена макроса END_OF_EVENT

};

// Обновление всех компонентов регулятора (после события evTick)

void TRegulator::Update()

{

float delta = InTube->MoveLiquid() + OutTube->MoveLiquid();

Vessel->ChangeLiquidAmount(delta);               // Изменяем объем жидкости

float curLA = Vessel->GetLiquidAmount();         //  в емкости

TSensorSignal sig1 = LoSensor->GetSignal(curLA); // Опрашиваем датчики

TSensorSignal sig2 = HiSensor->GetSignal(curLA);

TSensorSignal sig = sig1;                        // Находим сигнал

if (sig1 == sigNone) sig = sig2;

switch (sig)                    // Передаем сигнал выходной трубе

{

 case sigOpen  : OutTube->SetState(stOpen);   break;

 case sigClose : OutTube->SetState(stClosed); break;

};

ShowAll();                      // Перерисовка всех объектов

};

void TRegulator::ShowAll()

{

Vessel->Show();        // Перерисовка всех компонентов регулятора

InTube->Show();

OutTube->Show();

HiSensor->Show();

LoSensor->Show();

ShowParams();          // Вывод текущих параметров

};

void TRegulator::ShowParams()

{

setcolor(WHITE);

char buffer[80];       // Буфер для форматирования строки

sprintf(buffer, "     Pressure : %.2f", InTube->GetPressure());

outtextxy(400,100,buffer); // Вывод значения давления

sprintf(buffer, "Liquid amount : %.2f", Vessel->GetLiquidAmount());

outtextxy(400,120,buffer); // Вывод количества жидкости

};

// reality.h - Заголовок модуля элементов модели регулятора

#ifndef reality_h

#define reality_h

#include "reg.h"

#include "events.h"

// константы проектирования

int const cTimerInterval = 1; // период генерации событий времени

// Описание класса TTimer

class TTimer

{

private:

 long CurTime;         // текущее время

 int Interval;         // период генерации события evTick

public:

 TTimer(int anInterval);

 void HandleEvent(TEvent *Event);

};

// Описание класса TReality

class TReality

{

private:

 TRegulator *Regulator; // Поля - указатели на TRegulator и TTimer

 TTimer *Timer;

public:

 TReality();

 ~TReality();

 void Run();            // основной цикл обработки событий программы

};

#endif

// reality.cpp - Реализация модуля элементов модели регулятора

#include "reality.h"

#include <graphics.h>

#include <ctype.h>

#include <conio.h>

#include <bios.h>

// Методы класса TTimer

TTimer::TTimer(int anInterval)

{

Interval = anInterval;        // задаем интервал генерации evTick

long dummy = 0;               // фиктивная переменная для вызова biostime

CurTime = biostime(0,dummy);  // запоминаем текущее время

};

void TTimer::HandleEvent(TEvent* Event)

{

long tmp;

long dummy = 0;

long NextTime = CurTime + Interval; // вычисляем время следующего события evTick

tmp = biostime(0,dummy);            // узнаем текущее время

if((tmp >= NextTime)||(NextTime-tmp > Interval))

{

 CurTime = tmp;        // если время пришло, то устанавливаем новое значение

 Event->What = evTick; // CurTime и генерируем событие evTick

};

};

// Методы класса TReality

TReality::TReality()

{

int gdriver = DETECT;                  // Установка графического режима

int gmode;

initgraph(&gdriver, &gmode,"");

setcolor(GREEN);                       // Вывод подсказки

outtextxy(400,300,"Control keys");

outtextxy(330,320,"<- / ->   : Switch active sensor");

outtextxy(330,340,"Up / Down : Change height");

outtextxy(330,360," + / -    : Increase/Decrease pressure");

outtextxy(330,380,"   Q      : Quit");

Timer = new TTimer(cTimerInterval);    // Создание таймера

Regulator = new TRegulator;            // Создание объекта Регулятор

}

TReality::~TReality()

{

delete Regulator;      // удаление из памяти объекта Регулятор

delete Timer;          // удаление из памяти таймера

closegraph();          // отмена графического режима (переход в текстовый)

};

void TReality::Run()    // Основной цикл обработки событий

{

TEvent Event;                   // Создание пустого события

Event.What = evNothing;

do {

    Timer->HandleEvent(&Event); // Опрос таймера

    if (kbhit())                // Опрос клавиатуры

     {

      char ch = getch();

      switch(toupper(ch))       // Анализ событий от клавиатуры

        {

          case '+' : Event.What = evIncreasePressure;    break;

          case '-' : Event.What = evDecreasePressure;    break;

          case  0  : switch(getch())

                     {

                       case 75: Event.What = evLeftSensor;     break;

                       case 77: Event.What = evRightSensor;    break;

                       case 72: Event.What = evIncreaseHeight; break;

                       case 80: Event.What = evDecreaseHeight; break;

                     };                                  break;

          case 'Q' : Event.What = evQuit;                break;

        };

     };

    Regulator->HandleEvent(&Event);  // Передача события регулятору

   } while(Event.What != evQuit);    // Выход из цикла обработки событий

};

// main.cpp - Головная программа проекта "Регулятор уровня жидкости"

#include "reality.h"

int main()

{

 TReality Reality;     // создание объекта - модели

 Reality.Run();        // запуск цикла обработки событий

 return 0;

};

15


 

А также другие работы, которые могут Вас заинтересовать

7220. Автоматизация междугородной связи с использованием ЦСК АХЕ - 10 303 KB
  Введение. Успешная деятельность современного человеческого общества невозможна без наличия специальных средств связи, обеспечивающих общение и взаимный обмен информацией между людьми независимо от расстояния. С каждым годом в мире возрастает объём и...
7221. Спроектировать двухступенчатый горизонтальный коническо-цилиндрический редуктор общего назначения привода ленточного конвейера 1.39 MB
  Задание проекта Спроектировать двухступенчатый горизонтальный коническо-цилиндрический редуктор общего назначения привода ленточного конвейера. Рис. 1. - Кинематическая схема привода ленточного конвейера: 1-двигатель 2- ременная передача...
7222. Технология радиальной ковки для производства полых изделий из сплошной заготовки без прошивки 437 KB
  1.Введение Технология радиальной ковки для производства полых изделий из сплошной заготовки без прошивки Технология основана на использовании специальных режимов деформирования сплошной заготовки на радиально-ковочной машине (РКМ). Технология не пре...
7223. Расчёт электрических нагрузок электрической цепи питающей трехфазные асинхронные двигатели 276 KB
  Контрольное задание. Расчет электрических нагрузок по методу коэффициента максимума. Расчет среднесменной нагрузки. Расчёт активной среднесменной нагрузки. Расчёт реактивной среднесменной нагрузки. Расчёт средневзвешенных зна...
7224. Электропривод звена промышленного робота (поворот колонны) 1.44 MB
  Введение Современный электропривод представляет собой конструктивное единство электромеханического преобразователя энергии (двигателя), силового преобразователя и устройства управления. Он обеспечивает преобразование электрической энергии в механиче...
7225. Расчет асинхронного двигателя с фазным ротором 280 KB
  Расчет асинхронного двигателя с фазным ротором Техническое задание Спроектировать трехфазный асинхронный двигатель с фазным ротором: Р2 = 28 кВт U = 220/380 В 2р = 4 конструктивное исполнение IM1001 исполнение по способу защиты IP23 способ охла...
7226. Построить электронное устройство в соответствии с предложенной схемой и исходными данными 712.5 KB
  1. Введение Целью курсового проекта является закрепление знаний по курсу Схемотехника ЭВМ и освоение методов расчета, схемотехнического проектирования и конструирования блоков и элементов ЦВМ. При выполнении проекта необходимо построить электронно...
7227. Маркетинговые исследования рынка импортных косметических средств по уходу за кожей 260.8 KB
  Маркетинговые исследования рынка импортных косметических средств по уходу за кожей Введение Косметика в переводе с греческого - искусство украшать. Косметика зародилась одновременно с появлением человека. Ее история тесно связана с уровнем ...
7228. Выбор и расчет рациональных способов восстановления деталей на примере толкателя клапанов тракторного двигателя 370.5 KB
  Выбор и расчет рациональных способов восстановления деталей на примере толкателя клапанов тракторного двигателя Задание Необходимо выбрать оптимальный способ восстановления детали с подробным описанием операций, расчетом времени и себестоимости...