TP 1 & LA 1 MODUL 2



1. Prosedur[Kembali]

  1. Pahami terlebih dahulu kondisi yang akan digunakan
  2. Buka software Proteus 8.17
  3. Persiapkan alat dan bahan
  4. Buat rangkaian sesuai dengan kondisi dan modul
  5. Buka software STM32Cube IDE 
  6. Setelah membuka software, pilih perangkat STM32F103C8T6 
  7. Sesuaikan konfigurasi pin sesuai dengan rangkaian proteus 
  8. Buat kode program untuk mengoperasikan rangkaian tersebut sesuai dengan kondisi 
  9. Konfigurasi kan program dengan software Proteus
  10. Jalankan simulasi rangkaian.  
  11. Proses selesai

2. Hardware dan Diagram Blok[Kembali]

    Hardware

    

STM32F103C8


Heartbeat Sensor



LED


Buzzer

Resistor

Push Button

Beardboard

3. Rangkaian Simulasi dan Prinsip Kerja[Kembali]

Rangkaian Simulasi


Prinsip Kerja

Prinsip kerja program dimulai dari pembacaan sinyal analog sensor heartbeat menggunakan ADC, kemudian sinyal tersebut difilter dengan metode moving average untuk mengurangi noise sehingga data menjadi lebih stabil. Nilai hasil filter digunakan untuk membentuk baseline adaptif yang terus menyesuaikan terhadap kondisi sinyal, lalu ditentukan nilai threshold sebagai batas untuk mendeteksi adanya detak jantung. Ketika sinyal melewati threshold dan sebelumnya belum terdeteksi, sistem menganggap terjadi satu detak, kemudian menghitung interval waktu antar detak untuk mendapatkan nilai BPM menggunakan rumus 60000 dibagi interval. Jika dalam waktu tertentu tidak ada detak yang terdeteksi, maka BPM akan dianggap nol.

Berdasarkan nilai BPM yang diperoleh, sistem akan mengaktifkan output berupa LED dan buzzer sesuai kondisi. Jika BPM kurang dari 60, maka LED merah menyala dan buzzer tidak aktif. Jika BPM berada pada rentang 60 hingga 80, maka LED hijau menyala dan buzzer aktif sebagai indikator kondisi tersebut. Sedangkan jika BPM lebih dari 80, maka LED kuning menyala dan buzzer tidak aktif. Selain itu, terdapat tombol yang berfungsi untuk mematikan buzzer secara manual tanpa mempengaruhi kondisi LED, sehingga sistem tetap memberikan indikasi visual sesuai nilai BPM yang terbaca.

4. Flowchart dan Listing Program[Kembali]

Flowchart

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

}

void LED_Kuning() {

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);

}

void LED_Merah() {

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);

}

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) // Tombol di PA1 untuk Mute Buzzer

    {

        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 = 1000;

                if(interval > 0) BPM = 60000 / interval;

            }

            lastBeatTime = now;

        }


        if(filteredValue < threshold)

        {

            beatDetected = 0;

        }


        /* ==== TIMEOUT (TIDAK ADA DETAK) ==== */

        if(HAL_GetTick() - lastBeatTime > 2000)

        {

            BPM = 0;

        }


        /* ==== OUTPUT LOGIC (SESUAI PERMINTAAN) ==== */

        if(BPM > 0)

        {

        if(BPM < 60)

        {

            LED_Mati();

            LED_Merah();

            Buzzer_Off(); // buzzer dimatikan

        }

        else if(BPM <= 80)

        {

            LED_Mati();

            LED_Hijau();

            if(!buzzerOff) Buzzer_On();

            else Buzzer_Off();

        }

        else

        {

            LED_Mati();

            LED_Kuning();

            Buzzer_Off();

        }

        }

        else

        {

            LED_Mati();

            Buzzer_Off();

        }


        HAL_Delay(5);

    }

}


/* ================= CLOCK CONFIG ================= */

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 INIT ================= */

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 INIT ================= */

