![](/user_photo/764_YDw3h.jpg)
3.2 Описание языка программирования
Управляющая программа разработана на языке программирования высокого уровня Delphi 7 и предназначена для работы в операционных системах Windows 98, Windows 2000 и Windows XP.
Delphi — это среда быстрой разработки, в которой в качестве языка программирования используется язык Delphi. Язык Delphi — строго типизированный объектно-ориентированный язык, в основе которого лежит Object Pascal.
При написании программы использовались следующие типа данных: integer, real, string, boolean.
Язык Delphi поддерживает семь целых типов данных: shortint, smailint, Longint, Int64, Byte, word и Longword, описание которых приведено в таблице 4.
Object Pascal поддерживает и наиболее универсальный целый тип - Integer, который Эквивалентен Longint.
Таблица 4 – Целые типа данных
Тип |
Диапазон |
Формат |
Shortint |
-128-127 |
8 битов |
Smallint |
-32 768 - 32 767 |
16 битов |
Longint |
-2 147 483 648 - 2 147 483 647 |
32 бита |
Int64 |
-263- 263 - 1 |
64 бита |
Byte |
0-255 |
8 битов, беззнаковый |
Word |
0-65 535 |
16 битов, |
Longword |
0 - 4 294 967 295 |
32 бита, беззнаковый |
Язык Delphi поддерживает шесть вещественных типов: Reai48, single, Double, Extended. Типы различаются между собой диапазо-ном допустимых значений, количеством значащих цифр и количеством байтов, необходимых для хранения данных в памяти компьютера (таблица 5).
Таблица 5 – Вещественные типа данных
Тип |
Диапазон |
Real48 |
2.9x 10-39-1.7x1038 |
Single |
1.5 x 10-45-3.4х 1038 |
Double |
5.0x10-324 -1.7x10308 |
Extended |
3.6x10-4951 -1.1 х104932 |
Язык Delphi поддерживает и наиболее универсальный вещественный тип - Real, который эквивалентен Double.
Язык Delphi поддерживает три строковых типа: shortstring, Longstring
- WideString:
- тип shortstring представляет собой статически размещаемые в памяти компьютера строки длиной от 0 до 255 символов;
- тип Longstring представляет собой динамически размещаемые в памяти строки, длина которых ограничена только объемом свободной памяти;
- тип WideString представляет собой динамически размещаемые в памяти строки, длина которых ограничена только объемом свободной памяти. Каждый символ строки типа WideString является Unicode-символом.
В языке Delphi для обозначения строкового типа допускается использование идентификатора string. Тип string эквивалентен типу shortstring.
Логическая величина может принимать одно из двух значений True (истина) или False (ложь). В языке Delphi логические величины относят к типу Boolean.
3.3 Описания управляющей программы
Для корректной работы программы необходимо задать диапазон изменения плотности рабочей жидкости ρ и необходимый расход Q . По умолчанию ρ присваиваются значения от 850 до 870. При установки неверных диапазонов программа будет предупреждать об ошибке.
Далее следует выбрать com-порт, к которому подключен внешний модуль ЦАП/АЦП и установить скорость порта.
Программа автоматической коррекции может работать в трех основных режимах:
- единичный расчет;
- запись результатов в файл;
- запись результатов в com-порт.
Рисунок 15 – Предупреждение о неверном указании диапазона исходных данных
Режим единичного расчета позволяет в ручную ввести значение плотности и получить посчитанную величину управляющего напряжения U. Для наглядности исходные и полученные данные отображаются на графике.
Рисунок 16– Программа автоматической коррекции в режиме единичного расчета
В режиме записи результатов в файл происходит опрос com-порта и расчет управляющего воздействия. В поле «Периодичность опроса» задается частота опроса com-порта. Полученные данные в лог-файл. По умолчанию файл создается в корневом каталоге диска C с именем result.txt. Данные имеют табличную форму и могут в дальнейшем использоваться для статистических исследований.
Рисунок 17 – Лог-файл
Режим записи результатов в com-порт аналогичен режиму записи результатов в файл за исключением того, что программа полученные данные записывает в com-порт. В данном режиме так же можно установить периодичность опроса.
В режимах записи результата в файл и в com-порт для наглядности строиться временная диаграмма, на которой показывается текущая плотность и соответствующее ей напряжение.
Рисунок 18 – Программа автоматической коррекции в режиме записи результата в файл
Рисунок 18 – Временная диаграмма
3.4 Листинг программы
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, uRS232;
type
TForm1 = class(TForm)
Label1: TLabel;
Edit2: TEdit;
Label4: TLabel;
Label5: TLabel;
Edit3: TEdit;
Edit4: TEdit;
Label6: TLabel;
GroupBox1: TGroupBox;
GroupBox2: TGroupBox;
RadioGroup1: TRadioGroup;
Edit5: TEdit;
Label7: TLabel;
Button1: TButton;
Label8: TLabel;
Edit6: TEdit;
Image1: TImage;
Label9: TLabel;
ComboBox1: TComboBox;
Label10: TLabel;
ComboBox2: TComboBox;
GroupBox3: TGroupBox;
Button2: TButton;
Label11: TLabel;
Edit7: TEdit;
Label12: TLabel;
Image2: TImage;
Timer1: TTimer;
emu: TCheckBox;
Label2: TLabel;
function proverka():boolean;
procedure graphik1;
function Napryajenie(p:real):real;
procedure Button1Click(Sender: TObject);
procedure RadioGroup1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure emuClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
const Kqp=5;
Kuq=0.04;
var
Form1: TForm1;
x, Pred_y, Nov_y: integer;
f: textfile;
comport: trs232;
implementation
{$R *.dfm}
function TForm1.proverka():boolean;
var a: integer;
b: boolean;
begin
//Проверка введенных данных на корректность
b:=false;
try
a:=StrToInt(edit2.text);
except
on EConvertError do
begin
b:=true;
edit2.setfocus;
end;
end;
try
a:=StrToInt(edit3.text);
except
on EConvertError do
begin
b:=true;
edit3.setfocus;
end;
end;
try
a:=StrToInt(edit4.text);
except
on EConvertError do
begin
b:=true;
edit4.setfocus;
end;
end;
if b then
begin
showmessage('Ошибка в исходных данных');
end;
proverka:=b;
end;
procedure TForm1.graphik1;
var x0,y0,x,y: integer;
nap: real;
begin
//Рисование графика при единичном расчете
x0:=60;
y0:=40;
Image1.Canvas.Brush.Color:=clBtnFace;
Image1.Canvas.FillRect(rect(0,0,image1.Width,image1.Height));
image1.Canvas.Font.Size:=10;
image1.Canvas.Font.Color:=clBlack;
image1.Canvas.Font.Style:=[];
image1.Canvas.Pen.Color:=clBlack;
image1.Canvas.Pen.Style:=psSolid;
//оси
image1.Canvas.Pen.Width:=3;
image1.Canvas.MoveTo(x0,10);
image1.Canvas.LineTo(x0,image1.Height-y0);
image1.Canvas.LineTo(image1.Width-10,image1.Height-y0);
//график
image1.Canvas.Pen.Width:=1;
image1.Canvas.Pen.Style:=psDash;
image1.Canvas.MoveTo(x0,50);
image1.Canvas.LineTo(x0+40,50);
image1.Canvas.LineTo(x0+40,image1.Height-y0);
image1.Canvas.MoveTo(x0,image1.Height-y0-40);
image1.Canvas.LineTo(image1.Width-50,image1.Height-y0-40);
image1.Canvas.LineTo(image1.Width-50,image1.Height-y0);
image1.Canvas.Pen.Width:=2;
image1.Canvas.Pen.Color:=clBlue;
image1.Canvas.MoveTo(x0+40,50);
image1.Canvas.LineTo(image1.Width-50,image1.Height-y0-40);
//надписи
image1.Canvas.TextOut(x0-24,10,'U,B');
image1.Canvas.TextOut(image1.Height-10,image1.Height-15,'плотность,кг/м3');
nap:=Napryajenie(StrToInt(edit4.Text));
image1.Canvas.TextOut(x0-image1.Canvas.TextWidth(FloatToStr(nap))-5,image1.Height-y0-40-5,FloatToStr(nap));
nap:=Napryajenie(StrToInt(edit3.Text));
image1.Canvas.TextOut(x0-image1.Canvas.TextWidth(FloatToStr(nap))-5,45,FloatToStr(nap));
image1.Canvas.TextOut(x0+40-10,image1.Height-y0+5,edit3.Text);
image1.Canvas.TextOut(image1.Width-50-10,image1.Height-y0+5,edit4.Text);
//наша точка
x:=x0+40+round((image1.Width-50-x0-40)*(StrToInt(edit5.Text)-StrToInt(edit3.Text))/(StrToInt(edit4.Text)-StrToInt(edit3.Text)));
y:=50+Round((image1.Height-y0-40-50)*(StrToFloat(edit5.Text)-StrToInt(edit3.Text))/(StrToInt(edit4.Text)-StrToInt(edit3.Text)));
image1.Canvas.Pen.Color:=clRed;
image1.Canvas.Ellipse(x-3,y-3,x+3,y+3);
image1.Canvas.Pen.Width:=1;
image1.Canvas.Pen.Style:=psDot;
image1.Canvas.MoveTo(x,image1.Height-y0);
image1.Canvas.LineTo(x,y);
image1.Canvas.LineTo(x0,y);
image1.Canvas.Font.Color:=clRed;
image1.Canvas.TextOut(x-10,image1.Height-y0+5,edit5.Text);
image1.Canvas.TextOut(x0-image1.Canvas.TextWidth(edit6.Text)-5,y-5,edit6.Text);
end;
function TForm1.Napryajenie(p:real):real;
var p1, p2, Qz: integer;
begin
//Функция расчета напряжения по значению плотности
p1:=StrToInt(edit3.Text);
p2:=StrToInt(edit4.Text);
Qz:=StrToInt(edit2.Text);
if (p2<=p1) then
begin
ShowMessage('Неверно указан диапазон');
napryajenie:=0;
end
else
if (p>p2) or (p<p1) then
begin
ShowMessage('Значение не в диапазоне');
napryajenie:=0;
end
else
Napryajenie:=(Qz-p*Kqp/1000000)*Kuq;
end;
procedure TForm1.Button1Click(Sender: TObject);
var d: real;
begin
//Единичный расчет
if proverka then
begin
exit; //Если введены неверные данные, то завершаем процедуру
end;
try
d:=StrToFloat(edit5.text);
except
on EConvertError do
begin
edit5.setfocus;
exit;
end;
end;
Edit6.text:=FloatToStr(Napryajenie(StrToFloat(edit5.Text)));
if edit6.Text<>'0' then graphik1;
end;
procedure TForm1.RadioGroup1Click(Sender: TObject);
begin
//Переключение между режимами расчета
if RadioGroup1.ItemIndex=0 then
begin
GroupBox2.Visible:=true; //единичный расчет
GroupBox3.Visible:=false;
end else
if RadioGroup1.ItemIndex=1 then
begin
GroupBox2.Visible:=false; //запись результатов в файл
GroupBox3.Visible:=true;
end else
if RadioGroup1.ItemIndex=2 then
begin
GroupBox2.Visible:=false; // запись результатов в com-порт
GroupBox3.Visible:=true;
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
//Старт/остановка непрерывного значения
if proverka then
begin
exit;
end;
if Button2.Caption='Старт' then
begin
button2.Caption:='Стоп';
//Рисуем сетку для графика
Image2.Canvas.Brush.Color:=clBtnFace;
Image2.Canvas.FillRect(rect(0,0,image2.Width,image2.Height));
Image2.Canvas.Pen.Width:=2;
image2.Canvas.Pen.Color:=clBlack;
image2.Canvas.TextOut(5,215,edit3.Text);
image2.Canvas.TextOut(5,15,edit4.Text);
image2.Canvas.TextOut(35,0,'плотность');
image2.Canvas.TextOut(270,237,'время');
Image2.Canvas.MoveTo(27,220);
image2.Canvas.LineTo(33,220);
Image2.Canvas.MoveTo(27,20);
image2.Canvas.LineTo(33,20);
Image2.Canvas.Pen.Width:=3;
Image2.Canvas.MoveTo(30,235);
image2.Canvas.LineTo(313,235);
Image2.Canvas.MoveTo(30,0);
image2.Canvas.LineTo(30,250);
pred_y:=860; //
x:=35;
image2.Canvas.Pen.Color:=clBlue;
if RadioGroup1.ItemIndex=1 then
begin
//готовим файл для вывода результатов замера
AssignFile(f,'c:\result.txt');
if FileExists('c:\result.txt') then Append(f) else Rewrite(f);
end else
begin
//готовим com-порт для чтения данных
comport:=TRS232.Create(Form1);
case combobox1.ItemIndex of
0: comport.ComPort:=pnCom1;
1: comport.ComPort:=PnCom2;
2: comport.ComPort:=pnCom3;
3: comport.ComPort:=PnCom4;
end;
Case ComboBox2.ItemIndex of
0: comport.ComPortSpeed:=br110;
1: comport.ComPortSpeed:=br300;
2: comport.ComPortSpeed:=br600;
3: comport.ComPortSpeed:=br1200;
4: comport.ComPortSpeed:=br2400;
5: comport.ComPortSpeed:=br4800;
6: comport.ComPortSpeed:=br9600;
7: comport.ComPortSpeed:=br14400;
8: comport.ComPortSpeed:=br19200;
9: comport.ComPortSpeed:=br38400;
10: comport.ComPortSpeed:=br56000;
11: comport.ComPortSpeed:=br57600;
12: comport.ComPortSpeed:=br115200;
end;
comport.Connect;
end;
timer1.Interval:=StrToInt(edit7.Text);
timer1.Enabled:=true;
end else
begin
//Остановка замера
button2.Caption:='Старт';
timer1.Enabled:=false;
if RadioGroup1.ItemIndex=1 then
begin
CloseFile(f);
end;
end;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var s: string;
koord_y: integer;
napr: real;
begin
//При срабатывании счетчика
//Считываем показания датчика
if emu.Checked then Nov_y:=Pred_y+Round(Random(3)-1)
else
begin
if comport.ReadString(s,3) then Nov_Y:=StrToInt(s)
else
begin
ShowMessage('Не могу прочитать данные с com-порта');
timer1.Enabled:=false;
button2.OnClick(sender);
exit;
end;
end;
if nov_y>StrToInt(edit4.Text) then nov_y:=StrToInt(edit4.Text);
if nov_y<StrToInt(edit3.Text) then nov_y:=StrToInt(edit3.Text);
Image2.Canvas.Brush.Color:=clBtnFace;
Image2.Canvas.FillRect(rect(x+2,18,x+7,230));
koord_y:=20+round(200*(Pred_y-StrToInt(edit4.Text))/(StrToInt(edit3.Text)-StrToInt(edit4.Text)));
image2.Canvas.MoveTo(x,koord_y);
x:=x+5;
koord_y:=20+round(200*(nov_y-StrToInt(edit4.Text))/(StrToInt(edit3.Text)-StrToInt(edit4.Text)));
image2.Canvas.LineTo(x,koord_y);
pred_y:=nov_y;
image2.Canvas.TextOut(35,0,'плотность='+IntToStr(nov_y));
if x=310 then
begin
x:=35;
Image2.Canvas.FillRect(rect(x-1,18,x+7,230));
end;
//Считаем значение напряжения;
napr:=Napryajenie(nov_y);
image2.Canvas.TextOut(150,0,'Напряжение='+FloatToStr(napr));
//Третий этап
if RadioGroup1.ItemIndex=1 then
begin
//Пишем результаты расчета в файл
writeln(f,DateTimeToStr(Now)+' '+IntToStr(Nov_Y)+' '+FloatToStr(napr));
end else
begin
//Пишем результат расчета в com порт
if not emu.Checked then
comport.SendString(FloatToStr(Napr));
end;
end;
procedure TForm1.emuClick(Sender: TObject);
begin
//Включение режима эмуляции com-порта
comboBox1.Enabled:=not emu.Checked;
comboBox2.Enabled:=not emu.Checked;
end;
end.
4 ВОЗМОЖНОСТИ ПРАКТИЧЕСКОГО ПРИМЕНЕНИЯ
Программное обеспечение системы автоматической коррекции скорости (САК) может применяться на большом количестве станков с ЧПУ (CNC). Необходимость применения данной программы обусловлена высокими требованиями, предъявляемыми к точности изготовления деталей.
Возможной областью практического применения могут являться разнообразные токарные станки. Соответствие заданной и фактической скорости перемещения режущего инструмента или других узлов станка является залогом качественного изготовления детали. Отклонение фактической скорости от заданной может происходить по ряду причин. Одной из них является изменение плотности рабочей жидкости в гидросистеме станка. Исключить негативное влияние, вызываемое изменением плотности можно с помощью программы автоматической коррекции.