[menuju akhir]


Langkah-langkah percobaan :

1. Buka web WOKWI.COM dan cari STM 32 NUCLEO C031C6

2. Rangkai komponen sesuai dengan modul percobaan

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. Jalankan


2. Hardware dan Diagram Blok [Kembali]
a. Hardware
1. STM32 NUCLEO-G474RE

STM32 NUCLEO-G474RE adalah papan pengembangan (development board) berbasis mikrokontroler STM32 yang dirancang oleh STMicroelectronics untuk memudahkan proses pembelajaran, prototyping, dan pengembangan sistem embedded.

Secara spesifik, board ini menggunakan mikrokontroler STM32G474RE, yang termasuk dalam keluarga STM32 seri G4. Mikrokontroler ini berbasis inti ARM Cortex-M4 dengan kemampuan pemrosesan yang cukup tinggi serta dilengkapi dengan fitur DSP (Digital Signal Processing) dan FPU (Floating Point Unit), sehingga sangat cocok untuk aplikasi yang membutuhkan perhitungan matematis cepat seperti kontrol motor, sistem tenaga, dan pengolahan sinyal.


2. LDR Sensor



Light Dependent Resistor (LDR) adalah sensor cahaya yang nilai resistansinya berubah sesuai intensitas cahaya yang diterimanya.

3. PIR Sensor

Passive Infrared Sensor (PIR) adalah sensor gerak yang digunakan untuk mendeteksi keberadaan manusia atau objek hidup berdasarkan radiasi inframerah (panas tubuh).


4. Resistor 

Resistor adalah komponen elektronik pasif yang berfungsi untuk membatasi arus listrik dalam suatu rangkaian. Resistor bekerja berdasarkan hukum Ohm, yang menyatakan bahwa tegangan (V) = arus (I) × resistansi (R). Resistor memiliki satuan Ohm (Ω) dan digunakan dalam berbagai aplikasi seperti pembagian tegangan, kontrol arus, dan proteksi rangkaian elektronik.

5. LED

LED adalah dioda semikonduktor yang dapat memancarkan cahaya ketika dialiri arus listrik. LED digunakan dalam berbagai aplikasi seperti indikator elektronik, pencahayaan, dan display. LED hanya bekerja pada arah bias maju dan memiliki berbagai warna yang ditentukan oleh material semikonduktornya.

6. Push Button

Push button adalah komponen input berupa saklar mekanis yang bekerja ketika ditekan (push) oleh pengguna untuk menghubungkan atau memutuskan aliran listrik dalam suatu rangkaian.

Secara prinsip kerja, push button memiliki dua kondisi utama, yaitu Normally Open (NO) dan Normally Closed (NC). Pada tipe Normally Open, dalam kondisi tidak ditekan rangkaian berada dalam keadaan terbuka (tidak mengalirkan arus), dan ketika tombol ditekan, rangkaian menjadi tertutup sehingga arus dapat mengalir. Sebaliknya, pada tipe Normally Closed, rangkaian dalam kondisi normal tertutup dan akan terbuka saat tombol ditekan.


b. Diagram Blok




3. Rangkaian Simulasi dan Prinsip Kerja [Kembali]



Prinsip Kerja :

Rangkaian ini terdiri dari STM32 Nucleo C031C6 sebagai otak utama yang terhubung ke empat komponen yaitu sensor PIR di bagian atas, modul LDR di sebelah kiri, LED merah di sebelah kanan atas, dan push button hijau di sebelah kanan bawah. Semua komponen ini bekerja bersama untuk membentuk sistem lampu jalan otomatis.

Sistem pertama kali membaca nilai cahaya dari sensor LDR melalui pin PA0 menggunakan ADC 12-bit. Nilai pembacaan berkisar antara 0 hingga 4095. Jika nilai tersebut masih di bawah 2000 yang berarti lingkungan masih terang seperti siang hari, mikrokontroler langsung mematikan LED tanpa mempedulikan kondisi sensor lainnya. Ini mensimulasikan kondisi siang hari di mana lampu jalan tidak perlu menyala.

Ketika LDR membaca kondisi gelap dengan nilai ADC di atas 2000, sistem beralih memperhatikan sensor PIR yang terhubung ke pin PA1. Jika PIR mendeteksi adanya gerakan manusia di sekitar rangkaian, sinyal output PIR menjadi HIGH dan mikrokontroler langsung menyalakan LED melalui sinyal PWM pada pin PA6 dengan kecerahan penuh. Sistem sekaligus mencatat waktu deteksi tersebut.

Ketika PIR berhenti mendeteksi gerakan, LED tidak langsung mati melainkan menunggu selama 5 detik. Jika dalam waktu 5 detik tidak ada gerakan baru, LED akan mati secara otomatis. Inilah inti dari Percobaan 4 pada rangkaian ini yaitu lampu menyala saat ada orang lewat dan kembali mati sendiri setelah orang tersebut pergi dan 5 detik berlalu.

