TP P1K9
Langkah-langkah percobaan :
- Pahami terlebih dahulu kondisi yang
akan digunakan
- Buka
software Proteus 8.17
- Persiapkan
alat dan bahan
- Buat rangkaian sesuai dengan kondisi
dan modul
- Buka
software STM32Cube IDE
- Setelah membuka software, pilih
perangkat STM32F103C8T6
- Sesuaikan konfigurasi pin sesuai
dengan rangkaian proteus
- Buat kode program untuk
mengoperasikan rangkaian tersebut sesuai dengan kondisi
- Konfigurasi kan program dengan
software Proteus
- Jalankan
simulasi rangkaian.
- Proses selesai
2. Hardware dan Diagram Blok [Kembali]
a. Hardware
1. STM32F103C8
HeartBeat sensor
atau sensor detak jantung merupakan perangkat input analog yang berfungsi untuk
mendeteksi denyut nadi manusia dengan prinsip fotopletismografi (PPG). Sensor
ini biasanya bekerja menggunakan infra merah dan fototransistor untuk mengukur perubahan
volume darah di dalam pembuluh darah kecil di ujung jari atau telinga. Sinyal
yang dihasilkan bersifat analog, sehingga memerlukan fitur ADC (Analog to
Digital Converter) pada mikrokontroler agar data detak jantung dapat diproses
dan dikonversi menjadi nilai Beats Per Minute (BPM).
Push button
adalah komponen sakelar sederhana yang berfungsi untuk menghubungkan atau
memutuskan aliran arus listrik dalam suatu rangkaian dengan cara menekan
tombolnya. Pada penggunaan mikrokontroler, komponen ini berperan sebagai
perangkat input digital yang bekerja berdasarkan prinsip logika high atau low,
di mana status penekanannya dapat dibaca oleh pin GPIO atau digunakan untuk
memicu mekanisme interrupt eksternal. Agar pembacaan sinyal tetap stabil dan
terhindar dari kondisi floating, push button biasanya dikonfigurasi menggunakan
resistor pull-up atau pull-down yang memastikan level tegangan input tetap
berada pada kondisi logika yang jelas saat tombol tidak sedang ditekan.
4. LED
b. Diagram Blok
3. Rangkaian Simulasi dan Prinsip Kerja [Kembali]
a. Flowchart
#include "stm32f1xx_hal.h"
/* ================= HANDLE ================= */
ADC_HandleTypeDef hadc1;
/* ================= VARIABLE ================= */
uint32_t adcValue = 0;
uint32_t filteredValue = 0;
uint8_t beatDetected = 0;
uint32_t BPM = 0;
uint32_t lastBeatTime = 0;
uint32_t interval = 0;
uint8_t buzzerOff = 0; // Toggle dari tombol PA1
/* ================= FILTER MOVING AVERAGE ================= */
#define FILTER_SIZE 10
uint16_t buffer[FILTER_SIZE];
uint8_t indexBuf = 0;
uint16_t moving_average(uint16_t val) {
buffer[indexBuf++] = val;
if (indexBuf >= FILTER_SIZE) indexBuf = 0;
uint32_t sum = 0;
for (int i = 0; i < FILTER_SIZE; i++) sum += buffer[i];
return sum / FILTER_SIZE;
}
/* ================= LED CONTROL ================= */
void LED_Mati() {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_10, GPIO_PIN_RESET);
}
void LED_Normal() {
// Nyalakan LED Hijau jika kondisi normal (BPM >= 60)
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1 | GPIO_PIN_10, GPIO_PIN_RESET);
}
/* ================= BUZZER CONTROL ================= */
void Buzzer_On() { HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_SET); }
void Buzzer_Off() { HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET); }
/* ================= INTERRUPT (TOMBOL PA1) ================= */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
if (GPIO_Pin == GPIO_PIN_1) {
buzzerOff = !buzzerOff; // Mute buzzer secara manual
}
}
/* ================= PROTOTYPE ================= */
void SystemClock_Config(void);
void MX_GPIO_Init(void);
void MX_ADC1_Init(void);
/* ================= MAIN PROGRAM ================= */
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();
uint32_t baseline = 0;
while (1) {
/* 1. BACA SENSOR (ADC) */
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 10);
adcValue = HAL_ADC_GetValue(&hadc1);
/* 2. FILTERING */
filteredValue = moving_average(adcValue);
/* 3. ADAPTIVE THRESHOLD */
// Baseline mengikuti tren sinyal agar deteksi tetap akurat meski jari bergeser
baseline = (baseline * 9 + filteredValue) / 10;
uint32_t threshold = baseline + 50;
/* 4. DETEKSI DETAK JANTUNG */
if (filteredValue > threshold && beatDetected == 0) {
beatDetected = 1;
uint32_t now = HAL_GetTick();
// Hitung BPM
if (lastBeatTime != 0) {
interval = now - lastBeatTime;
if (interval > 0) BPM = 60000 / interval;
}
lastBeatTime = now;
// POLA BUZZER: Bunyi saat detak terdeteksi (JIKA BPM < 60)
if (BPM < 60 && BPM > 0 && !buzzerOff) {
Buzzer_On();
}
}
// Reset state saat sinyal turun
if (filteredValue < threshold) {
beatDetected = 0;
Buzzer_Off(); // Buzzer mati mengikuti irama detak
}
/* 5. TIMEOUT (JIKA JARI DILEPAS) */
if (HAL_GetTick() - lastBeatTime > 2000) {
BPM = 0;
Buzzer_Off();
}
/* 6. LOGIKA OUTPUT SESUAI PERMINTAAN */
if (BPM > 0 && BPM < 60) {
// Kondisi: BPM < 60
LED_Mati();
// Buzzer sudah dihandle di bagian deteksi detak di atas (pola sinkron)
}
else if (BPM >= 60) {
// Kondisi: BPM Normal
LED_Normal();
Buzzer_Off();
}
else {
// Kondisi: Tidak ada detak terdeteksi
LED_Mati();
Buzzer_Off();
}
HAL_Delay(5); // Sampling rate sekitar 200Hz
}
}
/* ================= KONFIGURASI CLOCK ================= */
void SystemClock_Config(void) {
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK |
RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
}
/* ================= KONFIGURASI ADC1 ================= */
void MX_ADC1_Init(void) {
ADC_ChannelConfTypeDef sConfig = {0};
__HAL_RCC_ADC1_CLK_ENABLE();
hadc1.Instance = ADC1;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
HAL_ADC_Init(&hadc1);
sConfig.Channel = ADC_CHANNEL_0; // PA0
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
}
/* ================= KONFIGURASI GPIO ================= */
void MX_GPIO_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/* PA0 sebagai ADC Input */
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* PA1 sebagai Button (Interrupt) */
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* PB0, PB1, PB10 sebagai LED & PB11 sebagai Buzzer */
GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_10 | GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Pastikan semua mati di awal */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_10 | GPIO_PIN_11, GPIO_PIN_RESET);
/* Aktifkan Interrupt Button */
HAL_NVIC_SetPriority(EXTI1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI1_IRQn);
}
5. Video Demo [Kembali]
6. Kondisi [Kembali]
8. Download File [Kembali]
- Download file lengkap (Rangkaian dan Program) (klik disini)
- Download video simulasi (klik disini)
- Download Datasheet Touch Sensor (klik disini)
- Download Datasheet Pir Sensor (klik disini)
- Download Datasheet Resistor (klik disini)
- Download Datasheet LED (klik disini)
- Download Datasheet Buzzer (klik disini)
Komentar
Posting Komentar