stspringer

Working_Garage_Lights_Lazer_Reed_PIR

Apr 4th, 2025 (edited)
71
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.09 KB | None | 0 0
  1. /*
  2. 🧠 Quick GPIO reference for ESP8266 NodeMCU / Wemos D1 Mini:
  3. D0 = 16
  4. D1 = 5 RELAY_PIN 5 turns the relay on HIGH when sensors get activated
  5. D2 = 4 LASER_PIN 4 laser beam across the garage door and the man door
  6. D3 = 0
  7. D4 = 2
  8. D5 = 14 PIR_PIN 14 detects body heat
  9. D6 = 12 SWITCH_PIN 12 3-way switch
  10. D7 = 13 REED_PIN 13 detects when the garage door is opened,so the garage lights will turn on for 4.5 minutes
  11. D8 = 15
  12. */
  13.  
  14. #include <ESP8266WiFi.h>
  15. #include <ESP8266WebServer.h>
  16.  
  17. // === Pin Definitions ===
  18. #define RELAY_PIN 5
  19. #define SWITCH_PIN 12
  20. #define REED_PIN 13
  21. #define PIR_PIN 14
  22. #define LASER_PIN 4 // Laser sensor pin (NPN NO, HIGH = triggered)
  23.  
  24. // === WiFi Config ===
  25. const char* ssid = "xxxxxxxxxx";
  26. const char* password = "xxxxxxxx";
  27.  
  28. IPAddress local_IP(xx,xx,xx,xx);
  29. IPAddress gateway(xx,xx,xx,xx);
  30. IPAddress subnet(255, 255, 255, 0);
  31. IPAddress primaryDNS(8, 8, 8, 8);
  32. IPAddress secondaryDNS(8, 8, 4, 4);
  33.  
  34. ESP8266WebServer server(80);
  35.  
  36. // === Timing and States ===
  37. unsigned long previousMillisState = 0;
  38. unsigned long stateMachineDelay = 100;
  39. unsigned long reedActivatedTime = 0;
  40. unsigned long pirActivatedTime = 0;
  41. unsigned long laserActivatedTime = 0;
  42. unsigned long lightOnTime = 0;
  43. unsigned long startupDelay = 5000; // ms
  44. unsigned long bootTime;
  45.  
  46. const unsigned long lightTimeout = 15000;
  47. const unsigned long pirLightTimeout = 15000;
  48. const unsigned long laserLightTimeout = 15000;
  49. const unsigned long reedResetTimeout = 15000;
  50. const unsigned long pirResetTimeout = 15000;
  51. const unsigned long laserResetTimeout = 15000;
  52.  
  53. bool wifiConnected = false;
  54. bool reedTriggered = false;
  55. bool pirTriggered = false;
  56. bool laserTriggered = false;
  57.  
  58. bool ignoreReedSwitch = true; // ⛔ Disable REED initially to prevent Garage lights from comming on at script startup
  59. bool ignorePIR = true; // ⛔ Disable PIR initially to prevent Garage lights from comming on at script startup
  60. bool ignoreLaser = false;
  61.  
  62. bool lightOn = false;
  63. bool sensorsEnabled = true;
  64.  
  65. int switchState = LOW;
  66. int relayState = LOW;
  67. int lightStatus = LOW;
  68.  
  69. enum States {
  70. CHECK_SWITCH,
  71. CHECK_RELAY,
  72. CHECK_LIGHT_STATUS,
  73. CHECK_REED_SENSOR,
  74. CHECK_PIR_SENSOR,
  75. CHECK_WEB_UPDATE
  76. };
  77.  
  78. States currentState = CHECK_SWITCH;
  79.  
  80. void setup() {
  81. Serial.begin(115200);
  82.  
  83. relayState = LOW;
  84. lightOn = false;
  85.  
  86. pinMode(SWITCH_PIN, INPUT);
  87. pinMode(RELAY_PIN, OUTPUT);
  88. pinMode(REED_PIN, INPUT_PULLUP);
  89. pinMode(PIR_PIN, INPUT);
  90. pinMode(LASER_PIN, INPUT);
  91. digitalWrite(RELAY_PIN, LOW); // Turn relay off on startup
  92. Serial.println("🐛 DEBUG: Relay explicitly set LOW at startup");
  93.  
  94. if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
  95. Serial.println("STA Failed to configure");
  96. }
  97. WiFi.begin(ssid, password);
  98. setupWebServer();
  99. }
  100.  
  101. void loop() {
  102. manageWiFiConnection();
  103. if (wifiConnected) server.handleClient();
  104.  
  105. if (millis() - previousMillisState >= stateMachineDelay) {
  106. previousMillisState = millis();
  107. runStateMachine();
  108. }
  109. }
  110.  
  111. void runStateMachine() {
  112. switch (currentState) {
  113. case CHECK_SWITCH:
  114. checkSwitch(); currentState = CHECK_RELAY; break;
  115. case CHECK_RELAY:
  116. checkRelay(); currentState = CHECK_LIGHT_STATUS; break;
  117. case CHECK_LIGHT_STATUS:
  118. checkLightStatus(); currentState = CHECK_REED_SENSOR; break;
  119. case CHECK_REED_SENSOR:
  120. if (sensorsEnabled && millis() - bootTime > startupDelay) checkReedSensor();
  121. currentState = CHECK_PIR_SENSOR;
  122. break;
  123. case CHECK_PIR_SENSOR:
  124. if (sensorsEnabled && millis() - bootTime > startupDelay) {
  125. checkPIRSensor();
  126. checkLaserSensor(); // Laser remains enabled
  127. }
  128. currentState = CHECK_WEB_UPDATE;
  129. break;
  130. case CHECK_WEB_UPDATE:
  131. checkWebUpdate(); currentState = CHECK_SWITCH; break;
  132. default:
  133. currentState = CHECK_SWITCH; break;
  134. }
  135. }
  136.  
  137. // === Input/Output Logic ===
  138.  
  139. void checkSwitch() {
  140. int currentSwitchState = digitalRead(SWITCH_PIN);
  141. if (currentSwitchState != switchState) {
  142. switchState = currentSwitchState;
  143. Serial.print("Switch state: ");
  144. Serial.println(switchState == LOW ? "DOWN" : "UP");
  145. if (switchState == HIGH) turnOnLightManually();
  146. else turnOffLight();
  147. }
  148. }
  149.  
  150. void checkRelay() {
  151. relayState = digitalRead(RELAY_PIN);
  152. Serial.print("Relay state: ");
  153. Serial.println(relayState == LOW ? "OFF" : "ON");
  154. if (relayState == HIGH) Serial.println("🐛 DEBUG: Relay is HIGH in checkRelay()");
  155. }
  156.  
  157. void checkLightStatus() {
  158. lightStatus = (switchState == LOW && relayState == LOW) ? LOW : HIGH;
  159. Serial.print("Light status: ");
  160. Serial.println(lightStatus == HIGH ? "ON" : "OFF");
  161. }
  162.  
  163. void checkReedSensor() {
  164. int reedState = digitalRead(REED_PIN);
  165. Serial.print("🐛 DEBUG: Reed state = ");
  166. Serial.println(reedState == LOW ? "CLOSED (triggered)" : "OPEN (normal)");
  167.  
  168. if (reedState == LOW && !reedTriggered && !ignoreReedSwitch) {
  169. reedTriggered = true;
  170. lightOnTime = reedActivatedTime = millis();
  171. turnOnLightFromSensor();
  172. Serial.println("Reed switch triggered: Relay ON, Light ON");
  173. }
  174.  
  175. if (lightOn && millis() - lightOnTime >= lightTimeout) {
  176. turnOffLight();
  177. Serial.println("Light timeout reached (Reed): Relay OFF, Light OFF");
  178. }
  179.  
  180. if (reedTriggered && millis() - reedActivatedTime >= reedResetTimeout) {
  181. reedTriggered = false;
  182. ignoreReedSwitch = true;
  183. Serial.println("Reed reset timeout reached");
  184. }
  185.  
  186. if (reedState == HIGH) ignoreReedSwitch = false;
  187. }
  188.  
  189. void checkPIRSensor() {
  190. int pirState = digitalRead(PIR_PIN);
  191. Serial.print("🐛 DEBUG: PIR state = ");
  192. Serial.println(pirState == HIGH ? "HIGH (triggered)" : "LOW");
  193.  
  194. if (pirState == HIGH && !pirTriggered && !ignorePIR) {
  195. pirTriggered = true;
  196. pirActivatedTime = lightOnTime = millis();
  197. turnOnLightFromSensor();
  198. Serial.println("PIR triggered: Relay ON, Light ON");
  199. }
  200.  
  201. if (lightOn && millis() - lightOnTime >= pirLightTimeout) {
  202. turnOffLight();
  203. Serial.println("PIR light timeout reached: Relay OFF, Light OFF");
  204. }
  205.  
  206. if (pirTriggered && millis() - pirActivatedTime >= pirResetTimeout) {
  207. pirTriggered = false;
  208. ignorePIR = true;
  209. Serial.println("PIR reset timeout reached");
  210. }
  211.  
  212. if (pirState == LOW) ignorePIR = false;
  213. }
  214.  
  215. void checkLaserSensor() {
  216. int laserState = digitalRead(LASER_PIN);
  217. if (laserState == LOW && !laserTriggered && !ignoreLaser) {
  218. laserTriggered = true;
  219. laserActivatedTime = lightOnTime = millis();
  220. turnOnLightFromSensor();
  221. Serial.println("Laser beam broken: Relay ON, Light ON");
  222. }
  223.  
  224. if (lightOn && millis() - lightOnTime >= laserLightTimeout) {
  225. turnOffLight();
  226. Serial.println("Laser light timeout reached: Relay OFF, Light OFF");
  227. }
  228.  
  229. if (laserTriggered && millis() - laserActivatedTime >= laserResetTimeout) {
  230. laserTriggered = false;
  231. ignoreLaser = true;
  232. Serial.println("Laser reset timeout reached");
  233. }
  234.  
  235. if (laserState == HIGH) ignoreLaser = false;
  236. }
  237.  
  238. void checkWebUpdate() {
  239. Serial.print("Web update: Light ");
  240. Serial.println(lightStatus == HIGH ? "ON" : "OFF");
  241. }
  242.  
  243. // === Control Functions ===
  244.  
  245. void turnOnLightManually() {
  246. if (digitalRead(SWITCH_PIN) == HIGH) {
  247. relayState = LOW;
  248. digitalWrite(RELAY_PIN, relayState);
  249. lightOn = true;
  250. sensorsEnabled = false;
  251. Serial.println("Switch UP: Relay OFF, Light ON, Sensors disabled.");
  252. }
  253. }
  254.  
  255. void turnOffLight() {
  256. if (digitalRead(SWITCH_PIN) == LOW) {
  257. relayState = LOW;
  258. digitalWrite(RELAY_PIN, relayState);
  259. lightOn = false;
  260. sensorsEnabled = true;
  261. Serial.println("Switch DOWN: Relay OFF, Light OFF, Sensors enabled.");
  262. }
  263. }
  264.  
  265. void turnOnLightFromSensor() {
  266. relayState = HIGH;
  267. digitalWrite(RELAY_PIN, relayState);
  268. Serial.println("🐛 DEBUG: Relay set HIGH in turnOnLightFromSensor()");
  269. lightOn = true;
  270. sensorsEnabled = true;
  271. }
  272.  
  273. // === Web Server ===
  274.  
  275. void setupWebServer() {
  276. server.on("/", HTTP_GET, []() { handleRoot(); });
  277.  
  278. server.on("/toggle", HTTP_GET, []() {
  279. relayState = !relayState;
  280. digitalWrite(RELAY_PIN, relayState);
  281. if (relayState == HIGH) {
  282. Serial.println("🐛 DEBUG: Relay toggled to HIGH via web");
  283. turnOnLightManually();
  284. } else {
  285. turnOffLight();
  286. }
  287. handleRoot();
  288. });
  289.  
  290. server.on("/lightstatus", HTTP_GET, []() {
  291. server.send(200, "text/plain", lightStatus == HIGH ? "ON" : "OFF");
  292. });
  293.  
  294. server.begin();
  295. Serial.println("Server started");
  296. }
  297.  
  298. void handleRoot() {
  299. String buttonText = (lightStatus == HIGH) ? "The Garage Lights Are ON" : "The Garage Lights Are OFF";
  300. String buttonColor = (lightStatus == HIGH) ? "green" : "red";
  301.  
  302. String html =
  303. "<html><head><style>"
  304. "body { text-align: center; font-family: Arial; }"
  305. "h1 { font-size: 60px; }"
  306. ".button { width: 600px; height: 250px; font-size: 75px; color: white; }"
  307. ".red { background-color: red; }"
  308. ".green { background-color: green; }"
  309. "</style><script>"
  310. "function toggleLight() { fetch('/toggle').then(() => getLightStatus()); }"
  311. "function getLightStatus() {"
  312. " fetch('/lightstatus').then(r => r.text()).then(state => {"
  313. " const btn = document.getElementById('lightStatus');"
  314. " btn.innerHTML = (state == 'ON') ? 'The Garage Lights Are ON' : 'The Garage Lights Are OFF';"
  315. " btn.className = 'button ' + ((state == 'ON') ? 'green' : 'red');"
  316. " });"
  317. "}"
  318. "setInterval(getLightStatus, 500);"
  319. "</script></head><body onload=\"getLightStatus();\">"
  320. "<h1>John's LED Garage Lights Controller</h1>"
  321. "<button onclick=\"toggleLight();\" class=\"button " + buttonColor + "\" id=\"lightStatus\">" + buttonText + "</button>"
  322. "</body></html>";
  323.  
  324. server.send(200, "text/html", html);
  325. }
  326.  
  327. // === Wi-Fi Manager ===
  328.  
  329. void manageWiFiConnection() {
  330. if (!wifiConnected && WiFi.status() == WL_CONNECTED) {
  331. wifiConnected = true;
  332. bootTime = millis(); // Set bootTime when connected
  333. Serial.println("Connected to Wi-Fi");
  334. Serial.print("IP Address: ");
  335. Serial.println(WiFi.localIP());
  336. }
  337. }
  338.  
  339. ScriptExplanation.ino
  340. /*
  341. I added a lazer Taiss/1 Pair photoelectric Switch 0-20M Through-Beam Reflection Optical Photoelectric Beam Sensor NPN NO to this script that is hooked up to an optocoupler
  342. 12V Optocoupler Isolation Board Optoelectronic Isolator EL817 PC817 Card Rail Bracket Input 3-5 V Optocoupler Isolation Module 1 Channel Opto PNP NPN Signal Converter
  343.  
  344. You hook up the optocoupler by giving 12v power to the two brown wires and the two blue wires goto ground the black wire is the signal wire. So on the two terminal input side of the optocoupler the + top terminal gets 12v source power
  345. the lower terminal negative gets the signal wire from the lazer. On the 3 terminal output side the top + terminal gets 3.3v from the ESP8266 and the lower negative terminal gets a ground from the ESP8266
  346. the middle terminal the ouput terminal connects to the GPIO pin 4
  347.  
  348. When the lazer beam is broken a high 3.3v signal is sent to GPIO pin 4 and the relay goes high which turns on the 120v garage lights 🙂
  349.  
  350.  
  351.  
  352.  
  353. */
Advertisement
Add Comment
Please, Sign In to add comment