Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- ==============================================================================================
- Arduino IDE - Boards manager ESP32 (espressif) terugzetten naar versie 2.0.17 voor deze schets
- ==============================================================================================
- Materiaal:
- =============
- Smallere versie van ESP32 met display:
- https://www.lilygo.cc/products/lilygo%C2%AE-ttgo-t-display-1-14-inch-lcd-esp32-control-board?variant=42720264650933
- https://www.amazon.nl/dp/B0CTG459MW (uitbreidingsbord)
- https://www.amazon.nl/dp/B07RCGWGD2 (numeriek keypad)
- https://www.amazon.nl/dp/B06W564ZSD (PCF8574: 8 bit parallel naar I2C)
- https://www.amazon.nl/dp/B07PZC9ZMM (relais met octocoupler - triggerstroom 5 mA)
- Aansluitingen:
- ==============
- Numeriek keypad -> PCF8574, vanaf P0 .. P6 (P0 .. P7 indien keypad met 4 kolommen)
- PCF8574 -> ESP32: GND -> GND, VCC -> 3V3, SDA -> 21, SCL -> 22 (normale I2C-aansluitingen)
- Relais -> ESP32: IN -> 26, DC+ -> V5, DC- -> GND */
- #include <WebServer.h> // arduino IDE - keuze bord: DOIT ESP32 DEVKIT V1
- #include <Preferences.h> // https://github.com/vshymanskyy/Preferences
- #include <I2CKeyPad.h> // https://github.com/RobTillaart/I2CKeyPad
- #include <TFT_eSPI.h> // https://github.com/Bodmer/TFT_eSPI
- #include <Wire.h>
- #include <esp_task_wdt.h> // voor de watchdog timer (onnodig om deze bibliotheek te installeren = core)
- Preferences flash; // om gegevens weg te schrijven en op te halen uit FLASH-geheugen
- WebServer mijnServer(80); // instantie van Webserver
- I2CKeyPad keyPad(0x20); // 0x20 = de 3 brugjes staan het verst van de parallelcontacten
- TFT_eSPI tft = TFT_eSPI(); // User_Setup: Setup25_TTGO_T_Display.h
- TFT_eSprite sprite = TFT_eSprite(&tft); // sprites voor vloeiende bewegingen op het display: hoofdsprite
- TFT_eSprite leftSp = TFT_eSprite(&tft); // sprite linkerkant scherm
- TFT_eSprite rightS = TFT_eSprite(&tft); // sprite rechterkant scherm
- const uint8_t relaisPin = 26; // relais stuurt het slot
- uint32_t WDT_TIMEOUT = 4000000; // waarde in sec voor watchdogtimer = 3 dagen voor de millis() rollover 2^32
- bool slot_open = false, code_veranderd = false, toetsen_actief = true, isCodeJuist = false;
- uint32_t slotMillis, codeMillis, keypadMillis; // voor de timers
- String codes[20]; // lege array van 20 strings om de codes in te laden
- String paswoord; // "paswoord" dat vergeleken wordt met de codes
- const char *netwerkNaam = "MynGeheim", *hetPaswoord = "TopSecret"; // voor access point
- const char *volgNr[] = { "code00", "code01", "code02", "code03", "code04", "code05", "code06", "code07", "code08", "code09",
- "code10", "code11", "code12", "code13", "code14", "code15", "code16", "code17", "code18", "code19" };
- void setup() {
- Serial.begin(115200);
- esp_task_wdt_init(WDT_TIMEOUT, true); // watchdogtimer. true = "panic mode", dus de ESP32 herstart als de timer afloopt
- esp_task_wdt_add(NULL); // esp_task_wdt_add(handle). NULL = huidige thread aan de watchdog toevoegen
- tft.init(), tft.setRotation(3); // initialiseren display + landscape
- sprite.createSprite(240, 135); // sprite voor snellere weergave op scherm
- digitalWrite(TFT_BL, LOW); // display uitzetten: backlight off
- pinMode(relaisPin, OUTPUT), digitalWrite(relaisPin, LOW);
- pinMode(35, INPUT_PULLUP); // knop naast usb = om rotatie scherm te wijzigen
- Wire.begin(), Wire.setClock(800000); // bepaalt de snelheid dat het keypad gelezen wordt. Was 400000 voor een ESP8266
- keyPad.begin();
- startWiFiHotSpot();
- startWebServer();
- }
- void loop() {
- keyPadAfhandelen(); // toetsaanslagen verwerken
- mijnServer.handleClient(); // webserver behandelt aanvragen van verbonden apparaten
- }
- void startWiFiHotSpot() { // start hotspot
- IPAddress local_IP(1, 2, 3, 4), gateway(1, 2, 3, 4), subnet(255, 255, 255, 0);
- WiFi.softAPConfig(local_IP, gateway, subnet); // stelt "1.2.3.4" in als adres in browser voor webserver
- WiFi.softAP(netwerkNaam, hetPaswoord, 1, 0, 8, false); // netw, pasw, kanaal, verborgen, ...
- }
- void startWebServer() { // webserver & navigatie pagina's
- codesOphalen(); // slotcodes uit flash-geheugen naar variabelen kopiëren
- mijnServer.on("/", paginaCodesInstellen); // functies voorzien voor elke pagina-link
- mijnServer.on("/codesOpgeslagen/", paginaCodesOpslaan);
- mijnServer.onNotFound(paginaNietGevonden);
- mijnServer.begin();
- }
- void keyPadAfhandelen() { // behandelt ingetikte cijfers en kijkt na of de code correct is
- const char keys[] = "123A456B789C*0#DNF"; // toetsen van klavier. N = NoKey, F = Fail
- uint8_t index = keyPad.getKey(); // input van toetsenbord opvragen
- if (index != 16) { // indien er een toets ingedrukt werd (geen "N" en dus geen index 16)
- if (toetsen_actief) { // toetsaanslagen worden alleen aanvaard na loslaten eerdere toets
- if (millis() - keypadMillis > 200) { // 200 milliSec UI debouncing
- toetsen_actief = false; // toetsenbord blokkeren als een toets ingetikt werd
- codeMillis = millis(); // gebruiker heeft max. 10 seconden per cijfer
- if (index == 12 || index == 14) paswoord = ""; // resetten code bij intikken "*" of "#"
- else paswoord += keys[index]; // ingetikt cijfer bijvoegen
- Serial.print(keys[index]); // debug info
- digitalWrite(TFT_BL, HIGH); // display aanzetten (backlight aan)
- sprite.fillSprite(TFT_BLACK); // vorige gegevens op display wissen
- for (uint8_t i = 0; i < paswoord.length(); i++) sprite.fillCircle(30 + i * 33, 68, 15, TFT_YELLOW);
- sprite.pushSprite(0, 0); // sprite naar display wegschrijven op coordinaten 0, 0
- checkCode(paswoord); // kijk of code correct is
- keypadMillis = millis(); // "10 seconden-vlag" zetten dat er een toets ingedrukt werd
- }
- }
- } else if (index == 16) toetsen_actief = true; // bij loslaten van toets (index 16), toetsenbord vrijgeven.
- if (paswoord.length() >= 6) paswoord = "", Serial.println(); // paswoord reset als er te veel werd ingetikt
- if (!timer_Intikken(10000, codeMillis)) paswoord = ""; // na 10 seconden niets intikken: paswoord reset
- if (millis() - keypadMillis > 5000) digitalWrite(TFT_BL, LOW); // 5 seconden na intikken: display uitzetten
- if (slot_open) digitalWrite(relaisPin, (timer_Slot_Open(5000, slotMillis)) ? HIGH : LOW);
- if (isCodeJuist) animatieDisplay("Slot Open");
- }
- void paginaCodesInstellen() { // startpagina van webserver
- mijnServer.send(200, "text/html", basisHtml() + instelHtml());
- }
- void paginaCodesOpslaan() { // knop "Opslaan" van webpagina stuurt naar deze functie
- flash.begin("codes", true); // true = alleen lezen
- for (byte i = 0; i < 20; i++) { // we lezen 20 waarden uit
- String idx = "a"; // nakijken of er iets gewijzigd werd
- idx = idx + i; // "a0".."a19"
- if (codes[i] != mijnServer.arg(idx)) code_veranderd = true; // vlag zetten als er wijzigingen waren
- codes[i] = mijnServer.arg(idx);
- }
- flash.end();
- mijnServer.send(200, "text/html", basisHtml() + ((code_veranderd) ? opgeslagenHtml() : geenWijzigingHtml()));
- if (code_veranderd) opslaan(), code_veranderd = false; // indien wijzigingen: opslaan en reset de vlag
- }
- void opslaan() { // enkel aangeroepen als er wijzigingen zijn aan een veld op de pagina
- flash.begin("codes", false); // false = ook schrijven
- for (byte i = 0; i < 20; i++) // alle 20 velden van webpagina opvragen en controleren op lengte
- if (codes[i].length() < 7 && codes[i].length() > 3) flash.putString(volgNr[i], codes[i]);
- flash.end(); // codes tussen 6 en 4 cijfers worden opgeslagen
- codesOphalen(); // nodig om de volgende keer bij startpagina de gewijzigde waarden weer te geven
- }
- void paginaNietGevonden() { // error 404
- mijnServer.send(404, "text/html", basisHtml() + nietGevondenHtml());
- }
- void checkCode(String mijnCode) { // slot openen moet via deze functie
- isCodeJuist = false;
- for (uint8_t i = 0; i < 20; i++) // alle 20 codes aflopen
- if (codes[i] == mijnCode) isCodeJuist = true; // kijken of er 1 overeenkomt
- if (isCodeJuist) { // indien juiste code: openen en teller van 5 seconden starten
- slot_open = true, slotMillis = millis();
- Serial.println("\nSlot open met code " + mijnCode);
- }
- }
- bool timer_Slot_Open(uint16_t mijnTijd, uint32_t beginTijd) { // timer om slot te sluiten
- if (millis() - beginTijd >= mijnTijd) slot_open = false, paswoord = "";
- return (millis() - beginTijd >= mijnTijd) ? false : true;
- }
- bool timer_Intikken(uint16_t mijnTijd, uint32_t beginTijd) { // timer max tijd tussen ingetikte cijfers
- return (millis() - beginTijd >= mijnTijd) ? false : true;
- }
- void codesOphalen() { // slotcodes uit flash-geheugen lezen en naar variabelen kopiëren
- flash.begin("codes", true); // true : FLASH alleen lezen
- for (byte i = 0; i < 20; i++) codes[i] = flash.getString(volgNr[i], "873491");
- flash.end();
- }
- void splitSprite(bool split) { // horizontaal splitsen [bool split = true] of samenvoegen [false]
- leftSp.createSprite(120, 135);
- rightS.createSprite(120, 135);
- for (byte ver = 0; ver < 135; ver++) { // sprite in 2 delen opdelen en gegevens naar de helften schrijven
- for (byte hor = 0; hor < 120; hor++) leftSp.drawPixel(hor, ver, sprite.readPixel(hor, ver));
- for (byte hor = 120; hor < 240; hor++) rightS.drawPixel(hor - 120, ver, sprite.readPixel(hor, ver));
- }
- if (split) leftSp.drawFastVLine(119, 0, 135, TFT_BLACK), rightS.drawFastVLine(0, 0, 135, TFT_BLACK);
- for (byte hor = 0; hor < 120; hor++) {
- if (split) leftSp.pushSprite(0 - hor, 0), rightS.pushSprite(hor + 120, 0);
- else leftSp.pushSprite(hor - 120, 0), rightS.pushSprite(240 - hor, 0);
- }
- leftSp.deleteSprite(), rightS.deleteSprite();
- }
- void animatieDisplay(String tekst) { // wordt aangeroepen bij openen slot
- digitalWrite(TFT_BL, HIGH); // display aanzetten
- sprite.fillSprite(sprite.color565(100, 100, 100)); // vul display met grijs
- for (int i = 0; i < 8192; i++) { // oppervlak met fijne textuur aanmaken
- byte j = random(100) + 50; // maak random grijswaarden
- sprite.drawPixel(random(240), random(135), sprite.color565(j, j, j)); // en zet op willekeurige plaatsen
- }
- sprite.setFreeFont(&FreeSansBold18pt7b); // keuze font
- sprite.setTextColor(TFT_YELLOW);
- sprite.drawCentreString(tekst, 120, 60, 1);
- splitSprite(false); // scherm vanuit buitenkanten (L + R) samenvoegen
- sprite.drawFastHLine(0, 134, 240, TFT_BLACK); // om te vermijden dat er lijnen achterblijven
- for (byte i = 0; i < 136; i++) { // schuif alles vloeiend naar boven
- sprite.pushSprite(0, 0 - i);
- }
- digitalWrite(TFT_BL, LOW); // display terug uitzetten
- isCodeJuist = false;
- }
- String basisHtml() { // basispagina html + css
- String html0 = "<!DOCTYPE html>\r\n<html lang='nl'>\r\n<head>\r\n";
- html0 += "<meta name=\"viewport\" content = \"width=device-width\">\r\n";
- html0 += "<title>Slot Boomgaard</title>\r\n<style>\r\n* {\r\n text-align: center;\r\n";
- html0 += " font-family: Arial, Helvetica, sans-serif;\r\n }\r\n";
- html0 += "body{\r\n background: linear-gradient(to right, Lavender, LightCyan);\r\n";
- html0 += "}\r\n\r\n.knop {\r\n width: 110px;\r\n color: #333333;\r\n";
- html0 += " border-radius: 5px;\r\n padding: 6px 6px;\r\n margin: 2px; \r\n font-family: Arial, Helvetica, ";
- html0 += "sans-serif;\r\n font-size: 19px;\r\n font-weight: 500;\r\n font-style: normal;\r\n";
- html0 += " text-decoration: none; \r\n text-align: center;\r\n";
- html0 += " text-shadow: -1px -1px rgba(0,0,0,1), 1px 1px rgba(255,255,255,1); \r\n";
- html0 += " background: transparent;\r\n display: inline-block;\r\n";
- html0 += " box-shadow: inset 0 1px 1px rgba(255,255,255,1), \r\n inset 1px 0px 1px rgba(255,255,255,1),\r\n";
- html0 += " inset -2px 0px 2px rgba(0,0,0,0.4), \r\n inset 0px -1px 1px rgba(0,0,0,0.7), \r\n";
- html0 += " 0px 2px 2px rgba(0,0,0,0.7), \r\n 1px 0px 1px rgba(0,0,0,0.7); \r\n";
- html0 += " border: 1px solid black;\r\n background: -webkit-linear-gradient( \r\n";
- html0 += " #e0e0e0 1% , #f2f2f2 3% , #fafafa 5% , #dfdfdf 10%, #ffffff 16%, \r\n";
- html0 += " #cfcfcf 30%, #b9b9b9 50%, #8c8c8c 87%, #6e6e6e 96%, #4b4b4b 98%, #222222 100%); \r\n";
- html0 += "}\r\n\r\n.knop:active{\r\n transform: scale(0.98);\r\n}\r\n\r\n#draai {\r\n";
- html0 += " margin: auto;\r\n padding: 20px;\r\n background-color: LightYellow;\r\n";
- html0 += " border: 1px solid black;\r\n border-radius: 10px;\r\n width: 280px;\r\n";
- html0 += " text-align: center;\r\n box-shadow: 0px 6px 6px rgba(0,0,0,0.7);\r\n";
- html0 += " font-size: 58px;\r\n font-weight: 900;\r\n position: relative;\r\n}\r\n";
- html0 += ".inputveld {\r\n font-size: 30px;\r\n width: 160px;\r\n}\r\n";
- html0 += "</style>\r\n</head>\r\n<body>\r\n<h1>Slot Boomgaard</h1>\r\n<div id='draai'>\r\n";
- return html0;
- }
- String instelHtml() { // startpagina = codes instellen
- String html1 = "<span style='color: red'>Wijzig Codes</span>\r\n</div><br>\r\n";
- html1 += "<p>Code moet een getal tussen 4 en 6 cijfers zijn</p>\r\n<br>\r\n";
- for (byte i = 0; i < 20; i++) { // waarden uit het flashgeheugen invullen in html-inputvelden
- html1 += (i + 1);
- html1 += ". ";
- html1 += "<input type='number' class='inputveld' id='a";
- html1 += i;
- html1 += "' value='";
- html1 += codes[i];
- html1 += "'><br><br>\r\n";
- }
- html1 += "<span class='knop' onClick='stuurDoor()'>Opslaan</span></a>\r\n";
- html1 += "</span><hr>";
- html1 += "</body>\r\n<script>\r\nfunction stuurDoor() {\r\n var url = 'codesOpgeslagen/?';\r\n";
- for (byte i = 0; i < 20; i++) { // alle (gewijzigde) waarden doorgeven in URL-parameters
- html1 += " url = url + 'a"; // http://1.2.3.4/codesOpgeslagen/?a0=123456&a1=987654 enz.
- html1 += i;
- html1 += "=' + document.getElementById('a";
- html1 += i;
- html1 += "').value + '&';\r\n";
- }
- html1 += "window.location.href=url;\r\n}\r\n</script>\r\n</html>\r\n";
- return html1;
- }
- String opgeslagenHtml() { // pagina "waarden zijn opgeslagen"
- String html2 = "<span style='color: green'>Bewaard</span>\r\n</div><br><br><br><br>\r\n<h1><span style='color: ";
- html2 += "green'>De waarden zijn opgeslagen.</span>\r\n</h1></body>\r\n</html>\r\n";
- return html2;
- }
- String geenWijzigingHtml() { // pagina "geen wijzigingen"
- String html2 = "<span style='color: green'>OK</span>\r\n</div><br><br><br><br>\r\n<h1><span style='color: ";
- html2 += "green'>Geen wijzigingen aangebracht.</span>\r\n</h1></body>\r\n</html>\r\n";
- return html2;
- }
- String nietGevondenHtml() { // pagina "error 404"
- String html3 = "404 Bestaat niet\r\n</div><br><br><br><br>\r\n";
- html3 += "<h1><span style='color: red'>Pagina ontbreekt</rd></h1>\r\n</body>\r\n</html>\r\n";
- return html3;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement