Освітлення
Початковий
Нічник з датчиком руху: м'яке світло для коридору та сходів
Стрічка WS2812B плавно розгоряється теплим світлом, коли вночі хтось проходить, і сама гасне через хвилину. Фоторезистор не дає нічнику вмикатися вдень.
Сценарій
Ніч, ви йдете на кухню. Щойно ступили в коридор — під плінтусом м'яко розгоряється тепле світло, не засліплюючи. Пройшли — через хвилину воно так само плавно гасне. Вдень нічник не реагує взагалі.
Компоненти
- ESP32 DevKit
- Стрічка WS2812B 5 В, 30–60 світлодіодів
- PIR-датчик HC-SR501 або мініатюрний AM312
- Фоторезистор (LDR) + резистор 10 кОм
- Блок живлення 5 В 2 А, резистор 330 Ом у лінію даних, конденсатор 1000 мкФ
Підключення
| Компонент | ESP32 |
|---|---|
| Стрічка DIN | GPIO 16 через 330 Ом |
| PIR OUT | GPIO 27 |
| Фоторезистор | 3V3 → LDR → GPIO 34 → 10 кОм → GND |
Стрічку й ESP32 живіть від одного 5 В блока, земля спільна (детальніше про живлення стрічок — у проєкті WLED). Оскільки нічник світить на 20 % яскравості, 30 світлодіодів споживатимуть лише ~0.4 А.
Бібліотека
Adafruit NeoPixel.
Код
#include <Adafruit_NeoPixel.h>
const int LED_PIN = 16;
const int NUM_LEDS = 30;
const int PIR_PIN = 27;
const int LDR_PIN = 34;
const int DARK_THRESHOLD = 1200; // 0..4095: менше — темніше
const unsigned long HOLD_MS = 60000; // світити хвилину після останнього руху
const uint8_t MAX_LEVEL = 50; // ~20 % яскравості — не сліпить уночі
Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
bool isOn = false;
int level = 0; // поточна яскравість 0..MAX_LEVEL
unsigned long lastMotion = 0;
unsigned long lastFade = 0;
void render() {
uint8_t l = strip.gamma8(map(level, 0, MAX_LEVEL, 0, 255)) * MAX_LEVEL / 255;
// Теплий білий ~2200 K
strip.fill(strip.Color(l, l * 45 / 100, l * 12 / 100));
strip.show();
}
void setup() {
Serial.begin(115200);
pinMode(PIR_PIN, INPUT);
strip.begin();
strip.clear();
strip.show();
}
void loop() {
bool motion = digitalRead(PIR_PIN) == HIGH;
// Вмикаємося лише в темряві. Якщо вже світимо — LDR бачить наше ж світло,
// тому рух просто продовжує таймер.
if (motion && (isOn || analogRead(LDR_PIN) < DARK_THRESHOLD)) {
isOn = true;
lastMotion = millis();
}
if (isOn && millis() - lastMotion > HOLD_MS) {
isOn = false;
}
// Плавність: розгоряємося за ~1 с, гаснемо за ~3 с
unsigned long step = isOn ? 20 : 60;
if (millis() - lastFade > step) {
lastFade = millis();
int target = isOn ? MAX_LEVEL : 0;
if (level != target) {
level += level < target ? 1 : -1;
render();
}
}
}
Налаштування
- Поріг темряви. Тимчасово додайте в
loop()рядокSerial.println(analogRead(LDR_PIN));і подивіться значення ввечері при вимкненому світлі. ВстановітьDARK_THRESHOLDтрохи вище. - Колір. Для холоднішого світла збільште синю складову:
strip.Color(l, l * 70 / 100, l * 40 / 100). - HC-SR501: поверніть потенціометр часу на мінімум — таймер тепер у коді.
Корисно знати
- Датчик руху краще ставити на рівні 1–1.5 м або на стелі, а стрічку — під плінтусом чи сходинками.
gamma8()робить зміну яскравості рівномірною для ока: без гамма-корекції перші кроки виглядали б «стрибком».- Для сходів: запаліть світлодіоди хвилею знизу вгору або зверху вниз — залежно від того, який із двох PIR-датчиків спрацював першим.
Ідеї
- Поставте стрічку на прошивку WLED і керуйте нею через Home Assistant, використовуючи PIR як тригер автоматизації.
- «Світанок» у спальні: за 20 хв до будильника світло поступово розгоряється.