#include <Arduino.h>
#include <Preferences.h>
#include <IRremote.h> // Use "IRremote" library, not IRremoteESP8266
// --- Pins ---
#define PIR_PIN 2 // PIR motion sensor
#define LDR_PIN 1 // LDR module A0 → GPIO1 (ADC)
#define IR_LED_PIN 3 // IR LED pin
// --- Config values (persistent) ---
int ldrThreshold;
unsigned long candleTimeout;
unsigned long lastMotionTime = 0;
Preferences prefs;
// --- Replace with your candle remote codes ---
uint32_t CANDLE_ON_CODE = 0xFFA25D;
uint32_t CANDLE_OFF_CODE = 0xFFE21D;
const int IR_BITS = 32; // NEC codes are 32 bits
// --- Load/Save Settings ---
void loadSettings() {
prefs.begin("candle", true);
ldrThreshold = prefs.getInt("ldrThreshold", 2000);
candleTimeout = prefs.getULong("candleTimeout", 10000UL); // 10s default
prefs.end();
}
void saveSettings() {
prefs.begin("candle", false);
prefs.putInt("ldrThreshold", ldrThreshold);
prefs.putULong("candleTimeout", candleTimeout);
prefs.end();
}
// --- Setup ---
void setup() {
Serial.begin(115200);
pinMode(PIR_PIN, INPUT);
// Init IR sender
IrSender.begin(IR_LED_PIN, ENABLE_LED_FEEDBACK);
// Load saved settings
loadSettings();
Serial.println("🌙 IR Night Motion Candle Ready!");
Serial.print("Loaded Timeout: "); Serial.print(candleTimeout / 1000); Serial.println(" sec");
Serial.print("Loaded LDR Threshold: "); Serial.println(ldrThreshold);
Serial.println("Commands:");
Serial.println(" T <seconds> → set candle timeout");
Serial.println(" L <value> → set LDR threshold (0–4095)");
Serial.println(" S → show current settings");
}
// --- Loop ---
void loop() {
// --- Handle Serial Commands ---
if (Serial.available() > 0) {
String input = Serial.readStringUntil('\n');
input.trim();
if (input.length() > 0) {
char cmd = toupper(input.charAt(0));
if (cmd == 'T') {
int val = input.substring(1).toInt();
if (val > 0) {
candleTimeout = val * 1000UL;
saveSettings();
Serial.print("⏱️ Timeout set to: ");
Serial.print(val);
Serial.println(" sec (saved)");
}
} else if (cmd == 'L') {
int val = input.substring(1).toInt();
if (val >= 0 && val <= 4095) {
ldrThreshold = val;
saveSettings();
Serial.print("🌑 LDR threshold set to: ");
Serial.print(val);
Serial.println(" (saved)");
}
} else if (cmd == 'S') {
Serial.println("📋 Current Settings:");
Serial.print(" Timeout: "); Serial.print(candleTimeout / 1000); Serial.println(" sec");
Serial.print(" LDR Threshold: "); Serial.println(ldrThreshold);
} else {
Serial.println("⚠️ Unknown command. Use T <sec>, L <val>, or S");
}
}
}
// --- Sensor Check ---
int ldrValue = analogRead(LDR_PIN);
int motion = digitalRead(PIR_PIN);
Serial.print("LDR: "); Serial.print(ldrValue);
Serial.print(" | Thr: "); Serial.print(ldrThreshold);
Serial.print(" | Motion: "); Serial.println(motion);
// Night + Motion → send ON
if (ldrValue < ldrThreshold && motion == HIGH) {
lastMotionTime = millis();
Serial.println("🌙 Motion + Night → IR Candle ON");
IrSender.sendNEC(CANDLE_ON_CODE, IR_BITS);
}
// Timeout expired → send OFF
if ((millis() - lastMotionTime > candleTimeout) && lastMotionTime > 0) {
Serial.println("⏱️ Timeout expired → IR Candle OFF");
IrSender.sendNEC(CANDLE_OFF_CODE, IR_BITS);
lastMotionTime = 0; // prevent repeat spam
}
delay(200);
}
Loading
xiao-esp32-c3
xiao-esp32-c3