Главная » Delphi » Приложение-термометр с иконкой в Tray

0

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

Термометр

Сначала о датчике. Мы постараемся построить программу так, чтобы в ней можно было использовать данные с любого датчика (необязательно температуры). Условие одно — данные должны укладываться в четыре символьных знака, не считая разделительной запятой. Для температуры зто будет представление ее в виде "36,6°". Точность (точнее — разрешающая способность) в 0,1° может показаться излишней, но в книге "Занимательная электроника" я уже писал, что представление температуры без десятых градуса — все равно, что наручные часы без секундной стрелки, вроде бы "по жизни" и не очень надо, но как-то… некрасиво.

В данном случае я предлагаю использовать возможность, которая имеется почти в любом компьютере — а именно игровой порт. В минимальной стандартной конфигурации игровой порт содержит целых четыре готовых аналого-цифровых преобразователя, не слишком высокого качества, ио для того чтобы демонстрировать температуру в пределах от 0 до 99 градусов с приемлемой погрешностью в 1—2 градуса, они вполне подойдут. Так что тем, кто захочет повторить эту программу в точности, придется браться за паяльник— но предварительно нужно приобрести разъем типа DB-I5M — ответную часть ("папу") 15-контактного разъема для стандартног о игрового nopia.

Кроме этого, в качестве собственно датчика потребуется терморезистор (тер- мистор) с номинальным сопротивлением примерно 50—L00 кОм при 20° (его можно приобрести там же) и один постоянный резистор любого номинала or 1 до 100 кОм (в принципе без последнего можно и обойтись).

Рис. 10.8. Подключение джойстика к разъему игрового порта (а), внутреннее устройство ехода АЦП (б) и подключение термистора к разъему (е). Нумерация соответствует виду спереди на гнездовую (компьютерную) часть разъема DB-15F

Штатное подключение джойстика к разъему игрового порта показано на рис. 10.8, а. На рис. 10.8, б изображен фрагмент внутренней схемы порта, относящийся к измерению сопротивления. Принцип измерения основан на отсчете времени, необходимого для зарядки конденсатора емкостью 10 нФ от источника питания +5 В через последовательно включенные внутренний резистор 2,2 кОм и измеряемый резистор (т. е. либо штатный потенциометр джойстика, обычно имеющий сопротивление около 100 кОм, либо наш тер- мистор). В начале цикла измерения конденсатор перемыкается накоротко, чтобы сбросить его до нуля, затем начинается зарядка. Когда конденсатор заряжается от 0 В до некоего порога (примерно до середины напряжения питания +5 В — в качестве порогового устройства выступает обычный вход логического элемента), то выходная схема выдает сигнал об окончании периода зарядки. И далее цикл измерения повторяется заново (такой принцип преобразования аналоговой величины в интервал времени называется прямое однократное интегрирование). Если внешнее сопротивление равно 0, то время зарядки будет примерно равно 22 мкс (/?С), при увеличении сопротивления время пропорционально увеличивается. Согласно описанию порта, измеренная величина времени должна быть на 10% больше величины RC— официальная формула почему-то дает сверхточную величину 24,2 мкс, что, конечно же, чистый выпендреж — на практике эта величина может меняться процентов на 30—50 в обе стороны. В Windows есть, разумеется, штатная процедура API, которая дает уже пересчитанную экранную координату джойстика.

Схема подключения термистора Rt к разъему показана на рис. 10.8, е. Мы использовали в качестве рабочей Х-координату джойстика 1, но можно, конечно, и любой другой вход. Датчик подключается вместо переменного резистора джойстика, между входом схемы (контакт 3) и питанием +5 В (контакт 1). Постоянный резистор (R1 на рисунке) нужен, чтобы вторая координата того же джойстика также была подключена к питанию— в принципе можно и просто соединить указанные контакты перемычкой. Если вы этого не сделаете, то система может решить, что "джойстик" не подключен вообще.

Заметки на полях

Считанный интервал времени можно измерить самостоятельно в условных единицах (или, более грамотно, — с использованием системных таймеров), если запускать преобразование и ожидать его окончания, отсчитывая время. Делается это непосредственно через порт, записью/чтением его регистра по адресу 201 h. Простейший вариант функции с использованием встроенного ассемблера выглядит примерно так (вначале мы запускаем преобразование, потом ждем, пока система выдаст сигнал, что оно окончено. Если, например, через 10 000 циклов — эта величина зааисит от быстродействия компьютера — мы так и не дождались окончания, выходим из процедуры):

function jctk: word;

begin

asm

mov @result,0 mov dx,201h mov cx,0 out dx,al @mc: in al,dx inc cx

cmp cx,10000 ja @mend test al,1 jne @mc

mov @result,cx

Smend: nop

end;

end;

