#include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/timers.h" #include "driver/gpio.h" #include "esp_log.h" #include "led_strip.h" #define LED_STRIP_PIN 2 // WS281x #define PIR_PIN 3 // AM312 or other 3,7V compatible PIR sensors #define LIGHT_SENSOR_PIN 4 // Digitale light sensor #define NUM_LEDS 15 // Number of LEDs on LED strip #define TIMEOUT_MS 10000 // Inactivity timeout (10 seconds) static const char *TAG = "NIGHTLIGHT"; led_strip_handle_t strip; TimerHandle_t off_timer; TaskHandle_t led_task_handle = NULL; // Turn off all LEDs void turn_off_leds() { for (int i = 0; i < NUM_LEDS; i++) { led_strip_set_pixel(strip, i, 0, 0, 0); led_strip_refresh(strip); vTaskDelay(pdMS_TO_TICKS(100)); } ESP_LOGI(TAG, "LEDs turned OFF"); } // Turn on LEDs void turn_on_leds() { for (int i = 0; i < NUM_LEDS; i++) { led_strip_set_pixel(strip, i, 255, 7, 0); // red led_strip_refresh(strip); vTaskDelay(pdMS_TO_TICKS(100)); } ESP_LOGI(TAG, "LEDs turned ON"); } // Timer callback: turns off LED if no motion is detected void off_timer_callback(TimerHandle_t xTimer) { if (gpio_get_level(PIR_PIN) == 1) { ESP_LOGI(TAG, "Motion still detected. Resetting off timer."); xTimerReset(off_timer, 0); } else { // No motion detected, it's safe to turn off LEDs turn_off_leds(); } } // PIR interrupt handler notifies LED task handler void IRAM_ATTR pir_isr_handler(void *arg) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; vTaskNotifyGiveFromISR(led_task_handle, &xHigherPriorityTaskWoken); portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } // LED task void led_task(void *arg) { while (1) { // wait for motion ulTaskNotifyTake(pdTRUE, portMAX_DELAY); ESP_LOGI(TAG, "Motion detected!"); // Reset off timer and turn on LEDs xTimerReset(off_timer, 0); // TODO: check light sensor GPIO value turn_on_leds(); } } void app_main(void) { ESP_LOGI(TAG, "Nightlight initializing..."); // Initialize LED strip led_strip_config_t strip_config = { .strip_gpio_num = LED_STRIP_PIN, .max_leds = NUM_LEDS, .flags.invert_out = false, }; led_strip_rmt_config_t rmt_config = { .clk_src = RMT_CLK_SRC_DEFAULT, .resolution_hz = 10 * 1000 * 1000, // 10MHz .mem_block_symbols = 64, .flags.with_dma = false, }; ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &strip)); ESP_ERROR_CHECK(led_strip_clear(strip)); ESP_LOGI(TAG, "LED strip initialized"); // Configure PIR sensor GPIO gpio_config_t pir_conf = { .intr_type = GPIO_INTR_POSEDGE, .mode = GPIO_MODE_INPUT, .pull_down_en = GPIO_PULLDOWN_ENABLE, .pull_up_en = GPIO_PULLUP_DISABLE, .pin_bit_mask = (1ULL << PIR_PIN) }; ESP_ERROR_CHECK(gpio_config(&pir_conf)); ESP_LOGI(TAG, "GPIO config for PIR sensor initialized"); // Configure light sensor GPIO gpio_config_t light_conf = { .mode = GPIO_MODE_INPUT, .pull_up_en = GPIO_PULLUP_DISABLE, .pull_down_en = GPIO_PULLDOWN_DISABLE, .pin_bit_mask = (1ULL << LIGHT_SENSOR_PIN) }; ESP_ERROR_CHECK(gpio_config(&light_conf)); ESP_LOGI(TAG, "GPIO config for light sensor initialized"); ESP_ERROR_CHECK(gpio_install_isr_service(0)); ESP_ERROR_CHECK(gpio_isr_handler_add(PIR_PIN, pir_isr_handler, NULL)); // Timer setup off_timer = xTimerCreate("off_timer", pdMS_TO_TICKS(TIMEOUT_MS), pdFALSE, NULL, off_timer_callback); // LED task setup xTaskCreate(led_task, "led_task", 2048, NULL, 10, &led_task_handle); ESP_LOGI(TAG, "System initialized."); vTaskSuspend(NULL); // Suspend main task }