void MX_GPIO_Init(void)

{

    __HAL_RCC_GPIOA_CLK_ENABLE();

    __HAL_RCC_GPIOB_CLK_ENABLE();


    GPIO_InitTypeDef GPIO_InitStruct = {0};


    /* PA0 = Input Sensor ADC */

    GPIO_InitStruct.Pin = GPIO_PIN_0;

    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;

    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);


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


    HAL_NVIC_SetPriority(EXTI1_IRQn, 0, 0);

    HAL_NVIC_EnableIRQ(EXTI1_IRQn);


    /* GPIOB: PIN 0(Hijau), 1(Kuning), 10(Merah), 11(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);


    /* Reset semua output ke LOW */

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_10 | GPIO_PIN_11, GPIO_PIN_RESET);

}

5. Video Demo[Kembali]

6. Analisa[Kembali]

1. Analisa bagaimana perbedaan implementasi PWM antara STM32 serta dampaknya terhadap kontrol motor dan LED.

Jawab:

PWM (Pulse Width Modulation) pada STM32 merupakan teknik pengaturan sinyal digital dengan mengubah duty cycle menggunakan timer internal seperti TIM1 dan TIM3 untuk menghasilkan frekuensi tetap dengan lebar pulsa berbeda. Pada LED, PWM digunakan untuk mengatur tingkat kecerahan, di mana duty cycle kecil membuat LED redup dan duty cycle besar membuat LED semakin terang. Pada motor DC, PWM digunakan untuk mengatur rata-rata tegangan sehingga mempengaruhi kecepatan putaran motor, sedangkan pada motor servo PWM digunakan untuk menentukan posisi sudut berdasarkan lebar pulsa tertentu. Implementasi PWM pada motor membutuhkan frekuensi dan presisi yang lebih stabil dibanding LED karena berpengaruh langsung terhadap kestabilan putaran dan posisi motor. STM32 juga menyediakan advanced timer untuk aplikasi kontrol motor yang lebih kompleks sehingga kontrol motor menjadi lebih presisi, stabil, dan efisien. 

2. Analisa bagaimana cara pembacaan nilai sensor analog menggunakan ADC pada STM32 

Jawab: 

ADC (Analog to Digital Converter) pada STM32 digunakan untuk mengubah sinyal analog dari sensor seperti LDR, LM35, dan heartbeat sensor menjadi data digital agar dapat diproses mikrokontroler. STM32 umumnya menggunakan ADC 12-bit sehingga hasil konversi berada pada rentang 0–4095. Proses pembacaan dimulai dengan mengatur GPIO sebagai mode analog, kemudian ADC melakukan sampling dan quantization terhadap tegangan input sensor. Setelah konversi selesai, data dibaca menggunakan fungsi HAL seperti HAL_ADC_Start(), HAL_ADC_PollForConversion(), dan HAL_ADC_GetValue(), lalu diolah menjadi besaran fisik seperti suhu atau intensitas cahaya. STM32 juga mendukung fitur seperti scan mode, continuous conversion, DMA, dan oversampling sehingga pembacaan sensor menjadi lebih cepat, akurat, dan cocok digunakan pada sistem monitoring maupun kontrol otomatis real-time. 

3. Analisa bagaimana penggunaan interrupt eksternal dalam mendeteksi input dari sensor atau tombol pada STM32

Jawab:

Interrupt eksternal pada STM32 digunakan agar mikrokontroler dapat merespons perubahan sinyal dari sensor atau tombol secara langsung tanpa harus melakukan polling terus-menerus. Ketika terjadi perubahan logika pada pin tertentu, CPU akan menghentikan sementara program utama dan menjalankan ISR (Interrupt Service Routine), kemudian kembali melanjutkan program utama setelah interrupt selesai ditangani. Interrupt dikonfigurasi menggunakan mode seperti GPIO_MODE_IT_RISING atau GPIO_MODE_IT_FALLING, sedangkan prioritas interrupt diatur menggunakan NVIC. Pada modul praktikum, interrupt digunakan untuk mengontrol buzzer, mengubah mode alat, serta menghidupkan atau mematikan sistem menggunakan push button. Penggunaan interrupt membuat sistem lebih responsif, efisien, dan sangat cocok diterapkan pada aplikasi real-time berbasis sensor dan otomatisasi.

