LAPORAN AKHIR 1




MODUL 2

LAPORAN AKHIR 1


1. Prosedur [kembali]

1. Persiapan

Siapkan: mikrokontroler (STM32), sensor detak jantung, potensiometer, LED + resistor, buzzer, push button, breadboard, dan power supply.

2. Perakitan

  • Hubungkan VCC & GND ke semua komponen
  • Sensor → pin ADC
  • Potensiometer → pin ADC
  • Push button → pin input digital
  • LED → pin output (via resistor)
  • Buzzer → pin output

3. Pemrograman

  • Baca nilai sensor & potensiometer (ADC)
  • Bandingkan nilai
  • Output:
    • Normal → LED hijau
    • Sedang → LED kuning
    • Tinggi → LED merah + buzzer 

4. Pengujian

  • Nyalakan rangkaian
  • Cek sensor (sentuh jari)
  • Putar potensiometer
  • Amati respon LED & buzzer


2. Hardware [kembali]

a) STM32F103C8


    b) LED



    c) Buzzer



    d) Resistor



    e) Heartbeat Sensor




    f) Push Button


       g) Diagram Blok


3. Rangkaian Simulasi dan Prinsip Kerja [kembali]



Prinsip Kerja:

Rangkaian bekerja dengan memanfaatkan sensor detak jantung (HB1) sebagai input utama yang menghasilkan sinyal analog sesuai denyut jantung. Sinyal ini kemudian masuk ke mikrokontroler (STM32) melalui pin ADC untuk dikonversi menjadi data digital. Selain itu, potensiometer (RV2) juga memberikan sinyal analog sebagai nilai referensi atau batas pembanding.

Di dalam mikrokontroler, data dari sensor detak jantung akan dibaca dan dibandingkan dengan nilai referensi dari potensiometer. Berdasarkan hasil perbandingan tersebut, sistem menentukan kondisi detak jantung, misalnya normal, sedang, atau tinggi.

Hasil keputusan ini kemudian digunakan untuk mengontrol output digital, yaitu:

  • LED hijau menyala saat kondisi normal
  • LED kuning menyala saat kondisi waspada
  • LED merah menyala saat kondisi berbahaya

Jika kondisi berbahaya terdeteksi, maka buzzer juga akan aktif sebagai alarm.

Selain itu, push button berfungsi sebagai input tambahan (misalnya untuk reset atau kontrol manual sistem).


4. Flowchart dan Listing Program [kembali]



Listing Program : 

#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;

/* ================= FILTER ================= */
#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 ================= */
void LED_Hijau() {
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);

}

void LED_Kuning() {
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
}

void LED_Merah() {
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
}

void LED_Mati() {
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_10, GPIO_PIN_RESET);
}

/* ================= 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); }

/* ================= INTERRUPT ================= */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if(GPIO_Pin == GPIO_PIN_1) // PA1
    {
        buzzerOff = !buzzerOff;
    }
}

/* ================= 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 = moving_average(adcValue);

    /* ==== BASELINE (ADAPTIF) ==== */
    baseline = (baseline * 9 + filteredValue) / 10;
    uint32_t threshold = baseline + 50;

    /* ==== DETEKSI DETAK + INTERVAL ==== */
    if(filteredValue > threshold && beatDetected == 0)
    {
        beatDetected = 1;

        uint32_t now = HAL_GetTick();

        if(lastBeatTime != 0)
        {
            interval = now - lastBeatTime;

                BPM = 60000 / interval;

        }

        lastBeatTime = now;
    }

    if(filteredValue < threshold)
    {
        beatDetected = 0;
    }

    /* ==== TIMEOUT (TIDAK ADA DETAK) ==== */
    if(HAL_GetTick() - lastBeatTime > 2000)
    {
        BPM = 0;
    }

    /* ==== OUTPUT ==== */
    if(BPM > 0)
    {
        if(BPM >30 && BPM < 60)
        {
            LED_Kuning();
            Buzzer_Off();
            buzzerOff = 0;
        }
        else if(BPM <= 80)
        {
            LED_Hijau();
            Buzzer_Off();
            buzzerOff = 0;
        }
        else
        {
            LED_Merah();
            if(!buzzerOff)
                Buzzer_On();
            else
                Buzzer_Off();
        }
    }
    else
    {
        LED_Mati();
        Buzzer_Off();
    }

    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);

  /* PA1 = BUTTON */
  GPIO_InitStruct.Pin = GPIO_PIN_1;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  HAL_NVIC_SetPriority(EXTI1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI1_IRQn);

  /* 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);
}


5. Video Demo [kembali]


6. Kondisi [kembali]

Program ini bekerja dengan mendeteksi sinyal detak jantung dari sensor yang kemudian difilter dan dibandingkan dengan nilai ambang (threshold) untuk menentukan adanya detak. Jika sinyal melewati threshold dan belum terdeteksi sebelumnya, maka sistem menghitung interval waktu antar detak untuk memperoleh nilai BPM; jika tidak ada detak selama lebih dari 2 detik, maka BPM dianggap 0. Berdasarkan nilai BPM, sistem menentukan kondisi: jika BPM = 0 maka semua LED dan buzzer mati; jika 30 < BPM < 60 maka LED kuning menyala (detak lambat); jika BPM ≤ 80 maka LED hijau menyala (normal); dan jika BPM > 80 maka LED merah menyala (detak tinggi/bahaya) serta buzzer akan aktif kecuali dimatikan. Selain itu, terdapat push button yang bekerja melalui interrupt untuk mengubah status buzzer (toggle ON/OFF), sehingga pengguna dapat mematikan buzzer secara manual saat kondisi bahaya.


7. Video Simulasi [kembali]


8. Link Download [kembali]

Komentar

Postingan populer dari blog ini