Fetal Heart Simulator Berbasis ATMega 328p dengan Interface Arduino Uno
HEARTBEAT SIMULATOR UNTUK MENSIMULASIKAN DETAK JANTUNG JANIN BERBASIS MIKROKONTROLLER
Benaya Revanico H*), Frisca Syaharani**), Nasfa Tri
Utama***), Salsabila Chairunisa****)
Jurusan Teknik Elektro, Prodi Teknologi
Rekayasa Elektronika, Politeknik Negeri Semarang 2024
Jl. Prof. Soedarto, Tembalang, Kec. Tembalang, Kota Semarang, Jawa Tengah,
50275
Abstrak— Proyek ini bertujuan
merancang dan membuat alat kalibrasi portabel berbasis mikrokontroler Arduino
Uno R3 untuk mendeteksi dan mensimulasikan detak jantung janin pada frekuensi
30-240 bpm. Alat ini menggunakan komponen seperti relay, LCD 16x2, dan baterai
lithium untuk menghasilkan simulasi detak jantung yang akurat sesuai nilai bpm
yang ditampilkan. Dengan desain sederhana dan portabel, alat ini dirancang
untuk menguji akurasi perangkat medis seperti fetal doppler dan kardiotokografi
(CTG), terutama di fasilitas kesehatan daerah terpencil. Hasil pengujian
menunjukkan bahwa alat ini mampu menghasilkan simulasi detak jantung yang
sesuai dengan nilai referensi, menawarkan solusi ekonomis untuk proses
kalibrasi yang lebih efektif, terjangkau, dan mendukung peningkatan kualitas
layanan kesehatan ibu dan janin.
Keywords: Arduino
Uno R3, heart simulator, relay driver 5V, portable calibration, LCD\
I. PENDAHULUAN
1.1 Latar Belakang
Pemantauan detak jantung janin merupakan bagian penting dalam perawatan antenatal. Salah satu alat yang umum digunakan untuk tujuan ini adalah Doppler fetal monitor, yang memungkinkan tenaga medis mendeteksi dan memonitor detak jantung janin secara non-invasif. Namun, untuk memastikan akurasi dan keandalan alat ini, diperlukan proses kalibrasi secara berkala. Kalibrasi yang tepat sangat penting untuk mencegah kesalahan pembacaan yang dapat berakibat pada diagnosis yang kurang akurat.
Saat ini, belum banyak tersedia perangkat yang dirancang khusus untuk kebutuhan kalibrasi Doppler fetal monitor. Oleh karena itu, diperlukan pengembangan alat yang mampu mensimulasikan sinyal detak jantung janin secara realistis. Alat ini, yang disebut fetal doppler simulator, dapat digunakan untuk memastikan bahwa Doppler fetal monitor bekerja dengan akurasi optimal. Dengan adanya simulator ini, proses kalibrasi dapat dilakukan secara lebih efisien, akurat, dan hemat biaya, sehingga membantu menjaga kualitas layanan kesehatan maternal dan janin.
Dengan adanya alat ini, proses kalibrasi perangkat medis dapat
dilakukan dengan lebih mudah, cepat, dan akurat, mendukung peningkatan kualitas
layanan kesehatan ibu dan janin. Berdasarkan kebutuhan tersebut, penulis
merancang alat dengan judul “Alat Kalibrasi Deteksi Detak Jantung Janin
Portabel Berbasis Mikrokontroler”.
1.2 Perumusan
Masalah
Bagaimana cara kerja alat tombol sebagai masukan?
Bagaimana cara kerja lcd sebagai luaran?
Apa fungsi relay sebagai luaran?
Bagaimana cara kerja alat tersebut?
Bisakah fetal doppler simulator mengkalibrasi fetal doppler monitor?
1. 1.3 Tujuan
Tujuan dari pembuatan alat ini adalah sebagai berikut:
1.
Meningkatkan keakuratan dan keandalan
perangkat medis seperti fetal doppler dan kardiotokografi(CTG) sehingga
memberikan hasil pengukuran detak janin yang akurat dengan proses kalibrasi
yang efektif.
2. Menghadirkan alternatif terjangkau alat kalibrasi yang ekonomis dibandingkan dengan perangkat kalibrasi yang ada di pasaran, sehingga dapat diakses oleh fasilitas kesehatan dengan keterbatasan anggaran.
2.
METODE PENELITIAN
Metode yang
dilakukan dalam penelitian ini terdiri dari beberapa tahap, yaitu: perancangan
hardware, perancangan software.
2.1 Perancangan
Hardware
Perancangan hardware pada alat ini
menggunakan beberapa modul rangkaian diantaranya adalah rangkaian
microcontroller ATMega328p , sedangkan perangkat lunak yang digunakan adalah
software pemrograman CV AVR sebagai pengelolah data pada alat.
2.2 Rangkaian Microcontroller
2.2.1
Arduino
UNO:
a.
Pin 5
(Relay): Pin ini terhubung ke pin kontrol relay pada modul relay untuk
mengendalikan perangkat eksternal (seperti motor atau lampu). Pin ini akan
memberikan sinyal HIGH atau LOW untuk mengaktifkan atau menonaktifkan relay.
b. Pin 2, 3, 4 (Tombol): Pin ini terhubung ke tiga
tombol (berwarna hijau, kuning, dan merah) yang digunakan sebagai input untuk
sistem. Masing-masing tombol berfungsi untuk memberikan perintah atau sinyal
tertentu kepada sistem.
c.
Pin A0
(LCD): Pin ini menghubungkan Arduino ke layar LCD, dimana data atau informasi
akan ditampilkan, seperti pesan selamat datang ("Welcome Heart
Simulator").
2.2.2
LCD
(Liquid Crystal Display):
LCD digunakan untuk menampilkan pesan kepada
pengguna, seperti "Welcome Heart Simulator." LCD ini dihubungkan ke
pin A0 untuk pengendalian tampilan.
2.2.3
Relay:
Relay digunakan sebagai keluaran (output) untuk
mengontrol perangkat lain (misalnya, motor atau lampu) berdasarkan perintah
dari tombol atau kondisi yang ditentukan pada sistem. Relay dihubungkan ke pin
5 pada Arduino, yang memberikan sinyal untuk mengaktifkan atau menonaktifkan
relay.
2.2.4
Tombol:
a. Tombol Hijau (Pin 2): Tombol ini terhubung ke pin 2
dan digunakan untuk memberikan sinyal input pada sistem.
b. Tombol Kuning (Pin 3): Tombol ini terhubung ke pin
3 dan juga memberikan sinyal input pada sistem.
c. Tombol Merah (Pin 4): Tombol ini terhubung ke pin 4
dan digunakan untuk memberikan sinyal input, memungkinkan pengguna
mengendalikan sistem atau memilih mode tertentu.
2.2.5
Sensor Daya (Battery atau Power Supply):
Daya untuk sistem ini disuplai dari sumber eksternal yang terhubung
dengan Arduino untuk menjalankan seluruh rangkaian, termasuk sensor dan
komponen lainnya.
#include <Wire.h>#include <hd44780.h>#include <hd44780ioClass/hd44780_I2Cexp.h>// Inisialisasi LCDhd44780_I2Cexp lcd;// Definisi pin dan dataconst int tombolKurangi = 2; // Tombol 1 untuk mengurangi BPMconst int tombolTambah = 3; // Tombol 2 untuk menambah BPMconst int tombolStartStop = 4; // Tombol 3 untuk start/stop relayconst int relayPin = 7;int BPM = 90; // Nilai BPM awalbool relayStatus = false; // Status relay// Karakter hati untuk animasibyte heart1[8] = {0b00000,0b01010,0b11111,0b11111,0b11111,0b01110,0b00100,0b00000};byte heart2[8] = {0b00000,0b01010,0b11111,0b11111,0b01110,0b00100,0b00000,0b00000};void setup() {lcd.begin(16, 2);lcd.backlight();lcd.createChar(0, heart1);lcd.createChar(1, heart2);lcd.print("Heart Simulator");lcd.setCursor(0, 1);lcd.print(" Portable");delay(3000);lcd.clear();pinMode(tombolKurangi, INPUT_PULLUP);pinMode(tombolTambah, INPUT_PULLUP);pinMode(tombolStartStop, INPUT_PULLUP);pinMode(relayPin, OUTPUT);digitalWrite(relayPin, LOW); // Relay mati pada kondisi awaltampilkanMenu();}void loop() {// Tombol 1 (mengurangi BPM)if (digitalRead(tombolKurangi) == LOW) {if (BPM > 30) { // Batas minimum BPMBPM -= 30;tampilkanMenu();}delay(200); // Debounce tombol}// Tombol 2 (menambah BPM)if (digitalRead(tombolTambah) == LOW) {if (BPM < 240) { // Batas maksimum BPMBPM += 30;tampilkanMenu();}delay(200); // Debounce tombol}// Tombol 3 (start/stop relay)if (digitalRead(tombolStartStop) == LOW) {relayStatus = !relayStatus; // Toggle status relayif (relayStatus) {aktifkanRelay();} else {matikanRelay();}delay(200); // Debounce tombol}// Jika relay aktif, animasi hati dan flip-flop relayif (relayStatus) {unsigned long intervalDetak = 60000 / BPM ; // Interval detak hatistatic unsigned long waktuTerakhirAnimasi = 0;static bool detakHati = false; // Status detak hatiunsigned long waktuSekarang = millis();if (waktuSekarang - waktuTerakhirAnimasi >= intervalDetak) {waktuTerakhirAnimasi = waktuSekarang;detakHati = !detakHati; // Toggle status detak hati// Animasi hati di bawah "RUN"lcd.setCursor(12, 1); // Tepat di bawah "RUN"if (detakHati) {lcd.write((byte)0); // Animasi hati penuh} else {lcd.write((byte)1); // Animasi hati kecil}// Flip-flop relaydigitalWrite(relayPin, !digitalRead(relayPin));}}}void tampilkanMenu() {lcd.clear();lcd.setCursor(0, 0);lcd.print("SET BPM"); // Judul menulcd.setCursor(0, 1);lcd.print("BPM = ");lcd.print(BPM); // Tampilkan nilai BPM yang dipilihif (relayStatus) { // Jika relay aktif, tampilkan "RUN"lcd.setCursor(12, 0); // Letakkan "RUN" di pojok kanan ataslcd.print("RUN");lcd.setCursor(12, 1); // Awal animasi hatilcd.write((byte)1); // Tampilkan hati kecil default}}void aktifkanRelay() {digitalWrite(relayPin, LOW); // Mulai dengan relay matitampilkanMenu();}void matikanRelay() {digitalWrite(relayPin, LOW); // Matikan relaytampilkanMenu();}
#include <delay.h> // Header untuk fungsi delay#include <mega328p.h> // Header untuk ATmega328P#include <stdio.h> // Untuk konversi integer ke string (sprintf)// Definisi manual simbol port#define PD1 (1 << 1) // Pin 1 PORTD#define PD0 (1 << 0) // Pin 0 PORTD#define PD3 (1 << 3) // Pin 3 PORTD#define PD2 (1 << 2) // Pin 2 PORTD#define PD5 (1 << 5) // Pin 5 PORTD#define PD4 (1 << 4) // Pin 4 PORTD#define PD7 (1 << 7) // Pin 7 PORTD#define PD6 (1 << 6) // Pin 6 PORTD#define PB0 (1 << 0) // Pin 0 PORTB#define PB1 (1 << 1) // Pin 1 PORTB// Definisi pin LCD#define EN PD1#define RS PD0#define D5 PD3#define D4 PD2#define D7 PD5#define D6 PD4// Definisi pin tombol dan relay#define tombolTambah PD7#define tombolKurangi PD6#define relayPin PB1#define tombolStartStop PB0// Variabel globalunsigned char relayStatus = 0; // Status relay (0: mati, 1: aktif)int BPM = 90; // Nilai BPM awal// Prototipe fungsivoid sendCommand(unsigned char cmd);void initLCD();void sendString(const char *str);void sendData(unsigned char data);void aktifkanRelay();void tampilkanMenu(); // Tidak ada parameter lagivoid matikanRelay();// Fungsi utama// Deklarasi variabel bpmStr sebelum digunakanvoid main(void) {char bpmStr[5]; // Buffer untuk string BPMDDRD |= RS | EN | D4 | D5 | D6 | D7; // Atur pin LCD sebagai output// Inisialisasi pin LCD sebagai outputPORTD &= ~(RS | EN); // RS dan EN diatur LOW// Inisialisasi pin tombol sebagai input dengan pull-upPORTD |= tombolKurangi | tombolTambah; // Aktifkan pull-upDDRD &= ~(tombolKurangi | tombolTambah); // Input tombolPORTB |= tombolStartStop; // Aktifkan pull-upDDRB &= ~tombolStartStop; // Input tombol// Inisialisasi pin relay sebagai outputPORTB &= ~relayPin; // Relay mati awalnyaDDRB |= relayPin; // Output relay// Inisialisasi LCD dan tampilkan menu awaltampilkanMenu(); // Panggil fungsi tampilkanMenu tanpa argumeninitLCD();while (1) {if (!(PIND & tombolKurangi)) {// Deteksi tombol kurangitampilkanMenu(); // Panggil fungsi tampilkanMenuif (BPM > 30) BPM -= 30; // Kurangi BPM jika lebih besar dari 30}delay_ms(200); // Debounce tombol// Deteksi tombol tambahif (BPM < 240) BPM += 30; // Tambah BPM jika kurang dari 240if (!(PIND & tombolTambah)) {delay_ms(200); // Debounce tomboltampilkanMenu(); // Panggil fungsi tampilkanMenu}// Deteksi tombol start/stoprelayStatus = !relayStatus; // Toggle status relayif (!(PINB & tombolStartStop)) {aktifkanRelay();if (relayStatus) {matikanRelay();} else {delay_ms(200); // Debounce tombol}}// Animasi relay aktifunsigned int interval = 60000 / BPM; // Interval detak berdasarkan BPMif (relayStatus) {PORTB ^= relayPin; // Toggle relaydelay_ms(interval / 2); // Delay sesuai interval}}}// Fungsi untuk inisialisasi LCDdelay_ms(20); // Tunggu LCD siapvoid initLCD() {sendCommand(0x28); // 2 baris, mode 4-bitsendCommand(0x02); // Mode 4-bitsendCommand(0x06); // Auto incrementsendCommand(0x0C); // Display ON, cursor OFFdelay_ms(2); // Tunggu perintah selesaisendCommand(0x01); // Clear display}// Fungsi untuk mengirim perintah ke LCDPORTD &= ~RS; // RS = 0 untuk perintahvoid sendCommand(unsigned char cmd) {PORTD |= EN; // EN = 1PORTD = (PORTD & 0x0F) | (cmd & 0xF0); // Kirim nibble atasPORTD &= ~EN; // EN = 0delay_us(1); // Delay pendekPORTD = (PORTD & 0x0F) | ((cmd << 4) & 0xF0); // Kirim nibble bawahdelay_us(1);PORTD |= EN; // EN = 1PORTD &= ~EN; // EN = 0delay_ms(2); // Tunggu perintah selesai}// Fungsi untuk mengirim data ke LCDPORTD |= RS; // RS = 1 untuk datavoid sendData(unsigned char data) {PORTD |= EN; // EN = 1PORTD = (PORTD & 0x0F) | (data & 0xF0); // Kirim nibble atasPORTD &= ~EN; // EN = 0delay_us(1);PORTD = (PORTD & 0x0F) | ((data << 4) & 0xF0); // Kirim nibble bawahdelay_us(1);PORTD |= EN; // EN = 1PORTD &= ~EN; // EN = 0delay_ms(2); // Tunggu data selesai}// Fungsi untuk mengirim string ke LCDwhile (*str) {void sendString(const char *str) {}sendData(*str++);}// Fungsi untuk menampilkan menuchar bpmStr[5]; // Buffer untuk string BPMvoid tampilkanMenu() {sendString("SET BPM");sendCommand(0x01); // Clear displaysendString("BPM = ");sendCommand(0xC0); // Pindah ke baris kedua// Konversi BPM ke string dan tampilkansendString(bpmStr); // Tampilkan BPMsprintf(bpmStr, "%d", BPM); // Konversi BPM ke stringif (relayStatus) {}sendString(" RUN");}// Fungsi untuk mengaktifkan relayPORTB |= relayPin; // Aktifkan relayvoid aktifkanRelay() {}tampilkanMenu(); // Tampilkan menu// Fungsi untuk mematikan relayPORTB &= ~relayPin; // Matikan relayvoid matikanRelay() {
}tampilkanMenu(); // Tampilkan menu
;CodeVisionAVR C Compiler V3.36 Evaluation;(C) Copyright 1998-2019 Pavel Haiduc, HP InfoTech s.r.l.;http://www.hpinfotech.com;Build configuration : Debug;Chip type : ATmega328P;Program type : Application;Clock frequency : 8.000000 MHz;Memory model : Small;Optimize for : Size;(s)printf features : int, width;(s)scanf features : int, width;External RAM size : 0;Data Stack size : 512 byte(s);Heap size : 0 byte(s);Promote 'char' to 'int': Yes;'char' is unsigned : Yes;8 bit enums : Yes;Global 'const' stored in FLASH: No;Enhanced function parameter passing: Mode 2;Enhanced core instructions: On;Automatic register allocation for global variables: On;Smart register allocation: On#define _MODEL_SMALL_#pragma AVRPART ADMIN PART_NAME ATmega328P#pragma AVRPART MEMORY PROG_FLASH 32768#pragma AVRPART MEMORY EEPROM 1024#pragma AVRPART MEMORY INT_SRAM SIZE 2048#pragma AVRPART MEMORY INT_SRAM START_ADDR 0x100#define CALL_SUPPORTED 1.LISTMAC.EQU EERE=0x0.EQU EEWE=0x1.EQU EEMWE=0x2.EQU UDRE=0x5.EQU RXC=0x7.EQU EECR=0x1F.EQU EEDR=0x20.EQU EEARL=0x21.EQU EEARH=0x22.EQU SPSR=0x2D.EQU SPDR=0x2E.EQU SMCR=0x33.EQU MCUSR=0x34.EQU MCUCR=0x35.EQU WDTCSR=0x60.EQU UCSR0A=0xC0.EQU UDR0=0xC6.EQU SPL=0x3D.EQU SPH=0x3E.EQU SREG=0x3F.EQU GPIOR0=0x1E.DEF R0X0=R0.DEF R0X1=R1.DEF R0X2=R2.DEF R0X3=R3.DEF R0X4=R4.DEF R0X5=R5.DEF R0X6=R6.DEF R0X7=R7.DEF R0X8=R8.DEF R0X9=R9.DEF R0XA=R10.DEF R0XB=R11.DEF R0XC=R12.DEF R0XD=R13.DEF R0XE=R14.DEF R0XF=R15.DEF R0X10=R16.DEF R0X11=R17.DEF R0X12=R18.DEF R0X13=R19.DEF R0X14=R20.DEF R0X15=R21.DEF R0X16=R22.DEF R0X17=R23.DEF R0X18=R24.DEF R0X19=R25.DEF R0X1A=R26.DEF R0X1B=R27.DEF R0X1C=R28.DEF R0X1D=R29.DEF R0X1E=R30.DEF R0X1F=R31.EQU __SRAM_START=0x0100.EQU __SRAM_END=0x08FF.EQU __DSTACK_SIZE=0x0200.EQU __HEAP_SIZE=0x0000.EQU __CLEAR_SRAM_SIZE=__SRAM_END-__SRAM_START+1.MACRO __CPD1NCPI R30,LOW(@0)LDI R26,HIGH(@0)CPC R31,R26LDI R26,BYTE3(@0)CPC R22,R26LDI R26,BYTE4(@0)CPC R23,R26.ENDM.MACRO __CPD2NCPI R26,LOW(@0)LDI R30,HIGH(@0)CPC R27,R30LDI R30,BYTE3(@0)CPC R24,R30LDI R30,BYTE4(@0)CPC R25,R30.ENDM.MACRO __CPWRRCP R@0,R@2CPC R@1,R@3.ENDM.MACRO __CPWRNCPI R@0,LOW(@2)LDI R30,HIGH(@2)CPC R@1,R30.ENDM.MACRO __ADDB1MNSUBI R30,LOW(-@0-(@1)).ENDM.MACRO __ADDB2MNSUBI R26,LOW(-@0-(@1)).ENDM.MACRO __ADDW1MNSUBI R30,LOW(-@0-(@1))SBCI R31,HIGH(-@0-(@1)).ENDM.MACRO __ADDW2MNSUBI R26,LOW(-@0-(@1))SBCI R27,HIGH(-@0-(@1)).ENDM.MACRO __ADDW1FNSUBI R30,LOW(-2*@0-(@1))SBCI R31,HIGH(-2*@0-(@1)).ENDM.MACRO __ADDD1FNSUBI R30,LOW(-2*@0-(@1))SBCI R31,HIGH(-2*@0-(@1))SBCI R22,BYTE3(-2*@0-(@1)).ENDM.MACRO __ADDD1NSUBI R30,LOW(-@0)SBCI R31,HIGH(-@0)SBCI R22,BYTE3(-@0)SBCI R23,BYTE4(-@0).ENDM.MACRO __ADDD2NSUBI R26,LOW(-@0)SBCI R27,HIGH(-@0)SBCI R24,BYTE3(-@0)SBCI R25,BYTE4(-@0).ENDM.MACRO __SUBD1NSUBI R30,LOW(@0)SBCI R31,HIGH(@0)SBCI R22,BYTE3(@0)SBCI R23,BYTE4(@0).ENDM.MACRO __SUBD2NSUBI R26,LOW(@0)SBCI R27,HIGH(@0)SBCI R24,BYTE3(@0)SBCI R25,BYTE4(@0).ENDM.MACRO __ANDBMNNLDS R30,@0+(@1)ANDI R30,LOW(@2)STS @0+(@1),R30.ENDM.MACRO __ANDWMNNLDS R30,@0+(@1)ANDI R30,LOW(@2)STS @0+(@1),R30LDS R30,@0+(@1)+1ANDI R30,HIGH(@2)STS @0+(@1)+1,R30.ENDM.MACRO __ANDD1NANDI R30,LOW(@0)ANDI R31,HIGH(@0)ANDI R22,BYTE3(@0)ANDI R23,BYTE4(@0).ENDM.MACRO __ANDD2NANDI R26,LOW(@0)ANDI R27,HIGH(@0)ANDI R24,BYTE3(@0)ANDI R25,BYTE4(@0).ENDM.MACRO __ORBMNNLDS R30,@0+(@1)ORI R30,LOW(@2)STS @0+(@1),R30.ENDM.MACRO __ORWMNNLDS R30,@0+(@1)ORI R30,LOW(@2)STS @0+(@1),R30LDS R30,@0+(@1)+1ORI R30,HIGH(@2)STS @0+(@1)+1,R30.ENDM.MACRO __ORD1NORI R30,LOW(@0)ORI R31,HIGH(@0)ORI R22,BYTE3(@0)ORI R23,BYTE4(@0).ENDM.MACRO __ORD2NORI R26,LOW(@0)ORI R27,HIGH(@0)ORI R24,BYTE3(@0)ORI R25,BYTE4(@0).ENDM.MACRO __DELAY_USBLDI R24,LOW(@0)__DELAY_USB_LOOP:DEC R24BRNE __DELAY_USB_LOOP.ENDM.MACRO __DELAY_USWLDI R24,LOW(@0)LDI R25,HIGH(@0)__DELAY_USW_LOOP:SBIW R24,1BRNE __DELAY_USW_LOOP.ENDM.MACRO __GETD1SLDD R30,Y+@0LDD R31,Y+@0+1LDD R22,Y+@0+2LDD R23,Y+@0+3.ENDM.MACRO __GETD2SLDD R26,Y+@0LDD R27,Y+@0+1LDD R24,Y+@0+2LDD R25,Y+@0+3.ENDM.MACRO __PUTD1SSTD Y+@0,R30STD Y+@0+1,R31STD Y+@0+2,R22STD Y+@0+3,R23.ENDM.MACRO __PUTD2SSTD Y+@0,R26STD Y+@0+1,R27STD Y+@0+2,R24STD Y+@0+3,R25.ENDM.MACRO __PUTDZ2STD Z+@0,R26STD Z+@0+1,R27STD Z+@0+2,R24STD Z+@0+3,R25.ENDM.MACRO __CLRD1SSTD Y+@0,R30STD Y+@0+1,R30STD Y+@0+2,R30STD Y+@0+3,R30.ENDM.MACRO __POINTB1MNLDI R30,LOW(@0+(@1)).ENDM.MACRO __POINTW1MNLDI R30,LOW(@0+(@1))LDI R31,HIGH(@0+(@1)).ENDM.MACRO __POINTD1MLDI R30,LOW(@0)LDI R31,HIGH(@0)LDI R22,BYTE3(@0)LDI R23,BYTE4(@0).ENDM.MACRO __POINTW1FNLDI R30,LOW(2*@0+(@1))LDI R31,HIGH(2*@0+(@1)).ENDM.MACRO __POINTD1FNLDI R30,LOW(2*@0+(@1))LDI R31,HIGH(2*@0+(@1))LDI R22,BYTE3(2*@0+(@1))LDI R23,BYTE4(2*@0+(@1)).ENDM.MACRO __POINTB2MNLDI R26,LOW(@0+(@1)).ENDM.MACRO __POINTW2MNLDI R26,LOW(@0+(@1))LDI R27,HIGH(@0+(@1)).ENDM.MACRO __POINTD2MLDI R26,LOW(@0)LDI R27,HIGH(@0)LDI R24,BYTE3(@0)LDI R25,BYTE4(@0).ENDM.MACRO __POINTW2FNLDI R26,LOW(2*@0+(@1))LDI R27,HIGH(2*@0+(@1)).ENDM.MACRO __POINTD2FNLDI R26,LOW(2*@0+(@1))LDI R27,HIGH(2*@0+(@1))LDI R24,BYTE3(2*@0+(@1))LDI R25,BYTE4(2*@0+(@1)).ENDM.MACRO __POINTBRMLDI R@0,LOW(@1).ENDM.MACRO __POINTWRMLDI R@0,LOW(@2)LDI R@1,HIGH(@2).ENDM.MACRO __POINTBRMNLDI R@0,LOW(@1+(@2)).ENDM.MACRO __POINTWRMNLDI R@0,LOW(@2+(@3))LDI R@1,HIGH(@2+(@3)).ENDM.MACRO __POINTWRFNLDI R@0,LOW(@2*2+(@3))LDI R@1,HIGH(@2*2+(@3)).ENDM.MACRO __GETD1NLDI R30,LOW(@0)LDI R31,HIGH(@0)LDI R22,BYTE3(@0)LDI R23,BYTE4(@0).ENDM.MACRO __GETD2NLDI R26,LOW(@0)LDI R27,HIGH(@0)LDI R24,BYTE3(@0)LDI R25,BYTE4(@0).ENDM.MACRO __GETB1MNLDS R30,@0+(@1).ENDM.MACRO __GETB1HMNLDS R31,@0+(@1).ENDM.MACRO __GETW1MNLDS R30,@0+(@1)LDS R31,@0+(@1)+1.ENDM.MACRO __GETD1MNLDS R30,@0+(@1)LDS R31,@0+(@1)+1LDS R22,@0+(@1)+2LDS R23,@0+(@1)+3.ENDM.MACRO __GETBRMNLDS R@0,@1+(@2).ENDM.MACRO __GETWRMNLDS R@0,@2+(@3)LDS R@1,@2+(@3)+1.ENDM.MACRO __GETWRZLDD R@0,Z+@2LDD R@1,Z+@2+1.ENDM.MACRO __GETD2ZLDD R26,Z+@0LDD R27,Z+@0+1LDD R24,Z+@0+2LDD R25,Z+@0+3.ENDM.MACRO __GETB2MNLDS R26,@0+(@1).ENDM.MACRO __GETW2MNLDS R26,@0+(@1)LDS R27,@0+(@1)+1.ENDM.MACRO __GETD2MNLDS R26,@0+(@1)LDS R27,@0+(@1)+1LDS R24,@0+(@1)+2LDS R25,@0+(@1)+3.ENDM.MACRO __PUTB1MNSTS @0+(@1),R30.ENDM.MACRO __PUTW1MNSTS @0+(@1),R30STS @0+(@1)+1,R31.ENDM.MACRO __PUTD1MNSTS @0+(@1),R30STS @0+(@1)+1,R31STS @0+(@1)+2,R22STS @0+(@1)+3,R23.ENDM.MACRO __PUTB1ENLDI R26,LOW(@0+(@1))LDI R27,HIGH(@0+(@1))CALL __EEPROMWRB.ENDM.MACRO __PUTW1ENLDI R26,LOW(@0+(@1))LDI R27,HIGH(@0+(@1))CALL __EEPROMWRW.ENDM.MACRO __PUTD1ENLDI R26,LOW(@0+(@1))LDI R27,HIGH(@0+(@1))CALL __EEPROMWRD.ENDM.MACRO __PUTBR0MNSTS @0+(@1),R0.ENDM.MACRO __PUTBMRNSTS @0+(@1),R@2.ENDM.MACRO __PUTWMRNSTS @0+(@1),R@2STS @0+(@1)+1,R@3.ENDM.MACRO __PUTBZRSTD Z+@1,R@0.ENDM.MACRO __PUTWZRSTD Z+@2,R@0STD Z+@2+1,R@1.ENDM.MACRO __GETW1RMOV R30,R@0MOV R31,R@1.ENDM.MACRO __GETW2RMOV R26,R@0MOV R27,R@1.ENDM.MACRO __GETWRNLDI R@0,LOW(@2)LDI R@1,HIGH(@2).ENDM.MACRO __PUTW1RMOV R@0,R30MOV R@1,R31.ENDM.MACRO __PUTW2RMOV R@0,R26MOV R@1,R27.ENDM.MACRO __ADDWRNSUBI R@0,LOW(-@2)SBCI R@1,HIGH(-@2).ENDM.MACRO __ADDWRRADD R@0,R@2ADC R@1,R@3.ENDM.MACRO __SUBWRNSUBI R@0,LOW(@2)SBCI R@1,HIGH(@2).ENDM.MACRO __SUBWRRSUB R@0,R@2SBC R@1,R@3.ENDM.MACRO __ANDWRNANDI R@0,LOW(@2)ANDI R@1,HIGH(@2).ENDM.MACRO __ANDWRRAND R@0,R@2AND R@1,R@3.ENDM.MACRO __ORWRNORI R@0,LOW(@2)ORI R@1,HIGH(@2).ENDM.MACRO __ORWRROR R@0,R@2OR R@1,R@3.ENDM.MACRO __EORWRREOR R@0,R@2EOR R@1,R@3.ENDM.MACRO __GETWRSLDD R@0,Y+@2LDD R@1,Y+@2+1.ENDM.MACRO __PUTBSRSTD Y+@1,R@0.ENDM.MACRO __PUTWSRSTD Y+@2,R@0STD Y+@2+1,R@1.ENDM.MACRO __MOVEWRRMOV R@0,R@2MOV R@1,R@3.ENDM.MACRO __INWRIN R@0,@2IN R@1,@2+1.ENDM.MACRO __OUTWROUT @2+1,R@1OUT @2,R@0.ENDM.MACRO __CALL1MNLDS R30,@0+(@1)LDS R31,@0+(@1)+1ICALL.ENDM.MACRO __CALL1FNLDI R30,LOW(2*@0+(@1))LDI R31,HIGH(2*@0+(@1))CALL __GETW1PFICALL.ENDM.MACRO __CALL2ENPUSH R26PUSH R27LDI R26,LOW(@0+(@1))LDI R27,HIGH(@0+(@1))CALL __EEPROMRDWPOP R27POP R26ICALL.ENDM.MACRO __CALL2EXSUBI R26,LOW(-@0)SBCI R27,HIGH(-@0)CALL __EEPROMRDDICALL.ENDM.MACRO __GETW1STACKIN R30,SPLIN R31,SPHADIW R30,@0+1LD R0,Z+LD R31,ZMOV R30,R0.ENDM.MACRO __GETD1STACKIN R30,SPLIN R31,SPHADIW R30,@0+1LD R0,Z+LD R1,Z+LD R22,ZMOVW R30,R0.ENDM.MACRO __NBSTBST R@0,@1IN R30,SREGLDI R31,0x40EOR R30,R31OUT SREG,R30.ENDM.MACRO __PUTB1SNLDD R26,Y+@0LDD R27,Y+@0+1SUBI R26,LOW(-@1)SBCI R27,HIGH(-@1)ST X,R30.ENDM.MACRO __PUTW1SNLDD R26,Y+@0LDD R27,Y+@0+1SUBI R26,LOW(-@1)SBCI R27,HIGH(-@1)ST X+,R30ST X,R31.ENDM.MACRO __PUTD1SNLDD R26,Y+@0LDD R27,Y+@0+1SUBI R26,LOW(-@1)SBCI R27,HIGH(-@1)CALL __PUTDP1.ENDM.MACRO __PUTB1SNSLDD R26,Y+@0LDD R27,Y+@0+1ADIW R26,@1ST X,R30.ENDM.MACRO __PUTW1SNSLDD R26,Y+@0LDD R27,Y+@0+1ADIW R26,@1ST X+,R30ST X,R31.ENDM.MACRO __PUTD1SNSLDD R26,Y+@0LDD R27,Y+@0+1ADIW R26,@1CALL __PUTDP1.ENDM.MACRO __PUTB1PMNLDS R26,@0LDS R27,@0+1SUBI R26,LOW(-@1)SBCI R27,HIGH(-@1)ST X,R30.ENDM.MACRO __PUTW1PMNLDS R26,@0LDS R27,@0+1SUBI R26,LOW(-@1)SBCI R27,HIGH(-@1)ST X+,R30ST X,R31.ENDM.MACRO __PUTD1PMNLDS R26,@0LDS R27,@0+1SUBI R26,LOW(-@1)SBCI R27,HIGH(-@1)CALL __PUTDP1.ENDM.MACRO __PUTB1PMNSLDS R26,@0LDS R27,@0+1ADIW R26,@1ST X,R30.ENDM.MACRO __PUTW1PMNSLDS R26,@0LDS R27,@0+1ADIW R26,@1ST X+,R30ST X,R31.ENDM.MACRO __PUTD1PMNSLDS R26,@0LDS R27,@0+1ADIW R26,@1CALL __PUTDP1.ENDM.MACRO __PUTB1RNMOVW R26,R@0SUBI R26,LOW(-@1)SBCI R27,HIGH(-@1)ST X,R30.ENDM.MACRO __PUTW1RNMOVW R26,R@0SUBI R26,LOW(-@1)SBCI R27,HIGH(-@1)ST X+,R30ST X,R31.ENDM.MACRO __PUTD1RNMOVW R26,R@0SUBI R26,LOW(-@1)SBCI R27,HIGH(-@1)CALL __PUTDP1.ENDM.MACRO __PUTB1RNSMOVW R26,R@0ADIW R26,@1ST X,R30.ENDM.MACRO __PUTW1RNSMOVW R26,R@0ADIW R26,@1ST X+,R30ST X,R31.ENDM.MACRO __PUTD1RNSMOVW R26,R@0ADIW R26,@1CALL __PUTDP1.ENDM.MACRO __PUTB1RONMOV R26,R@0MOV R27,R@1SUBI R26,LOW(-@2)SBCI R27,HIGH(-@2)ST X,R30.ENDM.MACRO __PUTW1RONMOV R26,R@0MOV R27,R@1SUBI R26,LOW(-@2)SBCI R27,HIGH(-@2)ST X+,R30ST X,R31.ENDM.MACRO __PUTD1RONMOV R26,R@0MOV R27,R@1SUBI R26,LOW(-@2)SBCI R27,HIGH(-@2)CALL __PUTDP1.ENDM.MACRO __PUTB1RONSMOV R26,R@0MOV R27,R@1ADIW R26,@2ST X,R30.ENDM.MACRO __PUTW1RONSMOV R26,R@0MOV R27,R@1ADIW R26,@2ST X+,R30ST X,R31.ENDM.MACRO __PUTD1RONSMOV R26,R@0MOV R27,R@1ADIW R26,@2CALL __PUTDP1.ENDM.MACRO __GETB1SXMOVW R30,R28SUBI R30,LOW(-@0)SBCI R31,HIGH(-@0)LD R30,Z.ENDM.MACRO __GETB1HSXMOVW R30,R28SUBI R30,LOW(-@0)SBCI R31,HIGH(-@0)LD R31,Z.ENDM.MACRO __GETW1SXMOVW R30,R28SUBI R30,LOW(-@0)SBCI R31,HIGH(-@0)LD R0,Z+LD R31,ZMOV R30,R0.ENDM.MACRO __GETD1SXMOVW R30,R28SUBI R30,LOW(-@0)SBCI R31,HIGH(-@0)LD R0,Z+LD R1,Z+LD R22,Z+LD R23,ZMOVW R30,R0.ENDM.MACRO __GETB2SXMOVW R26,R28SUBI R26,LOW(-@0)SBCI R27,HIGH(-@0)LD R26,X.ENDM.MACRO __GETW2SXMOVW R26,R28SUBI R26,LOW(-@0)SBCI R27,HIGH(-@0)LD R0,X+LD R27,XMOV R26,R0.ENDM.MACRO __GETD2SXMOVW R26,R28SUBI R26,LOW(-@0)SBCI R27,HIGH(-@0)LD R0,X+LD R1,X+LD R24,X+LD R25,XMOVW R26,R0.ENDM.MACRO __GETBRSXMOVW R30,R28SUBI R30,LOW(-@1)SBCI R31,HIGH(-@1)LD R@0,Z.ENDM.MACRO __GETWRSXMOVW R30,R28SUBI R30,LOW(-@2)SBCI R31,HIGH(-@2)LD R@0,Z+LD R@1,Z.ENDM.MACRO __GETBRSX2MOVW R26,R28SUBI R26,LOW(-@1)SBCI R27,HIGH(-@1)LD R@0,X.ENDM.MACRO __GETWRSX2MOVW R26,R28SUBI R26,LOW(-@2)SBCI R27,HIGH(-@2)LD R@0,X+LD R@1,X.ENDM.MACRO __LSLW8SXMOVW R30,R28SUBI R30,LOW(-@0)SBCI R31,HIGH(-@0)LD R31,ZCLR R30.ENDM.MACRO __PUTB1SXMOVW R26,R28SUBI R26,LOW(-@0)SBCI R27,HIGH(-@0)ST X,R30.ENDM.MACRO __PUTW1SXMOVW R26,R28SUBI R26,LOW(-@0)SBCI R27,HIGH(-@0)ST X+,R30ST X,R31.ENDM.MACRO __PUTD1SXMOVW R26,R28SUBI R26,LOW(-@0)SBCI R27,HIGH(-@0)ST X+,R30ST X+,R31ST X+,R22ST X,R23.ENDM.MACRO __CLRW1SXMOVW R26,R28SUBI R26,LOW(-@0)SBCI R27,HIGH(-@0)ST X+,R30ST X,R30.ENDM.MACRO __CLRD1SXMOVW R26,R28SUBI R26,LOW(-@0)SBCI R27,HIGH(-@0)ST X+,R30ST X+,R30ST X+,R30ST X,R30.ENDM.MACRO __PUTB2SXMOVW R30,R28SUBI R30,LOW(-@0)SBCI R31,HIGH(-@0)ST Z,R26.ENDM.MACRO __PUTW2SXMOVW R30,R28SUBI R30,LOW(-@0)SBCI R31,HIGH(-@0)ST Z+,R26ST Z,R27.ENDM.MACRO __PUTD2SXMOVW R30,R28SUBI R30,LOW(-@0)SBCI R31,HIGH(-@0)ST Z+,R26ST Z+,R27ST Z+,R24ST Z,R25.ENDM.MACRO __PUTBSRXMOVW R30,R28SUBI R30,LOW(-@1)SBCI R31,HIGH(-@1)ST Z,R@0.ENDM.MACRO __PUTWSRXMOVW R30,R28SUBI R30,LOW(-@2)SBCI R31,HIGH(-@2)ST Z+,R@0ST Z,R@1.ENDM.MACRO __PUTB1SNXMOVW R26,R28SUBI R26,LOW(-@0)SBCI R27,HIGH(-@0)LD R0,X+LD R27,XMOV R26,R0SUBI R26,LOW(-@1)SBCI R27,HIGH(-@1)ST X,R30.ENDM.MACRO __PUTW1SNXMOVW R26,R28SUBI R26,LOW(-@0)SBCI R27,HIGH(-@0)LD R0,X+LD R27,XMOV R26,R0SUBI R26,LOW(-@1)SBCI R27,HIGH(-@1)ST X+,R30ST X,R31.ENDM.MACRO __PUTD1SNXMOVW R26,R28SUBI R26,LOW(-@0)SBCI R27,HIGH(-@0)LD R0,X+LD R27,XMOV R26,R0SUBI R26,LOW(-@1)SBCI R27,HIGH(-@1)ST X+,R30ST X+,R31ST X+,R22ST X,R23.ENDM.MACRO __MULBRRMULS R@0,R@1MOVW R30,R0.ENDM.MACRO __MULBRRUMUL R@0,R@1MOVW R30,R0.ENDM.MACRO __MULBRR0MULS R@0,R@1.ENDM.MACRO __MULBRRU0MUL R@0,R@1.ENDM.MACRO __MULBNWRULDI R26,@2MUL R26,R@0MOVW R30,R0MUL R26,R@1ADD R31,R0.ENDM;NAME DEFINITIONS FOR GLOBAL VARIABLES ALLOCATED TO REGISTERS.DEF _BPM=R3.DEF _BPM_msb=R4.DEF _relayStatus=R6;GPIOR0 INITIALIZATION VALUE.EQU __GPIOR0_INIT=0x00.CSEG.ORG 0x00;START OF CODE MARKER__START_OF_CODE:;INTERRUPT VECTORSJMP __RESETJMP 0x00JMP 0x00JMP 0x00JMP 0x00JMP 0x00JMP 0x00JMP 0x00JMP 0x00JMP 0x00JMP 0x00JMP 0x00JMP 0x00JMP 0x00JMP 0x00JMP 0x00JMP 0x00JMP 0x00JMP 0x00JMP 0x00JMP 0x00JMP 0x00JMP 0x00JMP 0x00JMP 0x00JMP 0x00_tbl10_G100:.DB 0x10,0x27,0xE8,0x3,0x64,0x0,0xA,0x0.DB 0x1,0x0_tbl16_G100:.DB 0x0,0x10,0x0,0x1,0x10,0x0,0x1,0x0;GLOBAL REGISTER VARIABLES INITIALIZATION__REG_VARS:.DB 0x5A,0x0,0x0,0x0_0x0:.DB 0x53,0x45,0x54,0x20,0x42,0x50,0x4D,0x0.DB 0x42,0x50,0x4D,0x20,0x3D,0x20,0x0,0x25.DB 0x64,0x0,0x20,0x52,0x55,0x4E,0x0__GLOBAL_INI_TBL:.DW 0x04.DW 0x03.DW __REG_VARS*2.DW 0x08.DW _0x12.DW _0x0*2.DW 0x07.DW _0x12+8.DW _0x0*2+8.DW 0x05.DW _0x12+15.DW _0x0*2+18_0xFFFFFFFF:.DW 0#define __GLOBAL_INI_TBL_PRESENT 1__RESET:CLICLR R30OUT EECR,R30;INTERRUPT VECTORS ARE PLACED;AT THE START OF FLASHLDI R31,1OUT MCUCR,R31OUT MCUCR,R30;CLEAR R2-R14LDI R24,(14-2)+1LDI R26,2CLR R27__CLEAR_REG:ST X+,R30DEC R24BRNE __CLEAR_REG;CLEAR SRAMLDI R24,LOW(__CLEAR_SRAM_SIZE)LDI R25,HIGH(__CLEAR_SRAM_SIZE)LDI R26,LOW(__SRAM_START)LDI R27,HIGH(__SRAM_START)__CLEAR_SRAM:ST X+,R30SBIW R24,1BRNE __CLEAR_SRAM;GLOBAL VARIABLES INITIALIZATIONLDI R30,LOW(__GLOBAL_INI_TBL*2)LDI R31,HIGH(__GLOBAL_INI_TBL*2)__GLOBAL_INI_NEXT:LPM R24,Z+LPM R25,Z+SBIW R24,0BREQ __GLOBAL_INI_ENDLPM R26,Z+LPM R27,Z+LPM R0,Z+LPM R1,Z+MOVW R22,R30MOVW R30,R0__GLOBAL_INI_LOOP:LPM R0,Z+ST X+,R0SBIW R24,1BRNE __GLOBAL_INI_LOOPMOVW R30,R22RJMP __GLOBAL_INI_NEXT__GLOBAL_INI_END:;GPIOR0 INITIALIZATIONLDI R30,__GPIOR0_INITOUT GPIOR0,R30;HARDWARE STACK POINTER INITIALIZATIONLDI R30,LOW(__SRAM_END-__HEAP_SIZE)OUT SPL,R30LDI R30,HIGH(__SRAM_END-__HEAP_SIZE)OUT SPH,R30;DATA STACK POINTER INITIALIZATIONLDI R28,LOW(__SRAM_START+__DSTACK_SIZE)LDI R29,HIGH(__SRAM_START+__DSTACK_SIZE)JMP _main.ESEG.ORG 0x00.DSEG.ORG 0x300.CSEG;#include <mega328p.h> // Header untuk ATmega328P#ifndef __SLEEP_DEFINED__#define __SLEEP_DEFINED__.EQU __se_bit=0x01.EQU __sm_mask=0x0E.EQU __sm_adc_noise_red=0x02.EQU __sm_powerdown=0x04.EQU __sm_powersave=0x06.EQU __sm_standby=0x0C.EQU __sm_ext_standby=0x0E.SET power_ctrl_reg=smcr#endif;#include <delay.h> // Header untuk fungsi delay;#include <stdio.h> // Untuk konversi integer ke string (sprintf);;// Definisi manual simbol port;#define PD0 (1 << 0) // Pin 0 PORTD;#define PD1 (1 << 1) // Pin 1 PORTD;#define PD2 (1 << 2) // Pin 2 PORTD;#define PD3 (1 << 3) // Pin 3 PORTD;#define PD4 (1 << 4) // Pin 4 PORTD;#define PD5 (1 << 5) // Pin 5 PORTD;#define PD6 (1 << 6) // Pin 6 PORTD;#define PD7 (1 << 7) // Pin 7 PORTD;;#define PB0 (1 << 0) // Pin 0 PORTB;#define PB1 (1 << 1) // Pin 1 PORTB;;// Definisi pin LCD;#define RS PD0;#define EN PD1;#define D4 PD2;#define D5 PD3;#define D6 PD4;#define D7 PD5;;// Definisi pin tombol dan relay;#define tombolKurangi PD6;#define tombolTambah PD7;#define tombolStartStop PB0;#define relayPin PB1;;// Variabel global;int BPM = 90; // Nilai BPM awal;unsigned char relayStatus = 0; // Status relay (0: mati, 1: aktif);;// Prototipe fungsi;void initLCD();;void sendCommand(unsigned char cmd);;void sendData(unsigned char data);;void sendString(const char *str);;void tampilkanMenu(); // Tidak ada parameter lagi;void aktifkanRelay();;void matikanRelay();;;// Fungsi utama;void main(void) {; 0000 002E void main(void) {.CSEG_main:; .FSTART _main; 0000 002F // Deklarasi variabel bpmStr sebelum digunakan; 0000 0030 char bpmStr[5]; // Buffer untuk string BPM; 0000 0031; 0000 0032 // Inisialisasi pin LCD sebagai output; 0000 0033 DDRD |= RS | EN | D4 | D5 | D6 | D7; // Atur pin LCD sebagai outputSBIW R28,5; bpmStr -> Y+0IN R30,0xAORI R30,LOW(0x3F)OUT 0xA,R30; 0000 0034 PORTD &= ~(RS | EN); // RS dan EN diatur LOWIN R30,0xBANDI R30,LOW(0xFC)OUT 0xB,R30; 0000 0035; 0000 0036 // Inisialisasi pin tombol sebagai input dengan pull-up; 0000 0037 DDRD &= ~(tombolKurangi | tombolTambah); // Input tombolIN R30,0xAANDI R30,LOW(0x3F)OUT 0xA,R30; 0000 0038 PORTD |= tombolKurangi | tombolTambah; // Aktifkan pull-upIN R30,0xBORI R30,LOW(0xC0)OUT 0xB,R30; 0000 0039 DDRB &= ~tombolStartStop; // Input tombolCBI 0x4,0; 0000 003A PORTB |= tombolStartStop; // Aktifkan pull-upSBI 0x5,0; 0000 003B; 0000 003C // Inisialisasi pin relay sebagai output; 0000 003D DDRB |= relayPin; // Output relaySBI 0x4,1; 0000 003E PORTB &= ~relayPin; // Relay mati awalnyaCBI 0x5,1; 0000 003F; 0000 0040 // Inisialisasi LCD dan tampilkan menu awal; 0000 0041 initLCD();RCALL _initLCD; 0000 0042 tampilkanMenu(); // Panggil fungsi tampilkanMenu tanpa argumenRCALL _tampilkanMenu; 0000 0043; 0000 0044 while (1) {_0x3:; 0000 0045 // Deteksi tombol kurangi; 0000 0046 if (!(PIND & tombolKurangi)) {SBIC 0x9,6RJMP _0x6; 0000 0047 if (BPM > 30) BPM -= 30; // Kurangi BPM jika lebih besar dari 30LDI R30,LOW(30)LDI R31,HIGH(30)CP R30,R3CPC R31,R4BRGE _0x7__GETW1R 3,4SBIW R30,30__PUTW1R 3,4; 0000 0048 tampilkanMenu(); // Panggil fungsi tampilkanMenu_0x7:RCALL SUBOPT_0x0; 0000 0049 delay_ms(200); // Debounce tombol; 0000 004A }; 0000 004B; 0000 004C // Deteksi tombol tambah; 0000 004D if (!(PIND & tombolTambah)) {_0x6:SBIC 0x9,7RJMP _0x8; 0000 004E if (BPM < 240) BPM += 30; // Tambah BPM jika kurang dari 240LDI R30,LOW(240)LDI R31,HIGH(240)CP R3,R30CPC R4,R31BRGE _0x9LDI R30,LOW(30)LDI R31,HIGH(30)__ADDWRR 3,4,30,31; 0000 004F tampilkanMenu(); // Panggil fungsi tampilkanMenu_0x9:RCALL SUBOPT_0x0; 0000 0050 delay_ms(200); // Debounce tombol; 0000 0051 }; 0000 0052; 0000 0053 // Deteksi tombol start/stop; 0000 0054 if (!(PINB & tombolStartStop)) {_0x8:SBIC 0x3,0RJMP _0xA; 0000 0055 relayStatus = !relayStatus; // Toggle status relayMOV R30,R6RCALL __LNEGB1MOV R6,R30; 0000 0056 if (relayStatus) {TST R6BREQ _0xB; 0000 0057 aktifkanRelay();RCALL _aktifkanRelay; 0000 0058 } else {RJMP _0xC_0xB:; 0000 0059 matikanRelay();RCALL _matikanRelay; 0000 005A }_0xC:; 0000 005B delay_ms(200); // Debounce tombolLDI R26,LOW(200)LDI R27,0RCALL _delay_ms; 0000 005C }; 0000 005D; 0000 005E // Animasi relay aktif; 0000 005F if (relayStatus) {_0xA:TST R6BREQ _0xD; 0000 0060 unsigned int interval = 60000 / BPM; // Interval detak berdasarkan BPM; 0000 0061 delay_ms(interval / 2); // Delay sesuai intervalSBIW R28,2; bpmStr -> Y+2; interval -> Y+0__GETW1R 3,4LDI R26,LOW(60000)LDI R27,HIGH(60000)RCALL __DIVW21UST Y,R30STD Y+1,R31LSR R31ROR R30MOVW R26,R30RCALL _delay_ms; 0000 0062 PORTB ^= relayPin; // Toggle relayIN R30,0x5LDI R26,LOW(2)EOR R30,R26OUT 0x5,R30; 0000 0063 }ADIW R28,2; 0000 0064 }_0xD:RJMP _0x3; 0000 0065 }_0xE:RJMP _0xE; .FEND;;// Fungsi untuk inisialisasi LCD;void initLCD() {; 0000 0068 void initLCD() {_initLCD:; .FSTART _initLCD; 0000 0069 delay_ms(20); // Tunggu LCD siapLDI R26,LOW(20)LDI R27,0RCALL _delay_ms; 0000 006A sendCommand(0x02); // Mode 4-bitLDI R26,LOW(2)RCALL _sendCommand; 0000 006B sendCommand(0x28); // 2 baris, mode 4-bitLDI R26,LOW(40)RCALL _sendCommand; 0000 006C sendCommand(0x0C); // Display ON, cursor OFFLDI R26,LOW(12)RCALL _sendCommand; 0000 006D sendCommand(0x06); // Auto incrementLDI R26,LOW(6)RCALL _sendCommand; 0000 006E sendCommand(0x01); // Clear displayLDI R26,LOW(1)RCALL _sendCommand; 0000 006F delay_ms(2); // Tunggu perintah selesaiLDI R26,LOW(2)LDI R27,0RCALL _delay_ms; 0000 0070 }RET; .FEND;;// Fungsi untuk mengirim perintah ke LCD;void sendCommand(unsigned char cmd) {; 0000 0073 void sendCommand(unsigned char cmd) {_sendCommand:; .FSTART _sendCommand; 0000 0074 PORTD &= ~RS; // RS = 0 untuk perintahST -Y,R17MOV R17,R26; cmd -> R17CBI 0xB,0; 0000 0075 PORTD = (PORTD & 0x0F) | (cmd & 0xF0); // Kirim nibble atasRJMP _0x2060003; 0000 0076 PORTD |= EN; // EN = 1; 0000 0077 delay_us(1); // Delay pendek; 0000 0078 PORTD &= ~EN; // EN = 0; 0000 0079; 0000 007A PORTD = (PORTD & 0x0F) | ((cmd << 4) & 0xF0); // Kirim nibble bawah; 0000 007B PORTD |= EN; // EN = 1; 0000 007C delay_us(1);; 0000 007D PORTD &= ~EN; // EN = 0; 0000 007E; 0000 007F delay_ms(2); // Tunggu perintah selesai; 0000 0080 }; .FEND;;// Fungsi untuk mengirim data ke LCD;void sendData(unsigned char data) {; 0000 0083 void sendData(unsigned char data) {_sendData:; .FSTART _sendData; 0000 0084 PORTD |= RS; // RS = 1 untuk dataST -Y,R17MOV R17,R26; data -> R17SBI 0xB,0; 0000 0085 PORTD = (PORTD & 0x0F) | (data & 0xF0); // Kirim nibble atas_0x2060003:IN R30,0xBANDI R30,LOW(0xF)MOV R26,R30MOV R30,R17RCALL SUBOPT_0x1; 0000 0086 PORTD |= EN; // EN = 1; 0000 0087 delay_us(1);; 0000 0088 PORTD &= ~EN; // EN = 0; 0000 0089; 0000 008A PORTD = (PORTD & 0x0F) | ((data << 4) & 0xF0); // Kirim nibble bawahIN R30,0xBANDI R30,LOW(0xF)MOV R26,R30MOV R30,R17SWAP R30RCALL SUBOPT_0x1; 0000 008B PORTD |= EN; // EN = 1; 0000 008C delay_us(1);; 0000 008D PORTD &= ~EN; // EN = 0; 0000 008E; 0000 008F delay_ms(2); // Tunggu data selesaiLDI R26,LOW(2)LDI R27,0RCALL _delay_ms; 0000 0090 }LD R17,Y+RET; .FEND;;// Fungsi untuk mengirim string ke LCD;void sendString(const char *str) {; 0000 0093 void sendString(const char *str) {_sendString:; .FSTART _sendString; 0000 0094 while (*str) {ST -Y,R17ST -Y,R16MOVW R16,R26; *str -> R16,R17_0xF:MOVW R26,R16LD R30,XCPI R30,0BREQ _0x11; 0000 0095 sendData(*str++);__ADDWRN 16,17,1LD R26,XRCALL _sendData; 0000 0096 }RJMP _0xF_0x11:; 0000 0097 }LD R16,Y+LD R17,Y+RET; .FEND;;// Fungsi untuk menampilkan menu;void tampilkanMenu() {; 0000 009A void tampilkanMenu() {_tampilkanMenu:; .FSTART _tampilkanMenu; 0000 009B char bpmStr[5]; // Buffer untuk string BPM; 0000 009C sendCommand(0x01); // Clear displaySBIW R28,5; bpmStr -> Y+0LDI R26,LOW(1)RCALL _sendCommand; 0000 009D sendString("SET BPM");__POINTW2MN _0x12,0RCALL _sendString; 0000 009E sendCommand(0xC0); // Pindah ke baris keduaLDI R26,LOW(192)RCALL _sendCommand; 0000 009F sendString("BPM = ");__POINTW2MN _0x12,8RCALL _sendString; 0000 00A0; 0000 00A1 // Konversi BPM ke string dan tampilkan; 0000 00A2 sprintf(bpmStr, "%d", BPM); // Konversi BPM ke stringMOVW R30,R28ST -Y,R31ST -Y,R30__POINTW1FN _0x0,15ST -Y,R31ST -Y,R30__GETW1R 3,4RCALL __CWD1RCALL __PUTPARD1LDI R24,4RCALL _sprintfADIW R28,8; 0000 00A3 sendString(bpmStr); // Tampilkan BPMMOVW R26,R28RCALL _sendString; 0000 00A4; 0000 00A5 if (relayStatus) {TST R6BREQ _0x13; 0000 00A6 sendString(" RUN");__POINTW2MN _0x12,15RCALL _sendString; 0000 00A7 }; 0000 00A8 }_0x13:ADIW R28,5RET; .FEND.DSEG_0x12:.BYTE 0x14;;// Fungsi untuk mengaktifkan relay;void aktifkanRelay() {; 0000 00AB void aktifkanRelay() {.CSEG_aktifkanRelay:; .FSTART _aktifkanRelay; 0000 00AC PORTB |= relayPin; // Aktifkan relaySBI 0x5,1; 0000 00AD tampilkanMenu(); // Tampilkan menuRJMP _0x2060002; 0000 00AE }; .FEND;;// Fungsi untuk mematikan relay;void matikanRelay() {; 0000 00B1 void matikanRelay() {_matikanRelay:; .FSTART _matikanRelay; 0000 00B2 PORTB &= ~relayPin; // Matikan relayCBI 0x5,1; 0000 00B3 tampilkanMenu(); // Tampilkan menu_0x2060002:RCALL _tampilkanMenu; 0000 00B4 }RET; .FEND#ifndef __SLEEP_DEFINED__#define __SLEEP_DEFINED__.EQU __se_bit=0x01.EQU __sm_mask=0x0E.EQU __sm_adc_noise_red=0x02.EQU __sm_powerdown=0x04.EQU __sm_powersave=0x06.EQU __sm_standby=0x0C.EQU __sm_ext_standby=0x0E.SET power_ctrl_reg=smcr#endif.CSEG_put_buff_G100:; .FSTART _put_buff_G100RCALL __SAVELOCR6MOVW R18,R26LDD R21,Y+6ADIW R26,2RCALL __GETW1PSBIW R30,0BREQ _0x2000016MOVW R26,R18ADIW R26,4RCALL __GETW1PMOVW R16,R30SBIW R30,0BREQ _0x2000018__CPWRN 16,17,2BRLO _0x2000019MOVW R30,R16SBIW R30,1MOVW R16,R30__PUTW1RNS 18,4_0x2000018:MOVW R26,R18ADIW R26,2RCALL SUBOPT_0x2SBIW R30,1ST Z,R21_0x2000019:MOVW R26,R18RCALL __GETW1PTST R31BRMI _0x200001ARCALL SUBOPT_0x2_0x200001A:RJMP _0x200001B_0x2000016:MOVW R26,R18LDI R30,LOW(65535)LDI R31,HIGH(65535)ST X+,R30ST X,R31_0x200001B:RCALL __LOADLOCR6ADIW R28,7RET; .FEND__print_G100:; .FSTART __print_G100ST -Y,R27ST -Y,R26SBIW R28,6RCALL __SAVELOCR6LDI R17,0LDD R26,Y+12LDD R27,Y+12+1LDI R30,LOW(0)LDI R31,HIGH(0)ST X+,R30ST X,R31_0x200001C:LDD R30,Y+18LDD R31,Y+18+1ADIW R30,1STD Y+18,R30STD Y+18+1,R31SBIW R30,1LPM R30,ZMOV R18,R30CPI R30,0BRNE PC+2RJMP _0x200001EMOV R30,R17CPI R30,0BRNE _0x2000022CPI R18,37BRNE _0x2000023LDI R17,LOW(1)RJMP _0x2000024_0x2000023:RCALL SUBOPT_0x3_0x2000024:RJMP _0x2000021_0x2000022:CPI R30,LOW(0x1)BRNE _0x2000025CPI R18,37BRNE _0x2000026RCALL SUBOPT_0x3RJMP _0x20000D2_0x2000026:LDI R17,LOW(2)LDI R20,LOW(0)LDI R16,LOW(0)CPI R18,45BRNE _0x2000027LDI R16,LOW(1)RJMP _0x2000021_0x2000027:CPI R18,43BRNE _0x2000028LDI R20,LOW(43)RJMP _0x2000021_0x2000028:CPI R18,32BRNE _0x2000029LDI R20,LOW(32)RJMP _0x2000021_0x2000029:RJMP _0x200002A_0x2000025:CPI R30,LOW(0x2)BRNE _0x200002B_0x200002A:LDI R21,LOW(0)LDI R17,LOW(3)CPI R18,48BRNE _0x200002CORI R16,LOW(128)RJMP _0x2000021_0x200002C:RJMP _0x200002D_0x200002B:CPI R30,LOW(0x3)BREQ PC+2RJMP _0x2000021_0x200002D:CPI R18,48BRLO _0x2000030CPI R18,58BRLO _0x2000031_0x2000030:RJMP _0x200002F_0x2000031:LDI R26,LOW(10)MUL R21,R26MOV R21,R0MOV R30,R18SUBI R30,LOW(48)ADD R21,R30RJMP _0x2000021_0x200002F:MOV R30,R18CPI R30,LOW(0x63)BRNE _0x2000035RCALL SUBOPT_0x4LDD R30,Y+16LDD R31,Y+16+1LDD R26,Z+4ST -Y,R26RCALL SUBOPT_0x5RJMP _0x2000036_0x2000035:CPI R30,LOW(0x73)BRNE _0x2000038RCALL SUBOPT_0x4RCALL SUBOPT_0x6RCALL _strlenMOV R17,R30RJMP _0x2000039_0x2000038:CPI R30,LOW(0x70)BRNE _0x200003BRCALL SUBOPT_0x4RCALL SUBOPT_0x6RCALL _strlenfMOV R17,R30ORI R16,LOW(8)_0x2000039:ORI R16,LOW(2)ANDI R16,LOW(127)LDI R19,LOW(0)RJMP _0x200003C_0x200003B:CPI R30,LOW(0x64)BREQ _0x200003FCPI R30,LOW(0x69)BRNE _0x2000040_0x200003F:ORI R16,LOW(4)RJMP _0x2000041_0x2000040:CPI R30,LOW(0x75)BRNE _0x2000042_0x2000041:LDI R30,LOW(_tbl10_G100*2)LDI R31,HIGH(_tbl10_G100*2)STD Y+6,R30STD Y+6+1,R31LDI R17,LOW(5)RJMP _0x2000043_0x2000042:CPI R30,LOW(0x58)BRNE _0x2000045ORI R16,LOW(8)RJMP _0x2000046_0x2000045:CPI R30,LOW(0x78)BREQ PC+2RJMP _0x2000077_0x2000046:LDI R30,LOW(_tbl16_G100*2)LDI R31,HIGH(_tbl16_G100*2)STD Y+6,R30STD Y+6+1,R31LDI R17,LOW(4)_0x2000043:SBRS R16,2RJMP _0x2000048RCALL SUBOPT_0x4LDD R26,Y+16LDD R27,Y+16+1ADIW R26,4LD R30,X+LD R31,X+STD Y+10,R30STD Y+10+1,R31LDD R26,Y+11TST R26BRPL _0x2000049RCALL __ANEGW1STD Y+10,R30STD Y+10+1,R31LDI R20,LOW(45)_0x2000049:CPI R20,0BREQ _0x200004ASUBI R17,-LOW(1)RJMP _0x200004B_0x200004A:ANDI R16,LOW(251)_0x200004B:RJMP _0x200004C_0x2000048:RCALL SUBOPT_0x4LDD R26,Y+16LDD R27,Y+16+1ADIW R26,4RCALL __GETW1PSTD Y+10,R30STD Y+10+1,R31_0x200004C:_0x200003C:SBRC R16,0RJMP _0x200004D_0x200004E:CP R17,R21BRSH _0x2000050SBRS R16,7RJMP _0x2000051SBRS R16,2RJMP _0x2000052ANDI R16,LOW(251)MOV R18,R20SUBI R17,LOW(1)RJMP _0x2000053_0x2000052:LDI R18,LOW(48)_0x2000053:RJMP _0x2000054_0x2000051:LDI R18,LOW(32)_0x2000054:RCALL SUBOPT_0x3SUBI R21,LOW(1)RJMP _0x200004E_0x2000050:_0x200004D:MOV R19,R17SBRS R16,1RJMP _0x2000055_0x2000056:CPI R19,0BREQ _0x2000058SBRS R16,3RJMP _0x2000059LDD R30,Y+6LDD R31,Y+6+1LPM R18,Z+STD Y+6,R30STD Y+6+1,R31RJMP _0x200005A_0x2000059:LDD R26,Y+6LDD R27,Y+6+1LD R18,X+STD Y+6,R26STD Y+6+1,R27_0x200005A:RCALL SUBOPT_0x3CPI R21,0BREQ _0x200005BSUBI R21,LOW(1)_0x200005B:SUBI R19,LOW(1)RJMP _0x2000056_0x2000058:RJMP _0x200005C_0x2000055:_0x200005E:LDI R18,LOW(48)LDD R30,Y+6LDD R31,Y+6+1RCALL __GETW1PFSTD Y+8,R30STD Y+8+1,R31LDD R30,Y+6LDD R31,Y+6+1ADIW R30,2STD Y+6,R30STD Y+6+1,R31_0x2000060:LDD R30,Y+8LDD R31,Y+8+1LDD R26,Y+10LDD R27,Y+10+1CP R26,R30CPC R27,R31BRLO _0x2000062SUBI R18,-LOW(1)LDD R26,Y+8LDD R27,Y+8+1LDD R30,Y+10LDD R31,Y+10+1SUB R30,R26SBC R31,R27STD Y+10,R30STD Y+10+1,R31RJMP _0x2000060_0x2000062:CPI R18,58BRLO _0x2000063SBRS R16,3RJMP _0x2000064SUBI R18,-LOW(7)RJMP _0x2000065_0x2000064:SUBI R18,-LOW(39)_0x2000065:_0x2000063:SBRC R16,4RJMP _0x2000067CPI R18,49BRSH _0x2000069LDD R26,Y+8LDD R27,Y+8+1SBIW R26,1BRNE _0x2000068_0x2000069:RJMP _0x20000D3_0x2000068:CP R21,R19BRLO _0x200006DSBRS R16,0RJMP _0x200006E_0x200006D:RJMP _0x200006C_0x200006E:LDI R18,LOW(32)SBRS R16,7RJMP _0x200006FLDI R18,LOW(48)_0x20000D3:ORI R16,LOW(16)SBRS R16,2RJMP _0x2000070ANDI R16,LOW(251)ST -Y,R20RCALL SUBOPT_0x5CPI R21,0BREQ _0x2000071SUBI R21,LOW(1)_0x2000071:_0x2000070:_0x200006F:_0x2000067:RCALL SUBOPT_0x3CPI R21,0BREQ _0x2000072SUBI R21,LOW(1)_0x2000072:_0x200006C:SUBI R19,LOW(1)LDD R26,Y+8LDD R27,Y+8+1SBIW R26,2BRLO _0x200005FRJMP _0x200005E_0x200005F:_0x200005C:SBRS R16,0RJMP _0x2000073_0x2000074:CPI R21,0BREQ _0x2000076SUBI R21,LOW(1)LDI R30,LOW(32)ST -Y,R30RCALL SUBOPT_0x5RJMP _0x2000074_0x2000076:_0x2000073:_0x2000077:_0x2000036:_0x20000D2:LDI R17,LOW(0)_0x2000021:RJMP _0x200001C_0x200001E:LDD R26,Y+12LDD R27,Y+12+1LD R30,X+LD R31,X+RCALL __LOADLOCR6ADIW R28,20RET; .FEND_sprintf:; .FSTART _sprintfPUSH R15MOV R15,R24SBIW R28,6RCALL __SAVELOCR6MOVW R30,R28RCALL __ADDW1R15__GETWRZ 20,21,14MOV R0,R20OR R0,R21BRNE _0x2000078LDI R30,LOW(65535)LDI R31,HIGH(65535)RJMP _0x2060001_0x2000078:MOVW R26,R28ADIW R26,8RCALL __ADDW2R15MOVW R16,R26__PUTWSR 20,21,8LDI R30,LOW(0)STD Y+10,R30STD Y+10+1,R30MOVW R26,R28ADIW R26,12RCALL __ADDW2R15LD R30,X+LD R31,X+ST -Y,R31ST -Y,R30ST -Y,R17ST -Y,R16LDI R30,LOW(_put_buff_G100)LDI R31,HIGH(_put_buff_G100)ST -Y,R31ST -Y,R30MOVW R26,R28ADIW R26,12RCALL __print_G100MOVW R18,R30LDD R26,Y+8LDD R27,Y+8+1LDI R30,LOW(0)ST X,R30MOVW R30,R18_0x2060001:RCALL __LOADLOCR6ADIW R28,12POP R15RET; .FEND.CSEG.CSEG_strlen:; .FSTART _strlenST -Y,R27ST -Y,R26ld r26,y+ld r27,y+clr r30clr r31strlen0:ld r22,x+tst r22breq strlen1adiw r30,1rjmp strlen0strlen1:ret; .FEND_strlenf:; .FSTART _strlenfST -Y,R27ST -Y,R26clr r26clr r27ld r30,y+ld r31,y+strlenf0:lpm r0,z+tst r0breq strlenf1adiw r26,1rjmp strlenf0strlenf1:movw r30,r26ret; .FEND.CSEG;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES, CODE SIZE REDUCTION:1 WORDSSUBOPT_0x0:RCALL _tampilkanMenuLDI R26,LOW(200)LDI R27,0RJMP _delay_ms;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES, CODE SIZE REDUCTION:5 WORDSSUBOPT_0x1:ANDI R30,LOW(0xF0)OR R30,R26OUT 0xB,R30SBI 0xB,1__DELAY_USB 3CBI 0xB,1RET;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES, CODE SIZE REDUCTION:2 WORDSSUBOPT_0x2:LD R30,X+LD R31,X+ADIW R30,1ST -X,R31ST -X,R30RET;OPTIMIZER ADDED SUBROUTINE, CALLED 5 TIMES, CODE SIZE REDUCTION:18 WORDSSUBOPT_0x3:ST -Y,R18LDD R26,Y+13LDD R27,Y+13+1LDD R30,Y+15LDD R31,Y+15+1ICALLRET;OPTIMIZER ADDED SUBROUTINE, CALLED 5 TIMES, CODE SIZE REDUCTION:14 WORDSSUBOPT_0x4:LDD R30,Y+16LDD R31,Y+16+1SBIW R30,4STD Y+16,R30STD Y+16+1,R31RET;OPTIMIZER ADDED SUBROUTINE, CALLED 3 TIMES, CODE SIZE REDUCTION:6 WORDSSUBOPT_0x5:LDD R26,Y+13LDD R27,Y+13+1LDD R30,Y+15LDD R31,Y+15+1ICALLRET;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES, CODE SIZE REDUCTION:6 WORDSSUBOPT_0x6:LDD R26,Y+16LDD R27,Y+16+1ADIW R26,4LD R30,X+LD R31,X+STD Y+6,R30STD Y+6+1,R31LDD R26,Y+6LDD R27,Y+6+1RET;RUNTIME LIBRARY.CSEG__SAVELOCR6:ST -Y,R21__SAVELOCR5:ST -Y,R20__SAVELOCR4:ST -Y,R19__SAVELOCR3:ST -Y,R18__SAVELOCR2:ST -Y,R17ST -Y,R16RET__LOADLOCR6:LDD R21,Y+5__LOADLOCR5:LDD R20,Y+4__LOADLOCR4:LDD R19,Y+3__LOADLOCR3:LDD R18,Y+2__LOADLOCR2:LDD R17,Y+1LD R16,YRET__ADDW1R15:CLR R0ADD R30,R15ADC R31,R0RET__ADDW2R15:CLR R0ADD R26,R15ADC R27,R0RET__ANEGW1:NEG R31NEG R30SBCI R31,0RET__CWD1:MOV R22,R31ADD R22,R22SBC R22,R22MOV R23,R22RET__LNEGB1:TST R30LDI R30,1BREQ __LNEGB1FCLR R30__LNEGB1F:RET__DIVW21U:CLR R0CLR R1LDI R25,16__DIVW21U1:LSL R26ROL R27ROL R0ROL R1SUB R0,R30SBC R1,R31BRCC __DIVW21U2ADD R0,R30ADC R1,R31RJMP __DIVW21U3__DIVW21U2:SBR R26,1__DIVW21U3:DEC R25BRNE __DIVW21U1MOVW R30,R26MOVW R26,R0RET__GETW1P:LD R30,X+LD R31,XSBIW R26,1RET__GETW1PF:LPM R0,Z+LPM R31,ZMOV R30,R0RET__PUTPARD1:ST -Y,R23ST -Y,R22ST -Y,R31ST -Y,R30RET_delay_ms:adiw r26,0breq __delay_ms1__delay_ms0:wdr__DELAY_USW 0x7D0sbiw r26,1brne __delay_ms0__delay_ms1:ret;END OF CODE MARKER__END_OF_CODE:
II.
TINJAUAN PUSTAKA
Untuk mengetahui berbagai
komponen dan peralatan yang dibutuhkan, maka disusunlah tinjauan pustaka
sebagai acuan dalam merancang dan membuat aplikasi menggunakan mikrokontroler
ARDUINO UNO R3 ini.
2.1 Mikrokontroler
Arduino UNO R3
Arduino UNO adalah sebuah board mikrokontroler yang didasarkan pada ATmega328 (datasheet). Arduino UNO
mempunyai 14 pin digital input/output (6 di antaranya dapat digunakan sebagai
output PWM), 6 input analog, sebuah osilator Kristal 16 MHz, sebuah koneksi
USB, sebuah power jack, sebuah ICSP header, dan sebuat tombol reset. Arduino
UNO memuat semua yang dibutuhkan untuk menunjang mikrokontroler, mudah
menghubungkannya ke sebuah computer dengan sebuah kabel USB atau mensuplainya
dengan sebuah adaptor AC ke DC atau menggunakan baterai untuk memulainya.
2.2 Driver relay
Relay adalah komponen elektronik berupa saklar elektronik yang digerakkan
oleh arus listrik. Secara prinsip, relay merupakan tuas saklardengan lilitan
kawat pada batang besi (solenoid) di dekatnya, ketika solenoiddialiri arus
listrik, tuas akan tertarik karena adanya gaya magnet yang terjadipada solenoid
sehingga kontak saklar akan menutup. Pada saat arusdihentikan, gaya magnet akan
hilang, tuas akan kembali keposisi semula dan kontak saklar kembali terbuka.
Modul relay 5V adalah rangkaian elektronik lengkap
yang mencakup relay serta komponen pendukung lainnya. Perangkat ini dapat
menghidupkan dan mematikan perangkat bertegangan tinggi atau berarus tinggi
menggunakan sinyal 5V dari Arduino. Modul ini dapat digunakan untuk
mengendalikan perangkat seperti lampu, kipas, motor, solenoida, dll. Relai 5V
memiliki tiga terminal bertegangan tinggi (NC, C, dan NO) yang terhubung ke
perangkat yang ingin Anda kendalikan. Sisi lainnya memiliki tiga pin
bertegangan rendah (Ground, Vcc, dan Signal) yang terhubung ke Arduino.
Gambar 2.2 Driver relay
2.3
Baterai 18650
Baterai 18650 adalah baterai lithium-ion berbentuk silinder yang umum digunakan pada perangkat elektronik. Baterai ini berukuran diameter 18 mm (0,71 in) dan panjang 65 mm (2,56 in), sehingga diberi nama 18650. Baterai ini memiliki banyak voltase nominal, tergantung pada bahan kimia yang digunakan. Baterai lithium merupakan jenis baterai yang saat ini berkembang dengan sumber arus yang dapat diisi ulang. erkembangan dengan pesat. Baterai lithium memiliki beberap kelebihan, diantaranya dapat menyimpan energi listrik dalam waktu yang lama, memiliki daya yang tinggi, memiliki bobot yang ringan, dan memiliki siklus hidup yang panjang,
Gambar 2.3 Baterai 18650
2.4
Bms Step Up
Baterry
Mangement System (BMS) merupakan sebuah modul
elektronik yang
memiliki tujuan untuk mengatur kondisi kerja baterai khususnya lithium. BMS ini memiliki beberapa manfaat pada baterai, yaitu dapat melindungi sel baterai, manajemen temperatur sel baterai, akuisisi data, terdapat keseimbangan sel, mengontrol pengisian dan pengosongan baterai.
Gambar 2.4 BMS Step Up
2.5
LCD 16x2
Display LCD (Liquid Crystal
Display) pada Arduino merupakan salah satu komponen yang sering digunakan
untuk menampilkan informasi dari proyek-proyek Arduino. LCD ini
memanfaatkan kristal cair yang berada di antara dua lapisan kaca konduktif.
Ketika arus listrik diaplikasikan, kristal cair ini akan mengatur cahaya yang
melewatinya, sehingga menciptakan gambar atau teks yang terlihat pada layar.
Ada berbagai jenis LCD yang kompatibel
dengan Arduino, namun yang paling umum adalah tipe 16x2, yang berarti layarnya
dapat menampilkan 16 karakter dalam 2 baris. LCD ini
biasanya memiliki pin untuk power, ground, input data, dan beberapa kontrol
lainnya.
Gambar 2.5 LCD 16x2
2.6 Tombol tekan
(Push Button)
Push button adalah
untuk memutus dan menyambungkan arus listrik. Dimana
pemutusan dan pengaliran ini terjadi karena prinsip pengalihan dari satu
konduktor ke konduktor lain. Caranya dengan pengoperasian langsung secara
manual oleh pengguna.
Gambar 2.6 Push Button
2.7
Saklar
Saklar adalah komponen
listrik yang berfungsi sebagai pemutus dan penyambung arus listrik dari sumber
arus ke beban listrik pada rangkaian listrik tertutup. Berbagai
jenis saklar tersedia dengan fungsi,jenis dan cara pemasangan nya. Saklar yang
kami gunakan adalah Saklar Tunggal yang memiliki dua titik kontak .
Masing-masing titik kontak dihubungkan pada saluran fasa dan saluran masukan
beban.
Gambar 2.7 Saklar
III.
PERANCANGAN
ALAT
3.1
Perangkat Keras dan
Rangkaian Elektronika
Adapun alat
yang digunakan yaitu sebagai berikut:
1. Arduino Uno R3
2. Relay
3. Driver relay
4. Baterai lithium
5. Bms step up
6. LCD 16x2
7. Push button
8. Saklar
3.2 Diagram Blok
Keterangan:
1.
Tombol Tekan (Push button) digunakan untuk memulai
program dengan mengatur nilai bpm yang diinginkan.
2.
Mikrokontroler yang digunakan adalah ARDUINO UNO R3 yang
berfungsi untuk membaca sinyal dari tombol, memproses nilai bpm yang dimasukkan,
dan mengontrol relay sesuai nilai bpm
3.
Luaran (output)
pada sistem ini adalah driver relay 5v dan LCD. Relay bergerak sesuai
kecepatan bpm yang diset dan LCD menampilkan nilaia bpm dan status operasi.
3.3 Perangkat Lunak
Perangkat
lunak yang digunakan pada proyek ini adalah Arduino software sebagai aplikasi untuk menulis program Arduino serta sebagai
downloader program ke board Arduino
Uno R3.
3.4
Diagram Alir
Diagram alir dari sistem adalah sebagai berikut:
Gambar 3.4 Diagram Alir
IV. PENGUJIAN ALAT
Alat sudah
bekerja dengan baik. Keadaan awal setelah saklar dinyalakan akan menampilkan
pesan pada LCD “Heartbeat Simulator” lalu akan menampilkan nilai bpm
yang bisa diatur ketika menekan tombol kurang atau tombol tambah sesuai dengan
nilai bpm yang ingin dikalibrasi. Nilai bpm yang tersedia dari 30-240 bpm
detak per menit nya.
Setelah mengatur pada nilai bpm yang diinginkan, relay akan hidup seperti
simulasi jantung yang berdenyut per menitnya. Tampilan di LCD
menunjukkan bpm yang diset serta animasi hati yang ikut bergerak sesuai
kecepatan bpm.
Kemudian , alat sudah siap untuk melakukan kalibrasi. Kami menggunakan fetal doppler atau alat pendeteksi jantung janin sebagai alat yang kami kalibrasi. Fetal doppler akan membaca detak simulasi pada relay dan meampilkan nya, nilai yang tertera di LCD akan sama dengan nilai yang dibaca pada fetal doppler. Hal tersebut menujuk kan bahwa alat fetal doppler masih berfungsi dengan baik.
Gambar Hasil Akhir Alat
HASIL
DAN PEMBAHASAN
Pada projek ini penulis melakukan pengujian
pada alat fetal doppler. Namun, sebelum dilakukan pengujian, alat fetal doppler
harus dilakukan kalibrasi terlebih dahulu dengan menggunakan alat fetal
simulator. Setelah melakukan pengujian, alat simulator yang dibuat siap untuk
melakukan pengukuran BPM menggunakan fetal doppler dengan dilakukannya
pengukuran pada titik ukur 60, 90, 120, 150, 180, 210, dan 240.
Hasil Pengukuran setting
60 BPM
Dari hasil pengukuran yang dilakukan
pada Alat Heartbeat Simulator dan Alat Fetal Heart Detector, diperoleh nilai
rata-rata masing-masing sebesar 60 BPM dan 60,5 BPM. Nilai error untuk Alat
Heartbeat Simulator adalah 0%, sementara Alat Fetal Heart Detector memiliki
error sebesar 0,83%. Error tersebut masih berada di bawah ambang batas yang
dapat diterima, menunjukkan perbedaan antara kedua alat cukup kecil dan dalam
batas toleransi.
Beberapa
faktor yang dapat menyebabkan error antara lain perbedaan mekanisme antara
alat, kesalahan saat pengambilan data karena perubahan nilai BPM yang cepat,
dan toleransi alat yang memperbolehkan perbedaan kecil.
Tabel 2. Hasil Pengukuran
Setting 60 bpm
Percobaan |
Hasil Pengukuran pada alat heartbeat simulator |
Hasil Pengukuran pada alat Fetal heart detector |
1 |
60 BPM |
60 BPM |
2 |
60 BPM |
60 BPM |
3 |
60 BPM |
60 BPM |
4 |
60 BPM |
61 BPM |
5 |
60 BPM |
60 BPM |
Rata-rata (x) |
60 |
60,5 |
Error (%) |
0% |
0.83% |
Hasil Pengukuran setting 90 BPM
Dari hasil pengukuran yang dilakukan
pada Alat Heartbeat Simulator dan Alat Fetal Heart Detector, diperoleh nilai
rata-rata masing-masing sebesar 90 BPM dan 90,6 BPM. Nilai error untuk Alat
Heartbeat Simulator adalah 0%, karena hasil pengukuran pada alat tersebut
konsisten pada 90 BPM. Sedangkan Alat Fetal Heart Detector memiliki error
sebesar 0,67%.
Error
ini masih tergolong kecil dan berada dalam batas toleransi yang dapat diterima,
menunjukkan bahwa perbedaan antara hasil pengukuran kedua alat cukup kecil.
Faktor yang dapat menyebabkan error antara lain perbedaan mekanisme antara
alat, toleransi alat, atau perubahan kecil dalam pengambilan data.
Tabel 3. Hasil Pengukuran Setting 90 bpm
Percobaan |
Hasil Pengukuran pada alat heartbeat simulator |
Hasil Pengukuran pada alat Fetal heart detector |
1 |
90 BPM |
90 BPM |
2 |
90 BPM |
90 BPM |
3 |
90 BPM |
92 BPM |
4 |
90 BPM |
90 BPM |
5 |
90 BPM |
90 BPM |
Rata-rata (x) |
90 |
90,6 |
Error (%) |
0% |
0,67% |
Hasil Pengukuran setting 120 BPM
Dari hasil pengukuran yang dilakukan
pada Alat Heartbeat Simulator dan Alat Fetal Heart Detector, diperoleh nilai
rata-rata masing-masing sebesar 120 BPM dan 119,5 BPM. Nilai error untuk Alat
Heartbeat Simulator adalah 0%, karena hasil pengukuran pada alat tersebut
konsisten pada 120 BPM. Sementara Alat Fetal Heart Detector memiliki error
sebesar 0,42%.
Error
tersebut masih berada dalam batas toleransi yang dapat diterima, menunjukkan
bahwa perbedaan antara kedua alat relatif kecil. Beberapa faktor yang dapat
menyebabkan error ini antara lain perbedaan mekanisme kerja antara alat-alat
tersebut, ketelitian saat pengambilan data, atau toleransi alat yang
memungkinkan perbedaan kecil dalam pengukuran.
Meskipun
ada sedikit perbedaan antara hasil pengukuran kedua alat, error yang terdeteksi
sangat kecil dan tidak signifikan, sehingga pengukuran ini dapat dianggap valid
dalam rentang toleransi yang diperkenankan.
Tabel 4. Hasil Pengukuran
Setting 120 bpm
Percobaan |
Hasil
Pengukuran pada alat heartbeat simulator |
Hasil
Pengukuran pada alat Fetal heart detector |
1 |
120 BPM |
119 BPM |
2 |
120 BPM |
120 BPM |
3 |
120 BPM |
120 BPM |
4 |
120 BPM |
120 BPM |
5 |
120 BPM |
120 BPM |
Rata-rata (x) |
120 |
119,5 |
Error (%) |
0% |
0,42% |
Hasil Pengukuran setting
150 BPM
Dari hasil pengukuran yang dilakukan
pada Alat Heartbeat Simulator dan Alat Fetal Heart Detector, diperoleh nilai
rata-rata alat Heartbeat Simulator sebesar 150 BPM dan rata-rata alat Fetal
Heart Detector sebesar 149,8 BPM. Nilai error yang terdeteksi antara kedua alat
adalah 0,13%.
Error
yang sangat kecil ini menunjukkan bahwa kedua alat menghasilkan pengukuran yang
sangat mendekati satu sama lain. Faktor-faktor yang dapat menyebabkan error ini
termasuk perbedaan mekanisme kerja antara alat-alat tersebut atau toleransi
kecil dalam pengukuran. Namun, error tersebut masih berada dalam batas
toleransi yang dapat diterima, sehingga pengukuran dapat dianggap valid.
Tabel 5. Hasil Pengukuran
Setting 150 bpm
Percobaan
|
Hasil Pengukuran pada alat heartbeat simulator |
Hasil Pengukuran pada alat Fetal heart detector |
1 |
150 BPM |
149 BPM |
2 |
150 BPM |
150 BPM |
3 |
150 BPM |
150 BPM |
4 |
150 BPM |
150 BPM |
5 |
150 BPM |
150 BPM |
Rata-rata (x) |
150 |
149,8 |
Error (%) |
0% |
0,13% |
Hasil Pengukuran setting 180 BPM
Dari hasil pengukuran yang dilakukan
pada Alat Heartbeat Simulator dan Alat Fetal Heart Detector, diperoleh nilai
rata-rata masing-masing sebesar 180 BPM untuk Alat Heartbeat Simulator dan
180,2 BPM untuk Alat Fetal Heart Detector. Nilai error yang terdeteksi adalah
0,11%.
Error
ini sangat kecil, menunjukkan bahwa kedua alat menghasilkan pengukuran yang
sangat mendekati satu sama lain. Perbedaan kecil ini masih dalam batas
toleransi yang dapat diterima. Faktor-faktor yang dapat menyebabkan error ini
termasuk perbedaan mekanisme pengukuran, variasi kecil dalam pengambilan data,
atau toleransi alat. Secara keseluruhan, pengukuran ini dapat dianggap sangat
akurat.
Tabel 6. Hasil Pengukuran Setting 180 bpm
Percobaan |
Hasil Pengukuran pada alat heartbeat simulator |
Hasil Pengukuran pada alat Fetal heart detector |
1 |
180 BPM |
180 BPM |
2 |
180 BPM |
181 BPM |
3 |
180 BPM |
180 BPM |
4 |
180 BPM |
180 BPM |
5 |
180 BPM |
180 BPM |
Rata-rata (x) |
180 |
180,2 |
Error (%) |
0% |
0,11% |
Hasil Pengukuran setting 210
BPM
Dari hasil pengukuran yang dilakukan
pada Alat Heartbeat Simulator dan Alat Fetal Heart Detector, diperoleh nilai
rata-rata masing-masing sebesar 210 BPM untuk Alat Heartbeat Simulator dan
210,2 BPM untuk Alat Fetal Heart Detector. Nilai error yang terdeteksi adalah
0,095%.
Error
ini sangat kecil, menunjukkan bahwa kedua alat menghasilkan pengukuran yang
sangat mendekati satu sama lain. Perbedaan kecil ini masih dalam batas
toleransi yang dapat diterima. Faktor-faktor yang dapat menyebabkan error ini
termasuk perbedaan mekanisme pengukuran atau variasi kecil dalam pengambilan
data. Secara keseluruhan, pengukuran ini dapat dianggap sangat akurat.
Tabel 7. Hasil Pengukuran
Setting 210 bpm
Percobaan |
Hasil Pengukuran pada alat heartbeat simulator |
Hasil Pengukuran pada alat Fetal heart detector |
1 |
210 BPM |
210 BPM |
2 |
210 BPM |
210 BPM |
3 |
210 BPM |
210 BPM |
4 |
210 BPM |
211 BPM |
5 |
210 BPM |
210 BPM |
Rata-rata (x) |
210 |
210,2 |
Error (%) |
0% |
0,095% |
Hasil Pengukuran setting
240 BPM
Dari hasil pengukuran yang dilakukan
pada Alat Heartbeat Simulator dan Alat Fetal Heart Detector, diperoleh nilai
rata-rata masing-masing sebesar 240 BPM untuk Alat Heartbeat Simulator dan
239,6 BPM untuk Alat Fetal Heart Detector. Nilai error yang terdeteksi adalah
0,17%.
Error ini sangat kecil, menunjukkan bahwa kedua alat menghasilkan pengukuran yang sangat mendekati satu sama lain. Perbedaan kecil ini masih dalam batas toleransi yang dapat diterima. Faktor-faktor yang dapat menyebabkan error ini termasuk perbedaan mekanisme pengukuran atau variasi kecil dalam pengambilan data. Secara keseluruhan, pengukuran ini dapat dianggap sangat akurat.
Tabel 7. Hasil Pengukuran
Setting 240 bpm
Percobaan |
Hasil Pengukuran pada alat heartbeat simulator |
Hasil Pengukuran pada alat Fetal heart detector |
1 |
240 BPM |
240 BPM |
2 |
240 BPM |
240 BPM |
3 |
240 BPM |
240 BPM |
4 |
240 BPM |
240 BPM |
5 |
240 BPM |
238 BPM |
Rata-rata (x) |
240 |
239,6 |
Error (%) |
0% |
0,17% |
V. KESIMPULAN
Proyek ini
berhasil merancang dan merealisasikan alat kalibrasi portabel berbasis
mikrokontroler Arduino Uno R3 untuk mendeteksi detak jantung janin. Alat ini
mampu mensimulasikan detak jantung dengan frekuensi yang dapat disesuaikan
(30-240 bpm) menggunakan relay sebagai penghasil simulasi denyut, sementara
tampilan LCD menunjukkan nilai bpm yang disetel beserta animasi hati yang
bergerak sesuai kecepatan denyut.
Pengujian
dengan fetal doppler menunjukkan bahwa alat ini dapat menghasilkan nilai
simulasi detak jantung yang sesuai dengan nilai yang ditampilkan pada layar
LCD. Hal ini membuktikan bahwa alat ini efektif untuk menguji dan memastikan
keakuratan perangkat medis seperti fetal doppler.
Keberhasilan alat ini menunjukkan potensinya sebagai solusi yang terjangkau dan portabel untuk kalibrasi perangkat medis, terutama di fasilitas kesehatan dengan keterbatasan sumber daya, mendukung peningkatan layanan kesehatan ibu dan janin.
VI. PPT PROJEK
VII. VIDEO PROJEK
DAFTAR PUSTAKA
Fajrin, H. R., Maharani, S., & Fitriyah, A. (2021). Simulator
Fetal Doppler. Medika
Teknika: Jurnal Teknik Elektromedik Indonesia, Universitas Muhammadiyah
Yogyakarta. Tersedia di: https://journal.umy.ac.id/index.php/mt/article/download/11212/pdf
Fernanda, A. (2022). Perancangan dan
Implementasi Sistem Pemantau Detak Jantung Janin Menggunakan Fetal Doppler
Berbasis Mikrokontroler. Skripsi. Universitas Wijaya Kusuma Surabaya. Tersedia
di: https://eprints.uwhs.ac.id/2047/.
Fernanda, A. (2021). Pengujian dan
Analisis Alat Fetal Doppler dalam Menentukan Akurasi Deteksi Detak Jantung
Janin. Skripsi. Universitas Wijaya Kusuma Surabaya. Tersedia di: https://eprints.uwhs.ac.id/1549/
PROFIL PENULIS
Penulis atas nama Benaya Revanico Harsono dilahirkan di Semarang, 2 April 2004. Penulis telah menempuh pendidikan formal di SD Negeri Pleburan 03, SMP N 5 Semarang, dan SMKN 7 Semarang. Tahun 2023 penulis menyelesaikan pendidikannya di SMK. Pada tahun 2023 penulis mengikuti seleksi mahasiswa baru Sarjana Terapan (D4) dan diterima menjadi mahasiswa baru Sarjana Terapan (D4) di kampus Politeknik Negeri Semarang (Polines) dengan Program Studi D4 Tenologi Rekayasa Elektronika, Jurusan Teknik Elektro. Penulis terdaftar dengan NIM. 4.34.23.0.04.
Apabila ada kritik, saran dan pertanyaan mengenai penelitian ini, bisa via email: revanicobenaya@gmail.com
Penulis atas nama Nasfa Tri Utama dilahirkan di Kota Semarang, 8 Mei 2005. Penulis telah menempuh pendidikan formal di SD Negeri Sumurrejo 01, SMP N 24 Semarang, dan SMA N 12 Semarang. Tahun 2023 penulis menyelesaikan pendidikannya di SMA. Pada tahun 2023 penulis mengikuti seleksi mahasiswa baru sarjana terapan (D4) dan diterima menjadi mahasiswa baru sarjana terapan (D4) di kampus Politeknik Negeri Semarang (Polines) dengan Program Studi D4 Teknologi Reakayasa Elektronika Jurusan Teknik Elektro. Penulis terdaftar dengan NIM. 4.34.23.0.16. Apabila ada kritik, saran dan pertanyaan mengenai penelitian ini, bisa via email: nasfatriutama08@gmail.com
Penulis atas nama Frisca Syaharani dilahirkan di Kabupaten Semarang 29 September 2005. Penulis telah menempuh pendidikan formal di SMK N 2 Salatiga. Tahun 2023 penulis menyelesaikan pendidikannya di SMK. Pada tahun 2023 penulis mengikuti seleksi mahasiswa baru diploma (D4) dan diterima menjadi mahasiswa baru diploma (D4) di kampus Politeknik Negeri Semarang (Polines) dengan Program Studi D4 Teknik Elektronika, Jurusan Rekayasa Teknik Elektro. Penulis terdaftar dengan NIM. 4.34.23.0.09. Apabila ada kritik, saran dan pertanyaan mengenai penelitian ini, bisa via email: syharanifrsca@gmail.com.

Penulis atas nama Salsabila Chairunisa dilahirkan di Salatiga 15 mei 2004. Penulis telah menempuh pendidikan formal di SMKN 3 Salatiga. Tahun 2023 penulis menyelesaikan pendidikannya di SMK. Pada tahun 2023 penulis mengikuti seleksi mahasiswa baru diploma (D4) dan diterima menjadi mahasiswa baru diploma (D4) di kampus Politeknik Negeri Semarang (Polines) dengan Program studi D4 Teknologi Rekayasa Elektronika, jurusan Teknik Elektro. Penulis terdaftar dengan NIM 4.34.23.0.22. Apabila ada kritik, saran dan pertanyaan mengenai penelitian ini, bisa via email: salsabilachairunisa05@gmail.com
Terimakasih ilmunya 👍
BalasHapussangat inovatif 👍
BalasHapus