Tuesday, September 30, 2025

Panduan Praktis Mengirim dan Menerima Data melalui Serial Port dengan Lazarus dan CPort

 

Panduan Praktis Mengirim dan Menerima Data melalui Serial Port dengan Lazarus dan CPort


    Dalam era Internet of Things (IoT) dan otomatisasi industri, komunikasi serial port COM menjadi kunci penting dalam menghubungkan perangkat keras dan perangkat lunak. Dengan menggunakan Lazarus dan CPort, Anda dapat dengan mudah mengakses dan mengontrol serial port COM, membuka peluang untuk mengembangkan aplikasi yang inovatif dan efektif. Dalam artikel ini, kita akan membahas bagaimana memanfaatkan serial port COM dengan Lazarus dan CPort untuk membuat aplikasi yang cerdas dan terintegrasi.

Jadi tanpa banyak basa - basi kita langsung saja terjun untuk membuat aplikasinya, jadi yang di perlukan adalah komponen Cport yang sudah terinstall pada ide lazarus kalian (saya tidak akan bahas disini) dan Cport juga adalah komponen open source dan free jadi enak untuk digunakan. 

jika tidak mempunyai port serial anda bisa gunakan usb to serial device, agar bisa menggunakan komunikasi ini jika hanya untuk test internal antar program bisa juga menggunakan virtual serial port, banyak macam softwarenya tapi saya menggunakan free program yang bisa di download yaitu com0com, program sederhana ini sangat memuaskan untuk digunakan sebagai virtual serial port karena tidak ada batasanya hanya saya hanya menyediakan koneksi pair saja

penampakkan com0com

selain itu juga untuk contoh kali ini jelas ketika kita mencoba software yang kita buat kita juga membutuhkan software termite (serial terminal) karena siapa yang mau menerima data yang kita kirimkan ? ya kecuali nanti pada saat aplikasi mungkin kita akan berkomunikasi dengan microcontroller atau bahkan dengan software proteus dll 





Software Termite

bahan yang di butuhkan :
1. Cport for lazarus
2. com0com
3. Pascal Lazarus
4. termite

tidak juga harus dengan software itu yang penting fungsinya sama.

untuk pertama kita akan buat formnya seperti ini :

form


dan berikut ini adalah listingnya :

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, CPort,
  CPortCtl;

type

  { TForm1 }

  TForm1 = class(TForm)
    btn2: TButton;
    btn1: TButton;
    btn3: TButton;
    btn4: TButton;
    cbb1: TComComboBox;
    edt3: TEdit;
    edt2: TEdit;
    edt1: TEdit;
    GroupBox2: TGroupBox;
    GroupBox3: TGroupBox;
    GroupBox4: TGroupBox;
    port1: TComPort;
    GroupBox1: TGroupBox;
    procedure btn1Click(Sender: TObject);
    procedure btn2Click(Sender: TObject);
    procedure btn3Click(Sender: TObject);
    procedure btn4Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure port1RxChar(Sender: TObject; Count: Integer);
  private
    procedure SendByte(Value: Byte);
  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }
procedure TForm1.SendByte(Value: Byte);
begin
  port1.Write(Value, 1);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  cbb1.ComProperty:= cpPort; // dilakukan disini karena error jika lewat ide lazarus
end;

procedure TForm1.port1RxChar(Sender: TObject; Count: Integer);
var
  s: string;
begin
   port1.ReadStr(s,Count);
   edt3.Text:= s;
end;

procedure TForm1.btn1Click(Sender: TObject);
begin
  if port1.Connected = false then
    begin
      port1.Port:= cbb1.Text;
      port1.Open;
    end;
end;

procedure TForm1.btn2Click(Sender: TObject);
begin
  if port1.Connected = true then port1.Close;
end;

procedure TForm1.btn3Click(Sender: TObject);
begin
  SendByte(strtoint(edt1.Text));
end;

procedure TForm1.btn4Click(Sender: TObject);
begin
  port1.WriteStr(edt2.Text);
end;

end.



🔧 1. Komponen yang Digunakan

Unit yang di-uses:

  • Classes, SysUtils: Unit standar untuk operasi dasar Pascal.

  • Forms, Controls, Graphics, Dialogs, StdCtrls: Untuk komponen antarmuka pengguna (form, tombol, edit box, dll).

  • CPort, CPortCtl: Unit untuk menangani komunikasi serial (COM port).


🧱 2. Desain Form dan Komponen

Komponen pada TForm1:

  • 4 Tombol:

    • btn1: Tombol untuk membuka koneksi ke COM port.

    • btn2: Tombol untuk menutup koneksi ke COM port.

    • btn3: Tombol untuk mengirim byte (nilai angka).

    • btn4: Tombol untuk mengirim string (teks).

  • 3 Edit Box:

    • edt1: Tempat pengguna memasukkan angka (byte) untuk dikirim.

    • edt2: Tempat pengguna memasukkan string untuk dikirim.

    • edt3: Menampilkan data yang diterima dari COM port.

  • 1 ComboBox Khusus COM Port (TComComboBox):

    • cbb1: Combo box untuk memilih COM port yang tersedia di sistem.

  • 1 Objek TComPort:

    • port1: Objek yang digunakan untuk menangani komunikasi serial.

    • port1 : masih menggunakan default speed 9600 baud

    • port1 : menggunakan 8 data, no parity, 1 stop bit  (default) 

  • 4 GroupBox:

    • Untuk mengelompokkan komponen dalam tampilan GUI (tidak memiliki logika program langsung).


⚙️ 3. Logika Program

3.1. FormCreate(Sender: TObject)

cbb1.ComProperty := cpPort;
  • Mengatur cbb1 agar menampilkan daftar port COM yang tersedia. Ini harus dilakukan secara manual karena jika diset lewat properti di IDE bisa menyebabkan error.


3.2. btn1Click(Sender: TObject)Open COM Port

if not port1.Connected then begin port1.Port := cbb1.Text; port1.Open; end;
  • Mengecek apakah port1 belum terbuka, lalu membuka port yang dipilih di cbb1.


