Laporan Akhir M3 Percobaan 4



a. Prosedur [Kembali]

  1. Buka web WOKWI.COM dan cari STM 32 NUCLEO C031C6
  2. Rangkai komponen sesuai dengan gambar rangkaian di modul
  3. Klik pada Library Manager untuk membuat file baru yang bernama main.h dan main.c
  4. Masukan program yang telah di buat sesuai kondisi pada kedua file tersebut
  5. Simulasikan

b. Hardware dan Diagram Blok [Kembali]

  • Hardware

 1. STM32 NUCLEO-G474RE

2. Sensor IR



3. Motor Servo



4. Jumper



5. Breadboard 


6. OLED

7. Adaptor



8. kabel Mikro USB



9. Konektor

  • Diagram Blog


c. Rangkaian Simulasi dan Prinsip Kerja [Kembali]

1. Rangkaian Simulasi




2. Prinsip kerja

a. Kondisi Awal (Sistem Ready)

Saat kedua board dinyalakan, fungsi inisialisasi berjalan:

  • Master (Nucleo 1): Mengatur jumlah sisa_parkir = 10 (MAX_PARKIR), mengaktifkan layar OLED via I2C untuk menampilkan status ">> TERSEDIA <<" dengan slot 10/10, serta memosisikan palang masuk (Motor Servo TIM2 CH1) pada posisi tertutup (CCR1 = 1000). Master juga mengaktifkan interupsi UART (HAL_UART_Receive_IT) untuk bersiap menerima data dari Slave.
  • Slave (Nucleo 2): Memosisikan palang keluar pada kondisi tertutup (CCR1 = 1000) dan mengaktifkan interupsi RX UART-nya.

b. Proses Kendaraan Masuk (Kendali di Master / Pintu Masuk)

  • Deteksi Sensor: Sensor IR di pintu masuk menggunakan konfigurasi GPIO_PULLUP (aktif LOW). Ketika ada mobil menghalangi sensor, fungsi membaca nilai 0, yang kemudian dinegasikan menjadi logika 1 (True).
  • Evaluasi Kondisi & Aksi: Jika sensor mendeteksi mobil DAN sisa_parkir > 0 (masih ada slot kosong):
    1. Master memicu fungsi buka palang (mengubah nilai PWM CCR1 = 2000).
    2. Nilai sisa_parkir dikurangi 1.
    3. Master memperbarui tampilan layar OLED via I2C secara real-time.
    4. Master mengirimkan karakter data "M" melalui UART ke Slave sebagai informasi bahwa kendaraan telah masuk.
  • Palang Menutup: Begitu mobil melewati sensor (tidak terhalang), program memicu palang untuk menutup kembali (CCR1 = 1000).
  • Kondisi Parkir Penuh: Jika mobil datang tetapi sisa_parkir == 0, palang tidak akan terbuka, layar OLED menampilkan pesan peringatan ">> PENUH <<", dan LED hijau pada Master akan berkedip sebagai peringatan visual.

c. Proses Kendaraan Keluar (Kendali di Slave → Master)

  • Deteksi Sensor: Sensor IR di pintu keluar (Slave) mendeteksi adanya mobil yang ingin keluar.
  • Aksi di Slave:
    1. Slave langsung membuka palangnya sendiri.
    2. Slave mengirimkan karakter data "K" secara instan melalui UART ke Master.
  • Respon Master via Interrupt: Ketika karakter "K" sampai di pin RX Master, Hardware Interrupt secara otomatis memicu fungsi callback.
    1. Master memeriksa data, jika valid, ia menambah nilai sisa_parkir++.
    2. Master langsung memperbarui layar OLED sehingga jumlah slot kosong bertambah kembali di layar utama secara otomatis.
  • Palang Menutup: Setelah mobil melewati area sensor Slave, palang pintu keluar kembali ditutup.

