stspringer

Garage Lights Update

Sep 17th, 2024 (edited)
157
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.50 KB | Software | 0 0
  1. Garage Lights script written by John James Guarnieri 09_16_2024
  2. “NC” Normally Closed
  3. “NO” Normally Open
  4.  
  5. Hello Everyone,
  6.  
  7. I would like to share my script to help others with a real-world garage light controller using a web server with an ESP8266, to have your smartphone turn on and off your garage lights.
  8.  
  9. I have 120v LED lights hanging in my garage and I set up a wall-mounted 3-way switch with a relay and an ESP8266. I can turn the garage lights on or off with my Android phone via the web server and they can be turned on/off manually by the 3-way switch
  10.  
  11. The problem was if my phone stated the garage lights were off and someone used the 3-way switch and turned the garage lights on, how do I update my phone to state that the garage lights are on?
  12.  
  13. Well, I tested an automotive 12v bulb, which draws over 2a on a high beam, a bench power supply source voltage, 12v a 3v relay that handles 12v, and a 3.3v optocoupler that handles 12v.
  14.  
  15. I will eventually use a 120v optocoupler
  16.  
  17. Now the 3-way switch doesn’t have an on/off position like a regular wall light switch, it has two traveler wires, red and black, the red traveler wire is connected to the relay “NC” terminal, and the black traveler wire is connected to the “NO” terminal
  18.  
  19. I am using a Leviton 120v E5603-SW Decora Edge 15 Amp 3-Way Rocker Switch for my testing on 12v
  20.  
  21. When the switch is oriented correctly, “the top “UP” position of the switch would be where the text on the switch is NOT upside down.
  22.  
  23. THE CONFUSION STARTS HERE!
  24.  
  25. SWITCH “DOWN” “NC” HAS ZERO V, “NO” HAS 12V,
  26.  
  27. SWITCH “UP” “NC” HAS 12V, “NO” HAS ZERO V
  28.  
  29.  
  30. When the switch is “DOWN” the “NO” traveler wire going to the relay “NO” terminal has 12v power.
  31.  
  32. When the switch is “UP” the “NC” traveler wire going to the relay “NC” terminal has 12v power.
  33.  
  34. What you have to understand is when the switch is “DOWN” the relay is “OFF” and the “NC” terminal on the relay is “CLOSED” but the “NC” terminal has ZERO V so the light is “OFF” the “NO” terminal of the relay has 12v and is “OPEN”
  35.  
  36. What you have to understand is when the the switch is “UP” and the relay is “OFF” the “NC” terminal on the relay is “CLOSED” and the “NC” terminal has 12 V so the light is “ON”, the “NO” terminal of the relay has ZERO v and is “OPEN”
  37.  
  38.  
  39. How do I determine if my 3-way switch is up or down?
  40.  
  41. You use a single-channel optocoupler. When the switch is “UP” channel 1 will read a “HIGH” voltage of 2.72v, when the switch is “DOWN” channel 1 will read a “LOW” voltage, close to ZERO v
  42.  
  43. How do I hook up my optocoupler?
  44.  
  45. You run a jumper wire from the “NO” terminal of the relay to the + Positive of the channel 1 input, then you run a ground from the 12v source ground to the – Negative of channel 1 input.
  46.  
  47. The output of the optocoupler channel 1 connects to GPIO 12 of the ESP8266
  48.  
  49. When GPIO 12 is “LOW” ZERO V you know the switch is “DOWN”, when GPIO 12 is “HIGH” you know the switch is “UP”
  50.  
  51. WHEN THE RELAY IS ON!
  52.  
  53. REMEMBER: SWITCH “DOWN” “NC” HAS ZERO V, “NO” HAS 12V,
  54.  
  55. When the relay is “ON” and the switch is “DOWN” the light is “ON”, “NO” has 12v and is “CLOSED”, “NC” has ZERO V and is “OPEN”
  56.  
  57.  
  58. REMEMBER: SWITCH “UP” “NC” HAS 12V, “NO” HAS ZERO V
  59.  
  60. When the relay is “ON” and the switch is “UP” the light is “OFF”, “NO” has ZERO V and is “CLOSED”, “NC” has 12v and is “OPEN”
  61.  
  62.  
  63. For the 120v Garage lights, I will switch out the 12v optocoupler for a 120v optocoupler
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71. Garage_Lights_My_Working_Corrected_Logic MAIN TAB
  72.  
  73. #include <ESP8266WiFi.h>
  74. #include <ESP8266WebServer.h> // Include for the web server
  75.  
  76. // Declare global variables and constants
  77. #define SWITCH_PIN 12 // Pin connected to the optocoupler "determines if 3-way switch is up or down"
  78. #define RELAY_PIN 5 // Pin connected to the relay control
  79.  
  80. // Network credentials and static IP configuration
  81. const char* ssid = "XXXXXXXXXX";
  82. const char* password = "XXXXXXXXXX";
  83.  
  84. IPAddress local_IP(xxx, xxx, xxx, xxx);
  85. IPAddress gateway(xxx, xxx, xxx, x);
  86. IPAddress subnet(255, 255, 255, 0);
  87. IPAddress primaryDNS(8, 8, 8, 8);
  88. IPAddress secondaryDNS(8, 8, 4, 4);
  89.  
  90. ESP8266WebServer server(80); // Declare the web server object
  91.  
  92. // Timing variables for millis() based delay replacement
  93. unsigned long previousMillisState = 0;
  94. unsigned long stateMachineDelay = 100; // Delay for state machine transitions
  95. unsigned long previousMillisWiFi = 0; // Track previous millis for Wi-Fi
  96. unsigned long previousMillisWiFiDelay = 500; // Delay for Wi-Fi connection status messages
  97.  
  98. bool wifiConnected = false; // Track Wi-Fi connection state
  99.  
  100. void setup() {
  101. pinMode(SWITCH_PIN, INPUT);
  102. pinMode(RELAY_PIN, OUTPUT);
  103. Serial.begin(115200);
  104.  
  105. // Configure static IP
  106. if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
  107. Serial.println("STA Failed to configure");
  108. }
  109.  
  110. // Start WiFi connection attempt
  111. WiFi.begin(ssid, password);
  112.  
  113. // Setup web server routes
  114. setupWebServer();
  115. }
  116.  
  117. void loop() {
  118. // Handle Wi-Fi connection management
  119. manageWiFiConnection();
  120.  
  121. // Continue only if Wi-Fi is connected
  122. if (wifiConnected) {
  123. server.handleClient(); // Handle incoming client requests
  124. }
  125.  
  126. unsigned long currentMillis = millis();
  127.  
  128. // Check if it's time to transition the state machine
  129. if (currentMillis - previousMillisState >= stateMachineDelay) {
  130. previousMillisState = currentMillis;
  131.  
  132. // State machine to handle various checks
  133. runStateMachine();
  134. }
  135. }
  136.  
  137.  
  138.  
  139.  
  140. // RelayControl.ino TAB
  141.  
  142. int switchState = LOW; // Variable to store switch state "LOW" means the switch is "DOWN", "HIGH" means the switch is "UP"
  143. int relayState = LOW; // Relay starts OFF
  144. int lightStatus = LOW; // Light starts OFF
  145.  
  146.  
  147. enum States {
  148. CHECK_SWITCH,
  149. CHECK_RELAY,
  150. CHECK_LIGHT_STATUS,
  151. CHECK_WEB_UPDATE
  152. };
  153.  
  154. States currentState = CHECK_SWITCH;
  155.  
  156. void runStateMachine() {
  157. // State machine to handle various checks
  158. switch (currentState) {
  159. case CHECK_SWITCH:
  160. checkSwitch();
  161. currentState = CHECK_RELAY; // Move to the next state
  162. break;
  163.  
  164. case CHECK_RELAY:
  165. checkRelay();
  166. currentState = CHECK_LIGHT_STATUS; // Move to the next state
  167. break;
  168.  
  169. case CHECK_LIGHT_STATUS:
  170. checkLightStatus();
  171. currentState = CHECK_WEB_UPDATE; // Move to the next state
  172. break;
  173.  
  174. case CHECK_WEB_UPDATE:
  175. checkWebUpdate();
  176. currentState = CHECK_SWITCH; // Return to the first state to repeat the cycle
  177. break;
  178.  
  179. default:
  180. currentState = CHECK_SWITCH; // Default to the first state if something goes wrong
  181. break;
  182. }
  183. }
  184.  
  185. void checkSwitch() {
  186. int currentSwitchState = digitalRead(SWITCH_PIN); // Read current switch state
  187. if (currentSwitchState != switchState) {
  188. switchState = currentSwitchState; // Update switch state
  189. Serial.print("Switch state: ");
  190. Serial.println(switchState == LOW ? "DOWN" : "UP");
  191. }
  192. }
  193.  
  194. void checkRelay() {
  195. relayState = digitalRead(RELAY_PIN); // Read relay state
  196. Serial.print("Relay state: ");
  197. Serial.println(relayState == LOW ? "OFF" : "ON");
  198. }
  199.  
  200. void checkLightStatus() {
  201. // If switch is UP and relay is OFF, turn the light ON
  202. if (switchState == LOW && relayState == LOW) {
  203. lightStatus = LOW; // Light OFF
  204. Serial.println("Light status: OFF");
  205. }
  206. // If switch is DOWN, turn the light ON
  207. else if (switchState == HIGH && relayState == LOW) {
  208. lightStatus = HIGH; // Light ON
  209. Serial.println("Light status: ON");
  210. }
  211. else if (switchState == LOW && relayState == HIGH) {
  212. lightStatus = HIGH; // Light ON
  213. Serial.println("Light status: OFF");
  214. }// WebServerHandler.ino
  215.  
  216. void setupWebServer() {
  217. server.on("/", HTTP_GET, []() {
  218. handleRoot(); // Update and render the web page
  219. });
  220.  
  221. server.on("/toggle", HTTP_POST, []() {
  222. relayState = !relayState; // Toggle the relay state
  223. digitalWrite(RELAY_PIN, relayState); // Update the relay
  224. handleRoot(); // Re-render the page
  225. });
  226.  
  227. server.on("/lightstatus", handleLightStatus);
  228.  
  229. server.begin();
  230. Serial.println("Server started");
  231. }
  232.  
  233. void handleRoot() {
  234. String buttonText;
  235. String buttonColor;
  236.  
  237. if (lightStatus == LOW) {
  238. buttonText = "The Garage Lights Are OFF";
  239. buttonColor = "red";
  240. } else {
  241. buttonText = "The Garage Lights Are ON";
  242. buttonColor = "green";
  243. }
  244.  
  245. String html = "<html>\
  246. <head>\
  247. <title>John's LED Garage Lights Controller</title>\
  248. <style>\
  249. body { text-align: center; font-family: Arial; }\
  250. .button { width: 275px; height: 75px; font-size: 30px; color: white; }\
  251. .red { background-color: red; }\
  252. .green { background-color: green; }\
  253. </style>\
  254. <script>\
  255. function getLightStatus() {\
  256. var xhr = new XMLHttpRequest();\
  257. xhr.onreadystatechange = function() {\
  258. if (xhr.readyState == 4 && xhr.status == 200) {\
  259. var lightState = xhr.responseText;\
  260. var button = document.getElementById('lightStatus');\
  261. if (lightState == 'ON') {\
  262. button.innerHTML = 'The Garage Lights Are ON';\
  263. button.className = 'button green';\
  264. } else {\
  265. button.innerHTML = 'The Garage Lights Are OFF';\
  266. button.className = 'button red';\
  267. }\
  268. }\
  269. };\
  270. xhr.open('GET', '/lightstatus', true);\
  271. xhr.send();\
  272. }\
  273. setInterval(getLightStatus, 500); // Refresh every 500ms for quicker updates\
  274. </script>\
  275. </head>\
  276. <body>\
  277. <h1>John's LED Garage Lights Controller</h1>\
  278. <form action=\"/toggle\" method=\"POST\">\
  279. <button class=\"button " + buttonColor + "\" id=\"lightStatus\" type=\"submit\">" + buttonText + "</button>\
  280. </form>\
  281. </body>\
  282. </html>";
  283.  
  284. server.send(200, "text/html", html);
  285. }
  286.  
  287. void handleLightStatus() {
  288. if (lightStatus == LOW) {
  289. server.send(200, "text/plain", "OFF");
  290. } else {
  291. server.send(200, "text/plain", "ON");
  292. }
  293. }
  294. else if (switchState == HIGH && relayState == HIGH) {
  295. lightStatus = LOW; // Light ON
  296. Serial.println("Light status: OFF");
  297. }
  298. }
  299.  
  300. void checkWebUpdate() {
  301. if (lightStatus == HIGH) {
  302. Serial.println("Web update: Light ON");
  303. } else {
  304. Serial.println("Web update: Light OFF");
  305. }
  306. }
  307.  
  308.  
  309.  
  310.  
  311.  
  312.  
  313.  
  314. // WebServerHandler.ino TAB
  315.  
  316. void setupWebServer() {
  317. server.on("/", HTTP_GET, []() {
  318. handleRoot(); // Update and render the web page
  319. });
  320.  
  321. server.on("/toggle", HTTP_POST, []() {
  322. relayState = !relayState; // Toggle the relay state
  323. digitalWrite(RELAY_PIN, relayState); // Update the relay
  324. handleRoot(); // Re-render the page
  325. });
  326.  
  327. server.on("/lightstatus", handleLightStatus);
  328.  
  329. server.begin();
  330. Serial.println("Server started");
  331. }
  332.  
  333. void handleRoot() {
  334. String buttonText;
  335. String buttonColor;
  336.  
  337. if (lightStatus == LOW) {
  338. buttonText = "The Garage Lights Are OFF";
  339. buttonColor = "red";
  340. } else {
  341. buttonText = "The Garage Lights Are ON";
  342. buttonColor = "green";
  343. }
  344.  
  345. String html = "<html>\
  346. <head>\
  347. <title>John's LED Garage Lights Controller</title>\
  348. <style>\
  349. body { text-align: center; font-family: Arial; }\
  350. .button { width: 275px; height: 75px; font-size: 30px; color: white; }\
  351. .red { background-color: red; }\
  352. .green { background-color: green; }\
  353. </style>\
  354. <script>\
  355. function getLightStatus() {\
  356. var xhr = new XMLHttpRequest();\
  357. xhr.onreadystatechange = function() {\
  358. if (xhr.readyState == 4 && xhr.status == 200) {\
  359. var lightState = xhr.responseText;\
  360. var button = document.getElementById('lightStatus');\
  361. if (lightState == 'ON') {\
  362. button.innerHTML = 'The Garage Lights Are ON';\
  363. button.className = 'button green';\
  364. } else {\
  365. button.innerHTML = 'The Garage Lights Are OFF';\
  366. button.className = 'button red';\
  367. }\
  368. }\
  369. };\
  370. xhr.open('GET', '/lightstatus', true);\
  371. xhr.send();\
  372. }\
  373. setInterval(getLightStatus, 500); // Refresh every 500ms for quicker updates\
  374. </script>\
  375. </head>\
  376. <body>\
  377. <h1>John's LED Garage Lights Controller</h1>\
  378. <form action=\"/toggle\" method=\"POST\">\
  379. <button class=\"button " + buttonColor + "\" id=\"lightStatus\" type=\"submit\">" + buttonText + "</button>\
  380. </form>\
  381. </body>\
  382. </html>";
  383.  
  384. server.send(200, "text/html", html);
  385. }
  386.  
  387. void handleLightStatus() {
  388. if (lightStatus == LOW) {
  389. server.send(200, "text/plain", "OFF");
  390. } else {
  391. server.send(200, "text/plain", "ON");
  392. }
  393. }
  394.  
  395. // WebServerHandler.ino
  396.  
  397. void setupWebServer() {
  398. server.on("/", HTTP_GET, []() {
  399. handleRoot(); // Update and render the web page
  400. });
  401.  
  402. server.on("/toggle", HTTP_POST, []() {
  403. relayState = !relayState; // Toggle the relay state
  404. digitalWrite(RELAY_PIN, relayState); // Update the relay
  405. handleRoot(); // Re-render the page
  406. });
  407.  
  408. server.on("/lightstatus", handleLightStatus);
  409.  
  410. server.begin();
  411. Serial.println("Server started");
  412. }
  413.  
  414. void handleRoot() {
  415. String buttonText;
  416. String buttonColor;
  417.  
  418. if (lightStatus == LOW) {
  419. buttonText = "The Garage Lights Are OFF";
  420. buttonColor = "red";
  421. } else {
  422. buttonText = "The Garage Lights Are ON";
  423. buttonColor = "green";
  424. }
  425.  
  426. String html = "<html>\
  427. <head>\
  428. <title>John's LED Garage Lights Controller</title>\
  429. <style>\
  430. body { text-align: center; font-family: Arial; }\
  431. .button { width: 275px; height: 75px; font-size: 30px; color: white; }\
  432. .red { background-color: red; }\
  433. .green { background-color: green; }\
  434. </style>\
  435. <script>\
  436. function getLightStatus() {\
  437. var xhr = new XMLHttpRequest();\
  438. xhr.onreadystatechange = function() {\
  439. if (xhr.readyState == 4 && xhr.status == 200) {\
  440. var lightState = xhr.responseText;\
  441. var button = document.getElementById('lightStatus');\
  442. if (lightState == 'ON') {\
  443. button.innerHTML = 'The Garage Lights Are ON';\
  444. button.className = 'button green';\
  445. } else {\
  446. button.innerHTML = 'The Garage Lights Are OFF';\
  447. button.className = 'button red';\
  448. }\
  449. }\
  450. };\
  451. xhr.open('GET', '/lightstatus', true);\
  452. xhr.send();\
  453. }\
  454. setInterval(getLightStatus, 500); // Refresh every 500ms for quicker updates\
  455. </script>\// WiFiManager.ino
  456.  
  457. void manageWiFiConnection() {
  458. unsigned long currentMillis = millis(); // Declare currentMillis locally
  459.  
  460. // If not connected, try to connect
  461. if (!wifiConnected) {
  462. if (WiFi.status() != WL_CONNECTED) {
  463. // Print connection status every 500ms
  464. if (currentMillis - previousMillisWiFi >= previousMillisWiFiDelay) {
  465. previousMillisWiFi = currentMillis;
  466. Serial.println("Connecting to Wi-Fi...");
  467. }
  468. } else {
  469. // Successfully connected
  470. wifiConnected = true;
  471. Serial.println("Connected to Wi-Fi");
  472. Serial.print("IP Address: ");
  473. Serial.println(WiFi.localIP());
  474. }
  475. }
  476. }
  477. </head>\
  478. <body>\
  479. <h1>John's LED Garage Lights Controller</h1>\
  480. <form action=\"/toggle\" method=\"POST\">\
  481. <button class=\"button " + buttonColor + "\" id=\"lightStatus\" type=\"submit\">" + buttonText + "</button>\
  482. </form>\
  483. </body>\
  484. </html>";
  485.  
  486. server.send(200, "text/html", html);
  487. }
  488.  
  489. void handleLightStatus() {
  490. if (lightStatus == LOW) {
  491. server.send(200, "text/plain", "OFF");
  492. } else {
  493. server.send(200, "text/plain", "ON");
  494. }
  495. }
  496.  
  497.  
  498.  
  499.  
  500. // WiFiManager.ino TAB
  501.  
  502. void manageWiFiConnection() {
  503. unsigned long currentMillis = millis(); // Declare currentMillis locally
  504.  
  505. // If not connected, try to connect
  506. if (!wifiConnected) {
  507. if (WiFi.status() != WL_CONNECTED) {
  508. // Print connection status every 500ms
  509. if (currentMillis - previousMillisWiFi >= previousMillisWiFiDelay) {
  510. previousMillisWiFi = currentMillis;
  511. Serial.println("Connecting to Wi-Fi...");
  512. }
  513. } else {
  514. // Successfully connected
  515. wifiConnected = true;
  516. Serial.println("Connected to Wi-Fi");
  517. Serial.print("IP Address: ");
  518. Serial.println(WiFi.localIP());
  519. }
  520. }
  521. }
Advertisement
Add Comment
Please, Sign In to add comment