3.3. btn2Click(Sender: TObject)Close COM Port

if port1.Connected then port1.Close;
  • Menutup koneksi ke port jika sedang terbuka.


3.4. btn3Click(Sender: TObject)Kirim Byte

SendByte(StrToInt(edt1.Text));
  • Mengambil angka dari edt1, mengubahnya ke tipe Byte, lalu mengirimkannya.

Fungsi Pendukung:

procedure TForm1.SendByte(Value: Byte); begin port1.Write(Value, 1); end;
  • Mengirim satu byte ke port serial.


3.5. btn4Click(Sender: TObject)Kirim String

port1.WriteStr(edt2.Text);
  • Mengirim string yang dimasukkan di edt2 melalui port serial.


3.6. port1RxChar(Sender: TObject; Count: Integer)Terima Data

var s: string; begin port1.ReadStr(s, Count); edt3.Text := s; end;
  • Dipanggil otomatis saat data diterima dari COM port (Count karakter).

  • Membaca data dan menampilkannya di edt3.


🔁 Alur Kerja Program

  1. Saat form dijalankan, daftar COM port akan dimuat ke cbb1.

  2. Pengguna memilih COM port dari daftar.

  3. Tekan tombol btn1 → membuka koneksi ke COM port.

  4. Pengguna dapat:

    • Mengirim byte dengan tombol btn3.

    • Mengirim string dengan tombol btn4.

  5. Data yang diterima dari COM port akan langsung tampil di edt3.

  6. Tekan tombol btn2 → menutup koneksi COM port.


🛠️ Catatan Teknis Tambahan

  • Pastikan Anda menggunakan komponen CPort yang sudah diinstal di Lazarus.

  • Perlu mengatur BaudRate, Parity, StopBits, dan DataBits dari port1 agar sesuai dengan perangkat yang dikomunikasikan. (Belum diatur dalam kode ini, jadi memang masih default 9600 8N1).

  • Saat mengirim data byte, pastikan edt1.Text benar-benar angka valid (0–255), jika tidak bisa menyebabkan error runtime. Oleh karena itu edt1 di set "only Number" properties nya







Source Code dapat di download di Link ini





READ MORE

Monday, September 22, 2025

Membuat Aplikasi Spreadsheet Sederhana dengan Lazarus dan fpspreadsheet


Membuat Aplikasi Spreadsheet Sederhana dengan Lazarus dan fpspreadsheet

Lazarus adalah salah satu IDE (Integrated Development Environment) yang kuat dan gratis, yang memungkinkan pengembang untuk membuat aplikasi berbasis Pascal. Dalam artikel ini, kita akan membahas cara membuat aplikasi spreadsheet sederhana dengan menggunakan Lazarus dan pustaka fpspreadsheet, yang memungkinkan kita untuk membaca, menulis, dan mengedit file spreadsheet berbagai format seperti Excel, CSV, dan lainnya.

Aplikasi yang akan kita buat memungkinkan pengguna untuk membuka file spreadsheet, mengeditnya, dan menyimpannya kembali dalam format yang berbeda. Di bawah ini, kita akan menguraikan langkah-langkah implementasi dalam source code Lazarus yang sudah disediakan.

Persiapan Awal

Sebelum memulai, pastikan Anda sudah menginstal Lazarus IDE dan pustaka fpspreadsheet. Pustaka fpspreadsheet memungkinkan kita untuk bekerja dengan berbagai format file spreadsheet secara fleksibel. Jika pustaka ini belum terpasang, Anda bisa mengunduhnya melalui Paket Manajer Lazarus atau menggunakan perintah berikut:

sudo apt install libfpspreadsheet

Screenshot form yang dibuat :

ScreenShot Form

Komponen yang dipakai



Penjelasan Source Code

Berikut ini adalah penjelasan bagian-bagian utama dari kode sumber aplikasi spreadsheet sederhana yang telah disiapkan.

Unit dan Import

Pada bagian awal, kita mendeklarasikan unit-unit yang diperlukan, seperti fpspreadsheet, fpspreadsheetctrls, dan fpspreadsheetgrid, yang akan membantu dalam bekerja dengan spreadsheet. Berikut adalah deklarasi unit yang digunakan:

uses Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls, fpstypes, fpspreadsheet, fpspreadsheetctrls,fpspreadsheetgrid, fpsallformats, fpcanvas, lazutf8, fpsutils, fpsReaderWriter;
  • fpspreadsheet: Pustaka utama untuk memanipulasi file spreadsheet.

  • fpspreadsheetctrls dan fpspreadsheetgrid: Digunakan untuk menampilkan grid spreadsheet dalam aplikasi Lazarus.

  • fpsallformats: Mengizinkan aplikasi membaca dan menulis berbagai format spreadsheet seperti XLS, XLSX, CSV, dan lainnya.

Desain Form dan Komponen

Komponen yang digunakan dalam aplikasi ini meliputi:

  • Button1 dan Button2: Digunakan untuk membuka dan menyimpan file spreadsheet.

  • OpenDialog dan SaveDialog1: Digunakan untuk memilih file yang akan dibuka atau disimpan.

  • WorksheetGrid: Komponen utama untuk menampilkan data spreadsheet dalam grid yang dapat diedit.

Selain itu, ada objek sWorkbookSource1 dan sWorkbookTabControl1, yang berfungsi untuk memuat dan menampilkan data spreadsheet.

Fungsi LoadFile

Fungsi LoadFile bertanggung jawab untuk membaca file spreadsheet yang dipilih pengguna dan memuatnya ke dalam aplikasi. Fungsi ini menerima dua parameter: nama file dan indeks filter dari dialog pemilih file (untuk menentukan format file yang akan dibaca).

procedure TForm1.LoadFile(const AFileName: String; index : byte); var wb: TsWorkbook; begin wb := TsWorkbook.Create; case index of 1: wb.ReadFromFile(AFileName); // Semua jenis file spreadsheet 2: wb.ReadFromFile(AFileName); // Excel secara otomatis 3: wb.ReadFromFile(AFileName, sfOOXML); // Excel 2007+ 4: wb.ReadFromFile(AFileName, sfExcel8); // Excel 97-2003 5: wb.ReadFromFile(AFileName, sfExcel5); // Excel 5.0 6: wb.ReadFromFile(AFileName, sfExcel2); // Excel 2.1 7: wb.ReadFromFile(AFileName, sfOpenDocument); // LibreOffice 8: wb.ReadFromFile(AFileName, sfCSV); // File teks CSV else wb.Free; MessageDlg('File format not implemented.', mtError, [mbOk], 0); exit; end; sWorkbookSource1.LoadFromWorkbook(wb); end;

Dalam fungsi ini, objek TsWorkbook digunakan untuk memuat file spreadsheet berdasarkan format yang dipilih. Pengguna dapat memilih dari berbagai format file spreadsheet, dan aplikasi akan otomatis mendeteksi serta memproses file tersebut.

Fungsi SaveFile

Fungsi SaveFile digunakan untuk menyimpan data spreadsheet yang telah dimodifikasi ke dalam file baru dengan format yang dipilih oleh pengguna. Format yang dapat dipilih meliputi berbagai format Excel, OpenDocument, CSV, dan lainnya.

procedure TForm1.SaveFile(const AFileName: String; index : byte); var fmt: TsSpreadsheetFormat; begin Screen.Cursor := crHourglass; try case index of 1: fmt := sfOOXML; // Format Excel 2007+ 2: fmt := sfExcel8; // Format Excel 97-2003 3: fmt := sfExcel5; // Format Excel 5.0 4: fmt := sfExcel2; // Format Excel 2.1 5: fmt := sfOpenDocument; // Format OpenDocument 6: fmt := sfCSV; // Format CSV 7: fmt := sfWikiTable_WikiMedia; // Format WikiTable end; sWorkbookSource1.SaveToSpreadsheetFile(AFileName, fmt); finally Screen.Cursor := crDefault; end; end;

Fungsi ini mengubah format file berdasarkan pilihan pengguna dan menyimpannya menggunakan sWorkbookSource1.SaveToSpreadsheetFile.

saya menambahkan ini di file form lazarus untuk setting filternya, ya karena malas ketik jadi bagus copy paste aja

  object OpenDialog: TOpenDialog

    Filter = 'All spreadsheet files|*.xls;*.xlsx;*.ods;*.csv|All Excel files (*.xls, *.xlsx)|*.xls;*.xlsx|Excel XML spreadsheets (*.xlsx)|*.xlsx|Excel XP/2003 XML spreadsheets (*.xml)|*.xml|Excel 97-2003 spreadsheets (*.xls)|*.xls|Excel 5 spreadsheets (*.xls)|*.xls|Excel 2.1 spreadsheets (*.xls)|*.xls|LibreOffice/OpenOffice spreadsheets (*.ods)|*.ods|HTML files (*.html; *.htm)|*.html;*.htm|Comma-separated text files (*.csv; *.txt)|*.csv;*.txt'

    Left = 664

    Top = 93

  end

  object SaveDialog1: TSaveDialog

    Filter = 'Excel XML spreadsheet (*.xlsx)|*.xlsx|Excel 97-2003 spreadsheets (*.xls)|*.xls|Excel 5 spreadsheet (*.xls)|*.xls|Excel 2.1 spreadsheets (*.xls)|*.xls|LibreOffice/OpenOffice spreadsheet (*.ods)|*.ods|Comma-delimited files (*.csv)|*.csv|WikiTable (WikiMedia-Format, *.wikitable_wikimedia)|*.wikitable_wikimedia'

    Left = 736

    Top = 93 

bisa dilihat juga di video ketika saya copy pastenya

Event Handling: Button1Click dan Button2Click

Event handler untuk dua tombol utama:

  • Button1Click: Membuka file menggunakan OpenDialog dan memanggil fungsi LoadFile.

  • Button2Click: Menyimpan file menggunakan SaveDialog1 dan memanggil fungsi SaveFile.

procedure TForm1.Button1Click(Sender: TObject); begin if OpenDialog.Execute then LoadFile(OpenDialog.FileName, OpenDialog.FilterIndex); WorksheetGrid.SetFocus; WorksheetGrid.Row := 1; WorksheetGrid.Col := 1; end; procedure TForm1.Button2Click(Sender: TObject); begin if SaveDialog1.Execute then SaveFile(SaveDialog1.FileName, SaveDialog1.FilterIndex); end;

Pada Button1Click, file yang dipilih akan dimuat ke dalam worksheet grid, dan grid akan difokuskan ke sel pertama. Sedangkan pada Button2Click, aplikasi akan menyimpan file dengan format yang dipilih oleh pengguna.

Penutupan

Dengan langkah-langkah di atas, Anda telah membuat aplikasi spreadsheet sederhana yang dapat membuka dan menyimpan file dalam berbagai format menggunakan Lazarus dan pustaka fpspreadsheet. Aplikasi ini dapat menjadi dasar yang baik untuk pengembangan lebih lanjut, seperti penambahan fitur pengeditan sel, filter data, dan sebagainya.

Pustaka fpspreadsheet menawarkan banyak kemampuan untuk bekerja dengan data spreadsheet, dan dengan Lazarus sebagai IDE, Anda dapat dengan mudah membuat aplikasi desktop yang kuat dan fleksibel.

Sekarang sudah menjadi umum template management ISO, nah pada ISO sudah jelas bahwa document itu tercontrol... artinya formatnya pun terkontrol nah dengan lazarus bisa saja membuat alat bantu untuk memasukkan data excel itu ke database di olah baru di keluarkan kembali menjadi data yang kita inginkan. jika berminat silahkan komen dibawah dan emailkan saya file excelnya biar saya bantu dan buatkan artiklenya. 


SourceCode bisa di download disini





READ MORE

Sunday, September 7, 2025

Membuat Animasi Water Tank Level di Lazarus dengan BGRA Bitmap

 Membuat Animasi Water Tank Level di Lazarus dengan BGRA Bitmap





Visualisasi level air pada sebuah tangki sering digunakan dalam sistem SCADA, HMI, maupun aplikasi monitoring sederhana. Dengan Lazarus + BGRA Bitmap, kita bisa membuat animasi water tank level yang interaktif, misalnya dengan slider (TrackBar) untuk mengatur ketinggian air.

pada artikle kali ini saya hanya memfokuskan pada pengendalian animasi sederhananya jadi belum terkoneksi dengan rangkaian elektronik dan itu akan di bahas pada artikle lainnya, semoga secepatnya tinggalkan komen jika memang menginginkannya.

Prinsip sederhananya saya hanya mengupload gambar background dan memberi object kotak biru yang nantinya akan saya rubah ketinggiannya dengan mengubah nilai dari trackbar. Jadi terdapat 2 layer saja layer 1 adalah back ground dan layer 2 adalah kotak biru



ini gambar background "test.bmp"
ini gambar background "test.bmp"

 

















seperti yang terlihat gambar bitmap ini akan di upload pada component dan diatasnya akan di berikan object. dan object itulah yang akan kita kendalikan.

Persiapan Komponen

Buat sebuah form baru di Lazarus, lalu tambahkan komponen berikut:

  • TBGRAVirtualScreen → untuk menggambar grafik.

  • TTrackBar → untuk mengatur tinggi air.

  • TLabel → untuk menampilkan koordinat mouse.

  • Tambahkan juga unit BGRABitmap dan BGRABitmapTypes pada bagian uses.


Logika Utama Program

Ada beberapa poin penting dalam program ini:

  1. Inisialisasi Tangki dan Warna

    x0 := 111; y0 := 320; tebal := 2; lebar := 148; tinggi := 217; garis := BGRA(0,0,255,128); isian := BGRA(0,0,255,128);

    Di sini kita tentukan posisi, ukuran tangki, dan warna air.

  2. Memuat Background

    background := TBGRABitmap.Create; background.LoadFromFile('test.bmp');

    Background hanya diload sekali saat FormCreate.

  3. Kontrol Level Air dengan TrackBar

    TrackBar1.Min := 0; TrackBar1.Max := tinggi; TrackBar1.Position := 0;

    Nilai TrackBar dihubungkan dengan tinggi air di tangki.

  4. Menggambar Ulang pada VirtualScreen

    Bitmap.RectangleAntialias(x0, y0, x0+lebar, y0-tinggi, garis, tebal, isian);

    Bagian ini yang membuat animasi level air naik-turun sesuai posisi TrackBar.

  5. Menjaga Proporsi Background
    Ada perhitungan aspect ratio agar background tidak gepeng ketika digambar ulang.

    // hitung aspect ratio

      imgRatio := background.Width / background.Height;

      scrRatio := Bitmap.Width / Bitmap.Height;

      if imgRatio > scrRatio then

      begin

        // gambar lebih lebar daripada layar → sesuaikan lebar penuh

        drawWidth := Bitmap.Width;

        drawHeight := Round(drawWidth / imgRatio);

        xOff := 0;

        yOff := (Bitmap.Height - drawHeight) div 2;

      end

      else

      begin

        // gambar lebih tinggi daripada layar → sesuaikan tinggi penuh

        drawHeight := Bitmap.Height;

        drawWidth := Round(drawHeight * imgRatio);

        yOff := 0;

        xOff := (Bitmap.Width - drawWidth) div 2;

      end;

      // gambar background dengan stretch proporsional-- jangan lupa urutan menggambarnya

      Bitmap.StretchPutImage(Rect(xOff, yOff, xOff+drawWidth, yOff+drawHeight), background, dmSet); 

Dengan Lazarus dan BGRA Bitmap, kita bisa membuat simulasi visual yang menarik dengan mudah. Kode di atas adalah contoh dasar animasi water tank level yang nantinya bisa dikembangkan menjadi aplikasi monitoring real-time.


Kekurangan dari animasi yang saya buat adalah meletakkan objectnya, kordinatnya harus di cari secara manual makanya pada form ini bisa di lihat ada label yang menampilkan kordinat mouse pada virtualscreen dari BRGAbitmap, bisa di lihat disini 


jadi baru mencari dulu kordinat yang di perlukan dengan menjalankan aplikasi dan mencatat kordinat mouse secara manual saya masih belum dapat cara yang lebih mudah lagi jadi jika banyak object maka kesulitan dalam mengumpulkan kordinat ini juga bertambah.

mudah2an nantinya ada yang bisa menyumbangkan idenya untuk mengatasi hal ini











berikut adalah source code lengkapnya dan jangan lupa silahkan di instal komponen BRGABitmapnya terlebih dahulu.

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls,
  ComCtrls, BGRAVirtualScreen, BGRABitmap, BGRABitmapTypes;

type

  { TForm1 }

  TForm1 = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    TrackBar1: TTrackBar;
    VirtualScreen: TBGRAVirtualScreen;
    procedure FormCreate(Sender: TObject);
    procedure TrackBar1Change(Sender: TObject);
    procedure VirtualScreenMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure VirtualScreenRedraw(Sender: TObject; Bitmap: TBGRABitmap);
  private
    background: TBGRABitmap;
    x0,y0,tebal,lebar,tinggi : integer;
    garis,isian : TBGRAPixel;
  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  //buat kotak pada gambar
  x0 := 111; y0 := 320; tebal := 2; lebar := 148; tinggi := 217;
  garis := BGRA(0,0,255,128); isian := BGRA(0,0,255,128);
  // load background sekali saja
  background := TBGRABitmap.Create;
  background.LoadFromFile('test.bmp');

  //atur kondisi trackbar
  TrackBar1.Min := 0;
  TrackBar1.Max := tinggi;
  TrackBar1.position := 0;

  tinggi := TrackBar1.Position;
  VirtualScreen.RedrawBitmap;
end;

procedure TForm1.TrackBar1Change(Sender: TObject);
begin
  tinggi := TrackBar1.Position;
  VirtualScreen.RedrawBitmap;
