Sesuai dengan permintaan perubahan logika Anda sebelumnya, program memeriksa ambang batas cahaya.
Jika kondisi di atas tidak terpenuhi (misalnya saat gelap atau saat ada gerakan), sistem akan mengatur kecerahan LED secara cerdas:
#include "main.h" // Library utama STM32 HAL
// HANDLE
ADC_HandleTypeDef hadc1; // Handle ADC1 untuk membaca LDR
TIM_HandleTypeDef htim3; // Handle Timer 3 untuk PWM LED
// VARIABLE
volatile uint8_t emergency_mode = 0; // Mode darurat (0=normal, 1=darurat)
uint32_t last_motion_time = 0; // Waktu terakhir terdeteksi gerakan
// fallback tombol
uint8_t last_button_state = 1; // Status tombol sebelumnya (untuk edge detection)
// PARAMETER
#define LDR_THRESHOLD 2000 // Batas terang/gelap
#define MOTION_TIMEOUT 5000 // Delay 5 detik setelah gerakan
#define LED_OFF 0 // LED mati
#define LED_DIM 100 // LED redup
#define LED_FULL 1000 // LED terang penuh
// ================= CLOCK =================
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0}; // Struktur konfigurasi oscillator
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; // Struktur konfigurasi clock
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; // Pakai clock internal HSI
RCC_OscInitStruct.HSIState = RCC_HSI_ON; // Aktifkan HSI
HAL_RCC_OscConfig(&RCC_OscInitStruct); // Terapkan konfigurasi
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK; // Jenis clock
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; // Sumber clock dari HSI
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // Divider = 1
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0); // Terapkan
}
// ================= GPIO =================
void MX_GPIO_Init(void)
{
__HAL_RCC_GPIOA_CLK_ENABLE(); // Aktifkan clock GPIOA
__HAL_RCC_GPIOB_CLK_ENABLE(); // Aktifkan clock GPIOB
GPIO_InitTypeDef GPIO_InitStruct = {0}; // Struktur konfigurasi GPIO
// PIR → PA1
GPIO_InitStruct.Pin = GPIO_PIN_1; // Pin PA1
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; // Mode input
GPIO_InitStruct.Pull = GPIO_NOPULL; // Tanpa pull-up/down
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // Terapkan
// BUTTON → PB1 (PULL-UP + INTERRUPT)
GPIO_InitStruct.Pin = GPIO_PIN_1; // Pin PB1
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; // Interrupt saat ditekan (falling edge)
GPIO_InitStruct.Pull = GPIO_PULLUP; // Pull-up internal
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); // Terapkan
// LED PWM → PA6
GPIO_InitStruct.Pin = GPIO_PIN_6; // Pin PA6
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // Alternate function (PWM)
GPIO_InitStruct.Pull = GPIO_NOPULL; // Tanpa pull
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; // Kecepatan rendah
GPIO_InitStruct.Alternate = GPIO_AF1_TIM3; // Hubungkan ke TIM3
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // Terapkan
// IRQ untuk PB1 (EXTI0_1)
HAL_NVIC_SetPriority(EXTI0_1_IRQn, 0, 0); // Prioritas interrupt
HAL_NVIC_EnableIRQ(EXTI0_1_IRQn); // Aktifkan interrupt
}
// ================= ADC =================
void MX_ADC1_Init(void)
{
__HAL_RCC_ADC_CLK_ENABLE(); // Aktifkan clock ADC
hadc1.Instance = ADC1; // Gunakan ADC1
hadc1.Init.Resolution = ADC_RESOLUTION_12B; // Resolusi 12-bit
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; // Align kanan
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; // Tidak scan
hadc1.Init.ContinuousConvMode = DISABLE; // Tidak continuous
HAL_ADC_Init(&hadc1); // Inisialisasi ADC
ADC_ChannelConfTypeDef sConfig = {0}; // Struktur channel
sConfig.Channel = ADC_CHANNEL_0; // Channel 0 (LDR)
sConfig.Rank = ADC_REGULAR_RANK_1; // Rank 1
HAL_ADC_ConfigChannel(&hadc1, &sConfig); // Terapkan channel
}
// ================= PWM =================
void MX_TIM3_Init(void)
{
__HAL_RCC_TIM3_CLK_ENABLE(); // Aktifkan clock TIM3
htim3.Instance = TIM3; // Gunakan Timer 3
htim3.Init.Prescaler = 64; // Prescaler
htim3.Init.Period = 1000; // Period PWM (0–1000)
htim3.Init.CounterMode = TIM_COUNTERMODE_UP; // Counter naik
HAL_TIM_PWM_Init(&htim3); // Inisialisasi PWM
TIM_OC_InitTypeDef sConfigOC = {0}; // Struktur konfigurasi output compare
sConfigOC.OCMode = TIM_OCMODE_PWM1; // Mode PWM1
sConfigOC.Pulse = 0; // Duty awal 0
HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1); // Channel 1
}
// ================= INTERRUPT =================
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_1) // Jika interrupt dari pin 1 (PB1 tombol)
{
emergency_mode = !emergency_mode; // Toggle mode darurat
}
}
// ================= HELPER =================
uint16_t read_LDR(void)
{
HAL_ADC_Start(&hadc1); // Mulai ADC
HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); // Tunggu selesai
return HAL_ADC_GetValue(&hadc1); // Return nilai ADC
}
void set_LED(uint16_t value)
{
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, value); // Set duty PWM LED
}
// ================= MAIN =================
int main(void)
{
HAL_Init(); // Inisialisasi HAL
SystemClock_Config(); // Konfigurasi clock
MX_GPIO_Init(); // Inisialisasi GPIO
MX_ADC1_Init(); // Inisialisasi ADC
MX_TIM3_Init(); // Inisialisasi Timer
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); // Mulai PWM
while (1)
{
// ===== FALLBACK BUTTON =====
uint8_t current_button = HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN); // Baca tombol
if (last_button_state == 1 && current_button == 0) // Deteksi tekan
{
emergency_mode = !emergency_mode; // Toggle mode darurat
HAL_Delay(50); // Debounce sederhana
}
last_button_state = current_button; // Simpan state terakhir
// ===== MODE DARURAT =====
if (emergency_mode)
{
set_LED(LED_OFF); // Matikan LED
continue; // Skip logika lain
}
uint16_t ldr = read_LDR(); // Baca LDR
uint8_t pir = HAL_GPIO_ReadPin(PIR_PORT, PIR_PIN); // Baca PIR
// ===== LOGIKA UTAMA =====
// LDR terang DAN PIR tidak ada gerakan → MATI
if (ldr < LDR_THRESHOLD && pir == GPIO_PIN_RESET)
{
set_LED(LED_OFF); // Lampu mati
}
else
{
// Jika ada gerakan
if (pir == GPIO_PIN_SET)
{
last_motion_time = HAL_GetTick(); // Simpan waktu terakhir gerakan
}
// Jika masih dalam waktu delay
if (HAL_GetTick() - last_motion_time < MOTION_TIMEOUT)
{
set_LED(LED_FULL); // Lampu terang
}
else
{
set_LED(LED_DIM); // Lampu redup
}
}
HAL_Delay(100); // Delay 100 ms
}
}
Komentar
Posting Komentar