4. Analisa bagaimana cara kerja fungsi HAL_GetTick() pada STM32

Jawab:

HAL_GetTick() pada STM32 adalah fungsi dari library HAL yang digunakan untuk mengambil waktu sistem dalam satuan milidetik sejak mikrokontroler mulai berjalan. Fungsi ini bekerja menggunakan timer SysTick yang menghasilkan interrupt setiap 1 ms sehingga nilai counter internal terus bertambah selama sistem aktif. Pada modul praktikum, HAL_GetTick() digunakan untuk menghitung interval denyut jantung, menentukan nilai BPM, serta mendeteksi timeout ketika sensor tidak membaca sinyal dalam beberapa detik. Fungsi ini memudahkan pengaturan waktu tanpa memerlukan timer tambahan dan lebih efisien dibanding delay biasa karena mendukung proses timing secara non-blocking, walaupun resolusinya hanya dalam satuan milidetik sehingga kurang cocok untuk pengukuran dengan presisi sangat tinggi. 

5. Analisa bagaimana perbedaan konfigurasi dan kontrol pin PWM serta pemanfaatan timer internal pada STM32 dalam menghasilkan sinyal PWM

Jawab:

PWM pada STM32 dihasilkan menggunakan timer internal yang dihubungkan ke pin GPIO dalam mode alternate function, dengan konfigurasi meliputi prescaler, period, mode PWM, dan compare register untuk menentukan frekuensi serta duty cycle sinyal. Pin PWM dikonfigurasi sebagai GPIO_MODE_AF_PP, kemudian timer diaktifkan menggunakan fungsi seperti HAL_TIM_PWM_Start(), sedangkan duty cycle diubah menggunakan __HAL_TIM_SET_COMPARE(). Perbedaan konfigurasi PWM bergantung pada aplikasinya, di mana LED hanya membutuhkan pengaturan duty cycle sederhana untuk mengatur kecerahan, sedangkan motor servo memerlukan frekuensi stabil sekitar 50 Hz dengan lebar pulsa tertentu agar posisi akurat dan motor DC menggunakan PWM untuk mengatur kecepatan putaran. Pemanfaatan timer internal STM32 membuat sinyal PWM lebih stabil, presisi, dan tidak membebani CPU karena pembangkitan sinyal dilakukan langsung oleh hardware timer. 

6. Bagaimana mengatur pergerakan motor servo pada stm 32?

Jawab:

Motor servo pada STM32 dikendalikan menggunakan sinyal PWM dengan frekuensi standar sekitar 50 Hz atau periode 20 ms, di mana posisi servo ditentukan berdasarkan lebar pulsa HIGH, misalnya sekitar 1 ms untuk posisi 0°, 1,5 ms untuk posisi tengah, dan 2 ms untuk posisi 180°. Pada modul praktikum, PWM servo dihasilkan menggunakan timer seperti TIM3 dengan pengaturan prescaler dan period tertentu, kemudian posisi servo diatur menggunakan fungsi __HAL_TIM_SET_COMPARE() untuk mengubah duty cycle PWM. Pada sistem jemuran otomatis, sensor LDR dibaca menggunakan ADC untuk mendeteksi kondisi terang atau gelap, sehingga servo dapat bergerak menarik jemuran masuk saat gelap dan mengeluarkannya saat terang. Penggunaan timer internal STM32 membuat gerakan servo lebih stabil, halus, presisi, dan responsif terhadap perubahan kondisi sensor.

8. Download File[Kembali]

Rangkaian dan Program Proteus Download

Datasheet STM32F103C8 Download

Datasheet Heartbeat Sensor Download














   


Komentar

Postingan populer dari blog ini