TP1 Modul 2



1. Prosedur [Kembali]

1. Buka software proteus lalu rangkai komponen sesuai dengan gambar yang ada di modul

2. Buka software STM32CubeIDE lalu lakukan konfigurasi pin pada STM untuk menentukan GPIO input dan GPIO output

3. Masukan Program ke dalam software STM32CubeIDE lalu build untuk mendapatkan file .hex

4. Masukan file .hex ke dalam file library STM32F103C8 pada proteus

5. Simulasikan rangkaian

2. Hardware dan Diagram Blok[Kembali]

  • STM32F103C8

  • Touch Sensor

  • PIR Sensor
  • LED


  • Buzzer
  • Resistor 
  • Heart Beat Sensor

Diagram blog

                            

3. Rangkaian Simulasi dan Prinsip Kerja[Kembali]




  • Deteksi Sinyal Analog: Sensor Heartbeat bekerja dengan memancarkan cahaya ke pembuluh darah dan mendeteksi perubahan intensitas cahaya yang dipantulkan, yang kemudian dikonversi menjadi tegangan analog sesuai dengan denyut jantung pengguna.
  • Konversi Data (ADC): Mikrokontroler menerima sinyal analog tersebut melalui pin ADC (Analog to Digital Converter) untuk mengubah fluktuasi tegangan menjadi data digital yang dapat diolah secara matematis oleh prosesor.
  • Perhitungan BPM: Perangkat lunak melakukan kalkulasi berdasarkan interval antar puncak sinyal yang dideteksi dalam satuan waktu tertentu untuk menentukan nilai Beats Per Minute (BPM).
  • Komparasi Logika: Program menjalankan instruksi logika untuk membandingkan nilai BPM yang terbaca dengan nilai ambang batas (threshold) yang telah ditentukan, dalam hal ini adalah angka 60.

  • Eksekusi Kondisi Kurang dari 60: Ketika hasil perhitungan menunjukkan angka di bawah 60 (BPM < 60), prosesor akan mengirimkan sinyal logika High ke pin GPIO yang terhubung dengan LED Merah dan Buzzer.
  • Aktivasi Indikator Output: LED Merah akan menyala sebagai peringatan visual dan Buzzer akan aktif menghasilkan suara sebagai peringatan audio bahwa detak jantung berada di bawah normal.
  • Umpan Balik Real-time: Sistem terus melakukan pemindaian (looping) secara kontinu sehingga jika nilai BPM kembali menyentuh angka 60 atau lebih, maka status LED dan Buzzer akan berubah sesuai dengan algoritma program yang telah diatur.

4. Flowchart dan Listing Program[Kembali]

  • Flowchart


Listing program:

/* USER CODE BEGIN Header */

/**

******************************************************************************

* @file : main.c

* @brief : Main program body

******************************************************************************

* @attention

*

* Copyright (c) 2026 STMicroelectronics.

* All rights reserved.

*

* This software is licensed under terms that can be found in the LICENSE file

* in the root directory of this software component.

* If no LICENSE file comes with this software, it is provided AS-IS.

*

******************************************************************************

*/

/* USER CODE END Header */


#include "main.h"


/* Private variables ---------------------------------------------------------*/

ADC_HandleTypeDef hadc1;


/* USER CODE BEGIN PV */

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;

uint8_t buzzerPulse = 0;

uint32_t beatPulseStart = 0;


#define FILTER_SIZE 10

uint16_t filterBuf[FILTER_SIZE];

uint8_t filterIdx = 0;

/* USER CODE END PV */


/* Private function prototypes -----------------------------------------------*/

void SystemClock_Config(void);

static void MX_GPIO_Init(void);

static void MX_ADC1_Init(void);


/* USER CODE BEGIN 0 */


/* ===== FILTER MOVING AVERAGE ===== */

uint16_t moving_average(uint16_t val)