end;

procedure TForm1.VirtualScreenMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
    label1.Caption:= 'X = ' + inttostr(X) + ' , Y = ' + inttostr(Y);
end;

procedure TForm1.VirtualScreenRedraw(Sender: TObject; Bitmap: TBGRABitmap);
var
  imgRatio, scrRatio: Double;
  drawWidth, drawHeight, xOff, yOff: Integer;
begin
  // hitung aspect ratio
  imgRatio := background.Width / background.Height;
  scrRatio := Bitmap.Width / Bitmap.Height;

  if imgRatio > scrRatio then
  begin
    // gambar lebih lebar daripada layar → sesuaikan lebar penuh
    drawWidth := Bitmap.Width;
    drawHeight := Round(drawWidth / imgRatio);
    xOff := 0;
    yOff := (Bitmap.Height - drawHeight) div 2;
  end
  else
  begin
    // gambar lebih tinggi daripada layar → sesuaikan tinggi penuh
    drawHeight := Bitmap.Height;
    drawWidth := Round(drawHeight * imgRatio);
    yOff := 0;
    xOff := (Bitmap.Width - drawWidth) div 2;
  end;

  // gambar background dengan stretch proporsional-- jangan lupa urutan menggambarnya
  Bitmap.StretchPutImage(Rect(xOff, yOff, xOff+drawWidth, yOff+drawHeight), background, dmSet);

  //gambar object kotaknya-- jangan lupa urutan menggambarnya
  Bitmap.RectangleAntialias(x0,y0,x0+lebar,y0-tinggi,garis,tebal,isian);
end;

end.


dan berikut adalah lazarus formnya :

object Form1: TForm1
  Left = 350
  Height = 456
  Top = 250
  Width = 409
  Caption = 'Animasi Water Tank Sederhana'
  ClientHeight = 456
  ClientWidth = 409
  OnCreate = FormCreate
  object VirtualScreen: TBGRAVirtualScreen
    Left = 8
    Height = 392
    Top = 8
    Width = 392
    OnRedraw = VirtualScreenRedraw
    Alignment = taLeftJustify
    Color = clWhite
    ParentColor = False
    TabOrder = 0
    OnMouseMove = VirtualScreenMouseMove
  end
  object Label1: TLabel
    Left = 104
    Height = 15
    Top = 408
    Width = 34
    Caption = 'Label1'
  end
  object TrackBar1: TTrackBar
    Left = 0
    Height = 25
    Top = 424
    Width = 408
    Position = 0
    OnChange = TrackBar1Change
    TabOrder = 1
  end
  object Label2: TLabel
    Left = 8
    Height = 15
    Top = 408
    Width = 88
    Caption = 'Mouse Position :'
  end
end



Tambahan lagi jika teman - teman juga hanya memiliki ide dan ingin idenya bisa dibuat menjadi animasi, coba komen di bawah dan emailkan detail yang teman2 ingin capai siapa tau saya mampu membuatkan artikle nya

READ MORE

Monday, June 9, 2025

Module LCD dengan komunikasi I2C

Module LCD dengan komunikasi I2C

    Pemakaian LCD ini sudah sangat biasa dipakai saya hanya membahas kembali karena pada saat saya memakai modul ini banyak masalah yang saya temui dan saya sharing pada video kali ini 


    


dan untuk librarynya silahkan di download disini 


jika teman - teman mempunyai ide lain yang mau dibahas tolong komen dibawah dan emailkan detail datanya kepada saya, jika menarik akan saya coba buatkan artiklenya 
READ MORE

Saturday, October 22, 2022

"catatan pribadi" Masalah Koneksi Mysql80 dengan server

 Masalah Koneksi dengan mysql80 di server


waktu saya menggunakan mysql80 ini pertama kali ada masalah pada koneksi ke server yang pada versi sebelumnya hal ini tidak terjadi. tapi untungnya sudah banyak artikle yang membahas hal yang serupa.

jadi masalah ini terjadi karena koneksi pada versi ini harus di declare dulu baru bisa digunakan dan langsung saja caranya.


pilihlah command line untuk mysql


masukkan password mysql yang sudah di setting pada saat awal installasi


jika benar maka ini adalah tampilan berikutnya. tapi jika lupa maka yang harus dilakukan adalah menguninstall dan install ulang dengan setting password yang sudah catat ya

lalu ketik 

mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'password' PASSWORD EXPIRE NEVER;
jika benar maka muncul tulisan ini

Query OK, 0 rows affected (0.10 sec)

lalu ketik 

mysql> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '654321';

'654321' ini password yang anda pakai ya

jika benar maka ada tulisan

Query OK, 0 rows affected (0.35 sec)

lalu lamjut ketik 

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.28 sec)

lalu lanjut

mysql> use mysql;
Database changed

lalu lanjut

mysql> select user,host from user;

maka akan muncul

+------------------+-----------+
| user             | host      |
+------------------+-----------+
| mysql.infoschema | localhost |
| mysql.session    | localhost |
| mysql.sys        | localhost |
| root             | localhost |
+------------------+-----------+
5 rows in set (0.00 sec)

maka selesai lah, anda sekarang sudah bisa koneksi dengan server mysql80







READ MORE

Sunday, September 18, 2022

Program Latihan berhitung untuk anak

Mengajarkan Dasar matematika dengan program




Seperti yang kita tahu matematika dasar seperti penjumlahan, perkalian, pengurangan, dan pembagian adalah dasar matematika yang mana untuk menguasainya butuh hapalan, latihan yang berulang - ulang sehingga otak kita akan secara refleks menjawab. 

Dalam penguasaan matematika setelahnya tetap akan tergantung oleh kemampuan ini, dan contoh saja jika soal matematika rumusnya kita hapal dan cara kita tau tapi salah hitungannya ya tetap saja salah, apalagi jika sedang ujian tidak ada kata dikit lagi benar.