Push button yang terhubung ke pin PB1 berfungsi sebagai tombol darurat. Saat ditekan, sistem langsung mematikan LED dan mengabaikan seluruh pembacaan sensor hingga tombol ditekan kembali untuk kembali ke mode normal.

4. Flowchart dan Listing Program [Kembali]
a. Flowchart



b. Listing Program

  •  main.c
#include "main.h"

/* ================= HANDLE ================= */
ADC_HandleTypeDef hadc1;
TIM_HandleTypeDef htim3;

/* ================= VARIABLE ================= */
volatile uint8_t emergency_mode = 0;
uint32_t last_motion_time       = 0;
uint8_t  pir_ever_detected      = 0;   // flag: apakah PIR pernah deteksi gerakan
uint8_t  last_button_state      = 1;

/* =========================================
   SYSTEM CLOCK CONFIG
   STM32C031C6 → HSI 48 MHz internal
   ========================================= */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /* Aktifkan HSI 48 MHz */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState       = RCC_HSI_ON;
  RCC_OscInitStruct.HSIDiv         = RCC_HSI_DIV1;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    while (1);
  }

  /* Set SYSCLK = HSI = 48 MHz */
  RCC_ClkInitStruct.ClockType      = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK |
                                     RCC_CLOCKTYPE_PCLK1;
  RCC_ClkInitStruct.SYSCLKSource   = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider  = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  {
    while (1);
  }
}

/* =========================================
   GPIO INIT
   ========================================= */
void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* Aktifkan clock GPIO */
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /* PA0 → LDR (ADC input, dikonfigurasi di MX_ADC1_Init) */
  GPIO_InitStruct.Pin  = GPIO_PIN_0;
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* PA1 → PIR Sensor (digital input) */
  GPIO_InitStruct.Pin  = GPIO_PIN_1;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* PA6 → LED PWM (TIM3_CH1, Alternate Function) */
  GPIO_InitStruct.Pin       = GPIO_PIN_6;
  GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull      = GPIO_NOPULL;
  GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF1_TIM3;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* PB1 → Push Button (input pull-up, polling) */
  GPIO_InitStruct.Pin  = GPIO_PIN_1;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

/* =========================================
   ADC INIT → PA0 (LDR)
   ========================================= */
void MX_ADC1_Init(void)
{
  __HAL_RCC_ADC_CLK_ENABLE();

  hadc1.Instance                   = ADC1;
  hadc1.Init.ClockPrescaler        = ADC_CLOCK_SYNC_PCLK_DIV2;
  hadc1.Init.Resolution            = ADC_RESOLUTION_12B;
  hadc1.Init.DataAlign             = ADC_DATAALIGN_RIGHT;
  hadc1.Init.ScanConvMode          = ADC_SCAN_DISABLE;
  hadc1.Init.EOCSelection          = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait      = DISABLE;
  hadc1.Init.LowPowerAutoPowerOff  = DISABLE;
  hadc1.Init.ContinuousConvMode    = DISABLE;
  hadc1.Init.NbrOfConversion       = 1;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv      = ADC_SOFTWARE_START;
  hadc1.Init.ExternalTrigConvEdge  = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.Overrun               = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.SamplingTimeCommon1   = ADC_SAMPLETIME_39CYCLES_5;

  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    while (1);
  }

  /* Kalibrasi ADC */
  HAL_ADCEx_Calibration_Start(&hadc1);

  /* Konfigurasi channel PA0 */
  ADC_ChannelConfTypeDef sConfig = {0};
  sConfig.Channel      = ADC_CHANNEL_0;
  sConfig.Rank         = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    while (1);
  }
}

/* =========================================
   PWM INIT → TIM3_CH1 (PA6)
   Frekuensi PWM = 48MHz / (Prescaler+1) / (Period+1)
                 = 48MHz / 48 / 1000 = 1000 Hz
   ========================================= */
void MX_TIM3_Init(void)
{
  __HAL_RCC_TIM3_CLK_ENABLE();

  htim3.Instance               = TIM3;
  htim3.Init.Prescaler         = 47;       // 48MHz / 48 = 1MHz timer clock
  htim3.Init.Period            = 999;      // 1MHz / 1000 = 1kHz PWM
  htim3.Init.CounterMode       = TIM_COUNTERMODE_UP;
  htim3.Init.ClockDivision     = TIM_CLOCKDIVISION_DIV1;
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;

  if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
  {
    while (1);
  }

  TIM_OC_InitTypeDef sConfigOC = {0};
  sConfigOC.OCMode       = TIM_OCMODE_PWM1;
  sConfigOC.Pulse        = 0;              // Mulai dengan LED mati
  sConfigOC.OCPolarity   = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode   = TIM_OCFAST_DISABLE;

  if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    while (1);
  }
}

/* =========================================
   HELPER FUNCTIONS
   ========================================= */

/* Baca nilai LDR dari ADC */
uint16_t read_LDR(void)
{
  HAL_ADC_Start(&hadc1);
  HAL_ADC_PollForConversion(&hadc1, 100);
  uint16_t val = (uint16_t)HAL_ADC_GetValue(&hadc1);
  HAL_ADC_Stop(&hadc1);
  return val;
}