d. Flowchart dan Listing Program [Kembali]

  • Flowchart

                           







  • Listing Program

1. Program Nucleo 1 (Master Parking System)

/* USER CODE BEGIN Header */ 
/** ****************************************************************************** * @file           : main.c 
  * @brief          : Master Parking System - STM32G474RE 
  ****************************************************************************** */ 
/* USER CODE END Header */ 

/* Includes ------------------------------------------------------------------*/ 
#include "main.h" 

/* Private define ------------------------------------------------------------*/ 
/* Private includes ----------------------------------------------------------*/ 
/* USER CODE BEGIN Includes */ 
#define SSD1306_INCLUDE_FONT_7x10 
#include "ssd1306.h" 
#include "ssd1306_fonts.h" 
#include <stdio.h> 
#include <string.h> 
/* USER CODE END Includes */ 

/* Private typedef -----------------------------------------------------------*/ 
/* USER CODE BEGIN PTD */ 
/* USER CODE END PTD */  

/* USER CODE BEGIN PD */ 
#define MAX_PARKIR 10 
/* USER CODE END PD */ 
 
/* Private macro -------------------------------------------------------------*/ 
/* USER CODE BEGIN PM */ 
/* USER CODE END PM */ 
 
/* Private variables ---------------------------------------------------------*/ 
COM_InitTypeDef BspCOMInit; 
I2C_HandleTypeDef hi2c1; 
TIM_HandleTypeDef htim2; 
UART_HandleTypeDef huart1; // komunikasi ke slave (PC4/PC5) 
UART_HandleTypeDef huart2; // serial monitor via BSP COM1 (PA2/PA3) 
 
/* USER CODE BEGIN PV */ 
uint8_t sisa_parkir     = MAX_PARKIR; 
uint8_t kendaraan_masuk = 0; 
uint8_t uart_rx_buffer[1]; 
/* USER CODE END PV */ 
 
/* Private function prototypes -----------------------------------------------*/ 
void SystemClock_Config(void); 
static void MX_GPIO_Init(void); 
static void MX_I2C1_Init(void); 
static void MX_TIM2_Init(void); 
static void MX_USART1_UART_Init(void); 
static void MX_USART2_UART_Init(void); 
 
/* USER CODE BEGIN PFP */ 
void Update_Display(void); 
void Servo_Buka(void); 
void Servo_Tutup(void);
/* USER CODE END PFP */ 
 