oleh karena itu seperti yang saya jeaskan kita butuh latihan, nah latihan membutuhkan waktu dan perhatian kita jika bisa menggunakan software akan sangat membantu. nah berikut adalah softwarenya yang dibuat dengan delphi. simple program tapi cukup berguna.



jadi di sini ada 5 macam latihan : sesuai dengan tulisannya jika penjumlahan hanya akan ada soal penjumlahan saja dan seterusnya kecuali yang acak akan memberikan keempat latihan secara acak.

pada umumnya anak akan di berikan 2 sesi per hari jangan terlalu banyak nanti bosan per sesi rentang waktunya adalah 15 menit. rata2 anak jika sudah bisa mencapai 200 - 250 tanpa salah soal berarti sudah terbiasa.

untuk mempertahankan gunakan acak 1 sesi per hari jika terjadi penurunan maka kembali cek per latihan mana yang menurun dan lakukan 2 sesi per hari (kayak minim obat ya ada resepnya). ini sih yang saya lakukan pada anak saya dan berhasil.

jadi silahkan di download software nya  disini, {tidak perlu di install langsung saja di klik}


bagi yang ingin membuat programnya saya sediakan listingnya :

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    grp1: TGroupBox;
    lbl1: TLabel;
    lbl3: TLabel;
    lbl2: TLabel;
    lbl4: TLabel;
    edt1: TEdit;
    btn1: TButton;
    btn2: TButton;
    btn3: TButton;
    btn4: TButton;
    btn5: TButton;
    btn6: TButton;
    btn7: TButton;
    btn8: TButton;
    btn9: TButton;
    btn10: TButton;
    btn11: TButton;
    btn12: TButton;
    lbl5: TLabel;
    tmr1: TTimer;
    lbl6: TLabel;
    rg1: TRadioGroup;
    procedure FormCreate(Sender: TObject);
    procedure btn2Click(Sender: TObject);
    procedure btn12Click(Sender: TObject);
    procedure btn3Click(Sender: TObject);
    procedure btn4Click(Sender: TObject);
    procedure btn5Click(Sender: TObject);
    procedure btn6Click(Sender: TObject);
    procedure btn7Click(Sender: TObject);
    procedure btn8Click(Sender: TObject);
    procedure btn9Click(Sender: TObject);
    procedure btn10Click(Sender: TObject);
    procedure btn11Click(Sender: TObject);
    procedure btn1Click(Sender: TObject);
    procedure tmr1Timer(Sender: TObject);
    procedure edt1KeyPress(Sender: TObject; var Key: Char);
    procedure edt1Change(Sender: TObject);
    procedure rg1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }

    jawab : string;
    i,hasil_pembagi : byte;
    benar,salah,total : word;
    waktu : word;

    tabel1 : array [2..10,2..10] of Integer;

    procedure acak_soal ();
  end;

const
  A : array [1..10] of byte = (11,12,13,14,15,16,17,18,19,20);
var
  Form1: TForm1;

implementation

uses Math;

{$R *.dfm}

procedure Tform1.acak_soal ();
var
  c1 : integer;
  x,y : Byte;
begin
  //Randomize;
  if rg1.ItemIndex < 2 then
    begin
      c1 := RandomRange(11,21);
      lbl1.Caption := IntToStr(c1);

      c1 := RandomRange(4,11);
      lbl2.Caption := IntToStr(c1);
    end;
  if rg1.ItemIndex = 2 then
    begin
      c1 := RandomRange(2,11);
      lbl1.Caption := IntToStr(c1);

      c1 := RandomRange(2,11);
      lbl2.Caption := IntToStr(c1);
    end;
  if rg1.ItemIndex = 3 then
    begin
      x := RandomRange(2,11);
      y := RandomRange(2,11);
      lbl1.Caption := inttostr(tabel1[x,y]);
      lbl2.Caption := IntToStr(y);
      hasil_pembagi := x;
    end;      
  if rg1.ItemIndex = 4 then
    begin
      c1 := RandomRange(1,5);
      case c1 of
        1 : begin
              lbl3.Caption := '+';
              c1 := RandomRange(11,21);
              lbl1.Caption := IntToStr(c1);

              c1 := RandomRange(4,11);
              lbl2.Caption := IntToStr(c1);
            end;
        2 : begin
              lbl3.Caption := '-';
              c1 := RandomRange(11,21);
              lbl1.Caption := IntToStr(c1);

              c1 := RandomRange(4,11);
              lbl2.Caption := IntToStr(c1);
            end;
        3 : begin
              lbl3.Caption := 'x';
              c1 := RandomRange(2,11);
              lbl1.Caption := IntToStr(c1); 
              c1 := RandomRange(2,11);
              lbl2.Caption := IntToStr(c1);
            end;
        4 : begin
              lbl3.Caption := ':';
              x := RandomRange(2,11);
              y := RandomRange(2,11);
              lbl1.Caption := inttostr(tabel1[x,y]);
              lbl2.Caption := IntToStr(y);
              hasil_pembagi := x;
            end;
      end;
    end;

end;

procedure TForm1.FormCreate(Sender: TObject);
var
x,y : Byte;
begin
  waktu := 0;   tmr1.Enabled := false; btn1.Enabled := false;
  jawab := ''; lbl1.Caption := '';  lbl2.Caption := ''; lbl5.Caption := 'Benar = 0 Salah = 0 Total = 0';
  edt1.Text := jawab;
  Randomize;
  acak_soal;
  benar := 0;  salah := 0; total := 0;
  if rg1.ItemIndex = 0 then lbl3.Caption := '+';

  // menyiapkan tabel
  for x := 2 to 10 do
    begin
      for y := 2 to 10 do
        begin
          tabel1[x,y] := x*y;
        end;
    end;
end;

procedure TForm1.btn2Click(Sender: TObject);
begin
  jawab := jawab + '1';
  edt1.Text := jawab;
end;

procedure TForm1.btn12Click(Sender: TObject);
begin
  jawab := '';
  edt1.Text := jawab;
end;

procedure TForm1.btn3Click(Sender: TObject);
begin
  jawab := jawab + '2';
  edt1.Text := jawab;
end;