/* Set brightness LED via PWM */
void set_LED(uint16_t value)
{
  __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, value);
}

/* =========================================
   MAIN
   ========================================= */
int main(void)
{
  HAL_Init();
  SystemClock_Config();

  MX_GPIO_Init();
  MX_ADC1_Init();
  MX_TIM3_Init();

  /* Start PWM */
  HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);

  /* Pastikan LED mati di awal */
  set_LED(LED_OFF);

  while (1)
  {
    /* ===== POLLING PUSH BUTTON (EMERGENCY MODE) ===== */
    uint8_t current_button = HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN);

    if (last_button_state == 1 && current_button == 0)
    {
      emergency_mode = !emergency_mode;
      HAL_Delay(50); // debounce
    }
    last_button_state = current_button;

    /* ===== MODE DARURAT: LED MATI ===== */
    if (emergency_mode)
    {
      set_LED(LED_OFF);
      HAL_Delay(100);
      continue;
    }

    /* ===== BACA SENSOR ===== */
    uint16_t ldr_value = read_LDR();
    uint8_t  pir_state = HAL_GPIO_ReadPin(PIR_PORT, PIR_PIN);

    /* ===== KONDISI SIANG (LDR terang) ===== */
    if (ldr_value < LDR_THRESHOLD)
    {
      /* Siang hari → LED selalu mati, reset flag PIR */
      set_LED(LED_OFF);
      pir_ever_detected = 0;
      last_motion_time  = 0;
    }
    else
    {
      /* ===== KONDISI MALAM (LDR gelap) ===== */

      /* Jika PIR mendeteksi gerakan */
      if (pir_state == GPIO_PIN_SET)
      {
        last_motion_time  = HAL_GetTick();
        pir_ever_detected = 1;
        set_LED(LED_FULL); // LED NYALA PENUH
      }
      else
      {
        /*
         * PIR tidak mendeteksi gerakan.
         * Cek apakah sebelumnya pernah deteksi dan timeout sudah lewat.
         *
         * KONDISI PERCOBAAN 4:
         * LDR gelap + PIR sebelumnya deteksi → timeout → LED MATI
         */
        if (pir_ever_detected &&
            (HAL_GetTick() - last_motion_time >= MOTION_TIMEOUT))
        {
          set_LED(LED_OFF); // Kembali MATI setelah timeout
        }
        else if (!pir_ever_detected)
        {
          /* PIR belum pernah deteksi sama sekali sejak malam → LED MATI */
          set_LED(LED_OFF);
        }
        /* Jika belum timeout, LED tetap NYALA (tidak ada else set_LED disini) */
      }
    }

    HAL_Delay(100);
  }
}

/* =========================================
   ERROR HANDLER
   ========================================= */
void Error_Handler(void)
{
  __disable_irq();
  while (1) { }
}
  • main.h
#ifndef __MAIN_H
#define __MAIN_H

#ifdef __cplusplus
extern "C" {
#endif

#include "stm32c0xx_hal.h"

/* ================= PIN DEFINITIONS ================= */

// LDR (ADC) → PA0
#define LDR_PORT        GPIOA
#define LDR_PIN         GPIO_PIN_0

// PIR Sensor → PA1
#define PIR_PORT        GPIOA
#define PIR_PIN         GPIO_PIN_1

// Push Button (Polling + Interrupt) → PB1
#define BUTTON_PORT     GPIOB
#define BUTTON_PIN      GPIO_PIN_1

// LED PWM → PA6 (TIM3_CH1)
#define LED_PORT        GPIOA
#define LED_PIN         GPIO_PIN_6

/* ================= PARAMETER ================= */
#define LDR_THRESHOLD   2000    // Nilai ADC batas gelap/terang (0-4095 untuk 12-bit)
#define MOTION_TIMEOUT  5000    // Timeout PIR dalam milidetik (5 detik)

#define LED_OFF         0
#define LED_FULL        999     // Duty cycle maksimum (sesuai Period = 999)

/* ================= FUNCTION PROTOTYPES ================= */
void SystemClock_Config(void);
void MX_GPIO_Init(void);
void MX_ADC1_Init(void);
void MX_TIM3_Init(void);
uint16_t read_LDR(void);
void set_LED(uint16_t value);

#ifdef __cplusplus
}
#endif

#endif /* __MAIN_H */

5. Video Demo [Kembali]


6. Kondisi [Kembali]

Buatlah rangkaian seperti pada gambar percobaan 4 dengan keadaan LDR mendeteksi gelap, PIR sebelumnya mendeteksi gerakan lalu tidak lagi mendeteksi, maka lampu kembali kondisi mati.

7. Video Simulasi [Kembali]




8. Download File [Kembali]
1. Download File Rangkaian Klik Disini
2. Download Video Simulasi 

Komentar

Postingan populer dari blog ini