Sistem bekerja dengan membagi kondisi menjadi beberapa tingkatan prioritas:
A. Kondisi Tidak Aktif (Terang atau Tidak Ada Gerakan)
Ini merupakan kondisi dasar ketika sistem tidak perlu menyalakan LED.
Kondisi:
Nilai LDR menunjukkan kondisi terang (di bawah ambang batas / LDR_THRESHOLD) ATAU sensor PIR tidak mendeteksi gerakan (GPIO_PIN_RESET).
Hasil:
LED akan tetap mati (LED_OFF) karena tidak ada kebutuhan pencahayaan tambahan.
B. Kondisi Siap (Gelap Tanpa Gerakan)
Pada kondisi ini lingkungan sudah gelap, namun belum ada aktivitas yang terdeteksi oleh sensor PIR.
Kondisi:
Nilai LDR menunjukkan kondisi gelap (di atas LDR_THRESHOLD) DAN PIR tidak mendeteksi gerakan.
Hasil:
LED tetap dalam kondisi mati (LED_OFF) karena sistem hanya akan aktif jika ada gerakan.
C. Kondisi Aktif (Gelap dan Ada Gerakan)
Jika kondisi gelap dan terdapat gerakan, sistem akan mengaktifkan LED dengan intensitas penuh.
Deteksi Gerakan (Terang Penuh)
Jika sensor PIR mendeteksi gerakan saat kondisi gelap, maka waktu terakhir gerakan (last_motion_time) dicatat dan LED akan menyala sangat terang (LED_FULL).
Jeda Waktu (Timeout)
LED akan tetap menyala terang selama 5 detik (MOTION_TIMEOUT) setelah gerakan terakhir terdeteksi.
Kondisi Akhir (LED Mati Kembali)
Jika waktu 5 detik telah terlewati dan tidak ada gerakan tambahan, maka LED akan dimatikan kembali (LED_OFF).
#include "main.h"
#include <stdio.h>
/* Handle */
ADC_HandleTypeDef hadc1;
/* Variable */
uint16_t ldrValue = 0;
uint8_t pirState = 0;
uint32_t lastMotionTime = 0;
uint8_t ledActive = 0;
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();
LED_Off();
while (1)
{
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 100);
ldrValue = HAL_ADC_GetValue(&hadc1);
pirState = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1);
/* === LOGIKA KONDISI 6 === */
if (ledActive == 0 && ldrValue > 1000 && pirState == GPIO_PIN_SET)
{
printf(">>> GELAP + GERAKAN! LED NYALA 5 DETIK\r\n");
LED_On();
lastMotionTime = HAL_GetTick();
ledActive = 1;
}
/* Matikan LED setelah 5 detik */
if (ledActive == 1 && (HAL_GetTick() - lastMotionTime) >= 5000)
{
LED_Off();
ledActive = 0;
printf("LED mati setelah 5 detik\r\n");
}
/* Tampilan status */
static uint32_t lastPrint = 0;
if (HAL_GetTick() - lastPrint > 800)
{
printf("LDR: %4d | PIR: %d | LED: %s\r\n",
ldrValue, pirState, ledActive ? "NYALA" : "MATI");
lastPrint = HAL_GetTick();
}
HAL_Delay(100);
}
}
/* LED */
void LED_On(void) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET); }
void LED_Off(void) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET); }
/* ================== EDIT DI SINI ================== */
#define LDR_GELAP_THRESHOLD 1000 // Turunkan ke 900 kalau terlalu susah nyala
/* System Clock, GPIO, ADC, Interrupt */
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;
RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
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;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
}
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_NVIC_SetPriority(EXTI0_1_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(EXTI0_1_IRQn);
}
void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0};
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.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 1;
HAL_ADC_Init(&hadc1);
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_79CYCLES_5;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
}
void HAL_GPIO_EXTICallback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_1)
{
printf(">>> Push Button PB1 DITEKAN!\r\n");
}
}
void Error_Handler(void)
{
while (1) {}
}
Komentar
Posting Komentar