LA Percobaan Modul 3

  

[KEMBALI KE MENU SEBELUMNYA]

1. Prosedur[Kembali]

1. Persiapan Hardware

  • Hubungkan TX (PA9) Nucleo 1 ke RX (PA10) Nucleo 2.

  • Hubungkan RX (PA10) Nucleo 1 ke TX (PA9) Nucleo 2.

  • Wajib: Hubungkan GND kedua board agar referensi tegangan sama.

  • Pasang sensor IR pada PA1 & PA4 (Nucleo 1) dan Motor Servo pada PA0 (Nucleo 2).

2. Konfigurasi Software (STM32CubeIDE)

  • Nucleo 1 (Master): Aktifkan USART1 (Asynchronous) dan atur PA1, PA4 sebagai GPIO_Input.

  • Nucleo 2 (Slave): Aktifkan USART1 (Asynchronous) dan TIM2 CH1 sebagai PWM Generation CH1.

  • Samakan Baud Rate kedua board (contoh: 115200).

3. Implementasi Kode

  • Nucleo 1: Gunakan HAL_GPIO_ReadPin untuk cek sensor. Jika terdeteksi, kirim karakter unik menggunakan HAL_UART_Transmit.

  • Nucleo 2: Gunakan HAL_UART_Receive untuk menerima karakter. Jika karakter cocok, ubah nilai PWM (__HAL_TIM_SET_COMPARE) untuk menggerakkan servo (buka palang), beri delay, lalu kembalikan ke posisi semula (tutup palang).

4. Pengujian

  • Build dan Flash program ke masing-masing board.

  • Uji sensor IR dan pastikan servo merespon dengan membuka palang pintu secara otomatis.

2. Hardware dan Diagram Blok[Kembali]

A. Hardware

Rangkaian ini terdiri dari beberapa komponen esensial yang saling terintegrasi:
  • 1. STM32 NUCLEO-G474RE        

        2. STM32Bluepill
            3. PIR Sensor
        4. LED
        5. Resistor

3. Rangkaian Simulasi [Kembali]

PRINSIP KERJA:   
1. Inisialisasi Sistem

Saat sistem dinyalakan, kedua mikrokontroler (STM32 Nucleo) melakukan konfigurasi awal pada periferalnya:

Master: Mengatur USART1 (komunikasi dengan Slave), I2C (tampilan OLED), dan PWM pada TIM2 (kontrol Servo Masuk). Master juga menetapkan variabel kuota parkir awal (misalnya 5 atau 10 slot).
*Slave: Mengatur USART1 (menerima/mengirim data ke Master) dan PWM pada TIM2 (kontrol Servo Keluar).

2. Mekanisme Kendali Palang Masuk (Master)

Proses dimulai ketika kendaraan tiba di pintu masuk:

Deteksi: Sensor IR pada sisi Master (pintu masuk) mendeteksi adanya objek.
Logika Kuota: Master memeriksa variabel sisa slot. Jika sisa slot > 0, maka sistem akan memberikan akses.
Output Aktuator: Master mengirimkan sinyal *PWM (Pulse Width Modulation)* ke Motor Servo 1 untuk mengangkat palang pintu.
Update Data: Master mengurangi jumlah sisa slot parkir dan memperbarui informasi pada layar OLED melalui protokol I2C.

 3. Komunikasi UART dan Sinkronisasi

Agar kedua mikrokontroler memiliki data yang sinkron, komunikasi asinkron dilakukan:

Saat palang masuk terbuka, Master dapat mengirimkan karakter tertentu (misalnya 'M') ke Slave sebagai tanda ada kendaraan masuk.
Komunikasi ini berjalan melalui jalur TX (Transmit)* Master ke RX (Receive) Slave secara real-time.

4. Mekanisme Kendali Palang Keluar (Slave)

Saat kendaraan ingin keluar dari area parkir:

Deteksi Keluar: Sensor IR pada sisi Slave (pintu keluar) mendeteksi kendaraan.
Output Aktuator: Slave secara mandiri mengirimkan sinyal PWM ke Motor Servo 2 untuk membuka palang keluar.
Umpan Balik (Feedback): Setelah kendaraan terdeteksi lewat, Slave mengirimkan karakter instruksi (misalnya 'K' untuk Keluar) melalui jalur UART TX kembali ke Master.

