stspringer

Garage Door Opener Update 2

Nov 19th, 2024
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.75 KB | Source Code | 0 0
  1. /*
  2.  
  3.  
  4. *********
  5. THIS SCRIPT UPDATE PREVENTS THE RESUBMISSION DIALOG BOX FROM APPEARING IN THE WEB SERVER
  6. Door opener
  7.  
  8. https://forum.arduino.cc/t/garage-door-opener-with-esp8266-web-server/1154364/18
  9.  
  10. 11_17_2024 ADDED CODE TO UPDATE WEBSERVER IF OTHER DEVICE OPENS THE GARAGE DOOR, LIKE THE REMOTE OR THEDOOR PUSH BUTTON
  11. *********
  12.  
  13. MY ACTUAL GARAGE DOOR OPENER HAS THE TWO REED SWITCHES CONNECTED TO THE "NC" TERMINALS AND YHE COMMON TO GROUND, THE TOP REED SWITCH WILL HAVE WEB SERVER AS The Garage Door is Closing, Please Wait...
  14. THE BOTTOM REED SWITCH WILL HAVE WEB SERVER AS The Garage Door is Opening, Please Wait...
  15.  
  16. 11_18_2024 I edited void checkForExternalChanges() so that when the garage door is opening via any external device "remote" the web server will report just like if the web server was used to open or close the
  17. garage door message The Garage Door is Opening, Please Wait... or The Garage Door is Closing, Please Wait...
  18.  
  19.  
  20. DECLARATIONS
  21. Written by and edited by, John James Guarnieri, 09_05_2023
  22.  
  23. Credits noiasca Arduino Forum
  24.  
  25. Latest Working Script, John's Garage Door Opener, using the NORMALLY OPEN, "NO" Terminal on the relay
  26. Also in this setup, you are switching the "HOT side" of the load, so the "HOT" wire goes into the "NO" terminal, and the ground wire goes into "COMMON" terminal of the relay.
  27.  
  28. REMEMBER!, if the signal wire is "LOW", zero v, the relay is "ON", and the 'NO" terminal is "CLOSED" and has power, If the signal wire is "HIGH", 3.3v the relay is "OFF", and the "NC" terminal has power.
  29. We are using the "NO" terminal on the relay in this script to power the load
  30. THE CONFUSING PART OF THE 5V RELAY! "SIGNAL WIRE HIGH", Relay OFF, "NORMALL OPEN" terminal is "OFF", the green LED indicator is "OFF"
  31. "SIGNAL WIRE HIGH", Relay OFF, "NORMALLY CLOSED" terminal is "ON", green LED indicator is "OFF"
  32.  
  33. The 5v relay explained: When the relay signal pin is "LOW" the relay is "ON", and the green LED on the relay, is "ON" and the pole, or armature in the relay, is pulled to the "normally open" "NO" terminal
  34. when the signal wire is "HIGH" the relay is "OFF" and the pole or armature is back to the normally closed terminal "NC" and the green LED is "OFF", and power is sent to the load, if your load is connected
  35. to the "NC" terminal.
  36.  
  37.  
  38. */
  39.  
  40.  
  41. // Constants and Pins
  42. const int positionSwitchTop = 14; // Pin connected to Top reed switch when the top reed switch goes LOW the web server message is The Garage Door is Closing, Please Wait...
  43. const int positionSwitchBottom = 4; // Pin connected to Bottom reed switch when the bottom reed switch goes low the web message is The Garage Door is Opening, Please Wait...
  44. const int LED_Reed_Switch_Indicator = 16; // Built-in LED pin
  45.  
  46. // INT
  47. int Bottom_Reed_Switch_Proximity = digitalRead(positionSwitchBottom); // Read bottom reed switch
  48. int Top_Reed_Switch_Proximity = digitalRead(positionSwitchTop); // Read top reed switch
  49.  
  50. // BOOL
  51. bool The_Garage_Door_Is_Open = false;
  52. bool The_Garage_Door_Is_Closed = false;
  53.  
  54. // Library includes for Wi-Fi and Web Server
  55. #include <ESP8266WiFi.h>
  56. #include <ESP8266WebServer.h>
  57.  
  58. // Assign output variables to GPIO pins, using "const" ensures pin numbers remain fixed throughout the program, "uint8_t" is always 8 bits,
  59. const uint8_t output5 = 5; // Output pin for door
  60.  
  61. // Timing variables
  62. unsigned long lastTimeDoorWasActivated = 0; // millis() tracking
  63. const unsigned long doorDelay = 12000; // 12 seconds for door movement
  64.  
  65. // Enum for FSM
  66. enum class State { OPENED, CLOSING, CLOSED, OPENING };
  67.  
  68. State state5 = State::CLOSED; // Start state
  69.  
  70. // Wi-Fi settings
  71. const char* ssid = "xxxxxx";
  72. const char* password = "xxxxxxxx";
  73.  
  74. // Static IP settings
  75. //IPAddress local_IP(xxx.xxx.xxx.xxx); //IP USED FOR TESTING
  76.  
  77. IPAddress local_IP(xxx.xxx.xxx.xxx); //Actual Garage Door Opener IP
  78. IPAddress gateway(xxx.xxx.xxx.xxx;
  79. IPAddress subnet(255, 255, 255, 0);
  80. IPAddress primaryDNS(208, 67, 222, 222);
  81. IPAddress secondaryDNS(208, 67, 220, 220);
  82.  
  83. // Web server on port 80
  84. ESP8266WebServer server(80);
  85.  
  86. // Function to open the door
  87. void doorOpen() {
  88. lastTimeDoorWasActivated = millis();
  89. digitalWrite(output5, LOW); // Activate relay
  90. state5 = State::OPENING;
  91. Serial.println(F("state5 OPENING"));
  92. }
  93.  
  94. // Function to close the door
  95. void doorClose() {
  96. lastTimeDoorWasActivated = millis();
  97. digitalWrite(output5, LOW); // Activate relay
  98. state5 = State::CLOSING;
  99. Serial.println(F("state5 CLOSING"));
  100. }
  101.  
  102. void runFSM() {
  103. Serial.print(F("Current State: "));
  104. Serial.println((state5 == State::OPENED) ? "OPENED" :
  105. (state5 == State::CLOSED) ? "CLOSED" :
  106. (state5 == State::OPENING) ? "OPENING" : "CLOSING");
  107.  
  108. switch (state5) {
  109. case State::OPENED:
  110. The_Garage_Door_Is_Open = true;
  111. The_Garage_Door_Is_Closed = false;
  112. Serial.println(F("State: OPENED"));
  113. break;
  114.  
  115. case State::CLOSING:
  116. if (millis() - lastTimeDoorWasActivated > doorDelay) {
  117. digitalWrite(output5, HIGH); // Deactivate relay
  118. state5 = State::CLOSED; // Transition to CLOSED
  119. Serial.println(F("State transition: CLOSING to CLOSED"));
  120. }
  121. break;
  122.  
  123. case State::CLOSED:
  124. The_Garage_Door_Is_Open = false;
  125. The_Garage_Door_Is_Closed = true;
  126. Serial.println(F("State: CLOSED"));
  127. break;
  128.  
  129. case State::OPENING:
  130. if (millis() - lastTimeDoorWasActivated > doorDelay) {
  131. digitalWrite(output5, HIGH); // Deactivate relay
  132. state5 = State::OPENED; // Transition to OPENED
  133. Serial.println(F("State transition: OPENING to OPENED"));
  134. }
  135. break;
  136. }
  137. }
  138.  
  139. // Web server setup and connection
  140. void setup() {
  141. Serial.begin(115200);
  142. pinMode(output5, OUTPUT);
  143. pinMode(LED_Reed_Switch_Indicator, OUTPUT);
  144. pinMode(positionSwitchTop, INPUT_PULLUP);
  145. pinMode(positionSwitchBottom, INPUT_PULLUP);
  146.  
  147. WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS);
  148. WiFi.begin(ssid, password);
  149. while (WiFi.status() != WL_CONNECTED) {
  150. delay(500);
  151. Serial.print(".");
  152. }
  153. Serial.println("");
  154. Serial.println("WiFi connected.");
  155. Serial.println("IP address: ");
  156. Serial.println(WiFi.localIP());
  157.  
  158. server.on("/", HTTP_GET, handleRoot);
  159. server.on("/toggle", HTTP_POST, toggleDoor); // AJAX toggle for door
  160. server.on("/doorstatus", HTTP_GET, handleDoorStatus); // AJAX status check
  161. server.begin();
  162. Serial.println("Server started");
  163. }
  164.  
  165. void handleRoot() {
  166. String html = "<html>\
  167. <head>\
  168. <title>John's Garage Door Controller</title>\
  169. <style>\
  170. body { text-align: center; font-family: Arial; }\
  171. h1 { font-size: 80px; } /* Larger title text */\
  172. .button { width: 600px; height: 150px; font-size: 50px; color: white; } /* More rectangular button */\
  173. .red { background-color: red; }\
  174. .green { background-color: green; }\
  175. </style>\
  176. <script>\
  177. function toggleDoor() {\
  178. var xhr = new XMLHttpRequest();\
  179. xhr.open('POST', '/toggle', true);\
  180. xhr.send();\
  181. setTimeout(getDoorStatus, 500); /* Ensure status updates after toggle */\
  182. }\
  183. function getDoorStatus() {\
  184. var xhr = new XMLHttpRequest();\
  185. xhr.onreadystatechange = function() {\
  186. if (xhr.readyState == 4 && xhr.status == 200) {\
  187. var status = xhr.responseText;\
  188. var button = document.getElementById('doorStatus');\
  189. console.log('Door status:', status); /* Log for debugging */\
  190. if (status === 'OPEN') {\
  191. button.innerHTML = 'The Garage Door is Open';\
  192. button.className = 'button green';\
  193. } else if (status === 'CLOSED') {\
  194. button.innerHTML = 'The Garage Door is Closed';\
  195. button.className = 'button red';\
  196. } else if (status === 'OPENING') {\
  197. button.innerHTML = 'The Garage Door is Opening, Please Wait...';\
  198. button.className = 'button green'; /* Show green while opening */\
  199. } else if (status === 'CLOSING') {\
  200. button.innerHTML = 'The Garage Door is Closing, Please Wait...';\
  201. button.className = 'button red'; /* Show red while closing */\
  202. }\
  203. }\
  204. };\
  205. xhr.open('GET', '/doorstatus', true);\
  206. xhr.send();\
  207. }\
  208. setInterval(getDoorStatus, 300); /* Check status every 300ms */\
  209. </script>\
  210. </head>\
  211. <body>\
  212. <h1>John's Garage Door Controller</h1>\
  213. <button class=\"button red\" id=\"doorStatus\" onclick=\"toggleDoor()\">The Garage Door is Closed</button>\
  214. </body>\
  215. </html>";
  216.  
  217. server.send(200, "text/html", html);
  218. }
  219.  
  220.  
  221.  
  222. // AJAX function to provide door status
  223. void handleDoorStatus() {
  224. String doorStatus = (state5 == State::OPENED) ? "OPEN" :
  225. (state5 == State::CLOSED) ? "CLOSED" :
  226. (state5 == State::OPENING) ? "OPENING" : "CLOSING";
  227.  
  228. Serial.print(F("handleDoorStatus reports: "));
  229. Serial.println(doorStatus);
  230.  
  231. server.send(200, "text/plain", doorStatus); // Send status to web server
  232. }
  233.  
  234.  
  235. //THIS FUNCTION CHECKS FOR ANY EXTERNAL DEVICE THAT MAY BE OPENING OR CLOSING THE GARAGE DOOR AND UPDATES THE WEB SERVER ACCORDINGLY
  236. void checkForExternalChanges() {
  237. static int lastBottomSwitchState = HIGH; // Assuming switches are normally HIGH
  238. static int lastTopSwitchState = HIGH;
  239.  
  240. int currentBottomSwitchState = digitalRead(positionSwitchBottom);
  241. int currentTopSwitchState = digitalRead(positionSwitchTop);
  242.  
  243. // Detect changes on the bottom reed switch (door closing)
  244. if (currentBottomSwitchState != lastBottomSwitchState) {
  245. lastBottomSwitchState = currentBottomSwitchState;
  246. if (currentBottomSwitchState == LOW) {
  247. //if (state5 != State::CLOSING) {
  248. //state5 = State::CLOSING;
  249.  
  250. //My Edit 11_18_2024 WORKING
  251. if (state5 != State::CLOSING) {
  252. state5 = State::OPENING;
  253. lastTimeDoorWasActivated = millis(); // Start the 12-second timer
  254. Serial.println(F("External event: Door is Closing"));
  255. }
  256. }
  257. }
  258.  
  259. // Detect changes on the top reed switch (door opening)
  260. if (currentTopSwitchState != lastTopSwitchState) {
  261. lastTopSwitchState = currentTopSwitchState;
  262. if (currentTopSwitchState == LOW) {
  263.  
  264. // if (state5 != State::OPENING) {
  265. // state5 = State::OPENING;
  266.  
  267. //My Edit 11_18_2024 WORKING
  268. if (state5 != State::OPENING) {
  269. state5 = State::CLOSING;
  270. lastTimeDoorWasActivated = millis(); // Start the 12-second timer
  271. Serial.println(F("External event: Door is Opening"));
  272. }
  273. }
  274. }
  275. }
  276.  
  277.  
  278.  
  279. // Function to toggle the door's open/close state
  280. void toggleDoor() {
  281. if (state5 == State::CLOSED || state5 == State::CLOSING) {
  282. doorOpen();
  283. } else if (state5 == State::OPENED || state5 == State::OPENING) {
  284. doorClose();
  285. }
  286. server.send(200, "text/plain", "Toggled");
  287. }
  288.  
  289. // Reed switch status function (optional, based on initial code)
  290. void reedSwitchStatus() {
  291. if (digitalRead(positionSwitchBottom) == LOW) {
  292. Serial.println("Bottom Switch closed");
  293. } else if (state5 == State::OPENING) {
  294. digitalWrite(LED_BUILTIN, LOW);
  295. } else if (state5 == State::OPENED) {
  296. digitalWrite(output5, HIGH);
  297. Serial.println("Bottom_Reed_Switch_Proximity opened");
  298. }
  299.  
  300. if (digitalRead(positionSwitchTop) == LOW) {
  301. Serial.println("Top Switch closed");
  302. } else if (state5 == State::CLOSING) {
  303. digitalWrite(LED_BUILTIN, LOW);
  304. } else if (state5 == State::CLOSED) {
  305. digitalWrite(output5, HIGH);
  306. Serial.println("Top_Reed_Switch_Proximity opened");
  307. }
  308. }
  309.  
  310.  
  311.  
  312. void loop() {
  313. server.handleClient();
  314. reedSwitchStatus();
  315. checkForExternalChanges(); // New function to detect remote control use external device
  316. runFSM();
  317. }
  318.  
Tags: Arduino
Advertisement
Add Comment
Please, Sign In to add comment