#include <Adafruit_NeoPixel.h>
// --- НАСТРОЙКИ ПИНОВ ---
#define PIR_PIN 4 // Пин D2 (GPIO4) - датчик движения AM312
#define LED_DATA 2 // Пин D4 (GPIO2) - линия данных WS2812B
#define POWER_GATE 14 // Пин D5 (GPIO14) - затвор P-MOSFET (AO3401)
// --- НАСТРОЙКИ ВЫВЕСКИ ---
#define NUM_LEDS 8 // Укажи точное количество твоих светодиодов
#define MAX_BRIGHT 160 // Максимальная яркость (0-255, 160 - оптимально для батареи)
const unsigned long ON_TIME = 10000; // Время свечения после движения (в миллисекундах: 10 сек)
// Базовый цвет неона (R, G, B):
// (255, 60, 0) - Классический неоновый оранжево-красный
// (0, 220, 255) - Бирюзовый / Киберпанк циан
// (255, 0, 120) - Розовый неон
const uint8_t NEON_R = 255;
const uint8_t NEON_G = 60;
const uint8_t NEON_B = 0;
Adafruit_NeoPixel strip(NUM_LEDS, LED_DATA, NEO_GRB + NEO_KHZ800);
unsigned long lastMotionTime = 0;
bool isLit = false;
// Включение/отключение силового ключа AO3401
void setPowerGate(bool enable) {
if (enable) {
digitalWrite(POWER_GATE, LOW); // Открываем P-канальный MOSFET
delay(15); // Пауза для стабилизации конденсаторов
strip.begin();
} else {
strip.clear();
strip.show();
digitalWrite(POWER_GATE, HIGH); // Закрываем MOSFET (лента полностью обесточена)
}
}
// Заливка всех диодов цветом с заданной яркостью (0-255)
void setAllColor(uint8_t brightness) {
uint8_t r = (NEON_R * brightness) / 255;
uint8_t g = (NEON_G * brightness) / 255;
uint8_t b = (NEON_B * brightness) / 255;
for (int i = 0; i < NUM_LEDS; i++) {
strip.setPixelColor(i, strip.Color(r, g, b));
}
strip.show();
}
// Эффект розжига старой неоновой трубки
void neonIgnition() {
// Серия из 4-6 хаотичных вспышек
int flickers = random(4, 7);
for (int i = 0; i < flickers; i++) {
setAllColor(random(40, MAX_BRIGHT));
delay(random(20, 70));
setAllColor(0);
delay(random(30, 90));
}
// Финальный легкий сбой перед полным зажиганием
setAllColor(MAX_BRIGHT / 3);
delay(50);
setAllColor(0);
delay(40);
// Выход на рабочую яркость
setAllColor(MAX_BRIGHT);
}
void setup() {
pinMode(PIR_PIN, INPUT);
pinMode(POWER_GATE, OUTPUT);
digitalWrite(POWER_GATE, HIGH); // Изначально лента обесточена
randomSeed(analogRead(A0)); // Инициализация генератора случайных вспышек
}
void loop() {
int motion = digitalRead(PIR_PIN);
// Если зафиксировано движение
if (motion == HIGH) {
lastMotionTime = millis();
// Если лампа спала — будим и разжигаем неон
if (!isLit) {
setPowerGate(true);
neonIgnition();
isLit = true;
}
}
// Пока вывеска активна
if (isLit) {
// Живое микромерцание (лампа не просто статична, а едва заметно колеблется)
if (random(0, 100) < 5) {
uint8_t glitchBright = MAX_BRIGHT - random(10, 35);
setAllColor(glitchBright);
delay(random(15, 35));
setAllColor(MAX_BRIGHT);
}
// Проверка таймера отключения
if (millis() - lastMotionTime > ON_TIME) {
// Плавное угасание
for (int b = MAX_BRIGHT; b >= 0; b -= 10) {
setAllColor(b);
delay(15);
}
setPowerGate(false);
isLit = false;
}
}
delay(20);
}