/* USER CODE BEGIN 0 */ 
/* USER CODE END 0 */ 
 
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_I2C1_Init(); 
  MX_TIM2_Init(); 
  MX_USART1_UART_Init(); 
  MX_USART2_UART_Init(); 
 
  /* USER CODE BEGIN 2 */ 
  BSP_LED_Init(LED_GREEN); 
  BSP_PB_Init(BUTTON_USER, BUTTON_MODE_EXTI); 
 
  // Serial monitor via BSP COM1 (USART2 PA2/PA3) 
  BspCOMInit.BaudRate   = 115200; 
  BspCOMInit.WordLength = COM_WORDLENGTH_8B; 
  BspCOMInit.StopBits   = COM_STOPBITS_1; 
  BspCOMInit.Parity     = COM_PARITY_NONE; 
  BspCOMInit.HwFlowCtl  = COM_HWCONTROL_NONE; 
  if (BSP_COM_Init(COM1, &BspCOMInit) != BSP_ERROR_NONE) {  
    Error_Handler(); 
  } 
 
  ssd1306_Init(); 
 
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); 
  htim2.Instance->CCR1 = 1000; 
 
  // USART1 untuk komunikasi ke slave (PC4=TX, PC5=RX) 
  HAL_UART_Receive_IT(&huart1, uart_rx_buffer, 1); 
 
  printf("=== MASTER PARKING READY ===\r\n"); 
  printf("Slot tersedia: %d/%d\r\n", sisa_parkir, MAX_PARKIR); 
  Update_Display(); 
  /* USER CODE END 2 */ 
 
  /* USER CODE BEGIN WHILE */ 
  while (1) 
  { 
    /* USER CODE END WHILE */ 
 
    /* USER CODE BEGIN 3 */ 
    uint8_t ir = !HAL_GPIO_ReadPin(MASTER_IR_SENSOR_GPIO_Port, MASTER_IR_SENSOR_Pin); 
 
    printf("IR: %d | Sisa: %d\r\n", ir, sisa_parkir); 
 
    // DETEKSI MASUK 
    if (ir && sisa_parkir > 0 && !kendaraan_masuk) { 
      HAL_Delay(50); 
      ir = !HAL_GPIO_ReadPin(MASTER_IR_SENSOR_GPIO_Port, MASTER_IR_SENSOR_Pin); 
      if (ir) { 
        Servo_Buka(); 
        sisa_parkir--;  
        kendaraan_masuk = 1; 
        Update_Display(); 
        printf(">> MASUK! Sisa: %d/%d\r\n", sisa_parkir, MAX_PARKIR); 
        HAL_UART_Transmit(&huart1, (uint8_t*)"M", 1, 100); 
      } 
    } 

    // PARKIR PENUH 
    if (ir && sisa_parkir == 0 && !kendaraan_masuk) { 
      printf(">> PARKIR PENUH!\r\n"); 
      BSP_LED_Toggle(LED_GREEN); 
      HAL_Delay(200); 
    } 

    // KENDARAAN SUDAH LEWAT 
    if (!ir && kendaraan_masuk) { 
      HAL_Delay(50); 
      ir = !HAL_GPIO_ReadPin(MASTER_IR_SENSOR_GPIO_Port, MASTER_IR_SENSOR_Pin); 
      if (!ir) { 
        Servo_Tutup(); 
        kendaraan_masuk = 0; 
        printf(">> Palang ditutup\r\n"); 
      } 
    } 
    HAL_Delay(100); 
    /* USER CODE END 3 */ 
  } 
} 

/* USER CODE BEGIN 4 */
void Update_Display(void) { 
  char buf[25]; 
  ssd1306_Fill(Black); 

  ssd1306_SetCursor(2, 0); 
  ssd1306_WriteString("SISTEM PARKIR", Font_7x10, White); 
 
  ssd1306_SetCursor(2, 14); 
  sprintf(buf, "Slot: %d/%d", sisa_parkir, MAX_PARKIR); 
  ssd1306_WriteString(buf, Font_7x10, White); 
 
  ssd1306_SetCursor(2, 28); 
  if (sisa_parkir == 0) { 
    ssd1306_WriteString(">> PENUH <<", Font_7x10, White); 
  } else { 
    ssd1306_WriteString(">> TERSEDIA <<", Font_7x10, White); 
  } 
  ssd1306_UpdateScreen(); 
} 
 
void Servo_Buka(void) { 
  htim2.Instance->CCR1 = 2000; 
  HAL_Delay(600); 
} 
 
void Servo_Tutup(void) { 
  htim2.Instance->CCR1 = 1000; 
  HAL_Delay(600); 
} 
 
// Terima dari slave via USART1 (PC5=RX) 
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) 
{ 
  if (huart->Instance == USART1) 
  { 
    if (uart_rx_buffer[0] == 'K') 
    { 
      if(sisa_parkir < MAX_PARKIR) sisa_parkir++; 
 
      printf(">> KENDARAAN KELUAR (SLAVE)\r\n");  
      printf(">> Sisa: %d/%d\r\n", sisa_parkir, MAX_PARKIR); 
 
      Update_Display(); 
    } 
    HAL_UART_Receive_IT(&huart1, uart_rx_buffer, 1); 
  } 
} 
/* USER CODE END 4 */ 
 