5. Pembaruan Kuota Akhir (Loopback)

*Penerimaan Data: Master menerima karakter 'K' melalui pin RX-nya.
Logika Penambahan:* Karena ada kendaraan yang keluar, Master secara otomatis menambah jumlah variabel sisa slot parkir (Increment).
Visualisasi: Master kembali mengirimkan data teks terbaru ke layar OLED agar pengguna di pintu masuk dapat melihat bahwa slot parkir telah tersedia kembali.

4. Flowchart dan Listing Program[Kembali]

  • Flowchart


    Listing Program :

    /* 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  
    #include  
    /* 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); } void Update_Display(void) { char buf[25]; ssd1306_Fill(Black); // 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 */
    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) { // USART1 - komunikasi ke slave (PC4=TX, PC5=RX) 9600 baud 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) { // USART2 - serial monitor via BSP COM1 (PA2=TX, PA3=RX) 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

    Nucleo 2

    /* 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 #include /* 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_B OOST); 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

5. Soal Analisa[Kembali]

Analisa:
1. Bagaimana konfigurasi rangkaian dan program dari percobaan ynag telah dilakukan?
Jawaban:
Sistem ini dirancang menggunakan komunikasi UART antara dua board mikrokontroler.
Konfigurasi Rangkaian: Perangkat keras yang digunakan meliputi dua buah STM32 Nucleo G474RE (bertindak sebagai Master dan Slave), dua buah sensor IR, dua buah motor servo, kabel jumper, dan breadboard. Master dihubungkan ke sensor IR pada pin PA1 dan menggunakan USART1 (TX di PC4, RX di PC5) untuk berkomunikasi dengan Slave. Slave juga membaca sensor IR di PA1 dan menggunakan USART1 untuk merespon Master.
Program Master: Master bertugas menjaga gerbang masuk dan melacak kuota parkir. Jika sensor IR Master mendeteksi kendaraan dan kuota tersedia, Master membuka servo (mengirim sinyal PWM ke TIM2 CH1), mengurangi sisa slot parkir, memperbarui tampilan OLED via I2C, dan mengirimkan karakter 'M' via UART ke Slave.
Program Slave: Slave bertugas menjaga gerbang keluar. Saat sensor IR mendeteksi kendaraan, Slave menggerakkan servo untuk membuka palang, lalu mengirimkan karakter 'K' kembali ke Master via UART. Ketika Master menerima karakter 'K', program Master akan menambah kembali kuota sisa parkir.

 2. Jelaskan bagaimana proses komunikasi yang terjadi pada percobaan yang telah dilakukan (UART/SPI/I2C)!
Jawaban:
SPI (Contoh: Kontrol Greenhouse & Game): SPI adalah komunikasi serial sinkron yang menggunakan 3 jalur utama (MOSI, MISO, SCK) dan 1 jalur SS/CS. Sinyal clock (SCLK) secara konstan dialirkan dari Master ke Slave untuk proses sinkronisasi. Pada percobaan Greenhouse, Master membaca status sensor (LDR/Tombol) dan mengirimkan data biner ke Slave melalui pin MOSI. Slave menerima data tersebut dan menerjemahkannya untuk menghidupkan LED atau Kipas.
I2C (Contoh: Game Display): I2C adalah standar komunikasi serial dua arah yang hanya menggunakan dua saluran: SCL (Serial Clock) dan SDA (Serial Data). Pada percobaan sistem parkir dan game, protokol ini digunakan oleh Master untuk berkomunikasi dengan layar OLED. Master mengirimkan message frame yang berisi kondisi start, alamat perangkat, bit Read/Write, serta Data Frame yang memuat informasi teks atau skor untuk dirender oleh OLED.
UART (Contoh: Smart Entry & Sistem Parkir): UART menerjemahkan bit-bit paralel menjadi data serial asinkron. Komunikasi terjadi secara silang antara pin TX (Transmitter) dan RX (Receiver) tanpa adanya jalur clock. Pada percobaan Smart Entry, Nucleo membaca sensor PIR dan mengirim data karakter '1' atau '0'. Bluepill menerima karakter tersebut pada pin RX-nya dan menggunakan logika kondisional (if rx_data == '1') untuk menyalakan LED.

3. Analisa penyebab kesalahan pengiriman data yang sering error!
Jawaban:
Kesalahan atau error dalam pengiriman data antar mikrokontroler biasanya disebabkan oleh beberapa ketidaksesuaian pada tahap konfigurasi perangkat keras maupun perangkat lunak:
Ketidaksesuaian Parameter Konfigurasi: Jika nilai Baudrate (misalnya 9600) tidak diatur identik antara Transmitter dan Receiver pada UART, data tidak akan terbaca dengan benar. Pada SPI, perbedaan pengaturan Clock Polarity (CPOL) atau Clock Phase (CPHA) menyebabkan Master dan Slave salah membaca bit data pada siklus clock yang tidak tepat.
Kesalahan Pendefinisian Mode: Mikrokontroler harus didefinisikan secara eksplisit perannya. Jika kedua modul tidak sengaja dikonfigurasi dengan mode yang sama (misalnya, dua-duanya didefinisikan sebagai SPI_MODE_MASTER atau SPI_MODE_SLAVE), komunikasi tidak dapat terjalin.*Masalah Fisik (Hardware): Sambungan kabel *jumper pada breadboard yang tidak stabil atau kesalahan pemasangan pin (contohnya pin TX dihubungkan ke TX, bukan ke RX) dapat menggagalkan aliran paket data fisik.

4. Pada percobaan komunikasi antar mikrokontroler, mengapa konfigurasi parameter komunikasi seperti baudrate pada UART atau clock polarity dan clock phase pada SPI harus sama antara master dan slave? Jelaskan pengaruhnya terhadap proses pengiriman data!
Jawaban:
Menyamakan parameter komunikasi sangat krusial untuk menentukan kapan dan seberapa cepat bit-bit data disampel oleh receiver:
Baudrate (UART): UART adalah komunikasi asinkron, artinya tidak ada sinyal clock fisik yang dikirimkan untuk menyamakan waktu antara dua perangkat. Baudrate bertindak sebagai "kesepakatan waktu". Jika Master mengirim pada kecepatan 115200 bit per detik dan Slave membaca pada 9600 bit per detik, Slave akan melakukan sampling pada titik waktu yang sepenuhnya salah, menghasilkan data yang rusak atau tidak terbaca. 
Clock Polarity & Phase (SPI): SPI menggunakan mode sinkron dimana sinyal clock dialirkan dari Master ke Slave. Parameter Clock Polarity menentukan level tegangan awal (rendah/tinggi) saat diam, sedangkan Clock Phase menentukan pada transisi tepi mana (naik atau turun) bit data akan dibaca atau ditulis. Jika tidak disamakan, Master mungkin mengirim bit pada saat clock naik, namun Slave mencoba membacanya saat clock turun, sehingga sinkronisasi gagal dan data menjadi tidak selaras.

5. Analisa hubungan antara data sensor/input yang dibaca mikrokontroler dengan respon output yang dihasilkan pada sistem komunikasi yang telah dibuat!
Jawaban:
Hubungan antara data sensor dan respon sistem menggambarkan arsitektur kendali Master-Slave, dimana mikrokontroler pengirim hanya bertugas membaca environment fisik, dan mikrokontroler penerima bertugas sebagai aktuator.
Sebagai contoh pada percobaan Smart Entry, sensor PIR menangkap sinyal fisik berupa pergerakan yang memicu logika HIGH pada pin Input. Mikrokontroler Master merespon keadaan ini dengan menerjemahkannya ke dalam karakter serial ('1') lalu memancarkannya. Di sisi lain, mikrokontroler Slave terus menerus melakukan pemantauan jalur komunikasi (listening). Saat Slave menerima karakter '1', ia memberikan respon Output dengan memberi tegangan logika HIGH pada pin LED. Hal ini menunjukkan bahwa logika kontrol terpusat di satu titik (pengirim/Master), sedangkan aktuasi didelegasikan secara remote (penerima/Slave) melalui pengkabelan protokol serial.

6. Video Simulasi[Kembali]


7. Download File[Kembali]

Video Simulasi [Download] 

Komentar

Postingan populer dari blog ini

Laporan Akhir Dioda Zener

Laporan Akhir Reverse Bias Dioda

Laporan Akhir Forward Bias Dioda