stspringer

John's Motor Controller

Jun 20th, 2024 (edited)
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 19.89 KB | None | 0 0
  1. /////////////////////////////////////////////////////////////////////////////////////////////////
  2. //BEGIN SERVER TAB 1 UPDATE using "fetchAPI/JavaScript" 08_18_2023
  3. ////////////////////////////////////////////////////////////////////////////////////////////////
  4. //DECLARATIONS
  5. //Written by and edited by, John James Guarnieri, 09_05_2023
  6. //MODIFIED FROM MY GARAGE DOOR OPENER SCRIPT USED A 12V MOTOR INSTEAD OF A GARAGE DOOR
  7. //Credits noiasca Arduino Forum
  8.  
  9. //Latest Working Script, John's Garage Door Opener, using the NORMALLY OPEN, "NO" Terminal on the relay
  10. //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.
  11.  
  12. //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.
  13. //We are using the "NO" terminal on the relay in this script to power the load
  14. //THE CONFUSING PART OF THE 5V RELAY! "SIGNAL WIRE HIGH", Relay OFF, "NORMALL OPEN" terminal is "OFF", the green LED indicator is "OFF"
  15. //"SIGNAL WIRE HIGH", Relay OFF, "NORMALLY CLOSED" terminal is "ON", green LED indicator is "OFF"
  16.  
  17. //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
  18. //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
  19. //to the "NC" terminal.
  20.  
  21. //CONST INT
  22. const int positionSwitchTop = 14; // Pin connected to Top reed switch
  23. const int positionSwitchBottom = 4; // Pin connected to Bottom reed switch
  24. //
  25. const int LED_Reed_Switch_Indicator = 16; // Built in LED pin turns on when door is in motion, else it is off
  26.  
  27. //when using the D1 Min Pro module
  28. #define LED_BUILTINN D4
  29.  
  30. //INT
  31. int Bottom_Reed_Switch_Proximity = digitalRead(positionSwitchBottom); // Read the state of the bottom reed switch
  32. int Top_Reed_Switch_Proximity = digitalRead(positionSwitchTop); // Read the state of the top reed switch
  33.  
  34.  
  35. //BOOL
  36. bool The_Garage_Door_Is_Open = false;
  37. bool The_Garage_Door_Is_Closed = false;
  38.  
  39. //LIBRARY
  40. // Load Wi-Fi library
  41. #include <ESP8266WiFi.h>
  42. #include <ESP8266WebServer.h>
  43.  
  44. // Assign output variables to GPIO pins
  45. const uint8_t output5 = 5; // a output pin for door5
  46.  
  47. //UNSIGNED LONG
  48. unsigned long lastTimeDoorWasActivated = 0; // times for millis()
  49. const unsigned long doorDelay = 12000; // 12 seconds approximate time for garage door to fully open or close
  50.  
  51.  
  52. //ENUM FSM
  53. // how long does it take to open/close the door - set to 12 seconds
  54. enum class State { OPENED,
  55. CLOSING,
  56. CLOSED,
  57. OPENING }; // due to naming conflicts you will need a scoped enumeration (enum class)
  58. // 0 1 2 3 // the compiler will assign numbers to the enumeration items
  59.  
  60.  
  61. State state5 = State::CLOSED; // state5 a variable to store the current state for output5 running State Closed first
  62.  
  63. #if true // true for stspringer
  64. // Replace with your network credentials
  65. const char* ssid = "XXX, XXX, XXX,XXX";
  66. const char* password = "XXX, XXX, XXX,XXX";
  67. //My Add/ DEFINE STATIC IP 10.0.69.22 WORKING! https://www.youtube.com/watch?v=B9jJI7p2Gw4
  68.  
  69. //STATIC IP ADDRESS
  70.  
  71. //IPAddress local_IP(XXX, XXX, XXX, 22);//22 is the actual wireless ESP8266 in the garage digitalWrite(relayPin, //relayOnState);
  72. IPAddress local_IP(XXX, XXX, XXX, 19); // 19 for testing
  73. IPAddress gateway(XXX,XXX,XXX, XX);
  74. IPAddress subnet(255, 255, 255, 0);
  75. IPAddress primaryDNS(208, 67, 222, 222);
  76. IPAddress secondaryDNS(208, 67, 220, 220);
  77. #endif
  78.  
  79.  
  80. // Set web server port number to 80
  81. ESP8266WebServer server(80);
  82.  
  83. // open door
  84. void doorOpen()
  85. {
  86. lastTimeDoorWasActivated = millis();
  87. digitalWrite(output5, LOW); //the relay signal wire is LOW, zerov the "NO" terminal is now "closed", working, sending power to the load the green LED indicator is "ON"
  88. state5 = State::OPENING;
  89. Serial.println(F("state5 OPENING"));
  90. }
  91.  
  92. // forced close
  93. void doorClose()
  94. {
  95. lastTimeDoorWasActivated = millis();
  96. digitalWrite(output5, LOW); //the relay signal wire is LOW, zerov the "NO" terminal is now "closed", working, sending power to the load the green LED indicator is "ON"
  97. state5 = State::CLOSING; //running State Closed first
  98. Serial.println(F("state5 CLOSING"));
  99. }
  100.  
  101. void runFSM()
  102. {
  103. //Check state5 here
  104. //if (digitalRead(positionSwitchBottom) == LOW && state5 != State::CLOSED) state5 = State::CLOSED;//My Edit if the door is CLOSED but state5 is OPENED set stae5 to CLOSED
  105. //if (digitalRead(positionSwitchTop) == LOW && state5 != State::OPENED) state5 = State::OPENED;//My Edit if the door is OPENED but state5 is CLOSED set stae5 to OPENED
  106.  
  107. //My Add/EDIT check BOTTOM Reed Switch here
  108. if (digitalRead(positionSwitchBottom) == LOW && state5 != State::CLOSED) //bottom reed switch closing the circuit "ON", "LOW", initally when the BOTTOM reed switch is closed if the state on the web page is NOT CLOSED then make it CLOSED
  109. {
  110. state5 = State::CLOSED; //My Edit if the door is CLOSED but state5 is OPENED set state5 to CLOSED
  111.  
  112. if (The_Garage_Door_Is_Closed) //YES THE GARAGE DOOR IS CLOSED
  113. {
  114. state5 = State::OPENING; //the garage door is CLOSED so OPEN it, call OPENING
  115. }
  116. else //THE GARAGE DOOR IS OPENED
  117. {
  118. state5 = State::CLOSED; //the garage door is OPENED so close it, call CLOSED
  119. }
  120. } else if (digitalRead(positionSwitchBottom) == LOW && state5 == State::OPENED) // the garage door is in the physical CLOSED position, but state5 is showing OPENED on the web page, so set state5 to CLOSED
  121. {
  122. state5 = State::CLOSED;
  123. }
  124.  
  125.  
  126. //check TOP Reed Switch here
  127. if (digitalRead(positionSwitchTop) == LOW && state5 != State::OPENED) //TOP reed switch closing the circuit "ON", "LOW", initally when the TOP reed switch is CLOSED if the state on the web page is NOT OPENED then make it OPENED
  128. {
  129. state5 = State::OPENED; //My Edit if the door is OPENED but state5 is CLOSED, set state5 to OPENED
  130.  
  131. if (The_Garage_Door_Is_Open) //YES THE GARAGE DOOR IS OPENE
  132. {
  133. state5 = State::CLOSING; //the garage door is OPENED so CLOSE IT, call CLOSING
  134. }
  135. else //THE GARAGE DOOR IS CLOSED
  136. {
  137. state5 = State::OPENED; //the garage door CLOSED so OPEN it, CALL OPENED
  138. }
  139. } else if (digitalRead(positionSwitchTop) == LOW && state5 == State::CLOSED) // the garage door is in the physical OPENED position, but state5 is showing CLOSED on the web page, so set state5 to OPENED
  140. {
  141. state5 = State::OPENED;
  142. }
  143.  
  144. switch (state5) // state5 a variable to store the current state for output5
  145. {
  146. case State::OPENED:
  147. // here you could read a hardware button
  148. The_Garage_Door_Is_Open = true;
  149. The_Garage_Door_Is_Closed = false;
  150.  
  151. break;
  152. case State::CLOSING:
  153. if (millis() - lastTimeDoorWasActivated > doorDelay) //wait 12 seconds
  154. {
  155. //This triggers the 5v relay to turn "OFF" after 12 seconds.
  156. digitalWrite(output5, HIGH); //the relay signal wire is "HIGH" 3.3v, & "OFF" "NO" "Normally Open is "Open", zero volts" "NC" has 12v from power supply
  157. Serial.println(F("state5 CLOSED"));
  158. state5 = State::CLOSED; // state5 a variable to store the current state for output5
  159. }
  160. break;
  161. case State::CLOSED:
  162. // here you could read a hardware button
  163. The_Garage_Door_Is_Open = false;
  164. The_Garage_Door_Is_Closed = true;
  165.  
  166. break;
  167. case State::OPENING:
  168. if (millis() - lastTimeDoorWasActivated > doorDelay) //wait 12 seconds
  169. {
  170. //This triggers the 5v relay to turn "OFF" after 12 seconds.
  171. digitalWrite(output5, HIGH); //the relay signal wire is "HIGH" 3.3v, & "OFF" "NO" "Normally Open is "Open", zero volts" "NC" has 12v from power supply
  172. Serial.println(F("state5 OPENED"));
  173. state5 = State::OPENED; // state5 a variable to store the current state for output5
  174. }
  175. break;
  176. } //switch state
  177.  
  178. } //runFSM
  179.  
  180.  
  181. //SETUP
  182. void setup()
  183. {
  184. Serial.begin(115200);
  185. // Initialize the output variables as outputs
  186.  
  187. //OUTPUT
  188. pinMode(output5, OUTPUT);
  189. pinMode(LED_BUILTINN, OUTPUT);
  190.  
  191. //INPUT
  192. pinMode(positionSwitchTop, INPUT_PULLUP);
  193. pinMode(positionSwitchBottom, INPUT_PULLUP);
  194.  
  195. digitalWrite(LED_BUILTINN, HIGH); //The LED_BUILTINN D4 on D1 Min Pro is off
  196.  
  197. // Connect to Wi-Fi network with SSID and password
  198. Serial.print(F("Connecting to "));
  199. Serial.println(ssid);
  200.  
  201. //My Add/ Define Static IP Setings working!
  202. if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS))
  203. {
  204. Serial.println(F("STA Failed to configure"));
  205. }
  206.  
  207. WiFi.begin(ssid, password);
  208. while (WiFi.status() != WL_CONNECTED)
  209. {
  210. delay(500);
  211. Serial.print(".");
  212. }
  213. Serial.println("");
  214. Serial.println(F("WiFi connected."));
  215. // Print local IP address and start web server
  216. Serial.println(F("IP address: "));
  217. Serial.println(WiFi.localIP());
  218.  
  219. serverSetup(); //in TAB 2 server
  220. }
  221.  
  222. void reedSwitchStatus()
  223. {
  224.  
  225. ////////////////////////////////////////////////////////////////////////////////////////
  226. //BEGIN Bottom_Reed_Switch_Proximity
  227. ///////////////////////////////////////////////////////////////////////////////////////
  228.  
  229. // If the pin reads low, the switch is closed.
  230. if (Bottom_Reed_Switch_Proximity = LOW) //Bottom_Reed_Switch_Proximity "reed Switch" is Closed IMPORTANT WATCH OUT FOR == ERROR HERE SHOULD BE =
  231. {
  232. Serial.println("Bottom Switch closed");
  233. }
  234. else //Bottom_Reed_Switch_Proximity "reed Switch" is Open, turn on the blue built in LED 16 when the garage door is in motion
  235. {
  236. if (state5 == State::OPENING) {
  237. digitalWrite(LED_BUILTINN, LOW); //The LED_BUILTINN D4 on D1 Min Pro is on
  238. } else if (state5 == State::OPENED) {
  239. digitalWrite(output5, HIGH); //this insures we turn the relay signal wire "off" after an opening or closing of the garage door
  240. digitalWrite(positionSwitchBottom, HIGH); //reed switch open
  241. digitalWrite(LED_BUILTINN, HIGH); //The LED_BUILTINN D4 on D1 Min Pro is off
  242. Serial.println("Bottom_Reed_Switch_Proximity opened");
  243. }
  244.  
  245. } //if Bottom
  246.  
  247. ////////////////////////////////////////////////////////////////////////////////////////
  248. //BEGIN Top_Reed_Switch_Proximity
  249. ///////////////////////////////////////////////////////////////////////////////////////
  250.  
  251. // If the pin reads low, the switch is closed.
  252. if (Top_Reed_Switch_Proximity = LOW) //Top_Reed_Switch_Proximity "reed Switch" is Closed IMPORTANT WATCH OUT FOR == ERROR HERE SHOULD BE =
  253. {
  254. Serial.println("Top Switch closed");
  255. }
  256. else // Top_Reed_Switch_Proximity "reed Switch" is Open, turn on the blue built in LED 16 when the garage door is in motion
  257. {
  258. if (state5 == State::CLOSING)
  259. {
  260. digitalWrite(LED_BUILTINN, LOW); //The LED_BUILTINN D4 on D1 Min Pro is on
  261. } else if (state5 == State::CLOSED) {
  262. digitalWrite(output5, HIGH); //this insures we turn the relay signal wire off after an opening or closing of the garage door
  263. digitalWrite(positionSwitchTop, HIGH); //reed switch open
  264. digitalWrite(LED_BUILTINN, HIGH); //The LED_BUILTINN D4 on D1 Min Pro is off
  265. Serial.println("Top_Reed_Switch_Proximity opened");
  266. }
  267.  
  268. } //if Top
  269.  
  270. } //reedSwitch
  271.  
  272. void loop()
  273. {
  274. server.handleClient(); // call the webserver
  275. reedSwitchStatus();
  276. runFSM();
  277. }
  278.  
  279. /////////////////////////////////////////////////////////////////////////////////////////////////
  280. //END SERVER TAB 1 UPDATE using "fetchAPI/JavaScript" 08_18_2023
  281. ////////////////////////////////////////////////////////////////////////////////////////////////
  282.  
  283.  
  284. /////////////////////////////////////////////////////////////////////////////////////////////////
  285. //BEGIN SERVER TAB 2 UPDATE using "fetchAPI/JavaScript" 08_18_2023
  286. ////////////////////////////////////////////////////////////////////////////////////////////////
  287.  
  288. /*
  289. Webserver Parts
  290. Update page with FetchAPI & JavaScript
  291. button sends request to a dedicated resource to process commands
  292. */
  293.  
  294. // we need the button text in the page and in the JSON, hence a global structure to avoid duplicated code.
  295. struct Stateinfo {
  296. const char caption[42]; // text/caption for the button
  297. const char style[10]; // the CSS class (button, button2)
  298. };
  299.  
  300. // the order must fit to the order of the states in the enumeration
  301. Stateinfo stateinfo[4] {
  302. {"The Motor is OFF", "button"}, // green - button2
  303. {"Please wait...12 seconds Motor is working", "button2"}, // red - button
  304. {"The Motor is OFF", "button"}, // red - button
  305. {"Please wait...12 seconds Motor is working", "button2"} // green - button2
  306. };
  307.  
  308. // call this function in setup()
  309. void serverSetup() {
  310. server.on("/", handlePage); // the home page
  311. server.on("/j.js", handleJs); // javscript based on fetch API to update the page
  312. server.on("/json", handleJson); // send data in JSON format
  313. server.on("/cmd", handleCmd); // process commands
  314. server.begin();
  315. }
  316.  
  317. // the main handle for the page
  318. void handlePage() {
  319. //Serial.println(F(" D8 handle page"));
  320. String message;
  321. message.reserve(1000);
  322.  
  323. // Display the HTML web page
  324. message += F("<!DOCTYPE html>\n"
  325. "<html lang=\"en\">\n" // define the language of the content
  326. "<head>\n"
  327. "<title>John's Motor Controller</title>\n" // mostly displayed on the title bar of the browser tab
  328. "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n" // set the viewport for mobile devices
  329. "<link rel=\"icon\" href=\"data:,\">\n" // avoid loading of favicon.ico
  330. "<script src='j.js'></script>\n" // include the JavaScript
  331. "<style>\n" // inline style (or include a CSS)
  332. "html {font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n"
  333. "button, input[type=submit], .button {border: none; color: white; padding: 16px 40px; text-decoration: none; font-size: 20px; margin: 2px; cursor: pointer;}\n"
  334. ".button {background-color: #195B6A;}\n" //green
  335. //".button {background-color: #FF0000;}\n" //red
  336. //".button2 {background-color: #195B6A;}\n" //green
  337. ".button2 {background-color: #FF0000;}\n" //red
  338. "</style>\n"
  339. "</head>\n"
  340. "<body>\n"
  341. "<h1>John's Motor Controller</h1>\n");
  342.  
  343. // Display current state of output5
  344. message += F("<p>GPIO 5 - State<span id=\"output5\">");
  345. message += digitalRead(output5);
  346. message += F("</span></p>\n");
  347. // Display a form with one command button (=submit)
  348. Serial.println(stateinfo[(int)state5].caption);
  349. message += F("<form action=\"/cmd\" method=\"POST\"><button id=\"button5\" name=\"button5\" class=\"");
  350. message += stateinfo[(int)state5].style; // access the index based on the integer value of state5
  351. message += F("\">");
  352. message += stateinfo[(int)state5].caption;
  353. message += F("</button></form>\n");
  354.  
  355. // just for debugging - you will see 0, 1, 2, 3 as numeric representation of state5
  356. message += F("<p>global state5=<span id=\"state5\">"); message += (int)state5; message += F("</span></p>\n");
  357. message += F("<p>FetchAPI</p>\n");
  358. message += F("</body>\n");
  359. message += F("</html>");
  360.  
  361. server.send(200, "text/html", message);
  362. //Serial.print(F("handle page message length=")); Serial.println(message.length());
  363. }
  364.  
  365. // process incomming commands LOGIC HERE button5 pressed if state5 == State :: OPENED doorClose()
  366. void handleCmd() {
  367. if (server.hasArg("button5")) {
  368. if (state5 == State::OPENED) doorClose();
  369. else if (state5 == State::CLOSED) doorOpen();
  370. else Serial.println(F("D81 pressed cmd button in a state where no action is defined"));
  371. }
  372. handlePage(); // as HTML output we return the start page to the browser
  373. }
  374.  
  375. // Output: send data to browser as JSON
  376. // after amodification always check if JSON is still valid. Just call the JSON (json) in your webbrowser and check.
  377. void handleJson() {
  378. String message = "";
  379. message.reserve(1000);
  380. message = F(" {\"ss\":"); // Start of JSON and the first object "ss": with the actual runtime in seconds
  381. message += millis() / 1000;
  382.  
  383. message += F(",\"output5\":"); message += digitalRead(output5);
  384.  
  385. message += F(",\"state5\":"); message += (int)state5;
  386.  
  387. message += F(",\"style5\":\""); message += stateinfo[(int)state5].style; message += F("\""); // access the index based on the integer value of state5. Its text therefore the content must be enclosed in "
  388.  
  389. message += F(",\"caption5\":\""); message += stateinfo[(int)state5].caption; message += F("\"");
  390.  
  391. message += (F("}")); // End of JSON
  392. server.send(200, "application/json", message); // set MIME type https://www.ietf.org/rfc/rfc4627.txt
  393. //Serial.print(F("handleJson message length=")); Serial.println(message.length());
  394. }
  395.  
  396. // Output: a fetch API / JavaScript
  397. // a function in the JavaScript uses the fetchAPI to request a JSON file from the webserver.
  398. // The JavaScript process the JSON file and updates the values on the page
  399. void handleJs() {
  400. String message;
  401. message.reserve(1000);
  402. message += F("const url ='json';\n"
  403. "function renew(){\n"
  404. " document.getElementById('state5').style.color = 'blue';\n" // if the timer starts the request, this field gets blue
  405. " fetch(url)\n" // Call the fetch function passing the url of the API as a parameter
  406. " .then(response => {return response.json();})\n"
  407. " .then(jo => {\n"
  408. " for (var i in jo)\n"
  409. " {\n"
  410. " if (document.getElementById(i)) document.getElementById(i).innerHTML = jo[i];\n" // as long as the JSON name fits to the HTML id, the value will be replaced
  411. " }\n"
  412. // add other fields here (e.g. the delivered JSON name doesn't fit to the html id
  413. " document.getElementById('button5').innerHTML = jo['caption5'];\n"
  414. " document.getElementById('button5').className = jo['style5'];\n"
  415. " document.getElementById('state5').style.color = '';\n" // if everything was ok, the field will get the default color again
  416. " })\n"
  417. " .catch(function() {\n" // this is where you run code if the server returns any errors
  418. " document.getElementById('state5').style.color = 'red';\n" // indicator that something went wrong
  419. " });\n"
  420. "}\n"
  421. "document.addEventListener('DOMContentLoaded', renew, setInterval(renew, 1000));\n"); // call JSON every n milliseconds
  422.  
  423. server.send(200, "text/javascript", message);
  424. //Serial.print(F("handleJs message length=")); Serial.println(message.length());
  425. }
  426. //
  427. /////////////////////////////////////////////////////////////////////////////////////////////////
  428. //END SERVER TAB 2 UPDATE 08_18_2023
  429. ////////////////////////////////////////////////////////////////////////////////////////////////
  430.  
Advertisement
Add Comment
Please, Sign In to add comment