- Rangkai semua komponen
- Buat rangkaian di proteus
- Jalankan rangkaian dan cobakan sesuai kondisi
Rangkaian pada simulasi Proteus Design Suite ini bekerja sebagai alat sederhana untuk memantau detak jantung menggunakan mikrokontroler STM32F103C8T6. Sensor heartbeat akan mendeteksi denyut nadi dari jari dan menghasilkan sinyal listrik yang naik turun mengikuti detak jantung. Sinyal ini masuk ke mikrokontroler melalui pin ADC, lalu diolah agar lebih stabil menggunakan metode Moving Average Filter, sehingga gangguan (noise) bisa dikurangi dan bentuk sinyal detak lebih jelas.
Setelah itu, sistem menentukan nilai rata-rata (baseline) sebagai acuan, lalu membuat batas (threshold) untuk mendeteksi kapan terjadi satu detakan. Setiap kali sinyal melewati batas tersebut, mikrokontroler menganggap itu sebagai satu denyut jantung, kemudian menghitung jarak waktu antar detak untuk mendapatkan nilai BPM (detak per menit). Nilai BPM ini terus diperbarui secara real-time.
Hasil pembacaan tersebut kemudian digunakan untuk mengontrol output. Jika tidak ada detak yang terdeteksi, semua LED dan buzzer akan mati. Jika detak jantung kurang dari 60 BPM, LED tetap mati tetapi buzzer akan berbunyi mengikuti irama detak jantung (bunyi sebentar setiap ada detakan). Jika detak berada di kisaran normal (60–100 BPM), LED hijau akan menyala sebagai tanda kondisi normal dan buzzer tidak berbunyi. Sedangkan jika detak terlalu cepat (di atas 100 BPM), LED merah menyala dan buzzer akan aktif sebagai peringatan. Dengan cara ini, rangkaian tidak hanya membaca detak jantung, tetapi juga memberikan indikator kondisi secara langsung melalui lampu dan suara.
#include "stm32f1xx_hal.h"
/* ================= HANDLE ================= */
ADC_HandleTypeDef hadc1;
/* ================= VARIABLE ================= */
uint32_t adcValue;
uint32_t filteredValue;
uint8_t beatDetected = 0;
uint32_t BPM = 0;
uint32_t lastBeatTime = 0;
uint32_t interval = 0;
/* ================= FILTER ================= */
#define FILTER_SIZE 8
uint16_t buffer[FILTER_SIZE];
uint8_t bufIndex = 0;
uint16_t MovingAverage(uint16_t val)
{
buffer[bufIndex++] = val;
if(bufIndex >= FILTER_SIZE)
bufIndex = 0;
uint32_t sum = 0;
for(int i=0;i<FILTER_SIZE;i++)
sum += buffer[i];
return sum / FILTER_SIZE;
}
/* ================= LED ================= */
void LED_Mati()
{
HAL_GPIO_WritePin(GPIOB,
GPIO_PIN_0 |
GPIO_PIN_1 |
GPIO_PIN_10,
GPIO_PIN_RESET);
}
void LED_Hijau()
{
LED_Mati();
HAL_GPIO_WritePin(GPIOB,
GPIO_PIN_0,
GPIO_PIN_SET);
}
void LED_Merah()
{
LED_Mati();
HAL_GPIO_WritePin(GPIOB,
GPIO_PIN_10,
GPIO_PIN_SET);
}
/* ================= BUZZER ================= */
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);
}
/* ================= PROTOTYPE ================= */
void SystemClock_Config(void);
void MX_GPIO_Init(void);
void MX_ADC1_Init(void);
/* ================= MAIN ================= */
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();
uint32_t baseline = 0;
while (1)
{
/* ===== BACA ADC ===== */
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 10);
adcValue = HAL_ADC_GetValue(&hadc1);
/* ===== FILTER ===== */
filteredValue =
MovingAverage(adcValue);
/* ===== BASELINE ===== */
baseline =
(baseline * 9 +
filteredValue) / 10;
uint32_t threshold =
baseline + 40;
/* ===== DETEKSI DETAK ===== */
if(filteredValue > threshold &&
beatDetected == 0)
{
beatDetected = 1;
uint32_t now =
HAL_GetTick();
if(lastBeatTime != 0)
{
interval =
now -
lastBeatTime;
if(interval > 250 &&
interval < 2000)
{
BPM =
60000 /
interval;
}
}
lastBeatTime = now;
/* ===== BUZZER IKUT DETAK ===== */
if(BPM < 60 &&
BPM > 0)
{
Buzzer_On();
HAL_Delay(70);
Buzzer_Off();
}
}
if(filteredValue < threshold)
{
beatDetected = 0;
}
/* ===== TIMEOUT ===== */
if(HAL_GetTick() -
lastBeatTime > 2500)
{
BPM = 0;
}
/* ===== OUTPUT ===== */
if(BPM == 0)
{
LED_Mati();
Buzzer_Off();
}
else if(BPM < 60)
{
LED_Mati();
}
else if(BPM <= 100)
{
LED_Hijau();
Buzzer_Off();
}
else
{
LED_Merah();
Buzzer_On();
}
HAL_Delay(5);
}
}
/* ================= 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);
}
/* ================= ADC ================= */
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;
sConfig.Rank =
ADC_REGULAR_RANK_1;
sConfig.SamplingTime =
ADC_SAMPLETIME_71CYCLES_5;
HAL_ADC_ConfigChannel(
&hadc1,
&sConfig);
}
/* ================= GPIO ================= */
void MX_GPIO_Init(void)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* PA0 = ADC */
GPIO_InitStruct.Pin =
GPIO_PIN_0;
GPIO_InitStruct.Mode =
GPIO_MODE_ANALOG;
HAL_GPIO_Init(
GPIOA,
&GPIO_InitStruct);
/* LED + 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);
HAL_GPIO_WritePin(
GPIOB,
GPIO_PIN_0 |
GPIO_PIN_1 |
GPIO_PIN_10 |
GPIO_PIN_11,
GPIO_PIN_RESET);
}
- Link download rangkaian klik disini




Tidak ada komentar:
Posting Komentar