procedure TForm1.btn4Click(Sender: TObject);
begin
  jawab := jawab + '3';
  edt1.Text := jawab;
end;

procedure TForm1.btn5Click(Sender: TObject);
begin
  jawab := jawab + '4';
  edt1.Text := jawab;
end;

procedure TForm1.btn6Click(Sender: TObject);
begin
  jawab := jawab + '5';
  edt1.Text := jawab;
end;

procedure TForm1.btn7Click(Sender: TObject);
begin
  jawab := jawab + '6';
  edt1.Text := jawab;
end;

procedure TForm1.btn8Click(Sender: TObject);
begin
  jawab := jawab + '7';
  edt1.Text := jawab;
end;

procedure TForm1.btn9Click(Sender: TObject);
begin
  jawab := jawab + '8';
  edt1.Text := jawab;
end;

procedure TForm1.btn10Click(Sender: TObject);
begin
  jawab := jawab + '9';
  edt1.Text := jawab;
end;

procedure TForm1.btn11Click(Sender: TObject);
begin
  jawab := jawab + '0';
  edt1.Text := jawab;
end;

procedure TForm1.btn1Click(Sender: TObject);
var
  x,y : word;
begin
  if rg1.ItemIndex = 0 then
    begin
      x := strtoint(lbl1.Caption) + strtoint(lbl2.Caption);
    end;
  if rg1.ItemIndex = 1 then
    begin
      x := strtoint(lbl1.Caption) - strtoint(lbl2.Caption);
    end;
  if rg1.ItemIndex = 2 then
    begin
      x := tabel1[strtoint(lbl1.Caption),strtoint(lbl2.Caption)];
    end;
  if rg1.ItemIndex = 3 then
    begin
      x := hasil_pembagi;
    end;
  if rg1.ItemIndex = 4 then
    begin
      if lbl3.Caption = '+' then x := strtoint(lbl1.Caption) + strtoint(lbl2.Caption);
      if lbl3.Caption = '-' then x := strtoint(lbl1.Caption) - strtoint(lbl2.Caption);
      if lbl3.Caption = 'x' then  x := tabel1[strtoint(lbl1.Caption),strtoint(lbl2.Caption)];
      if lbl3.Caption = ':' then x :=  hasil_pembagi;
    end;

  if edt1.Text = '' then edt1.Text := '0';  // jika kosong rubah jadi 0
  y := strtoint(edt1.Text);

  if x = y then
    begin
      inc(benar);
      edt1.Text := '';
    end
  else inc(salah);
  total := benar + salah ;
  acak_soal;
  lbl5.Caption := 'Benar = '+inttostr(benar)+' Salah = '+inttostr(salah)+ ' Total = '+ inttostr(total);

  jawab := '';
end;

procedure TForm1.tmr1Timer(Sender: TObject);
begin
  inc(waktu);
  lbl6.Caption := inttostr(900 - waktu);
  if waktu >= 900 then
    begin
      tmr1.Enabled := false;
      waktu := 0; btn1.Enabled := false;
      ShowMessage('Waktu sudah habis catat berapa benar dan salah kirimkan ke wa ayah');
    end;
end;

