#include <LedControlMS.h>
#define NBR_MTX 3
// MAX7219 pins: DIN, CLK, CS
LedControl lc = LedControl(27, 26, 25, NBR_MTX);
// ----- Pin definitions -----
const int SENSOR_BUTTON_PIN = 33; // shared analog pin for LDR + button
const int RELAY_PIN = 32; // relay control pin
// ----- Thresholds -----
// 根據剛才的監測數據先設為 500。
// 若用手電筒照射感測器時數值大於 500,代表有光;若電路特性相反,請修改下方邏輯。
const int BRIGHT_THRESHOLD = 300;
// ----- Relay state -----
bool relayState = false;
// ----- Button control -----
bool lastPressed = false;
unsigned long lastPressTime = 0;
const unsigned long debounceDelay = 250;
// ----- 亮度記憶 -----
bool isTooBright = false;
void setup() {
Serial.begin(115200);
Serial.println("System Start");
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, LOW); // relay OFF initially
// LED matrix setup
for (int i = 0; i < NBR_MTX; i++) {
lc.shutdown(i, false);
lc.setIntensity(i, 8);
lc.clearDisplay(i);
}
showOFF();
}
void loop() {
int sensorValue = analogRead(SENSOR_BUTTON_PIN);
// 考量 ESP32 類比讀取的微小雜訊,設定 <= 5 確保按鈕能穩定觸發
bool pressed = (sensorValue <= 300);
// 關鍵:只有在按鈕「沒有被按下」時,才讀取並更新環境亮度。
if (!pressed) {
isTooBright = (sensorValue > BRIGHT_THRESHOLD);
// 💡 注意:如果你的電路是「越亮數值越小」,請把上面的 > 改成 <
}
// 每 500 毫秒印一次資訊,避免 Serial 狂洗畫面導致看不清
static unsigned long lastPrintTime = 0;
if (millis() - lastPrintTime > 500) {
Serial.print("Analog value: ");
Serial.print(sensorValue);
Serial.print(" | Bright: ");
Serial.print(isTooBright ? "YES" : "NO");
Serial.print(" | Button: ");
Serial.print(pressed ? "PRESSED" : "RELEASED");
Serial.print(" | Relay: ");
Serial.println(relayState ? "ON" : "OFF");
lastPrintTime = millis();
}
// 防彈跳與狀態切換邏輯
if (pressed && !lastPressed && (millis() - lastPressTime > debounceDelay)) {
lastPressTime = millis();
// 依據題目:有接收燈光時 (isTooBright 為 true) 按按鈕才會切換
if (isTooBright) {
relayState = !relayState;
updateRelayAndDisplay();
Serial.print("Relay changed to: ");
Serial.println(relayState ? "ON" : "OFF");
} else {
Serial.println("Not bright enough, button disabled.");
}
}
lastPressed = pressed;
delay(20); // 稍微縮短延遲,讓按鈕反應更靈敏
}
void updateRelayAndDisplay() {
if (relayState) {
digitalWrite(RELAY_PIN, HIGH);
showON();
} else {
digitalWrite(RELAY_PIN, LOW);
showOFF();
}
}
void drawSmallPattern(const char* pattern[8]) {
lc.clearAll();
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 24; col++) {
if (pattern[row][col] == '1') {
int matrix = col / 8;
int localCol = col % 8;
lc.setLed(matrix, row, localCol, true);
}
}
}
}
void showON() {
const char* onPattern[8] = {
"000000011100010001000000",
"000000100010011001000000",
"000000100010010101000000",
"000000100010010011000000",
"000000100010010001000000",
"000000100010010001000000",
"000000011100010001000000",
"000000000000000000000000"
};
drawSmallPattern(onPattern);
}
void showOFF() {
const char* offPattern[8] = {
"000011100010001111110000",
"000100010101001000010000",
"000100010101001000010000",
"000100010111001111100000",
"000100010101001000010000",
"000100010101001000010000",
"000011100010001000010000",
"000000000000000000000000"
};
drawSmallPattern(offPattern);
}
#include <LedControlMS.h>
#define NBR_MTX 3
// MAX7219 pins: DIN, CLK, CS
LedControl lc = LedControl(27, 26, 25, NBR_MTX);
// ----- Pin definitions -----
const int SENSOR_BUTTON_PIN = 33; // shared analog pin for LDR + button
const int RELAY_PIN = 32; // relay control pin
// ----- Thresholds -----
const int BUTTON_THRESHOLD = 4000; // above this = button pressed
const int LIGHT_MIN = 350; // light ON lower bound
const int LIGHT_MAX = 550; // light ON upper bound
// ----- Relay state -----
bool relayState = false;
// ----- Button control -----
bool lastPressed = false;
unsigned long lastPressTime = 0;
const unsigned long debounceDelay = 250;
// ----- Remember last light state -----
bool lightDetected = false;
void setup() {
Serial.begin(115200);
Serial.println("System Start");
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, LOW); // relay OFF initially
// LED matrix setup
for (int i = 0; i < NBR_MTX; i++) {
lc.shutdown(i, false);
lc.setIntensity(i, 8);
lc.clearDisplay(i);
}
showOFF();
}
void loop() {
int sensorValue = analogRead(SENSOR_BUTTON_PIN);
// Button pressed when analog value is above 4000
bool pressed = (sensorValue > BUTTON_THRESHOLD);
// Only update light state when button is NOT pressed
// because button press changes the analog reading
if (!pressed) {
lightDetected = (sensorValue >= LIGHT_MIN && sensorValue <= LIGHT_MAX);
}
// Print status every 500 ms
static unsigned long lastPrintTime = 0;
if (millis() - lastPrintTime > 500) {
Serial.print("Analog value: ");
Serial.print(sensorValue);
Serial.print(" | Light: ");
Serial.print(lightDetected ? "ON" : "OFF");
Serial.print(" | Button: ");
Serial.print(pressed ? "PRESSED" : "RELEASED");
Serial.print(" | Relay: ");
Serial.println(relayState ? "ON" : "OFF");
lastPrintTime = millis();
}
// Debounced button press detection
if (pressed && !lastPressed && (millis() - lastPressTime > debounceDelay)) {
lastPressTime = millis();
// Only allow toggle if light is detected
if (lightDetected) {
relayState = !relayState;
updateRelayAndDisplay();
Serial.print("Relay changed to: ");
Serial.println(relayState ? "ON" : "OFF");
} else {
Serial.println("Light is OFF, button disabled.");
}
}
lastPressed = pressed;
delay(20);
}
void updateRelayAndDisplay() {
if (relayState) {
digitalWrite(RELAY_PIN, HIGH);
showON();
} else {
digitalWrite(RELAY_PIN, LOW);
showOFF();
}
}
void drawSmallPattern(const char* pattern[8]) {
lc.clearAll();
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 24; col++) {
if (pattern[row][col] == '1') {
int matrix = col / 8;
int localCol = col % 8;
lc.setLed(matrix, row, localCol, true);
}
}
}
}
void showON() {
const char* onPattern[8] = {
"000000000110001010000000",
"000000001001001110000000",
"000000001001001010000000",
"000000001001001010000000",
"000000001001001010000000",
"000000000110001010000000",
"000000000000000000000000",
"000000000000000000000000"
};
drawSmallPattern(onPattern);
}
void showOFF() {
const char* offPattern[8] = {
"000000000110001111000000",
"000000001001001100000000",
"000000001001001110000000",
"000000001001001100000000",
"000000001001001100000000",
"000000000110001100000000",
"000000000000000000000000",
"000000000000000000000000"
};
drawSmallPattern(offPattern);
}
#include <LedControlMS.h>
#define NBR_MTX 3
// MAX7219 pins: DIN, CLK, CS
LedControl lc = LedControl(27, 26, 25, NBR_MTX);
// ----- Pin definitions -----
const int SENSOR_BUTTON_PIN = 33; // shared analog pin for LDR + button
const int RELAY_PIN = 32; // relay control pin
const int Light_Pin = 35;
// ----- Thresholds -----
const int BUTTON_THRESHOLD = 4000; // 數值大於 4000 代表按鈕被按下
const int LIGHT_THRESHOLD = 300; // 數值大於 300 代表有光
// ----- Relay state -----
bool relayState = false;
// ----- Button control -----
bool lastPressed = false;
unsigned long lastPressTime = 0;
const unsigned long debounceDelay = 250;
// ----- Remember last light state -----
bool lightDetected = false;
void setup() {
Serial.begin(115200);
Serial.println("System Start");
pinMode(RELAY_PIN, OUTPUT);
pinMode(Light_Pin, INPUT);
digitalWrite(RELAY_PIN, LOW); // relay OFF initially
// LED matrix setup
for (int i = 0; i < NBR_MTX; i++) {
lc.shutdown(i, false);
lc.setIntensity(i, 8); // 亮度設定 (0~15)
lc.clearDisplay(i);
}
showOFF(); // 初始顯示 OFF
}
void loop() {
int sensorValue = analogRead(SENSOR_BUTTON_PIN);
int lightValue = analogRead(Light_Pin);
// 判斷是否按下按鈕 (數值大於 4000)
bool pressed = (sensorValue > BUTTON_THRESHOLD);
// 只有在「沒有按下按鈕」的時候,才去更新光線狀態
if (!pressed) {
lightDetected = (sensorValue >= LIGHT_THRESHOLD);
}
// 每 500ms 印出一次狀態方便觀察
static unsigned long lastPrintTime = 0;
if (millis() - lastPrintTime > 500) {
Serial.print("Analog value: ");
Serial.print(sensorValue);
Serial.print(" | Light: ");
Serial.print(lightDetected ? "ON" : "OFF");
Serial.print(" | Button: ");
Serial.print(pressed ? "PRESSED" : "RELEASED");
Serial.print(" | Relay: ");
Serial.println(relayState ? "ON" : "OFF");
Serial.print(" | Light: " );
Serial.print(lightValue);
lastPrintTime = millis();
}
// 處理按鈕防彈跳與觸發邏輯
if (pressed && !lastPressed && (millis() - lastPressTime > debounceDelay)) {
lastPressTime = millis();
// 只有在「有光」的狀態下,按鈕才會有反應
if (lightDetected) {
relayState = !relayState;
updateRelayAndDisplay();
Serial.print("Relay changed to: ");
Serial.println(relayState ? "ON" : "OFF");
} else {
Serial.println("Light is OFF, button disabled.");
}
}
lastPressed = pressed;
delay(20);
}
void updateRelayAndDisplay() {
if (relayState == true) {
digitalWrite(RELAY_PIN, HIGH);
showOFF();
} else {
digitalWrite(RELAY_PIN, LOW);
showON();
}
}
// ===== LED 顯示功能 =====
void showON() {
// 先清空 3 塊面板
for (int i = 0; i < NBR_MTX; i++) {
lc.clearDisplay(i);
}
// 利用函式庫內建的字庫顯示字元
// 參數: (第幾個矩陣, 字元在字庫中的索引)
lc.displayChar(0, lc.getCharArrayPosition('O'));
lc.displayChar(1, lc.getCharArrayPosition('N'));
lc.displayChar(2, lc.getCharArrayPosition(' ')); // 第三塊留白
}
void showOFF() {
// 先清空 3 塊面板
for (int i = 0; i < NBR_MTX; i++) {
lc.clearDisplay(i);
}
lc.displayChar(1, lc.getCharArrayPosition('O'));
lc.displayChar(0, lc.getCharArrayPosition('F'));
lc.displayChar(2, lc.getCharArrayPosition('F'));
}