TP 1



1. Prosedur [Kembali]

  1. Buka platform simulasi Wokwi lalu rangkai komponen (STM32 Nucleo, Sensor Infrared, LED RGB, Buzzer, dan Switch) sesuai dengan gambar skema yang ada di modul.

  2. Buka tab editor kode pada Wokwi lalu lakukan konfigurasi pin pada file main.h dan main.c untuk menentukan pin ADC input, Interrupt dan GPIO output.

  3. Masukkan program sistem jemuran otomatis ke dalam editor kode Wokwi.

  4. Jalankan simulasi dengan menekan tombol "Start Simulation" (ikon Play) pada Wokwi untuk melakukan compile dan menjalankan program.

  5. Simulasikan rangkaian dengan mengubah status intensitas cahaya dari LDR sensor dan tekan button sebagai interrupt untuk masuk ke mode manual

2. Hardware [Kembali]

  • Hardware
1. STM32 NUCLEO-G474RE


2. LDR Sensor

3. LED

5. Buzzer

6. Resistor 

  • Diagram Blok

3. Rangkaian Simulasi dan Prinsip Kerja [Kembali]


  • Sensor LDR mendeteksi perubahan intensitas cahaya lingkungan, sehingga menghasilkan nilai fluktuasi tegangan analog secara terus-menerus.

  • Sinyal analog tersebut diteruskan ke mikrokontroler STM32 sebagai input pembacaan ADC pada pin PA0, sedangkan sinyal dari Push Button diteruskan sebagai input Interrupt (pembacaan digital) pada pin PB1.

  • Berdasarkan nilai pembacaan sensor dan status mode, mikrokontroler akan menghasilkan sinyal keluaran PWM pada pin PA6 untuk mengontrol pergerakan Motor Servo.

  • Pada Push Button, sistem akan memicu interrupt setiap menerima logika 0 (falling edge). Ketika tombol ditekan, sistem beralih ke mode manual di mana posisi jemuran (servo) akan berganti masuk atau keluar secara paksa dengan mengabaikan pembacaan sensor LDR.

  • Pada sensor LDR (saat mode otomatis), jika nilai pembacaan ADC mendeteksi lingkungan terang (di atas threshold), output PWM akan mendorong servo ke posisi keluar (menjemur). Sebaliknya, jika mendeteksi lingkungan gelap atau mendung, output PWM akan menarik servo ke posisi masuk (menghindari hujan).

4. Flowchart [Kembali]

  • Flowchart
  • Listing Program
  • main.h :
#ifndef __MAIN_H
#define __MAIN_H
 
#include "stm32c0xx_hal.h"
 
// ================= PIN DEFINITIONS =================
#define LDR_PIN     GPIO_PIN_0
#define LDR_PORT    GPIOA
 
#define BUTTON_PIN  GPIO_PIN_1
#define BUTTON_PORT GPIOB
 
#define SERVO_PIN   GPIO_PIN_6
#define SERVO_PORT  GPIOA
 
// ================= FUNCTION PROTOTYPES =================
void SystemClock_Config(void);
void MX_GPIO_Init(void);
void MX_ADC1_Init(void);
void MX_TIM3_Init(void);
 
#endif /* __MAIN_H */

  • main.c :
#include "main.h"
 
// ================= HANDLE =================
ADC_HandleTypeDef hadc1;
TIM_HandleTypeDef htim3;
 
// ================= VARIABLE =================
uint8_t manual_mode = 0;
uint8_t posisi_servo = 0;
uint8_t last_button = 1;
 
// ================= THRESHOLD =================
// Sesuaikan nilai ini saat simulasi jika batas terang/gelap kurang pas
#define LDR_THRESHOLD 2000
 
// ================= 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;
  HAL_RCC_OscConfig(&RCC_OscInitStruct);
 
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
 
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
}
 
// ================= GPIO =================
void MX_GPIO_Init(void)
{
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
 
  GPIO_InitTypeDef GPIO_InitStruct = {0};
 
  // LDR PA0
  GPIO_InitStruct.Pin = GPIO_PIN_0;
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
  // BUTTON PB1 (Gunakan Pull-Up internal)
  GPIO_InitStruct.Pin = GPIO_PIN_1;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);  
 
  // SERVO PA6
  GPIO_InitStruct.Pin = GPIO_PIN_6;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Alternate = GPIO_AF1_TIM3;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
 
// ================= ADC =================
void MX_ADC1_Init(void)
{
  __HAL_RCC_ADC_CLK_ENABLE();
 
  hadc1.Instance = ADC1;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
 
  HAL_ADC_Init(&hadc1);
}
 
// ================= PWM (FIX SERVO) =================
void MX_TIM3_Init(void)
{
  __HAL_RCC_TIM3_CLK_ENABLE();
 
  htim3.Instance = TIM3;
 
  // 1us tick (asumsi clock 48MHz pada STM32C0)
  htim3.Init.Prescaler = 48 - 1;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = 20000 - 1; // 20ms = 50Hz (standar sinyal servo)
 
  HAL_TIM_PWM_Init(&htim3);
 
  TIM_OC_InitTypeDef sConfigOC = {0};
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 1500; // Posisi tengah awal (90 derajat)
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
 
  HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1);
}
 
// ================= SERVO CONTROL =================
void set_servo(uint8_t state)
{
  if (state == 0)
  {
    // Posisi Masuk Atap (Gelap/Hujan)
    __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 1000);
  }
  else
  {  
    // Posisi Keluar Atap (Terang/Jemur)
    __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 2000);
  }
}
 
// ================= ADC READ =================
uint16_t read_LDR(void)
{
  ADC_ChannelConfTypeDef sConfig = {0};
 
  sConfig.Channel = ADC_CHANNEL_0;
  sConfig.Rank = ADC_REGULAR_RANK_1;
 
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);
 
  HAL_ADC_Start(&hadc1);
  HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
 
  return HAL_ADC_GetValue(&hadc1);
}
 
// ================= MAIN =================
int main(void)
{
  HAL_Init();
  SystemClock_Config();
 
  MX_GPIO_Init();
  MX_ADC1_Init();
  MX_TIM3_Init();
 
  HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
 
  while (1)
  {
    // ===== BUTTON TOGGLE (MANUAL MODE) =====
    uint8_t button = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1);
 
    if (last_button == 1 && button == 0)
    {
      manual_mode = !manual_mode;
      posisi_servo = !posisi_servo;
      set_servo(posisi_servo);
      HAL_Delay(50); // Debounce tombol
    }
 
    last_button = button;
 
    // ===== MODE OTOMATIS =====
    if (!manual_mode)
    {
      uint16_t ldr = read_LDR();  
     
      // LOGIKA UTAMA: Cek intensitas cahaya
      if (ldr >= LDR_THRESHOLD)
      {
        posisi_servo = 1; // Terang -> Servo Keluar (Jemur)
      }
      else
      {
        posisi_servo = 0; // Gelap/Mendung -> Servo Masuk (Amankan)
      }
 
      set_servo(posisi_servo);
    }
 
    HAL_Delay(100);
  }
}

5. Video Demo [Kembali]




6. Kondisi [Kembali]

Buatlah rangkaian dengan kondisi ketika sensor cahaya (LDR) mendeteksi cahaya sangat rendah, maka jemuran akan segera masuk ke dalam atap. Jika cahaya sedang, jemuran berada pada posisi setengah terbuka, dan jika terang, jemuran berada di luar atap.


7. Video Simulasi [Kembali]



8. Download File [Kembali]

Rangkaian Simulasi [Klik]

Video Simulasi [Klik]

Komentar

Postingan populer dari blog ini