void SystemClock_Config(void) 
{ 
  RCC_OscInitTypeDef RCC_OscInitStruct = {0}; 
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; 
 
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST); 
  RCC_OscInitStruct.OscillatorType      = RCC_OSCILLATORTYPE_HSI; 
  RCC_OscInitStruct.HSIState            = RCC_HSI_ON; 
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; 
  RCC_OscInitStruct.PLL.PLLState        = RCC_PLL_ON; 
  RCC_OscInitStruct.PLL.PLLSource       = RCC_PLLSOURCE_HSI; 
  RCC_OscInitStruct.PLL.PLLM            = RCC_PLLM_DIV4; 
  RCC_OscInitStruct.PLL.PLLN            = 85; 
  RCC_OscInitStruct.PLL.PLLP            = RCC_PLLP_DIV2; 
  RCC_OscInitStruct.PLL.PLLQ            = RCC_PLLQ_DIV2; 
  RCC_OscInitStruct.PLL.PLLR            = RCC_PLLR_DIV2; 
  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_PLLCLK; 
  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_4) != HAL_OK) Error_Handler(); 
} 
 
static void MX_I2C1_Init(void) 
{ 
  hi2c1.Instance             = I2C1; 
  hi2c1.Init.Timing          = 0x40B285C2; 
  hi2c1.Init.OwnAddress1     = 0; 
  hi2c1.Init.AddressingMode  = I2C_ADDRESSINGMODE_7BIT; 
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; 
  hi2c1.Init.OwnAddress2     = 0; 
  hi2c1.Init.OwnAddress2Masks= I2C_OA2_NOMASK; 
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; 
  hi2c1.Init.NoStretchMode   = I2C_NOSTRETCH_DISABLE; 
  if (HAL_I2C_Init(&hi2c1) != HAL_OK) Error_Handler(); 
  if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK) Error_Handler(); 
  if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK) Error_Handler(); 
} 
 
static void MX_TIM2_Init(void) 
{ 
  TIM_ClockConfigTypeDef  sClockSourceConfig = {0}; 
  TIM_MasterConfigTypeDef sMasterConfig      = {0}; 
  TIM_OC_InitTypeDef      sConfigOC          = {0};
 
  htim2.Instance               = TIM2; 
  htim2.Init.Prescaler         = 169; 
  htim2.Init.CounterMode       = TIM_COUNTERMODE_UP; 
  htim2.Init.Period            = 19999; 
  htim2.Init.ClockDivision     = TIM_CLOCKDIVISION_DIV1; 
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; 
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK) Error_Handler(); 
 
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; 
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK) Error_Handler(); 
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK) Error_Handler(); 
 
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; 
  sMasterConfig.MasterSlaveMode     = TIM_MASTERSLAVEMODE_DISABLE; 
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) Error_Handler(); 
 
  sConfigOC.OCMode     = TIM_OCMODE_PWM1; 
  sConfigOC.Pulse      = 1000; 
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; 
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; 
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) Error_Handler(); 
  HAL_TIM_MspPostInit(&htim2); 
} 
 
static void MX_USART1_UART_Init(void) 
{ 
  huart1.Instance                    = USART1; 
  huart1.Init.BaudRate               = 9600; 
  huart1.Init.WordLength             = UART_WORDLENGTH_8B; 
  huart1.Init.StopBits               = UART_STOPBITS_1; 
  huart1.Init.Parity                 = UART_PARITY_NONE; 
  huart1.Init.Mode                   = UART_MODE_TX_RX; 
  huart1.Init.HwFlowCtl              = UART_HWCONTROL_NONE; 
  huart1.Init.OverSampling           = UART_OVERSAMPLING_16; 
  huart1.Init.OneBitSampling         = UART_ONE_BIT_SAMPLE_DISABLE; 
  huart1.Init.ClockPrescaler         = UART_PRESCALER_DIV1; 
  huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; 
  if (HAL_UART_Init(&huart1) != HAL_OK) Error_Handler(); 
  if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK) Error_Handler(); 
  if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK) Error_Handler(); 
  if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK) Error_Handler(); 
} 
 