procedure TForm1.edt1KeyPress(Sender: TObject; var Key: Char);
begin
  if not (key in['0'..'9',#8,#13,#32]) then
     begin
       key:=#0;
       showmessage('inputan hanya angka bro');
     end;
end;

procedure TForm1.edt1Change(Sender: TObject);
begin
  jawab := edt1.Text;
end;

procedure TForm1.rg1Click(Sender: TObject);
begin
  tmr1.Enabled := false;
  lbl6.Caption := '900';
  if rg1.ItemIndex = 0 then lbl3.Caption := '+';
  if rg1.ItemIndex = 1 then lbl3.Caption := '-';
  if rg1.ItemIndex = 2 then lbl3.Caption := 'X';
  if rg1.ItemIndex = 3 then lbl3.Caption := ':';
  if rg1.ItemIndex = 4 then ;
  ShowMessage('Lama test adalah 15 menit, dan dimulai setelah di kilk OK');
  waktu := 0;
  acak_soal;
  tmr1.Enabled := true; btn1.Enabled := true;
end;

end.



jika teman - teman ada ide untuk game pengembangan anak bisa komen di bawah dan kirimkan detail datanya, jika menarik saya akan coba buatkan 



READ MORE

Thursday, April 4, 2019

SOP Kalibrasi Control Valve


INSTRUKSI KERJA
Perbaikkan dan Kalibrasi Control Valve
1.      Tujuan
Procedure ini menjelaskan tata aturan dalam Perbaikkan Control Valve secara sistematis yang mencangkup troubleshooting umum, agar bisa menetukan apakah Control Valve ini masih bisa dipakai dan akurat.

2.      Prasarat dan Kondisi awal
2.1        Pastikan bahwa Control valve  ini tidak sedang terinterlock dengan sistem lainnya dan jika iya catat dalam form permit  agar supervisor operasional mengerti kondisinya dan bisa mengambil langkah untuk mematikan interlock atau hal lainnya sesuai dengan SOP.
2.2        Pastikan control valve ini bisa di operasikan full open dan full close jika tidak ini akan membatasi
Ruang lingkup troubleshooting nantinya.
2.3     pastikan dalam bekerja menggunakan sarung tangan panas jika sensor pada tempat yang panas dan plant sedang running.
2.4     Pastikan alat yang di bawa sudah lengkap menghindari loss time untuk ambil tool
2.5     pastikan jenis Control valve  yang akan di cek agar analisanya troubleshootingnya bisa tepat

3.      Referensi
4.1.     Manual book KOSO-AR

4.      Tanggung Jawab
4.1
Supervisior
:

4.2
Karu instrument
:

4.3
Teknisi instrument
:


5.      Alat Pendukung
5.1        Alat Pelindung Diri
·  Helm
·  Sepatu Safety
·  Earplug
·  Kaca mata safety
5.2        Alat Pendukung Lainnya
·  Radio Komunikasi
·  MultiTester
· Current injector
· Obeng + amplas halus
· Contact cleaner (no residu)

6.      Test Item
6.1        Test mekanis
6.2        Test Visual
6.3        Test Motor Listrik
6.4        Test Modul Kontrol
6.5        Kalibrasi control valve



7.      Procedure test dan penjelasannya
     
7.1        Test mekanis

Test mekanis ini dilakukan dengan cara
·         Di putar manual (di lakukan dengan power motor di matikan)
·         Di putar dengan motor
                Asal energy gerak sebuah control Valve dari manual oleh operator dan listrik dari gerakkan
                motor Listrik, maksudnya adalah dari kedua sumber ini apakah salah satunya bisa atau  
                 keduanya tidak bisa menggerakkan control valve. Adapun jika salah satunya berat maka  
                kita sudah bisa melakukan troubleshooting lanjutan berdasarkan kondisi ini. Jika di putar 
                motor tidak mau atau berat dan di putar manual ringan bisa jadi bearing motor sudah rusak 
                menyebabkan motor berat dan biasanya trip.
Dengan memutar manual kita di harap bisa test untuk posisi full closed dan full open atau posisi di antaranya apakah sudah maksimum baik untuk full close dan full open. Dan untuk posisi di antaranya apakah ada yang berat atau stag. Hal ini akan membatu untuk menganalisa keadaan mekanisnya. Agar jika semua amam bisa fokus ke hal lainnya.

2.1        Test Visual
Pada langkah ini kita akan melakukan inspeksi visual melihat indikasi kerusakan baik terbakar, cacat, putus kabel dan sebagainya

2.2        Test Motor Listrik


Motor Listrik yang di pakai pada control valve biasanya adalah motor 1 phasa yang bisa di rubah arah putarannya dan bisa di lihat pada diagram di atas, untuk merubah putaran terletak pada fungsi switch LS1 dan LS2.
Dengan mengetahui diagram motor maka kita bisa test motor apakah masih bagus atau sudah rusak tapi harus lepas capasitor dulu karena menggangu pengukuran. Bisa juga di lakukan pengetesan meger (insulationn test) jika sudah rendah nilainya maka bisa di bilang motor tersebut rusak.
Atau jika mau lebih yakin di test tersendiri untuk forward dan reverse nya dengan membuat rangkaian luar. Dengan cara ini kita bisa lebih yakin akan torsinya



2.1        Test Modul Kontrol




Precondition,
Control Valve pasti mempunyai deteksi posisi biasanya sebuah resistor potensio meter, type potensionya ada yang derajat kebebasannya 2700 dan ada yang 3600 tergantung dengan sistem mekanisnya, dan sebagai tambahan pengaman biasanya motornya di beri limit switch agar tidak bergerak dari batas maksimum menghindari kerusakan mekanis dan semua ini perlu di indentifikasi komponennya karena tiap type atau mode atau merk akan menentukan letak dan jenis alat yang di gunakan untuk fungsi ini.


Di harapkan pada test mekanis kita sudah yakin kalau mekanis tidak ada masalah dan dengan asummsi itu troubleshooting ini tidak membahas mekanis.
·         Power motor di matikan sehingga pergerakan control valve hanya bergantung pada manual operasi.
·         Memasang current injector di sisi SP dan Multitester pada sisi OP
·         Men-set SP pada titik 0% atau 4mA
·         Memutar control valve pada posisi full close
                
                 Testing
7.4.1        Merubah nilai SP menjadi 0% dan memutar control valve pada posisi full close.
7.4.2        Dengan kondisi 7.4.1 seharusnya kita mendapat nilai feedback (OP) sama dengan nilai SP yaitu di 4mA, tetapi jika tidak maka harus adjust Zero pada modul kontrollernya sehingga kita menadapatkan nilai yang sama atau jika tidak bisa mendekati nilai SP-nya.
7.4.3        Merubah nilai SP menjadi 100% dan memutar control valve pada posisi full open.
7.4.4        Dengan kondisi 7.4.3 seharusnya kita mendapat nilai feedback   (OP) sama dengan nilai SP yaitu 20mA, tetapi jika tidak maka harus adjust span pada modul controllernya sehingga kita mendapat nilai yang sama atau jika tidak mendekati nilai SP-nya.
7.4.5        Jika setelah proses 7.4.4 masih belum bisa tepat (masih selisih jauh) pada posisi full open dan full closednya maka ulangi proses 7.4.1 sampai 7.4.4 sampai maksimal 3 kali jika di rasa perlu dan mengalami perbaikkan.
7.4.6        Jika pada proses 7.4.5 tidak mengalami perbaikan maka bisa di pastikan modul atau encoder mengalami kerusakan dan perlu di servis atau di ganti
7.5  Kalibrasi control valve
Dengan melakukan langkah 7.4 jika berhasil maka sebenarnya pada point 7.4.1 sampai 7.4.4 adalah proses kalibrasi control valve hanya saja power motor harus sudah terpasang sehingga pengaturan full open dan close nya dari putaan motor.


8                    Acuan Standar

8.4  Pada Test Mekanis seharusnya yang kita dapat adalah jika di putar manual ringan dan jika di putar lewat motor pun tetap ringan tidak menyebabkan arus motor  yang tinggi, panas, suara kasar dan tidak bergetar.
8.5  Pada langkah ini kita memastikan semuanya dalam keadaan normal artinya seperti biasanya, hal kita perlu cermati jika ada bau terbakar, kapasitor yang kembung, kabel terbakar, bekas panas berlebih dll.
8.6  Pada langkah ini kita inginkan mengukur hambatan motor normal (biasanya kisaran 150 ohm tapi bisa bervariasi tergantung motornya) dan test meger untuk memastikan keadaan isolasi coilnya dan pengukuran siapa tahu ada short body dll.

8.7  Cleaning sangat di butuhkan seharusnya terminal bersih dari karat dan oksidasi, dan juga ujung dari transmitter itu harus bersih dan tidak ada cacat. jika tidak cacat maka cukup hanya dengan di beri contact cleaner.



READ MORE