Kontrol motor servo dengan delphi melalui port parallel lpt

Motor servo berputar ke posisi sudut tertentu berdasarkan lebar pulsa yang diberikan padanya. Pada umumnya lebar pulsa yang dibutuhkan adalah 1ms – 2ms, dengan perida 20ms seperti diagram berikut :

Membangkitkan sinyal pulsa ini menjadi masalah tersendiri jika menggunakan pc melalui port paralel, karena disisi komputer cara ini (akses langsung ke perangkat) dianggap tidak aman.

Beberapa metode/trik bisa dilakukan untuk menggerakkan motor servo melalui lpt port seperti kode berikut :


for i:=1 to 10 do
begin
Out32($378, $01);
delay(1);
Out32($378, $00);
delay(19);
end;

cara ini menjadi tidak efektif karena fungsi ‘delay()’ tidak bisa menjamin timingnya. contohnya jika delay(1) tidak ada garansi akan tepat 1ms. Maka yang terjadi adalah servo agak bergerak tidak beraturan.

jadi kunci memitar motor servo tepat pada posisinya adalah timing yang pas dan tepat. untuk itu digunakan fungsi ‘QueryPerformanceCounter(lastTick);’ yang lebih presisi pewaktuannya.

skema simulasi gerak servo untuk membuka pintu menggunakan port parallel:

 

program delphi penggerak motor servo, simulasi buka tutup:

 

unit servo;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    ButtonBuka: TButton;
    ButtonTutup: TButton;
    Label1: TLabel;
    Label2: TLabel;
    procedure ButtonBukaClick(Sender: TObject);
    procedure ButtonTutupClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  nilaiPort : byte;

const
  //cek alamat resource lpt port melalui device manager
  baseRegister = $DC00;
  dataRegister = baseRegister + 0;
  statusRegister = baseRegister + 1;
  controlRegister = baseRegister + 2;

  sudutBuka = 180;
  sudutTutup = 0;
  maskPinServo = $01;


implementation

{$R *.dfm}

function Inp32(PortAdr: word): byte; stdcall; external 'inpout32.dll';
function Out32(PortAdr: word; Data: byte): byte; stdcall; external 'inpout32.dll';

procedure gerakServo(maskPort : byte; sudut : byte);
var
	lastTick, tick : Int64;
	lastTick20 : Int64;
	mikroDetik : integer;
	Frequency : Int64;
	i : integer;
begin
	QueryPerformanceFrequency(Frequency);
	mikroDetik := 500 + (Round(sudut/180) * 2000);

	for i := 1 to 20 do
	begin
		nilaiPort := nilaiPort or maskPort;
		Out32(dataRegister, nilaiPort);

		QueryPerformanceCounter(lastTick);
		lastTick20 := lastTick + round((20000 / 1000000) * Frequency);
		lastTick := lastTick + round((mikroDetik / 1000000) * Frequency);

		while true do
		begin
			QueryPerformanceCounter(tick);
			if tick > lastTick then
				break;
		end;

		nilaiPort := nilaiPort and (not maskPort);
		Out32(dataRegister, nilaiPort);

		while true do
		begin
			QueryPerformanceCounter(tick);
			if tick > lastTick20 then
				break;
		end;
	end;
end;

procedure TForm1.ButtonBukaClick(Sender: TObject);
begin
	gerakServo(maskPinServo, sudutBuka);
end;

procedure TForm1.ButtonTutupClick(Sender: TObject);
begin
	gerakServo(maskPinServo, sudutTutup);
end;

end.