static void MX_USART2_UART_Init(void) 
{ 
  huart2.Instance                    = USART2; 
  huart2.Init.BaudRate               = 115200; 
  huart2.Init.WordLength             = UART_WORDLENGTH_8B; 
  huart2.Init.StopBits               = UART_STOPBITS_1; 
  huart2.Init.Parity                 = UART_PARITY_NONE; 
  huart2.Init.Mode                   = UART_MODE_TX_RX; 
  huart2.Init.HwFlowCtl              = UART_HWCONTROL_NONE; 
  huart2.Init.OverSampling           = UART_OVERSAMPLING_16; 
  huart2.Init.OneBitSampling         = UART_ONE_BIT_SAMPLE_DISABLE; 
  huart2.Init.ClockPrescaler         = UART_PRESCALER_DIV1; 
  huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; 
  if (HAL_UART_Init(&huart2) != HAL_OK) Error_Handler(); 
  if (HAL_UARTEx_SetTxFifoThreshold(&huart2, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK) Error_Handler(); 
  if (HAL_UARTEx_SetRxFifoThreshold(&huart2, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK) Error_Handler(); 
  if (HAL_UARTEx_DisableFifoMode(&huart2) != HAL_OK) Error_Handler(); 
} 
 
static void MX_GPIO_Init(void) 
{ 
  GPIO_InitTypeDef GPIO_InitStruct = {0}; 
 
  __HAL_RCC_GPIOC_CLK_ENABLE(); 
  __HAL_RCC_GPIOF_CLK_ENABLE(); 
  __HAL_RCC_GPIOA_CLK_ENABLE(); 
  __HAL_RCC_GPIOB_CLK_ENABLE(); 
 
  // IR sensor PA1 - aktif LOW -> PULLUP 
  GPIO_InitStruct.Pin  = MASTER_IR_SENSOR_Pin; 
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT; 
  GPIO_InitStruct.Pull = GPIO_PULLUP; 
  HAL_GPIO_Init(MASTER_IR_SENSOR_GPIO_Port, &GPIO_InitStruct); 
 
  // USART1 TX=PC4, RX=PC5 untuk komunikasi ke slave 
  GPIO_InitStruct.Pin       = MASTER_TX_Pin | MASTER_RX_Pin; 
  GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP; 
  GPIO_InitStruct.Pull      = GPIO_NOPULL; 
  GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_LOW; 
  GPIO_InitStruct.Alternate = GPIO_AF7_USART1; 
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); 
} 
 
void Error_Handler(void) 
{ 
  __disable_irq(); 
  while (1) {} 
} 
 
#ifdef USE_FULL_ASSERT 
void assert_failed(uint8_t *file, uint32_t line) {} 
#endif

2. Program Nucleo 2 (Slave Parking System - Pintu Keluar)

/* USER CODE BEGIN Header */ 
/** ****************************************************************************** * @file           : main.c 
  * @brief          : Slave Parking System - STM32G474RE (Pintu Keluar) 
  ****************************************************************************** */ 
/* USER CODE END Header */ 
 
/* Includes ------------------------------------------------------------------*/ 
#include "main.h" 
 
/* Private includes ----------------------------------------------------------*/ 
/* USER CODE BEGIN Includes */ 
#include <stdio.h> 
#include <string.h> 
/* USER CODE END Includes */ 
 
/* Private typedef -----------------------------------------------------------*/ 
/* USER CODE BEGIN PTD */ 
/* USER CODE END PTD */ 
 
/* Private define ------------------------------------------------------------*/ 
/* USER CODE BEGIN PD */ 
/* USER CODE END PD */ 
/* Private macro -------------------------------------------------------------*/ 
/* USER CODE BEGIN PM */ 
/* USER CODE END PM */ 
 
/* Private variables ---------------------------------------------------------*/ 
COM_InitTypeDef BspCOMInit; 
TIM_HandleTypeDef htim2; 
UART_HandleTypeDef huart1; 
UART_HandleTypeDef huart2; 
 
/* USER CODE BEGIN PV */ 
uint8_t kendaraan_keluar = 0; 
uint8_t uart_rx_buffer[1]; 
/* USER CODE END PV */ 
 
/* Private function prototypes -----------------------------------------------*/ 
void SystemClock_Config(void); 
static void MX_GPIO_Init(void); 
static void MX_TIM2_Init(void); 
static void MX_USART1_UART_Init(void); 
static void MX_USART2_UART_Init(void); 
 
/* USER CODE BEGIN PFP */ 
void Servo_Buka(void); 
void Servo_Tutup(void); 
/* USER CODE END PFP */ 
 
/* USER CODE BEGIN 0 */ 
/* USER CODE END 0 */ 
 
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_TIM2_Init(); 
  MX_USART1_UART_Init(); 
  MX_USART2_UART_Init(); 
 
  /* USER CODE BEGIN 2 */ 
  BSP_LED_Init(LED_GREEN); 
  BSP_PB_Init(BUTTON_USER, BUTTON_MODE_EXTI); 
  HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin, GPIO_PIN_RESET); 
  
  BspCOMInit.BaudRate   = 115200; 
  BspCOMInit.WordLength = COM_WORDLENGTH_8B; 
  BspCOMInit.StopBits   = COM_STOPBITS_1; 
  BspCOMInit.Parity     = COM_PARITY_NONE; 
  BspCOMInit.HwFlowCtl  = COM_HWCONTROL_NONE; 
  if (BSP_COM_Init(COM1, &BspCOMInit) != BSP_ERROR_NONE) { 
    Error_Handler(); 
  } 
  
  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); 
  htim2.Instance->CCR1 = 1000; 
  
  // USART2 RX interrupt - terima dari master 
  HAL_UART_Receive_IT(&huart1, uart_rx_buffer, 1);
  printf("=== SLAVE READY - Pintu Keluar ===\r\n"); 
  /* USER CODE END 2 */ 
 
  /* USER CODE BEGIN WHILE */ 
  while (1) 
  { 
    /* USER CODE END WHILE */ 
 
    /* USER CODE BEGIN 3 */ 
    uint8_t ir = !HAL_GPIO_ReadPin(SLAVE_IR_SENSOR_GPIO_Port, SLAVE_IR_SENSOR_Pin); 
 
    printf("IR: %d\r\n", ir); 
 
    // === DETEKSI KENDARAAN KELUAR === 
    if (ir && !kendaraan_keluar) { 
      HAL_Delay(50); 
      ir = !HAL_GPIO_ReadPin(SLAVE_IR_SENSOR_GPIO_Port, SLAVE_IR_SENSOR_Pin); 
      if (ir) { 
        Servo_Buka();                                        // 1. buka palang 
        kendaraan_keluar = 1;                                // 2. set flag 
        HAL_UART_Transmit(&huart1, (uint8_t*)"K", 1, 100);   // 3. kirim ke master 
        HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin, GPIO_PIN_SET); 
        printf(">> KELUAR! Kuota +1 dikirim ke master\r\n"); 
      } 
    } 
 
    // === KENDARAAN SUDAH LEWAT === 
    if (!ir && kendaraan_keluar) { 
      HAL_Delay(50); 
      ir = !HAL_GPIO_ReadPin(SLAVE_IR_SENSOR_GPIO_Port, SLAVE_IR_SENSOR_Pin); 
      if (!ir) { 
        Servo_Tutup(); 
        kendaraan_keluar = 0; 
        HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin, GPIO_PIN_RESET); 
        printf(">> Palang ditutup, siap kendaraan berikutnya\r\n"); 
      } 
    } 
 
    HAL_Delay(100); 
  } 
  /* USER CODE END 3 */ 
} 
 