Эта процедура вполне будет работать и в Windows 9х. Аналоговые входы игровых портов можно использовать и для измерения напряжения, подввая его на нужный контакт через последовательный резистор (иначе разрешающая способность будет очень мала). Только следует учесть, что диапазон измерений здесь будет ограничен снизу напряжением примерно 2,8—3,2 В, иначе конденсатор никогда не зарядится до порогового значения. Зато выше этого порога можно подввать в принципе любое напряжение — такое, чтобы мощность на внутреннем резисторе 2,2 кОм (произведение падения напряжения на нем на ток через входные резисторы) не превысила 0,1 Вт. Разумеется, особенной линейности ждать от такого измерителя не приходится — но в компьютере это и не принципиально, ведь пересчитывать полученное значение можно по формулам любой степени сложности, достаточно измерительный канал один раз от- капибровать.

Зависимость сопротивления от температуры для термисторов (полупроводниковых терморезисторов) имеет отрицательный наклон и описывается довольно сложной формулой:

Рис. 10.9. Окно программы Температура" (а) и ее значки в Tray (6)

Теперь напишем саму процедуру калибровки но нажатию кнопки Buttoni. Флаг Fiagc будет сигнализировать о том, на каком этапе калибровки мы находимся.

procedure TForml.ButtonlClick(Sender: TObject); var err:integer; begin { Калибровка}

if Buttoni.Caption=’Калибровать’ then begin

Buttoni.Caption: =’ Ok'; Editl.Enabled:=True;

Labe13.Caption:=’Введите значение температуры 1 :'; FlagC:=l;

Edi 11.Text:=FloatToS t r F(t,ffFixed,3,2); Editl.SetFocus; end elae

if FlagC=l then (первая калибровочная точкаI begin try

if posf,’, Editl. Text) <>0 than

{исправляем ошибку с разделительным знаком) tl-.=StrToFloat (Editl.Text) else val(Editl.Text,tl,err);

{реальное значение температуры 1) if err<>0 then raise Exception.Create(”);; except

ShowMessage(‘Неправильный формат действительного числа’); Editl.SetFocus; exit; end;

xtl:=xt; {данные с датчика для температуры 1}

Labe13.Caption:=’Введите значение температуры 2 :';

FlagC:=2;

Editl.Text:=FloatToStrF(t,ffFixed,3,2); Editl.SetFocus; end else

if FlagC=2 then {вторая калибровочная точка) begin try

if pos(‘,Editl.Text)<>0 then

{исправляем ошибку с разделительным знаком/ t2:=StrToFloat(Editl.Text) else val(Editl.Text,t2,err);

{реальное значение температуры 2/ if erroO then raise Exception.Create(”);; except

ShowMessage(1 Неправильный формат действительного числа’); Editl.SetFocus; exit; end;

xt2:=xt; {данные с датчика для температуры 2}

Label3.Captions*’ ;

FlagC:=0;

Buttonl.Caption: = ‘Калибровать 1; Editl.Enabled:=False; {расчет коэффициентов:) if tlot2 then begin

tl:=tl+273.15; t2:=t2+273.15; B:=tl*t2*ln(xtl/xt2)/(t2-tl); A:=xtl/exp(B/tl);

Label5,Caption:=FloatToStrF(a,ffExponent, 4, 2) ; Label7.Caption:’=FloatToStrF(b, ffGeneral, 5,1) ; st:=’Калибровка прошла удачно'; ShowMessage(st); end else begin

st:=’Температуры 1 и 2 не могут быть равны между собой.’ +#13+’Повторите калибровку.'; ShowMessage(st); end; end; end;

Здесь мы применили хитрый метод избавления от возможной ошибки при вводе действительного числа с "неправильным" разделительным знаком: процедура val есть наследство Turbo Pascal и потому понимает только точку, а процедура strToFloat использует системные настройки. Если обе процедуры не выполнятся (строка вообще некорректна), возникнет то или иное исключение (которое в случае val мы вызываем искусственно). Поэтому вводить число можно в любой форме и при любых региональных настройках (кроме как для упомянутых австралийских аборигенов, если они что-то особенное придумали).

Методика выполнения калибровки такая: устанавливаете датчик при определенной температуре рядом с термометром и жмете на кнопку Калибровка. При этом она поменяет заголовок на Ok, а рядом с оживившимся редактором появится приглашение ввести действительную температуру. Вводите ее значение, и после нажатия на кнопку повторяете процесс при другом значении температуры. Все — коэффициенты рассчитаны. Чем дальше будут отстоять друг от друга значения ti и t2, тем точнее будет калибровка. Датчик и термометр лучше опускать в перемешиваемую воду (изолировав, конечно, его выводы— можно засунуть в полиэтиленовый пакет), на воздухе разница температур между ними может быть слишком велика. Несомненно, читатель сам доведет программу до умв, организовав запоминание полученных коэффициентов в INI-файле, как мы это делали в предыдущей главе— пусть это будет ему домашнее задание.

В этой главе мы сосредоточились на иконках потому, что данный момент обычно вызывает больше всего вопросов. Ну, а примеры обращения с обычными изображениями мы уже встречали раньше, при создании SiideShow, а также еще вернемся к этим вопросам не раз на протяжении всей книги, поэтому не будем терять времени и перейдем к следующему вопросу — к ресурсным файлам.

Источник: Ревнч Ю. В.  Нестандартные приемы программирования на Delphi. — СПб.: БХВ-Петербург, 2005. — 560 е.: ил.

По теме:

  • Комментарии