{

filterBuf[filterIdx++] = val;

if (filterIdx >= FILTER_SIZE) filterIdx = 0;

uint32_t sum = 0;

for (int i = 0; i < FILTER_SIZE; i++) sum += filterBuf[i];

return (uint16_t)(sum / FILTER_SIZE);

}


/* ===== LED - Active HIGH ===== */

/* Pin → Resistor → LED → GND */

void LED_Hijau(void) { HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); }

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

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

void LED_Mati(void)

{

HAL_GPIO_WritePin(GPIOB,

GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_10,

GPIO_PIN_RESET);

}


/* ===== BUZZER - Active HIGH ===== */

void Buzzer_On(void) { HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_SET); }

void Buzzer_Off(void) { HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET); }


/* USER CODE END 0 */


/**

* @brief The application entry point.

* @retval int

*/

int main(void)

{

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */


HAL_Init();


/* USER CODE BEGIN Init */

/* USER CODE END Init */


SystemClock_Config();


/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */


MX_GPIO_Init();

MX_ADC1_Init();


/* USER CODE BEGIN 2 */

LED_Mati();

Buzzer_Off();

/* USER CODE END 2 */


/* USER CODE BEGIN WHILE */

while (1)

{

/* USER CODE END WHILE */


/* USER CODE BEGIN 3 */


/* ===== BACA ADC ===== */

HAL_ADC_Start(&hadc1);

HAL_ADC_PollForConversion(&hadc1, 10);

adcValue = HAL_ADC_GetValue(&hadc1);


/* ===== FILTER ===== */

filteredValue = moving_average((uint16_t)adcValue);



uint32_t threshold = 2000;


/* ===== DETEKSI DETAK ===== */

if (filteredValue > threshold && beatDetected == 0)

{

beatDetected = 1;

uint32_t now = HAL_GetTick();


if (lastBeatTime != 0)

{

interval = now - lastBeatTime;


/* Hanya hitung BPM jika interval masuk akal (20-200 BPM) */

if (interval > 300 && interval < 3000)

{

BPM = 60000 / interval;

}

}

lastBeatTime = now;


/* Jika BPM < 60: aktifkan pulse buzzer ikuti pola detak */

if (BPM > 0 && BPM < 60 && !buzzerOff)

{

buzzerPulse = 1;

beatPulseStart = HAL_GetTick();

}

}


/* Reset flag detak saat sinyal turun */

if (filteredValue < threshold)

{

beatDetected = 0;

}


/* ===== TIMEOUT TIDAK ADA DETAK 2 DETIK ===== */

if (lastBeatTime != 0 && HAL_GetTick() - lastBeatTime > 2000)

{

BPM = 0;

buzzerPulse = 0;

lastBeatTime = 0;

Buzzer_Off();

}


/* ===== PULSE BUZZER 80ms IKUTI POLA DETAK ===== */

if (buzzerPulse)

{

if (HAL_GetTick() - beatPulseStart < 80)

{

Buzzer_On();

}

else

{

Buzzer_Off();

buzzerPulse = 0;

}

}


/* ===== OUTPUT LED & BUZZER ===== */

if (BPM > 0)

{

if (BPM < 60)

{

/*

* KONDISI UTAMA:

* BPM < 60 → semua LED mati

* Buzzer bunyi mengikuti pola detak

*/

LED_Mati();

if (buzzerOff)

{

Buzzer_Off();

buzzerPulse = 0;

}

}

else if (BPM <= 80)

{

/* BPM normal 60-80: LED Hijau, buzzer mati */

// LED_Mati();

LED_Hijau();

Buzzer_Off();

buzzerPulse = 0;

buzzerOff = 0;

}

else

{

/* BPM tinggi > 80: LED Merah, buzzer nyala terus */

//LED_Mati();

LED_Merah();

buzzerPulse = 0;

if (!buzzerOff) Buzzer_On();

else Buzzer_Off();

}

}

else

{

/* Tidak ada detak */

LED_Mati();

Buzzer_Off();

buzzerPulse = 0;

}


HAL_Delay(5);


/* USER CODE END 3 */

}

}


