PIR 모션 센서 연동 인터랙티브 LED 매트릭스 도어 디스플레이 - 아두이노 홀리데이 인사
부품 및 소모품
| 아두이노 우노 (Arduino UNO) |
1개 |
| 아두이노 나노 R3 |
1개 |
| PIR 모션 센서 (일반) |
1개 |
| 릴레이 (일반) |
1개 |
| 점퍼 와이어 (일반) |
1세트 |
| PC 파워서플라이 전원 코드 |
1개 |
| RGB LED 스트립 |
1개 |
| 8x8 네오픽셀 패널 |
3개 |
필수 도구 및 기계
프로젝트 소개
이 프로젝트는 3개의 WS2812B 8x8 RGB LED 매트릭스와 PIR 모션 센서를 결합해 방문객이 문 가까이 다가오면 "Happy Holidays & Happy New Year!" 텍스트로 인사하고, 아무도 감지되지 않을 때는 모니터 스크린세이버처럼 다양한 이펙트를 표시합니다.
아두이노 우노로 제어하고 5V 30A 파워서플라이로 전원 공급합니다.
3가지 코드 세트를 결합(킷배시)했습니다:
- FastLED 라이브러리 DemoReel100 예제의 대기/대기모드 이펙트
- PIR 모션 센서 코드
- 네오픽셀 설정 코드 (정확히는 잘 기억 안 남, 거의 한 달 전에 코드들을 합쳤음)
또 다른 PIR 모션 센서를 5V 릴레이에 연결해 12V RGB LED 스트링을 연장 코드로 제어하고 아두이노 나노로 제어합니다.
LED 스트링과 홀리데이 조명(연장 코드 연결)은 1번 PIR 센서가 움직임을 감지하면 켜집니다. 계단 1단 근처 천장에 위치.
몇 계단 올라가면 2번 PIR 센서가 우노에 알리고 누군가가 문 가까이 왔을 때 매트릭스에 텍스트 표시.
코드
아두이노 홀리데이
#include
FASTLED_USING_NAMESPACE
#include
#include
#include
#ifndef PSTR
#define PSTR // 아두이노 듀 호환
#endif
#define PIN 6
#define DATA_PIN 6
#define LED_TYPE WS2811
#define COLOR_ORDER GRB
#define NUM_LEDS 192
CRGB leds[NUM_LEDS];
const uint8_t kMatrixWidth = 24;
const uint8_t kMatrixHeight = 8;
const bool kMatrixSerpentineLayout = true;
#define NUM_LEDS (kMatrixWidth * kMatrixHeight)
#define MAX_DIMENSION ((kMatrixWidth > kMatrixHeight) ? kMatrixWidth : kMatrixHeight)
#define BRIGHTNESS 50
#define FRAMES_PER_SECOND 120
static uint16_t x;
static uint16_t y;
static uint16_t z;
Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(24, 8, PIN,
NEO_MATRIX_TOP + NEO_MATRIX_RIGHT + NEO_MATRIX_COLUMNS + NEO_MATRIX_PROGRESSIVE,
NEO_GRB + NEO_KHZ800);
const uint16_t colors[] = {
matrix.Color(255, 0, 0),
matrix.Color(0, 255, 0),
matrix.Color(0, 0, 255),
matrix.Color(0, 255, 255),
matrix.Color(255, 0, 255),
matrix.Color(255, 255, 0),
matrix.Color(255, 255, 255)
};
uint16_t speed = 20;
uint16_t scale = 30;
uint8_t noise[MAX_DIMENSION][MAX_DIMENSION];
CRGBPalette16 currentPalette(PartyColors_p);
uint8_t colorLoop = 1;
int pirSensorPin = 5; // PIR 센서 입력 핀
int pirState = true; // 움직임 미감지 상태로 시작
int val = 0; // 핀 상태 읽기 변수
int minimummSecsLowForInactive = 5000; // 센서가 이 시간 이상 LOW면 비활성 상태 가정
long unsigned int timeLow;
boolean takeLowTime;
int calibrationTime = 30; // 센서 캘리브레이션 시간 (데이터시트 기준 10-60초)
void setup() {
delay(3000); // 복구용 3초 지연
FastLED.addLeds(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.setBrightness(BRIGHTNESS);
matrix.setTextWrap(false);
matrix.setBrightness(40);
matrix.setTextColor(colors[0]);
pinMode(pirSensorPin, INPUT);
LEDS.addLeds(leds, NUM_LEDS);
x = random16();
y = random16();
z = random16();
}
int a = matrix.width();
int pass = 0;
typedef void (*SimplePatternList[])();
SimplePatternList gPatterns = { rainbow, rainbowWithGlitter, confetti, sinelon, juggle, bpm, cylon };
uint8_t gCurrentPatternNumber = 0;
uint8_t gHue = 0;
void fadeall() {
for (int i = 0; i < NUM_LEDS; i++) {
leds[i].nscale8(250);
}
}
void loop() {
val = digitalRead(pirSensorPin);
if (val == HIGH) { // 움직임 감지
matrix.fillScreen(1);
matrix.setCursor(a, 0);
matrix.print(F("Happy Holidays & Happy New Year!"));
if (--a < -200) {
a = matrix.width();
if (++pass >= 6) pass = 0;
matrix.setTextColor(colors[pass]);
}
matrix.show();
delay(100);
if (pirState) {
pirState = false;
}
takeLowTime = true;
} else { // 움직임 없음 - 스크린세이버 이펙트
gPatterns[gCurrentPatternNumber]();
FastLED.show();
FastLED.delay(1000 / FRAMES_PER_SECOND);
EVERY_N_MILLISECONDS(20) {
gHue++;
}
EVERY_N_SECONDS(10) {
nextPattern();
}
}
}
#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
void nextPattern() {
gCurrentPatternNumber = (gCurrentPatternNumber + 1) % ARRAY_SIZE(gPatterns);
}
void rainbow() {
fill_rainbow(leds, NUM_LEDS, gHue, 7);
}
void rainbowWithGlitter() {
rainbow();
addGlitter(80);
}
void addGlitter(fract8 chanceOfGlitter) {
if (random8() < chanceOfGlitter) {
leds[random16(NUM_LEDS)] += CRGB::White;
}
}
void confetti() {
fadeToBlackBy(leds, NUM_LEDS, 10);
int pos = random16(NUM_LEDS);
leds[pos] += CHSV(gHue + random8(64), 200, 255);
}
void sinelon() {
fadeToBlackBy(leds, NUM_LEDS, 20);
int pos = beatsin16(13, 0, NUM_LEDS - 1);
leds[pos] += CHSV(gHue, 255, 192);
}
void bpm() {
uint8_t BeatsPerMinute = 62;
CRGBPalette16 palette = PartyColors_p;
uint8_t beat = beatsin8(BeatsPerMinute, 64, 255);
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = ColorFromPalette(palette, gHue + (i * 2), beat - gHue + (i * 10));
}
}
void juggle() {
fadeToBlackBy(leds, NUM_LEDS, 20);
byte dothue = 0;
for (int i = 0; i < 8; i++) {
leds[beatsin16(i + 7, 0, NUM_LEDS - 1)] |= CHSV(dothue, 200, 255);
dothue += 32;
}
}
void cylon() {
static uint8_t hue = 0;
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CHSV(hue++, 255, 255);
FastLED.show();
fadeall();
delay(10);
}
for (int i = (NUM_LEDS) - 1; i >= 0; i--) {
leds[i] = CHSV(hue++, 255, 255);
FastLED.show();
fadeall();
delay(10);
}
}
회로도
회로도 이미지 참조