136 lines
3.8 KiB
C
136 lines
3.8 KiB
C
#include <stdio.h>
|
|
#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
|
|
}
|