/**

* @brief System Clock Configuration

* @retval None

*/

void SystemClock_Config(void)

{

RCC_OscInitTypeDef RCC_OscInitStruct = {0};

RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};


RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;

RCC_OscInitStruct.HSIState = RCC_HSI_ON;

RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;

RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;

if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)

{

Error_Handler();

}


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;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)

{

Error_Handler();

}


PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;

PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV2;

if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)

{

Error_Handler();

}

}


/**

* @brief ADC1 Initialization Function

* @retval None

*/

static void MX_ADC1_Init(void)

{

/* USER CODE BEGIN ADC1_Init 0 */

/* USER CODE END ADC1_Init 0 */


ADC_ChannelConfTypeDef sConfig = {0};


/* USER CODE BEGIN ADC1_Init 1 */

/* USER CODE END ADC1_Init 1 */


hadc1.Instance = ADC1;

hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;

hadc1.Init.ContinuousConvMode = DISABLE;

hadc1.Init.DiscontinuousConvMode = DISABLE;

hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;

hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;

hadc1.Init.NbrOfConversion = 1;

if (HAL_ADC_Init(&hadc1) != HAL_OK)

{

Error_Handler();

}


sConfig.Channel = ADC_CHANNEL_0;

sConfig.Rank = ADC_REGULAR_RANK_1;

sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;

if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)

{

Error_Handler();

}


/* USER CODE BEGIN ADC1_Init 2 */

/* USER CODE END ADC1_Init 2 */

}


/**

* @brief GPIO Initialization Function

* @retval None

*/

static void MX_GPIO_Init(void)

{

GPIO_InitTypeDef GPIO_InitStruct = {0};


/* USER CODE BEGIN MX_GPIO_Init_1 */

/* USER CODE END MX_GPIO_Init_1 */


__HAL_RCC_GPIOD_CLK_ENABLE();

__HAL_RCC_GPIOA_CLK_ENABLE();

__HAL_RCC_GPIOB_CLK_ENABLE();


/* Semua output awal LOW → LED & Buzzer mati */

HAL_GPIO_WritePin(GPIOB,

GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_10 | GPIO_PIN_11,

GPIO_PIN_RESET);


/* PA1 = Push Button (interrupt falling edge, pull-up) */

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 PB11 = LED + Buzzer (output push-pull) */

GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_10 | GPIO_PIN_11;

GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

GPIO_InitStruct.Pull = GPIO_NOPULL;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;

HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);


HAL_NVIC_SetPriority(EXTI1_IRQn, 0, 0);

HAL_NVIC_EnableIRQ(EXTI1_IRQn);


/* USER CODE BEGIN MX_GPIO_Init_2 */

/* USER CODE END MX_GPIO_Init_2 */

}


/* USER CODE BEGIN 4 */

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

{

if (GPIO_Pin == GPIO_PIN_1)

buzzerOff = !buzzerOff;

}

/* USER CODE END 4 */


/**

* @brief Error Handler

* @retval None

*/

void Error_Handler(void)

{

/* USER CODE BEGIN Error_Handler_Debug */

__disable_irq();

while (1) {}

/* USER CODE END Error_Handler_Debug */

}


#ifdef USE_FULL_ASSERT

void assert_failed(uint8_t *file, uint32_t line)

{

/* USER CODE BEGIN 6 */

/* USER CODE END 6 */

}

#endif /* USE_FULL_ASSERT */

5. Video Demo [Kembali]


6. Kondisi[Kembali]

Buatlah rangkaian seperti pada gambar percobaan 1 dengan kondisi  Sensor Heartbeat membaca BPM < 60 LED mati dan buzzer ber bunyi dengan pola yang sama dengan detak jantung

7. Video Simulasi[Kembali]




8. Download File [Kembali]

1. Download HTML [disini]

2. Download Rangkaian Proteus  [disini]







Komentar

Postingan populer dari blog ini

TUGAS ELEKTRONIKA