/* USER CODE BEGIN 4 */ 
void Servo_Buka(void) { 
  htim2.Instance->CCR1 = 2000; 
  HAL_Delay(600); 
} 
 
void Servo_Tutup(void) {  
  htim2.Instance->CCR1 = 1000; 
  HAL_Delay(600); 
} 
 
// Terima info dari master via USART2 
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) 
{ 
  if (huart->Instance == USART1) 
  { 
    if (uart_rx_buffer[0] == 'M') 
    { 
      printf(">> INFO: KENDARAAN MASUK (MASTER)\r\n"); 
    }
    HAL_UART_Receive_IT(&huart1, uart_rx_buffer, 1); 
  } 
} 
/* USER CODE END 4 */ 
 
void SystemClock_Config(void) 
{ 
  RCC_OscInitTypeDef RCC_OscInitStruct = {0}; 
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; 
 
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST); 
  RCC_OscInitStruct.OscillatorType      = RCC_OSCILLATORTYPE_HSI; 
  RCC_OscInitStruct.HSIState            = RCC_HSI_ON; 
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; 
  RCC_OscInitStruct.PLL.PLLState        = RCC_PLL_ON; 
  RCC_OscInitStruct.PLL.PLLSource       = RCC_PLLSOURCE_HSI; 
  RCC_OscInitStruct.PLL.PLLM            = RCC_PLLM_DIV4; 
  RCC_OscInitStruct.PLL.PLLN            = 85; 
  RCC_OscInitStruct.PLL.PLLP            = RCC_PLLP_DIV2; 
  RCC_OscInitStruct.PLL.PLLQ            = RCC_PLLQ_DIV2; 
  RCC_OscInitStruct.PLL.PLLR            = RCC_PLLR_DIV2; 
  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_PLLCLK; 
  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_4) != HAL_OK) Error_Handler(); 
} 
 
