M2 - Laporan Akhir 1

a. Prosedur

  • Siapkan seluruh komponen yang digunakan, yaitu board STM32 Blue Pill, modul programmer ST-LINK, sensor heartbeat, pushbutton atau touch sensor, buzzer, LED hijau, LED merah, LED kuning, resistor 220Ω, breadboard, dan kabel jumper.
  • Hubungkan board STM32 dengan sumber tegangan, kemudian sambungkan pin VCC dan GND pada sensor heartbeat ke pin 3.3V  dan GND pada STM32.
  • Hubungkan pin output (OUT atau Signal) dari sensor heartbeat ke salah satu pin input pada STM32 sensor ini berfungsi untuk membaca perubahan aliran darah pada ujung jari yang kemudian diubah menjadi sinyal detak jantung.
  • Hubungkan pushbutton ke salah satu pin input digital STM32 yang akan digunakan sebagai tombol untuk mengaktifkan atau menonaktifkan sistem pembacaan detak jantung.
  • Pasang LED hijau, LED kuning, dan LED merah dengan resistor 220Ω secara seri, lalu hubungkan masing-masing ke pin output STM32. LED digunakan sebagai indikator kondisi pembacaan detak jantung.
  • Hubungkan buzzer ke salah satu pin output STM32 dan ground. Buzzer berfungsi sebagai indikator suara ketika detak jantung BPM nya terlalu rendah atau terlalu tinggi.
  • Periksa kembali seluruh rangkaian untuk memastikan koneksi VCC, GND, input, dan output sudah sesuai serta tidak terjadi kesalahan wiring.
  • Hubungkan board STM32 ke komputer menggunakan ST-LINK, kemudian upload program yang telah dibuat menggunakan software seperti STM32CubeIDE. 
  • Setelah program berhasil di-upload, letakkan ujung jari pada permukaan sensor heartbeat secara stabil agar sensor dapat membaca perubahan denyut nadi.
  • b. Hardware dan Diagram Blok

    A. Hardware
    1. STM32F103C8


    2. Heartbeat Sensor


    3. Breadboard


    4. LED

    5. Buzzer

    6. Resistor

    7. Push Button


    B. Diagram Blok

    c. Rangkaian Simulasi dan Prinsip Kerja



    Prinsip Kerja:
    Prinsip kerja rangkaian ini dimulai ketika sensor detak jantung Heart Beat Sensor mendeteksi perubahan aliran darah pada ujung jari pengguna. Sensor ini bekerja berdasarkan perubahan intensitas cahaya yang dipantulkan oleh pembuluh darah, kemudian menghasilkan sinyal analog berupa tegangan yang berubah mengikuti denyut jantung. Sinyal tersebut dikirim ke mikrokontroler STM32F103C8 melalui pin input analog (ADC). Di dalam mikrokontroler, sinyal dibaca, diproses, dan dihitung jumlah puncak denyutnya dalam satuan BPM (Beat Per Minute). Potensiometer RV1 berfungsi sebagai pengatur atau simulasi nilai tegangan referensi/threshold untuk membantu proses pengujian atau kalibrasi sinyal input.

    Setelah data denyut jantung diproses, mikrokontroler akan memberikan keluaran ke tiga LED indikator dan buzzer sesuai kondisi BPM yang terdeteksi. Jika nilai detak jantung berada di bawah batas normal, LED merah dapat menyala sebagai indikator kondisi rendah. Jika berada pada rentang tertentu, LED kuning menyala sebagai tanda waspada, dan jika berada pada kondisi normal maka LED hijau menyala sebagai indikator aman. Selain itu, buzzer akan aktif apabila nilai BPM melewati batas yang telah diprogram, sehingga memberikan alarm suara. Resistor R1, R2, dan R3 digunakan untuk membatasi arus yang mengalir ke LED agar komponen tidak rusak. Secara keseluruhan, rangkaian ini bekerja sebagai sistem monitoring detak jantung yang membaca sinyal biologis, mengolahnya dengan mikrokontroler, lalu menampilkan status melalui indikator visual dan audio.

    d. Flowchart dan Listing Program



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

    }

    g. Download File


    Comments

    Popular posts from this blog