static void MX_TIM2_Init(void) 
{ 
  TIM_ClockConfigTypeDef  sClockSourceConfig = {0}; 
  TIM_MasterConfigTypeDef sMasterConfig      = {0}; 
  TIM_OC_InitTypeDef      sConfigOC          = {0}; 
 
  htim2.Instance               = TIM2; 
  htim2.Init.Prescaler         = 169; 
  htim2.Init.CounterMode       = TIM_COUNTERMODE_UP; 
  htim2.Init.Period            = 19999; 
  htim2.Init.ClockDivision     = TIM_CLOCKDIVISION_DIV1; 
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; 
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK) Error_Handler(); 
 
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; 
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK) Error_Handler(); 
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK) Error_Handler(); 
 
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; 
  sMasterConfig.MasterSlaveMode     = TIM_MASTERSLAVEMODE_DISABLE; 
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) Error_Handler(); 
 
  sConfigOC.OCMode     = TIM_OCMODE_PWM1; 
  sConfigOC.Pulse      = 1000; 
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; 
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; 
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) Error_Handler(); 
  HAL_TIM_MspPostInit(&htim2);
} 
 
static void MX_USART1_UART_Init(void) 
{ 
  huart1.Instance                    = USART1; 
  huart1.Init.BaudRate               = 9600; 
  huart1.Init.WordLength             = UART_WORDLENGTH_8B; 
  huart1.Init.StopBits               = UART_STOPBITS_1; 
  huart1.Init.Parity                 = UART_PARITY_NONE; 
  huart1.Init.Mode                   = UART_MODE_TX_RX; 
  huart1.Init.HwFlowCtl              = UART_HWCONTROL_NONE; 
  huart1.Init.OverSampling           = UART_OVERSAMPLING_16; 
  huart1.Init.OneBitSampling         = UART_ONE_BIT_SAMPLE_DISABLE; 
  huart1.Init.ClockPrescaler         = UART_PRESCALER_DIV1; 
  huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; 
  if (HAL_UART_Init(&huart1) != HAL_OK) Error_Handler(); 
  if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK) Error_Handler(); 
  if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK) Error_Handler(); 
  if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK) Error_Handler(); 
} 
 
static void MX_USART2_UART_Init(void) 
{ 
  huart2.Instance                    = USART2; 
  huart2.Init.BaudRate               = 115200; 
  huart2.Init.WordLength             = UART_WORDLENGTH_8B; 
  huart2.Init.StopBits               = UART_STOPBITS_1; 
  huart2.Init.Parity                 = UART_PARITY_NONE; 
  huart2.Init.Mode                   = UART_MODE_TX_RX; 
  huart2.Init.HwFlowCtl              = UART_HWCONTROL_NONE; 
  huart2.Init.OverSampling           = UART_OVERSAMPLING_16; 
  huart2.Init.OneBitSampling         = UART_ONE_BIT_SAMPLE_DISABLE; 
  huart2.Init.ClockPrescaler         = UART_PRESCALER_DIV1; 
  huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; 
  if (HAL_UART_Init(&huart2) != HAL_OK) Error_Handler(); 
  if (HAL_UARTEx_SetTxFifoThreshold(&huart2, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK) Error_Handler(); 
  if (HAL_UARTEx_SetRxFifoThreshold(&huart2, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK) Error_Handler(); 
  if (HAL_UARTEx_DisableFifoMode(&huart2) != HAL_OK) Error_Handler(); 
} 
 
static void MX_GPIO_Init(void) 
{ 
  GPIO_InitTypeDef GPIO_InitStruct = {0}; 
 
  __HAL_RCC_GPIOC_CLK_ENABLE(); 
  __HAL_RCC_GPIOF_CLK_ENABLE(); 
  __HAL_RCC_GPIOA_CLK_ENABLE(); 
  __HAL_RCC_GPIOB_CLK_ENABLE(); 
 
  // LED GREEN PB7 - output 
  HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin, GPIO_PIN_RESET); 
  GPIO_InitStruct.Pin   = LED_GREEN_Pin; 
  GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP; 
  GPIO_InitStruct.Pull  = GPIO_NOPULL; 
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; 
  HAL_GPIO_Init(LED_GREEN_GPIO_Port, &GPIO_InitStruct); 
 
  // IR sensor PA1 - aktif LOW -> PULLUP 
  GPIO_InitStruct.Pin  = SLAVE_IR_SENSOR_Pin; 
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT; 
  GPIO_InitStruct.Pull = GPIO_PULLUP; 
  HAL_GPIO_Init(SLAVE_IR_SENSOR_GPIO_Port, &GPIO_InitStruct);
 
  // USART2 PA2=TX, PA3=RX untuk komunikasi ke master 
  GPIO_InitStruct.Pin       = SLAVE_USART1_TX_Pin | SLAVE_USART1_RX_Pin; 
  GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP; 
  GPIO_InitStruct.Pull      = GPIO_NOPULL; 
  GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_LOW; 
  GPIO_InitStruct.Alternate = GPIO_AF7_USART1; 
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 
} 
 
void Error_Handler(void) 
{ 
  __disable_irq(); 
  while (1) {} 
} 
 
#ifdef USE_FULL_ASSERT 
void assert_failed(uint8_t *file, uint32_t line) {} 
#endif

e. Video Demo [Kembali]


f. Analisa [Kembali]

     
 



g. Download File [Kembali]

File Tugas Pendahuluan(.Zip) [Klik Disini]

Download File Analisa [Klik Disini]

Video Demo [Klik Disini]

Download Datasheet STM32 Nucleo G474RE [Klik Disini]

Download Datasheet Sensor IR [Klik Disini]

Download Datasheet Motor Servo [Klik Disini]

Komentar

Postingan populer dari blog ini