From 31fea83a3a6414558a31c235ca7f02809ba12a6a Mon Sep 17 00:00:00 2001 From: willem Date: Wed, 27 Sep 2023 14:09:52 +0200 Subject: [PATCH] esp32 + ota + doublereset --- .../lib/nixie/NCM107_component.h | 2 + FW/NCM107-ESP32C3/pins.txt | 32 +- FW/NCM107-ESP32C3/platformio.ini | 15 +- FW/NCM107-ESP32C3/src/clock.cpp | 30 +- FW/NCM107-ESP32C3/src/clock.h | 7 +- FW/NCM107-ESP32C3/src/connection.cpp | 16 + FW/NCM107-ESP32C3/src/connection.h | 6 + FW/NCM107-ESP32C3/src/defines.h | 41 + FW/NCM107-ESP32C3/src/main.cpp | 324 +------- FW/NCM107-ESP32C3/src/ntp.cpp | 117 --- FW/NCM107-ESP32C3/src/ntp.h | 17 - FW/NCM107-ESP32C3/src/ota.cpp | 63 ++ FW/NCM107-ESP32C3/src/ota.h | 9 + FW/NCM107-ESP32C3/src/tubes.cpp | 246 ++++++ FW/NCM107-ESP32C3/src/tubes.h | 15 + FW/NCM107-ESP32C3/src/wifimanager.cpp | 756 ++++++++++++++++++ FW/NCM107-ESP32C3/src/wifimanager.h | 303 +++++++ 17 files changed, 1516 insertions(+), 483 deletions(-) create mode 100644 FW/NCM107-ESP32C3/lib/nixie/NCM107_component.h create mode 100644 FW/NCM107-ESP32C3/src/connection.cpp create mode 100644 FW/NCM107-ESP32C3/src/connection.h create mode 100644 FW/NCM107-ESP32C3/src/defines.h delete mode 100644 FW/NCM107-ESP32C3/src/ntp.cpp delete mode 100644 FW/NCM107-ESP32C3/src/ntp.h create mode 100644 FW/NCM107-ESP32C3/src/ota.cpp create mode 100644 FW/NCM107-ESP32C3/src/ota.h create mode 100644 FW/NCM107-ESP32C3/src/tubes.cpp create mode 100644 FW/NCM107-ESP32C3/src/tubes.h create mode 100644 FW/NCM107-ESP32C3/src/wifimanager.cpp create mode 100644 FW/NCM107-ESP32C3/src/wifimanager.h diff --git a/FW/NCM107-ESP32C3/lib/nixie/NCM107_component.h b/FW/NCM107-ESP32C3/lib/nixie/NCM107_component.h new file mode 100644 index 0000000..34370fe --- /dev/null +++ b/FW/NCM107-ESP32C3/lib/nixie/NCM107_component.h @@ -0,0 +1,2 @@ +#include "esphome.h" + diff --git a/FW/NCM107-ESP32C3/pins.txt b/FW/NCM107-ESP32C3/pins.txt index 30391d2..f0f1a3d 100644 --- a/FW/NCM107-ESP32C3/pins.txt +++ b/FW/NCM107-ESP32C3/pins.txt @@ -1,19 +1,23 @@ -Anode0Pin 5=PD5= PIN 11 (ANT0) ==> GPIO10 -Anode1Pin 7=PD7= PIN 13 (ANT1) ==> GPIO3 -Anode2Pin 8=PB0= PIN 14 (ANT2) ==> GPIO8 +Anode0Pin 5=PD5= PIN 11 (ANT0) ==> GPIO5 gr - ok +Anode1Pin 7=PD7= PIN 13 (ANT1) ==> GPIO13 gr - ok +Anode2Pin 8=PB0= PIN 14 (ANT2) ==> GPIO17 gr - ok -LEpin=10=PB2= PIN 16 (LE) ==> GPIO7 +LEpin=10=PB2= PIN 16 (LE) ==> GPIO22 gr - ok -MOSI=PB3 PIN 17 (MOSI) ==> GPIO6 -SCK=PB5 PIN 19 (SCK) ==> GPIO5 +MOSI=PB3 PIN 17 (MOSI) ==> GPIO23 gr - ok +SCK=PB5 PIN 19 (SCK) ==> GPIO18 gr - ok -SDA=PC4 PIN 27 (SDA) ==> GPIO0 -SCL=PC5 PIN 28 (SCL) ==> GPIO1 +SDA=PC4 PIN 27 (SDA) ==> x +SCL=PC5 PIN 28 (SCL) ==> x -MODE=A0 =PC0 PIN 23 (SW1) ==> x -DOWN=A1 =PC1 PIN 24 (SW2) ==> GPIO4 -UP=A2 =PC2 PIN 25 (SW3) ==> GPIO2 +MODE=A0 =PC0 PIN 23 (SW1) ==> GPIO16 pa - ok +DOWN=A1 =PC1 PIN 24 (SW2) ==> GPIO4 pa - ok +UP=A2 =PC2 PIN 25 (SW3) ==> GPIO2 pa - ok -LEDR=9=PB1 PIN 15 (PWM2) x -LEDG=6=PD6 PIN 12 (PWM1) x -LEDB=3=PD3. PIN 5 (PWM3) x +LEDR=9=PB1 PIN 15 (PWM2) ==> GPIO25 ye - ok +LEDG=6=PD6 PIN 12 (PWM1) ==> GPIO26 ye - ok +LEDB=3=PD3 PIN 5 (PWM3) ==> GPIO27 ye - ok + + +GND pin 8 ok +VCC PIN 7 ok diff --git a/FW/NCM107-ESP32C3/platformio.ini b/FW/NCM107-ESP32C3/platformio.ini index 66458e8..c19fea3 100644 --- a/FW/NCM107-ESP32C3/platformio.ini +++ b/FW/NCM107-ESP32C3/platformio.ini @@ -8,16 +8,19 @@ ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html -[env:seeed_xiao_esp32c3] +[env:esp32] platform = espressif32 -board = seeed_xiao_esp32c3 +board = esp32dev framework = arduino +monitor_speed = 115200 lib_deps = - paulstoffregen/Time@^1.6.1 jchristensen/Timezone@^1.2.4 - ESPNtpClient -build_src_filter = ${env.build_src_filter} + khoih-prog/ESP_WifiManager@^1.12.1 + LittleFS + #jandrassy/ArduinoOTA@^1.0.11 lib_ldf_mode = deep+ build_flags = -DCORE_DEBUG_LEVEL=3 - -DNDEF_DEBUG=1 \ No newline at end of file + -DNDEF_DEBUG=1 +upload_protocol = espota +upload_port = nixie_clock.local \ No newline at end of file diff --git a/FW/NCM107-ESP32C3/src/clock.cpp b/FW/NCM107-ESP32C3/src/clock.cpp index b84e332..5995d9b 100644 --- a/FW/NCM107-ESP32C3/src/clock.cpp +++ b/FW/NCM107-ESP32C3/src/clock.cpp @@ -1,17 +1,14 @@ #include "clock.h" -bool RTC_present; -bool NTPinit = false; -// Central European Time (Frankfurt, Paris) +bool RTC_present = false; +bool provider_Set = false; +// // Central European Time (Frankfurt, Paris) TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120}; // Central European Summer Time TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60}; // Central European Standard Time Timezone myTZ(CEST, CET); TimeChangeRule *tcr; - - - bool timeIsSet() { return RTC_present; @@ -29,31 +26,34 @@ void printDateTime(time_t t, const char *tz) time_t getLocalTime() { - if(!getWifiStatus) return 0; - time_t utc = getNtpTime(); + if(!getWifiStatus()) return 0; + time_t utc; + time(&utc); time_t local = myTZ.toLocal(utc, &tcr); printDateTime(local,tcr -> abbrev); printDateTime(utc,"UTC"); - return utc; + return local; } void initClock() { - initWifi(); + getLocalTime(); } + void loopClock() { - if(getWifiStatus()) + if(getWifiStatus()) { - if(!NTPinit && getWifiStatus()) + if(getWifiStatus() & !provider_Set) { - initNTP(); setSyncProvider(getLocalTime); - setSyncInterval(300); - NTPinit = true; + setSyncInterval(10); + provider_Set = true; + log_i("timesync provider set"); } + RTC_present = timeStatus ? timeSet: true, false; } else diff --git a/FW/NCM107-ESP32C3/src/clock.h b/FW/NCM107-ESP32C3/src/clock.h index 129f33d..d7dba0e 100644 --- a/FW/NCM107-ESP32C3/src/clock.h +++ b/FW/NCM107-ESP32C3/src/clock.h @@ -1,17 +1,12 @@ #pragma once #include -#include "ntp.h" -#include "TimeLib.h" +#include "connection.h" #include "util.h" #include // https://github.com/JChristensen/Timezone -#include - - void initClock(); void loopClock(); String getTimeNow(); String updateDateString(); -// bool isValidDate(); bool timeIsSet(); \ No newline at end of file diff --git a/FW/NCM107-ESP32C3/src/connection.cpp b/FW/NCM107-ESP32C3/src/connection.cpp new file mode 100644 index 0000000..be4c27c --- /dev/null +++ b/FW/NCM107-ESP32C3/src/connection.cpp @@ -0,0 +1,16 @@ +#include "connection.h" + +bool printed = false; +bool wifiConnected = false; + +bool getWifiStatus() +{ + wifiConnected = WiFi.status() == WL_CONNECTED; + + if(!printed && wifiConnected) + { + log_i("IP number assigned by DHCP is %s",WiFi.localIP()); + printed = true; + } + return wifiConnected; +} diff --git a/FW/NCM107-ESP32C3/src/connection.h b/FW/NCM107-ESP32C3/src/connection.h new file mode 100644 index 0000000..f84d46a --- /dev/null +++ b/FW/NCM107-ESP32C3/src/connection.h @@ -0,0 +1,6 @@ +#pragma once +#include "Arduino.h" +#include + +bool getWifiStatus(); + diff --git a/FW/NCM107-ESP32C3/src/defines.h b/FW/NCM107-ESP32C3/src/defines.h new file mode 100644 index 0000000..09dedce --- /dev/null +++ b/FW/NCM107-ESP32C3/src/defines.h @@ -0,0 +1,41 @@ +#pragma once + + +#define Anode0Pin 5 +#define Anode1Pin 13 +#define Anode2Pin 17 +#define mosiPin 23 +#define misoPin 19 +#define sckPin 18 +#define LEpin 22 +#define upPin 2 +#define downPin 4 +#define modePin 16 +#define ledRPin 25 +#define ledGPin 26 +#define ledBPin 27 + +#define Anode0ON digitalWrite(Anode0Pin,HIGH) +#define Anode0OFF digitalWrite(Anode0Pin,LOW) + +#define Anode1ON digitalWrite(Anode1Pin,HIGH) +#define Anode1OFF digitalWrite(Anode1Pin,LOW) + +#define Anode2ON digitalWrite(Anode2Pin,HIGH) +#define Anode2OFF digitalWrite(Anode2Pin,LOW) + +#define TimeIndex 0 +#define DateIndex 1 +// #define AlarmIndex 2 +// #define hModeIndex 3 +// #define TimeHoursIndex 4 +// #define TimeMintuesIndex 5 +// #define TimeSecondsIndex 6 +// #define DateDayIndex 7 +// #define DateMonthIndex 8 +// #define DateYearIndex 9 +// #define AlarmHourIndex 10 +// #define AlarmMinuteIndex 11 +// #define AlarmSecondIndex 12 +// #define Alarm01 13 +// #define hModeValueIndex 14 \ No newline at end of file diff --git a/FW/NCM107-ESP32C3/src/main.cpp b/FW/NCM107-ESP32C3/src/main.cpp index a3cf826..34ab28e 100644 --- a/FW/NCM107-ESP32C3/src/main.cpp +++ b/FW/NCM107-ESP32C3/src/main.cpp @@ -1,83 +1,9 @@ #include #include "clock.h" - - -#include -#include - -#define Anode0Pin 10 -#define Anode1Pin 3 -#define Anode2Pin 8 - -#define Anode0ON digitalWrite(Anode0Pin,HIGH) -#define Anode0OFF digitalWrite(Anode0Pin,LOW) - -#define Anode1ON digitalWrite(Anode1Pin,HIGH) -#define Anode1OFF digitalWrite(Anode1Pin,LOW) - -#define Anode2ON digitalWrite(Anode2Pin,HIGH) -#define Anode2OFF digitalWrite(Anode2Pin,LOW) - -#define mosiPin 5 -#define misoPin 9 -#define sckPin 6 -#define LEpin 7 - - #define TimeIndex 0 - #define DateIndex 1 -// #define AlarmIndex 2 -// #define hModeIndex 3 -// #define TimeHoursIndex 4 -// #define TimeMintuesIndex 5 -// #define TimeSecondsIndex 6 -// #define DateDayIndex 7 -// #define DateMonthIndex 8 -// #define DateYearIndex 9 -// #define AlarmHourIndex 10 -// #define AlarmMinuteIndex 11 -// #define AlarmSecondIndex 12 -// #define Alarm01 13 -// #define hModeValueIndex 14 - -String updateDateString(); -String updateDisplayString(); -// void doDotBlink(); -// void checkAlarmTime(); -// String PreZero(int digit); -word doEditBlink(int pos); -// byte decToBcd(byte val); -String antiPoisoning2(String fromStr, String toStr); -// String getTimeNow(); -String antiPoisoning2(String fromStr, String toStr); -bool doTest(); -// void getRTCTime(); -void modesChanger(); -void doIndication(); - -const word fpsLimit=16666; // 1/60*1.000.000 //limit maximum refresh rate on 60 fps - -String stringToDisplay="000000";// Conten of this string will be displayed on tubes (must be 6 chars length) -int menuPosition=0; // 0 - time - // 1 - date - // 2 - alarm - // 3 - 12/24 hours mode - - -// 0 1 2 3 4 5 6 7 8 9 -//word SymbolArray[10]={65534, 65533, 65531, 65527, 65519, 65503, 65471, 65407, 65279, 65023}; -word SymbolArray[10]={1022, 1021, 1019, 1015, 1007, 991, 959, 895, 767, 511}; - -byte dotPattern=B00000000; //bit mask for separeting dots - //B00000000 - turn off up and down dots - //B1100000 - turn off all dots - - - -int teststate = -1; -String testStringArray[12]={"000000","111111","222222","333333","444444","555555","666666","777777","888888","999999","",""}; -unsigned long startOfTest; - - +#include "defines.h" +#include "wifimanager.h" +#include "tubes.h" +#include "ota.h" /******************************************************************************************************* Init Programm @@ -88,252 +14,34 @@ void setup() Serial.begin(115200); log_i("init hardware"); + initTubes(); + + pinMode(ledRPin, OUTPUT); + pinMode(ledGPin, OUTPUT); + pinMode(ledBPin, OUTPUT); - pinMode(LEpin, OUTPUT); - - // SPI setup - SPI.begin(mosiPin,misoPin,sckPin); // - SPI.setDataMode (SPI_MODE3); // Mode 3 SPI - SPI.setClockDivider(SPI_CLOCK_DIV128); // SCK = 16MHz/128= 125kHz - - pinMode(Anode0Pin, OUTPUT); - pinMode(Anode1Pin, OUTPUT); - pinMode(Anode2Pin, OUTPUT); + digitalWrite(ledRPin, 0); + digitalWrite(ledGPin, 0); + digitalWrite(ledBPin, 0); log_i("init clock"); + setupwifiman(); initClock(); + initOTA(); - //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! while(!timeIsSet()) { doTest(); loopClock(); } - log_i("init done, GO!"); - - //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - } - -//antipoisoning transaction -bool modeChangedByUser=false; -bool transactionInProgress=false; -#define timeModePeriod 60000 -#define dateModePeriod 5000 -long modesChangePeriod=timeModePeriod; -//antipoisoning end - /*************************************************************************************************************** MAIN Programm ***************************************************************************************************************/ void loop() { - - loopClock(); - - if ((menuPosition==TimeIndex) || (modeChangedByUser==false) ) modesChanger(); - doIndication(); - - static bool updateDateTime=false; - switch (menuPosition) - { - case TimeIndex: //time mode - if (!transactionInProgress) stringToDisplay=updateDisplayString(); - break; - case DateIndex: //date mode - if (!transactionInProgress) stringToDisplay=updateDateString(); - dotPattern=B01000000;//turn on lower dots - break; - - } -} - -int dlay=500; -// bool test=1; -byte strIndex=-1; -// bool digitsLock=false; - -bool doTest() -{ - if(!timeIsSet()) return true; - - if(teststate == -1) - { - Serial.println(F("Start Test")); - startOfTest=millis(); - teststate = 0; - Serial.println(testStringArray[10]); - } - - // byte b=1; - - if ((millis()-startOfTest)>dlay) - { - startOfTest=millis(); - strIndex=strIndex+1; - if (strIndex==10) dlay=3000; - - stringToDisplay=testStringArray[strIndex]; - Serial.print("stringToDisplay="); - Serial.println(stringToDisplay); - Serial.print("strIndex="); - Serial.println(strIndex); - Serial.print("i="); - Serial.println(teststate); - - if (strIndex==11) strIndex = -1; - - } - - doIndication(); - - return false; -} - -void doIndication() -{ - static byte b=1; - - static unsigned long lastTimeInterval1Started; - if ((micros()-lastTimeInterval1Started)>5000) - { - lastTimeInterval1Started=micros(); - Anode0OFF; Anode1OFF; Anode2OFF; - unsigned long var32; - unsigned long tmpVar; - - int curTube=b*2-2; - var32=SymbolArray[stringToDisplay.substring(curTube, curTube+1).toInt()]; - tmpVar=SymbolArray[stringToDisplay.substring(curTube+1, curTube+2).toInt()]; - - var32 |= tmpVar<<10; - - digitalWrite(LEpin, LOW); // allow data input (Transparent mode) - - SPI.transfer(var32>>16); //[A3][A2][A1][A0][RC9][RC8][RC7][RC6] - A5-A0 - anodes - SPI.transfer(var32>>8); //[RC5][RC4][RC3][RC2][RC1][RC0][LC9][RC8] - RC9-RC0 - Right tubes cathodes - SPI.transfer(var32); - - digitalWrite(LEpin, HIGH); // latching data - - switch (b) - { - case 1:{Anode0ON; Anode1OFF; Anode2OFF; break;}; - case 2:{Anode0OFF; Anode1ON; Anode2OFF; break;}; - case 3:{Anode0OFF; Anode1OFF; Anode2ON; break;}; - } - b=b+1; - if (b==4) {b=1;} - } -} - - -void doDotBlink() -{ - static unsigned long lastTimeBlink=millis(); - static bool dotState=0; - if ((millis()-lastTimeBlink)>1000) - { - lastTimeBlink=millis(); - dotState=!dotState; - if (dotState) - { - dotPattern=B11000000; - /*digitalWrite(pinUpperDots, HIGH); - digitalWrite(pinLowerDots, HIGH);*/ - } - else - { - dotPattern=B00000000; - /*digitalWrite(pinUpperDots, LOW); - digitalWrite(pinLowerDots, LOW);*/ - } - } -} - - -byte decToBcd(byte val){ -// Convert normal decimal numbers to binary coded decimal - return ( (val/10*16) + (val%10) ); -} - -byte bcdToDec(byte val) { -// Convert binary coded decimal to normal decimal numbers - return ( (val/16*10) + (val%16) ); -} - -void modesChanger() -{ - static unsigned long lastTimeModeChanged=millis(); - static unsigned long lastTimeAntiPoisoningIterate=millis(); - if ((millis()-lastTimeModeChanged)>modesChangePeriod) - { - lastTimeModeChanged=millis(); - if (menuPosition==TimeIndex) {menuPosition=DateIndex; modesChangePeriod=dateModePeriod;} - else {menuPosition=TimeIndex; modesChangePeriod=timeModePeriod;} - if (modeChangedByUser==true) - { - menuPosition=TimeIndex; - } - modeChangedByUser=false; - } - if ((millis()-lastTimeModeChanged)<2000) - { - if ((millis()-lastTimeAntiPoisoningIterate)>100) - { - lastTimeAntiPoisoningIterate=millis(); - if (menuPosition==TimeIndex) - stringToDisplay=antiPoisoning2(updateDateString(), getTimeNow()); - else stringToDisplay=antiPoisoning2(getTimeNow(), updateDateString()); - // Serial.println("StrTDInToModeChng="+stringToDisplay); - } - } else transactionInProgress=false; -} - -String antiPoisoning2(String fromStr, String toStr) -{ - //static bool transactionInProgress=false; - //byte fromDigits[6]; - static byte toDigits[6]; - static byte currentDigits[6]; - static byte iterationCounter=0; - if (!transactionInProgress) - { - transactionInProgress=true; - for (int i=0; i<6; i++) - { - currentDigits[i]=fromStr.substring(i, i+1).toInt(); - toDigits[i]=toStr.substring(i, i+1).toInt(); - } - } - for (int i=0; i<6; i++) - { - if (iterationCounter<10) currentDigits[i]++; - else if (currentDigits[i]!=toDigits[i]) currentDigits[i]++; - if (currentDigits[i]==10) currentDigits[i]=0; - } - iterationCounter++; - if (iterationCounter==20) - { - iterationCounter=0; - transactionInProgress=false; - } - String tmpStr; - for (int i=0; i<6; i++) - tmpStr+=currentDigits[i]; - return tmpStr; -} - -String updateDisplayString() -{ - static unsigned long lastTimeStringWasUpdated; - if ((millis()-lastTimeStringWasUpdated)>1000) - { - lastTimeStringWasUpdated=millis(); - return getTimeNow(); - } - return stringToDisplay; + loopTubes(); + loopOTA(); } \ No newline at end of file diff --git a/FW/NCM107-ESP32C3/src/ntp.cpp b/FW/NCM107-ESP32C3/src/ntp.cpp deleted file mode 100644 index edc34f7..0000000 --- a/FW/NCM107-ESP32C3/src/ntp.cpp +++ /dev/null @@ -1,117 +0,0 @@ -#include "ntp.h" - - -static const char ntpServerName[] = "us.pool.ntp.org"; -// const int timeZone = 2; -// unsigned int localPort = 8888; // local port to listen for UDP packets -const char *ssid = "iot"; -const char *password = "Rijnstraat214"; -// const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message -// byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets -// const unsigned int remotePort = 123; - -bool printed = false; -bool wifiConnected = false; - - - -// WiFiUDP Udp; - - -// bool timeUpdated() -// { -// return _timeupdated; -// } - -void initWifi() -{ - log_i("init wifi"); - WiFi.begin(ssid, password); -} - -void initNTP() -{ - log_i("init ntp"); - NTP.setTimeZone(TZ_Etc_UTC); - NTP.begin(); - // Udp.begin(localPort); -} - -bool getWifiStatus() -{ - wifiConnected = WiFi.status() == WL_CONNECTED; - - if(!printed && wifiConnected) - { - Serial.print("IP number assigned by DHCP is "); - Serial.println(WiFi.localIP()); - printed = true; - } - return wifiConnected; -} - - -// // send an NTP request to the time server at the given address -// void sendNTPpacket(IPAddress &address) -// { -// // set all bytes in the buffer to 0 -// memset(packetBuffer, 0, NTP_PACKET_SIZE); -// // Initialize values needed to form NTP request -// // (see URL above for details on the packets) -// packetBuffer[0] = 0b11100011; // LI, Version, Mode -// packetBuffer[1] = 0; // Stratum, or type of clock -// packetBuffer[2] = 6; // Polling Interval -// packetBuffer[3] = 0xEC; // Peer Clock Precision -// // 8 bytes of zero for Root Delay & Root Dispersion -// packetBuffer[12] = 49; -// packetBuffer[13] = 0x4E; -// packetBuffer[14] = 49; -// packetBuffer[15] = 52; -// // all NTP fields have been given values, now -// // you can send a packet requesting a timestamp: -// Udp.beginPacket(address, 123); // NTP requests are to port 123 -// Udp.write(packetBuffer, NTP_PACKET_SIZE); -// Udp.endPacket(); -// } - -time_t getNtpTime() -{ - static int last = 0; - - if ((millis () - last) > 1000) { - last = millis (); - Serial.println (NTP.getTimeDateStringUs ()); - } - - return NTP.getLastNTPSync(); -// IPAddress ntpServerIP; // NTP server's ip address - -// while (Udp.parsePacket() > 0) -// ; // discard any previously received packets -// Serial.println("Transmit NTP Request"); -// // get a random server from the pool -// WiFi.hostByName(ntpServerName, ntpServerIP); -// Serial.print(ntpServerName); -// Serial.print(": "); -// Serial.println(ntpServerIP); -// sendNTPpacket(ntpServerIP); -// uint32_t beginWait = millis(); -// while (millis() - beginWait < 3000) -// { -// int size = Udp.parsePacket(); -// if (size >= NTP_PACKET_SIZE) -// { -// Serial.printf("Receive NTP Response in %dms \n",(millis() - beginWait)); -// Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer -// unsigned long secsSince1900; -// // convert four bytes starting at location 40 to a long integer -// secsSince1900 = (unsigned long)packetBuffer[40] << 24; -// secsSince1900 |= (unsigned long)packetBuffer[41] << 16; -// secsSince1900 |= (unsigned long)packetBuffer[42] << 8; -// secsSince1900 |= (unsigned long)packetBuffer[43]; -// return secsSince1900 - 2208988800UL * SECS_PER_HOUR; -// } -// } -// Serial.println("No NTP Response :-("); -// return 0; // return 0 if unable to get the time -} diff --git a/FW/NCM107-ESP32C3/src/ntp.h b/FW/NCM107-ESP32C3/src/ntp.h deleted file mode 100644 index 29064e7..0000000 --- a/FW/NCM107-ESP32C3/src/ntp.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "Arduino.h" -#include -#include -#include -#include - - - -void initNTP(); -void initWifi(); - -void loopNTP(); - -time_t getNtpTime(); -bool getWifiStatus(); -bool timeUpdated(); diff --git a/FW/NCM107-ESP32C3/src/ota.cpp b/FW/NCM107-ESP32C3/src/ota.cpp new file mode 100644 index 0000000..206c8e1 --- /dev/null +++ b/FW/NCM107-ESP32C3/src/ota.cpp @@ -0,0 +1,63 @@ +#include "ota.h" + + +void initOTA() { + Serial.begin(115200); + Serial.println("Booting"); +// WiFi.mode(WIFI_STA); +// WiFi.begin(ssid, password); + while (WiFi.waitForConnectResult() != WL_CONNECTED) { + Serial.println("Connection Failed! Rebooting..."); + delay(5000); + ESP.restart(); + } + + // Port defaults to 3232 + // ArduinoOTA.setPort(3232); + + // Hostname defaults to esp3232-[MAC] + ArduinoOTA.setHostname("nixie_clock"); + + // No authentication by default + // ArduinoOTA.setPassword("admin"); + + // Password can be set with it's md5 value as well + // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3 + // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3"); + + ArduinoOTA + .onStart([]() { + String type; + if (ArduinoOTA.getCommand() == U_FLASH) + type = "sketch"; + else // U_SPIFFS + type = "filesystem"; + + // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end() + Serial.println("Start updating " + type); + }) + .onEnd([]() { + Serial.println("\nEnd"); + }) + .onProgress([](unsigned int progress, unsigned int total) { + Serial.printf("Progress: %u%%\r", (progress / (total / 100))); + }) + .onError([](ota_error_t error) { + Serial.printf("Error[%u]: ", error); + if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); + else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed"); + else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed"); + else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); + else if (error == OTA_END_ERROR) Serial.println("End Failed"); + }); + + ArduinoOTA.begin(); + + Serial.println("Ready"); + Serial.print("IP address: "); + Serial.println(WiFi.localIP()); +} + +void loopOTA() { + ArduinoOTA.handle(); +} \ No newline at end of file diff --git a/FW/NCM107-ESP32C3/src/ota.h b/FW/NCM107-ESP32C3/src/ota.h new file mode 100644 index 0000000..9a70830 --- /dev/null +++ b/FW/NCM107-ESP32C3/src/ota.h @@ -0,0 +1,9 @@ +#pragma once + +#include +#include +#include +#include + +void initOTA(); +void loopOTA(); \ No newline at end of file diff --git a/FW/NCM107-ESP32C3/src/tubes.cpp b/FW/NCM107-ESP32C3/src/tubes.cpp new file mode 100644 index 0000000..c83c96a --- /dev/null +++ b/FW/NCM107-ESP32C3/src/tubes.cpp @@ -0,0 +1,246 @@ +#include "tubes.h" + + +const word fpsLimit=16666; // 1/60*1.000.000 //limit maximum refresh rate on 60 fps + +String stringToDisplay="000000";// Conten of this string will be displayed on tubes (must be 6 chars length) +int menuPosition=0; // 0 - time + // 1 - date + // 2 - alarm + // 3 - 12/24 hours mode + + +// 0 1 2 3 4 5 6 7 8 9 +//word SymbolArray[10]={65534, 65533, 65531, 65527, 65519, 65503, 65471, 65407, 65279, 65023}; +word SymbolArray[10]={1022, 1021, 1019, 1015, 1007, 991, 959, 895, 767, 511}; + +byte dotPattern=B00000000; //bit mask for separeting dots + //B00000000 - turn off up and down dots + //B1100000 - turn off all dots + + + +int teststate = -1; +String testStringArray[12]={"000000","111111","222222","333333","444444","555555","666666","777777","888888","999999","",""}; +unsigned long startOfTest; + +bool modeChangedByUser=false; +bool transactionInProgress=false; +#define timeModePeriod 60000 +#define dateModePeriod 5000 +long modesChangePeriod=timeModePeriod; + + + +static unsigned long lastTimeInterval1Started; + + + +int dlay=500; +// bool test=1; +byte strIndex=-1; +// bool digitsLock=false; + +bool doTest() +{ + if(!timeIsSet()) return true; + + if(teststate == -1) + { + Serial.println(F("Start Test")); + startOfTest=millis(); + teststate = 0; + Serial.println(testStringArray[10]); + } + + // byte b=1; + + if ((millis()-startOfTest)>dlay) + { + startOfTest=millis(); + strIndex=strIndex+1; + if (strIndex==10) dlay=3000; + + stringToDisplay=testStringArray[strIndex]; + Serial.print("stringToDisplay="); + Serial.println(stringToDisplay); + Serial.print("strIndex="); + Serial.println(strIndex); + Serial.print("i="); + Serial.println(teststate); + + if (strIndex==11) strIndex = -1; + + } + + doIndication(); + + return false; +} + + +String antiPoisoning2(String fromStr, String toStr) +{ + //static bool transactionInProgress=false; + //byte fromDigits[6]; + static byte toDigits[6]; + static byte currentDigits[6]; + static byte iterationCounter=0; + if (!transactionInProgress) + { + transactionInProgress=true; + for (int i=0; i<6; i++) + { + currentDigits[i]=fromStr.substring(i, i+1).toInt(); + toDigits[i]=toStr.substring(i, i+1).toInt(); + } + } + for (int i=0; i<6; i++) + { + if (iterationCounter<10) currentDigits[i]++; + else if (currentDigits[i]!=toDigits[i]) currentDigits[i]++; + if (currentDigits[i]==10) currentDigits[i]=0; + } + iterationCounter++; + if (iterationCounter==20) + { + iterationCounter=0; + transactionInProgress=false; + } + String tmpStr; + for (int i=0; i<6; i++) + tmpStr+=currentDigits[i]; + return tmpStr; +} + +void modesChanger() +{ + static unsigned long lastTimeModeChanged=millis(); + static unsigned long lastTimeAntiPoisoningIterate=millis(); + if ((millis()-lastTimeModeChanged)>modesChangePeriod) + { + lastTimeModeChanged=millis(); + if (menuPosition==TimeIndex) {menuPosition=DateIndex; modesChangePeriod=dateModePeriod;} + else {menuPosition=TimeIndex; modesChangePeriod=timeModePeriod;} + if (modeChangedByUser==true) + { + menuPosition=TimeIndex; + } + modeChangedByUser=false; + } + if ((millis()-lastTimeModeChanged)<2000) + { + if ((millis()-lastTimeAntiPoisoningIterate)>100) + { + lastTimeAntiPoisoningIterate=millis(); + if (menuPosition==TimeIndex) + stringToDisplay=antiPoisoning2(updateDateString(), getTimeNow()); + else stringToDisplay=antiPoisoning2(getTimeNow(), updateDateString()); + // Serial.println("StrTDInToModeChng="+stringToDisplay); + } + } else transactionInProgress=false; +} + + +String updateDisplayString() +{ + static unsigned long lastTimeStringWasUpdated; + if ((millis()-lastTimeStringWasUpdated)>1000) + { + lastTimeStringWasUpdated=millis(); + return getTimeNow(); + } + return stringToDisplay; +} + + + +void doIndication() +{ + static byte b=1; + if ((millis()-lastTimeInterval1Started)>3) + { + lastTimeInterval1Started=millis(); + log_v("update tubes"); + Anode0OFF; Anode1OFF; Anode2OFF; + unsigned long var32; + unsigned long tmpVar; + + int curTube=b*2-2; + var32=SymbolArray[stringToDisplay.substring(curTube, curTube+1).toInt()]; + tmpVar=SymbolArray[stringToDisplay.substring(curTube+1, curTube+2).toInt()]; + + var32 |= tmpVar<<10; + + digitalWrite(LEpin, LOW); // allow data input (Transparent mode) + + SPI.transfer(var32>>16); //[A3][A2][A1][A0][RC9][RC8][RC7][RC6] - A5-A0 - anodes + SPI.transfer(var32>>8); //[RC5][RC4][RC3][RC2][RC1][RC0][LC9][RC8] - RC9-RC0 - Right tubes cathodes + SPI.transfer(var32); + + digitalWrite(LEpin, HIGH); // latching data + + switch (b) + { + case 1:{Anode0ON; Anode1OFF; Anode2OFF; break;}; + case 2:{Anode0OFF; Anode1ON; Anode2OFF; break;}; + case 3:{Anode0OFF; Anode1OFF; Anode2ON; break;}; + } + b=b+1; + if (b==4) {b=1;} + } +} + +void doDotBlink() +{ + static unsigned long lastTimeBlink=millis(); + static bool dotState=0; + if ((millis()-lastTimeBlink)>1000) + { + lastTimeBlink=millis(); + dotState=!dotState; + if (dotState) + { + dotPattern=B11000000; + } + else + { + dotPattern=B00000000; + } + } +} + + +void initTubes() +{ + pinMode(LEpin, OUTPUT); + + // SPI setup + SPI.begin(sckPin,misoPin,mosiPin); // + SPI.setDataMode (SPI_MODE3); // Mode 3 SPI + SPI.setClockDivider(SPI_CLOCK_DIV128); // SCK = 16MHz/128= 125kHz + + pinMode(Anode0Pin, OUTPUT); + pinMode(Anode1Pin, OUTPUT); + pinMode(Anode2Pin, OUTPUT); +} + +void loopTubes() +{ + if ((menuPosition==TimeIndex) || (modeChangedByUser==false) ) modesChanger(); + doIndication(); + + static bool updateDateTime=false; + switch (menuPosition) + { + case TimeIndex: //time mode + if (!transactionInProgress) stringToDisplay=updateDisplayString(); + break; + case DateIndex: //date mode + if (!transactionInProgress) stringToDisplay=updateDateString(); + dotPattern=B01000000;//turn on lower dots + break; + + } + +} \ No newline at end of file diff --git a/FW/NCM107-ESP32C3/src/tubes.h b/FW/NCM107-ESP32C3/src/tubes.h new file mode 100644 index 0000000..cecf24d --- /dev/null +++ b/FW/NCM107-ESP32C3/src/tubes.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include "defines.h" +#include +#include "clock.h" + + +void initTubes(); +void loopTubes(); + +void doIndication(); +void doDotBlink(); +bool doTest(); + diff --git a/FW/NCM107-ESP32C3/src/wifimanager.cpp b/FW/NCM107-ESP32C3/src/wifimanager.cpp new file mode 100644 index 0000000..83c1140 --- /dev/null +++ b/FW/NCM107-ESP32C3/src/wifimanager.cpp @@ -0,0 +1,756 @@ +#include "wifimanager.h" + +#ifdef ESP32 + + WiFiMulti wifiMulti; + + #if USE_LITTLEFS + FS* filesystem = &FileFS; + + #elif USE_SPIFFS + FS* filesystem = &SPIFFS; + #else + FS* filesystem = &FFat; + #endif +#endif +//DoubleResetDetector drd(DRD_TIMEOUT, DRD_ADDRESS); +DoubleResetDetector* drd;////// + +// Onboard LED I/O pin on NodeMCU board +const int PIN_LED = 2; // D4 on NodeMCU and WeMos. GPIO2/ADC12 of ESP32. Controls the onboard LED. + + +// Indicates whether ESP has WiFi credentials saved from previous session, or double reset detected +bool initialConfig = false; + +WM_Config WM_config; + +#if ( USE_DHCP_IP ) + // Use DHCP + + #if (_WIFIMGR_LOGLEVEL_ > 3) + #warning Using DHCP IP + #endif + + IPAddress stationIP = IPAddress(0, 0, 0, 0); + IPAddress gatewayIP = IPAddress(192, 168, 2, 1); + IPAddress netMask = IPAddress(255, 255, 255, 0); + +#else + // Use static IP + + #if (_WIFIMGR_LOGLEVEL_ > 3) + #warning Using static IP + #endif + + #ifdef ESP32 + IPAddress stationIP = IPAddress(192, 168, 2, 232); + #else + IPAddress stationIP = IPAddress(192, 168, 2, 186); + #endif + + IPAddress gatewayIP = IPAddress(192, 168, 2, 1); + IPAddress netMask = IPAddress(255, 255, 255, 0); +#endif + +//////////////////////////////////////////// + +#define USE_CONFIGURABLE_DNS true + +IPAddress dns1IP = gatewayIP; +IPAddress dns2IP = IPAddress(8, 8, 8, 8); + +#define USE_CUSTOM_AP_IP false + +// New in v1.4.0 +IPAddress APStaticIP = IPAddress(192, 168, 232, 1); +IPAddress APStaticGW = IPAddress(192, 168, 232, 1); +IPAddress APStaticSN = IPAddress(255, 255, 255, 0); + +// Must be placed before #include , or default port 80 will be used +//#define HTTP_PORT 8080 + +#include //https://github.com/khoih-prog/ESP_WiFiManager + +// Redundant, for v1.8.0 only +//#include //https://github.com/khoih-prog/ESP_WiFiManager + +// SSID and PW for Config Portal +String ssid = "ESP_" + String(ESP_getChipId(), HEX); +String password; + +// SSID and PW for your Router +String Router_SSID; +String Router_Pass; + +// Function Prototypes +uint8_t connectMultiWiFi(); + +/////////////////////////////////////////// +// New in v1.4.0 +/****************************************** + * // Defined in ESP_WiFiManager.h +typedef struct +{ + IPAddress _ap_static_ip; + IPAddress _ap_static_gw; + IPAddress _ap_static_sn; + +} WiFi_AP_IPConfig; + +typedef struct +{ + IPAddress _sta_static_ip; + IPAddress _sta_static_gw; + IPAddress _sta_static_sn; +#if USE_CONFIGURABLE_DNS + IPAddress _sta_static_dns1; + IPAddress _sta_static_dns2; +#endif +} WiFi_STA_IPConfig; +******************************************/ + +WiFi_AP_IPConfig WM_AP_IPconfig; +WiFi_STA_IPConfig WM_STA_IPconfig; + +void initAPIPConfigStruct(WiFi_AP_IPConfig &in_WM_AP_IPconfig) +{ + in_WM_AP_IPconfig._ap_static_ip = APStaticIP; + in_WM_AP_IPconfig._ap_static_gw = APStaticGW; + in_WM_AP_IPconfig._ap_static_sn = APStaticSN; +} + +void initSTAIPConfigStruct(WiFi_STA_IPConfig &in_WM_STA_IPconfig) +{ + in_WM_STA_IPconfig._sta_static_ip = stationIP; + in_WM_STA_IPconfig._sta_static_gw = gatewayIP; + in_WM_STA_IPconfig._sta_static_sn = netMask; +#if USE_CONFIGURABLE_DNS + in_WM_STA_IPconfig._sta_static_dns1 = dns1IP; + in_WM_STA_IPconfig._sta_static_dns2 = dns2IP; +#endif +} + +void displayIPConfigStruct(WiFi_STA_IPConfig in_WM_STA_IPconfig) +{ + LOGERROR3(F("stationIP ="), in_WM_STA_IPconfig._sta_static_ip, ", gatewayIP =", in_WM_STA_IPconfig._sta_static_gw); + LOGERROR1(F("netMask ="), in_WM_STA_IPconfig._sta_static_sn); +#if USE_CONFIGURABLE_DNS + LOGERROR3(F("dns1IP ="), in_WM_STA_IPconfig._sta_static_dns1, ", dns2IP =", in_WM_STA_IPconfig._sta_static_dns2); +#endif +} + +void configWiFi(WiFi_STA_IPConfig in_WM_STA_IPconfig) +{ + #if USE_CONFIGURABLE_DNS + // Set static IP, Gateway, Subnetmask, DNS1 and DNS2. New in v1.0.5 + WiFi.config(in_WM_STA_IPconfig._sta_static_ip, in_WM_STA_IPconfig._sta_static_gw, in_WM_STA_IPconfig._sta_static_sn, in_WM_STA_IPconfig._sta_static_dns1, in_WM_STA_IPconfig._sta_static_dns2); + #else + // Set static IP, Gateway, Subnetmask, Use auto DNS1 and DNS2. + WiFi.config(in_WM_STA_IPconfig._sta_static_ip, in_WM_STA_IPconfig._sta_static_gw, in_WM_STA_IPconfig._sta_static_sn); + #endif +} + +/////////////////////////////////////////// + +uint8_t connectMultiWiFi() +{ +#if ESP32 + // For ESP32, this better be 0 to shorten the connect time. + // For ESP32-S2/C3, must be > 500 + #if ( USING_ESP32_S2 || USING_ESP32_C3 ) + #define WIFI_MULTI_1ST_CONNECT_WAITING_MS 500L + #else + // For ESP32 core v1.0.6, must be >= 500 + #define WIFI_MULTI_1ST_CONNECT_WAITING_MS 800L + #endif +#else + // For ESP8266, this better be 2200 to enable connect the 1st time + #define WIFI_MULTI_1ST_CONNECT_WAITING_MS 2200L +#endif + +#define WIFI_MULTI_CONNECT_WAITING_MS 500L + + uint8_t status; + + //WiFi.mode(WIFI_STA); + + LOGERROR(F("ConnectMultiWiFi with :")); + + if ( (Router_SSID != "") && (Router_Pass != "") ) + { + LOGERROR3(F("* Flash-stored Router_SSID = "), Router_SSID, F(", Router_Pass = "), Router_Pass ); + LOGERROR3(F("* Add SSID = "), Router_SSID, F(", PW = "), Router_Pass ); + wifiMulti.addAP(Router_SSID.c_str(), Router_Pass.c_str()); + } + + for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++) + { + // Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8) + if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) ) + { + LOGERROR3(F("* Additional SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw ); + } + } + + LOGERROR(F("Connecting MultiWifi...")); + + //WiFi.mode(WIFI_STA); + +#if !USE_DHCP_IP + // New in v1.4.0 + configWiFi(WM_STA_IPconfig); + ////// +#endif + + int i = 0; + + status = wifiMulti.run(); + delay(WIFI_MULTI_1ST_CONNECT_WAITING_MS); + + while ( ( i++ < 20 ) && ( status != WL_CONNECTED ) ) + { + status = WiFi.status(); + + if ( status == WL_CONNECTED ) + break; + else + delay(WIFI_MULTI_CONNECT_WAITING_MS); + } + + if ( status == WL_CONNECTED ) + { + LOGERROR1(F("WiFi connected after time: "), i); + LOGERROR3(F("SSID:"), WiFi.SSID(), F(",RSSI="), WiFi.RSSI()); + LOGERROR3(F("Channel:"), WiFi.channel(), F(",IP address:"), WiFi.localIP() ); + } + else + { + LOGERROR(F("WiFi not connected")); + + // To avoid unnecessary DRD + drd->loop(); + +#if ESP8266 + ESP.reset(); +#else + ESP.restart(); +#endif + } + + return status; +} + +#if USE_ESP_WIFIMANAGER_NTP + +void printLocalTime() +{ +#if ESP8266 + static time_t now; + + now = time(nullptr); + + if ( now > 1451602800 ) + { + Serial.print("Local Date/Time: "); + Serial.print(ctime(&now)); + } +#else + struct tm timeinfo; + + getLocalTime( &timeinfo ); + + // Valid only if year > 2000. + // You can get from timeinfo : tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec + if (timeinfo.tm_year > 100 ) + { + Serial.print("Local Date/Time: "); + Serial.print( asctime( &timeinfo ) ); + } +#endif +} + +#endif + +void heartBeatPrint() +{ +#if USE_ESP_WIFIMANAGER_NTP + printLocalTime(); +#else + static int num = 1; + + if (WiFi.status() == WL_CONNECTED) + Serial.print(F("H")); // H means connected to WiFi + else + Serial.print(F("F")); // F means not connected to WiFi + + if (num == 80) + { + Serial.println(); + num = 1; + } + else if (num++ % 10 == 0) + { + Serial.print(F(" ")); + } +#endif +} + +void check_WiFi() +{ + if ( (WiFi.status() != WL_CONNECTED) ) + { + Serial.println(F("\nWiFi lost. Call connectMultiWiFi in loop")); + connectMultiWiFi(); + } +} + +void check_status() +{ + static ulong checkstatus_timeout = 0; + static ulong checkwifi_timeout = 0; + + static ulong current_millis; + +#define WIFICHECK_INTERVAL 1000L + +#if USE_ESP_WIFIMANAGER_NTP + #define HEARTBEAT_INTERVAL 60000L +#else + #define HEARTBEAT_INTERVAL 10000L +#endif + + current_millis = millis(); + + // Check WiFi every WIFICHECK_INTERVAL (1) seconds. + if ((current_millis > checkwifi_timeout) || (checkwifi_timeout == 0)) + { + check_WiFi(); + checkwifi_timeout = current_millis + WIFICHECK_INTERVAL; + } + + // Print hearbeat every HEARTBEAT_INTERVAL (10) seconds. + if ((current_millis > checkstatus_timeout) || (checkstatus_timeout == 0)) + { + heartBeatPrint(); + checkstatus_timeout = current_millis + HEARTBEAT_INTERVAL; + } +} + +int calcChecksum(uint8_t* address, uint16_t sizeToCalc) +{ + uint16_t checkSum = 0; + + for (uint16_t index = 0; index < sizeToCalc; index++) + { + checkSum += * ( ( (byte*) address ) + index); + } + + return checkSum; +} + +bool loadConfigData() +{ + File file = FileFS.open(CONFIG_FILENAME, "r"); + LOGERROR(F("LoadWiFiCfgFile ")); + + memset((void*) &WM_config, 0, sizeof(WM_config)); + + // New in v1.4.0 + memset((void*) &WM_STA_IPconfig, 0, sizeof(WM_STA_IPconfig)); + ////// + + if (file) + { + file.readBytes((char *) &WM_config, sizeof(WM_config)); + + // New in v1.4.0 + file.readBytes((char *) &WM_STA_IPconfig, sizeof(WM_STA_IPconfig)); + ////// + + file.close(); + LOGERROR(F("OK")); + + if ( WM_config.checksum != calcChecksum( (uint8_t*) &WM_config, sizeof(WM_config) - sizeof(WM_config.checksum) ) ) + { + LOGERROR(F("WM_config checksum wrong")); + + return false; + } + + // New in v1.4.0 + displayIPConfigStruct(WM_STA_IPconfig); + ////// + + return true; + } + else + { + LOGERROR(F("failed")); + + return false; + } +} + +void saveConfigData() +{ + File file = FileFS.open(CONFIG_FILENAME, "w"); + LOGERROR(F("SaveWiFiCfgFile ")); + + if (file) + { + WM_config.checksum = calcChecksum( (uint8_t*) &WM_config, sizeof(WM_config) - sizeof(WM_config.checksum) ); + + file.write((uint8_t*) &WM_config, sizeof(WM_config)); + + displayIPConfigStruct(WM_STA_IPconfig); + + // New in v1.4.0 + file.write((uint8_t*) &WM_STA_IPconfig, sizeof(WM_STA_IPconfig)); + ////// + + file.close(); + LOGERROR(F("OK")); + } + else + { + LOGERROR(F("failed")); + } +} + +unsigned long drdtimeout; + + +void setupwifiman() +{ + // put your setup code here, to run once: + // initialize the LED digital pin as an output. + pinMode(PIN_LED, OUTPUT); + + Serial.begin(115200); + while (!Serial); + + delay(200); + + Serial.print(F("\nStarting ConfigOnDoubleReset with DoubleResetDetect using ")); Serial.print(FS_Name); + Serial.print(F(" on ")); Serial.println(ARDUINO_BOARD); + Serial.println(ESP_WIFIMANAGER_VERSION); + Serial.println(ESP_DOUBLE_RESET_DETECTOR_VERSION); + +#if defined(ESP_WIFIMANAGER_VERSION_MIN) + if (ESP_WIFIMANAGER_VERSION_INT < ESP_WIFIMANAGER_VERSION_MIN) + { + Serial.print("Warning. Must use this example on Version equal or later than : "); + Serial.println(ESP_WIFIMANAGER_VERSION_MIN_TARGET); + } +#endif + + Serial.setDebugOutput(false); + + if (FORMAT_FILESYSTEM) + FileFS.format(); + + // Format FileFS if not yet +#ifdef ESP32 + if (!FileFS.begin(true)) +#else + if (!FileFS.begin()) +#endif + { +#ifdef ESP8266 + FileFS.format(); +#endif + + Serial.println(F("SPIFFS/LittleFS failed! Already tried formatting.")); + + if (!FileFS.begin()) + { + // prevents debug info from the library to hide err message. + delay(100); + +#if USE_LITTLEFS + Serial.println(F("LittleFS failed!. Please use SPIFFS or EEPROM. Stay forever")); +#else + Serial.println(F("SPIFFS failed!. Please use LittleFS or EEPROM. Stay forever")); +#endif + + while (true) + { + delay(1); + } + } + } + + drd = new DoubleResetDetector(DRD_TIMEOUT, DRD_ADDRESS); + + unsigned long startedAt = millis(); + + // New in v1.4.0 + initAPIPConfigStruct(WM_AP_IPconfig); + initSTAIPConfigStruct(WM_STA_IPconfig); + ////// + + //Local intialization. Once its business is done, there is no need to keep it around + // Use this to default DHCP hostname to ESP8266-XXXXXX or ESP32-XXXXXX + //ESP_WiFiManager ESP_wifiManager; + // Use this to personalize DHCP hostname (RFC952 conformed) + ESP_WiFiManager ESP_wifiManager("ConfigOnDoubleReset"); + +#if USE_CUSTOM_AP_IP + //set custom ip for portal + // New in v1.4.0 + ESP_wifiManager.setAPStaticIPConfig(WM_AP_IPconfig); + ////// +#endif + + ESP_wifiManager.setMinimumSignalQuality(-1); + + // From v1.0.10 only + // Set config portal channel, default = 1. Use 0 => random channel from 1-13 + ESP_wifiManager.setConfigPortalChannel(0); + ////// + +#if !USE_DHCP_IP + // Set (static IP, Gateway, Subnetmask, DNS1 and DNS2) or (IP, Gateway, Subnetmask). New in v1.0.5 + // New in v1.4.0 + ESP_wifiManager.setSTAStaticIPConfig(WM_STA_IPconfig); + ////// +#endif + + // New from v1.1.1 +#if USING_CORS_FEATURE + ESP_wifiManager.setCORSHeader("Your Access-Control-Allow-Origin"); +#endif + + // We can't use WiFi.SSID() in ESP32 as it's only valid after connected. + // SSID and Password stored in ESP32 wifi_ap_record_t and wifi_config_t are also cleared in reboot + // Have to create a new function to store in EEPROM/SPIFFS for this purpose + Router_SSID = ESP_wifiManager.WiFi_SSID(); + Router_Pass = ESP_wifiManager.WiFi_Pass(); + + //Remove this line if you do not want to see WiFi password printed + Serial.println("ESP Self-Stored: SSID = " + Router_SSID + ", Pass = " + Router_Pass); + + // SSID/PWD to uppercase + ssid.toUpperCase(); + password = "nixie"; + + bool configDataLoaded = false; + + // From v1.1.0, Don't permit NULL password + if ( (Router_SSID != "") && (Router_Pass != "") ) + { + LOGERROR3(F("* Add SSID = "), Router_SSID, F(", PW = "), Router_Pass); + wifiMulti.addAP(Router_SSID.c_str(), Router_Pass.c_str()); + + ESP_wifiManager.setConfigPortalTimeout(240); //If no access point name has been previously entered disable timeout. + Serial.println(F("Got ESP Self-Stored Credentials. Timeout 120s for Config Portal")); + } + + if (loadConfigData()) + { + configDataLoaded = true; + + ESP_wifiManager.setConfigPortalTimeout(240); //If no access point name has been previously entered disable timeout. + Serial.println(F("Got stored Credentials. Timeout 120s for Config Portal")); + +#if USE_ESP_WIFIMANAGER_NTP + if ( strlen(WM_config.TZ_Name) > 0 ) + { + LOGERROR3(F("Current TZ_Name ="), WM_config.TZ_Name, F(", TZ = "), WM_config.TZ); + + #if ESP8266 + configTime(WM_config.TZ, "pool.ntp.org"); + #else + //configTzTime(WM_config.TZ, "pool.ntp.org" ); + configTzTime(WM_config.TZ, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org"); + #endif + } + else + { + Serial.println(F("Current Timezone is not set. Enter Config Portal to set.")); + } +#endif + } + else + { + // Enter CP only if no stored SSID on flash and file + Serial.println(F("Open Config Portal without Timeout: No stored Credentials.")); + initialConfig = true; + } + + if (drd->detectDoubleReset()) + { + // DRD, disable timeout. + ESP_wifiManager.setConfigPortalTimeout(0); + + Serial.println(F("Open Config Portal without Timeout: Double Reset Detected")); + initialConfig = true; + } + + if (initialConfig) + { + Serial.print(F("Starting configuration portal @ ")); + +#if USE_CUSTOM_AP_IP + Serial.print(APStaticIP); +#else + Serial.print(F("192.168.4.1")); +#endif + +#if defined(HTTP_PORT_TO_USE) + Serial.print(F(":")); Serial.print(HTTP_PORT_TO_USE); +#endif + + Serial.print(F(", SSID = ")); + Serial.print(ssid); + Serial.print(F(", PWD = ")); + Serial.println(password); + + digitalWrite(PIN_LED, LED_ON); // turn the LED on by making the voltage LOW to tell us we are in configuration mode. + + //sets timeout in seconds until configuration portal gets turned off. + //If not specified device will remain in configuration mode until + //switched off via webserver or device is restarted. + //ESP_wifiManager.setConfigPortalTimeout(600); + +#if DISPLAY_STORED_CREDENTIALS_IN_CP + // New. Update Credentials, got from loadConfigData(), to display on CP + ESP_wifiManager.setCredentials(WM_config.WiFi_Creds[0].wifi_ssid, WM_config.WiFi_Creds[0].wifi_pw, + WM_config.WiFi_Creds[1].wifi_ssid, WM_config.WiFi_Creds[1].wifi_pw); +#endif + + // Starts an access point + if (!ESP_wifiManager.startConfigPortal((const char *) ssid.c_str(), (const char *) password.c_str())) + Serial.println(F("Not connected to WiFi but continuing anyway.")); + else + { + Serial.println(F("WiFi connected...yeey :)")); + } + + // Stored for later usage, from v1.1.0, but clear first + memset(&WM_config, 0, sizeof(WM_config)); + + for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++) + { + String tempSSID = ESP_wifiManager.getSSID(i); + String tempPW = ESP_wifiManager.getPW(i); + + if (strlen(tempSSID.c_str()) < sizeof(WM_config.WiFi_Creds[i].wifi_ssid) - 1) + strcpy(WM_config.WiFi_Creds[i].wifi_ssid, tempSSID.c_str()); + else + strncpy(WM_config.WiFi_Creds[i].wifi_ssid, tempSSID.c_str(), sizeof(WM_config.WiFi_Creds[i].wifi_ssid) - 1); + + if (strlen(tempPW.c_str()) < sizeof(WM_config.WiFi_Creds[i].wifi_pw) - 1) + strcpy(WM_config.WiFi_Creds[i].wifi_pw, tempPW.c_str()); + else + strncpy(WM_config.WiFi_Creds[i].wifi_pw, tempPW.c_str(), sizeof(WM_config.WiFi_Creds[i].wifi_pw) - 1); + + // Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8) + if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) ) + { + LOGERROR3(F("* Add SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw ); + wifiMulti.addAP(WM_config.WiFi_Creds[i].wifi_ssid, WM_config.WiFi_Creds[i].wifi_pw); + } + } + +#if USE_ESP_WIFIMANAGER_NTP + String tempTZ = ESP_wifiManager.getTimezoneName(); + + if (strlen(tempTZ.c_str()) < sizeof(WM_config.TZ_Name) - 1) + strcpy(WM_config.TZ_Name, tempTZ.c_str()); + else + strncpy(WM_config.TZ_Name, tempTZ.c_str(), sizeof(WM_config.TZ_Name) - 1); + + const char * TZ_Result = ESP_wifiManager.getTZ(WM_config.TZ_Name); + + if (strlen(TZ_Result) < sizeof(WM_config.TZ) - 1) + strcpy(WM_config.TZ, TZ_Result); + else + strncpy(WM_config.TZ, TZ_Result, sizeof(WM_config.TZ_Name) - 1); + + if ( strlen(WM_config.TZ_Name) > 0 ) + { + LOGERROR3(F("Saving current TZ_Name ="), WM_config.TZ_Name, F(", TZ = "), WM_config.TZ); + + #if ESP8266 + configTime(WM_config.TZ, "pool.ntp.org"); + #else + //configTzTime(WM_config.TZ, "pool.ntp.org" ); + configTzTime(WM_config.TZ, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org"); + #endif + } + else + { + LOGERROR(F("Current Timezone Name is not set. Enter Config Portal to set.")); + } +#endif + + // New in v1.4.0 + ESP_wifiManager.getSTAStaticIPConfig(WM_STA_IPconfig); + ////// + + saveConfigData(); + } + + digitalWrite(PIN_LED, LED_OFF); // Turn led off as we are not in configuration mode. + + startedAt = millis(); + + if (!initialConfig) + { + // Load stored data, the addAP ready for MultiWiFi reconnection + if (!configDataLoaded) + loadConfigData(); + + for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++) + { + // Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8) + if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) ) + { + LOGERROR3(F("* Add SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw ); + wifiMulti.addAP(WM_config.WiFi_Creds[i].wifi_ssid, WM_config.WiFi_Creds[i].wifi_pw); + } + } + + if ( WiFi.status() != WL_CONNECTED ) + { + Serial.println(F("ConnectMultiWiFi in setup")); + + connectMultiWiFi(); + } + } + + Serial.print(F("After waiting ")); + Serial.print((float) (millis() - startedAt) / 1000); + Serial.print(F(" secs more in setup(), connection result is ")); + + if (WiFi.status() == WL_CONNECTED) + { + Serial.print(F("connected. Local IP: ")); + Serial.println(WiFi.localIP()); + } + else + Serial.println(ESP_wifiManager.getStatus(WiFi.status())); + + drdtimeout=millis(); + +} + + + +void loopwifiman() +{ + // Call the double reset detector loop method every so often, + // so that it can recognise when the timeout expires. + // You can also call drd.stop() when you wish to no longer + // consider the next reset as a double reset. + + + drd->loop(); + + + // put your main code here, to run repeatedly + check_status(); + +} diff --git a/FW/NCM107-ESP32C3/src/wifimanager.h b/FW/NCM107-ESP32C3/src/wifimanager.h new file mode 100644 index 0000000..c9cf949 --- /dev/null +++ b/FW/NCM107-ESP32C3/src/wifimanager.h @@ -0,0 +1,303 @@ +#pragma once + +/**************************************************************************************************************************** + ConfigOnDoubleReset.ino + For ESP8266 / ESP32 boards + + ESP_WiFiManager is a library for the ESP8266/ESP32 platform (https://github.com/esp8266/Arduino) to enable easy + configuration and reconfiguration of WiFi credentials using a Captive Portal. Inspired by: + http://www.esp8266.com/viewtopic.php?f=29&t=2520 + https://github.com/chriscook8/esp-arduino-apboot + https://github.com/esp8266/Arduino/blob/master/libraries/DNSServer/examples/CaptivePortalAdvanced/ + + Modified from Tzapu https://github.com/tzapu/WiFiManager + and from Ken Taylor https://github.com/kentaylor + + Built by Khoi Hoang https://github.com/khoih-prog/ESP_WiFiManager + Licensed under MIT license + *****************************************************************************************************************************/ +/**************************************************************************************************************************** + This example will open a configuration portal when the reset button is pressed twice. + This method works well on Wemos boards which have a single reset button on board. It avoids using a pin for launching the configuration portal. + + How It Works + 1) ESP8266 + Save data in RTC memory + 2) ESP32 + Save data in EEPROM from address 256, size 512 bytes (both configurable) + + So when the device starts up it checks this region of ram for a flag to see if it has been recently reset. + If so it launches a configuration portal, if not it sets the reset flag. After running for a while this flag is cleared so that + it will only launch the configuration portal in response to closely spaced resets. + + Settings + There are two values to be set in the sketch. + + DRD_TIMEOUT - Number of seconds to wait for the second reset. Set to 10 in the example. + DRD_ADDRESS - The address in ESP8266 RTC RAM to store the flag. This memory must not be used for other purposes in the same sketch. Set to 0 in the example. + + This example, originally relied on the Double Reset Detector library from https://github.com/datacute/DoubleResetDetector + To support ESP32, use ESP_DoubleResetDetector library from //https://github.com/khoih-prog/ESP_DoubleResetDetector + *****************************************************************************************************************************/ + +void loopwifiman(); +void setupwifiman(); + +#if !( defined(ESP8266) || defined(ESP32) ) + #error This code is intended to run on the ESP8266 or ESP32 platform! Please check your Tools->Board setting. +#endif + +#define ESP_WIFIMANAGER_VERSION_MIN_TARGET "ESP_WiFiManager v1.12.0" +#define ESP_WIFIMANAGER_VERSION_MIN 1012000 + +// Use from 0 to 4. Higher number, more debugging messages and memory usage. +#define _WIFIMGR_LOGLEVEL_ 1 + +// To not display stored SSIDs and PWDs on Config Portal, select false. Default is true +// Even the stored Credentials are not display, just leave them all blank to reconnect and reuse the stored Credentials +//#define DISPLAY_STORED_CREDENTIALS_IN_CP false + +#include + +//Ported to ESP32 +#ifdef ESP32 + #include + #include + #include + + // From v1.1.0 + #include + + // LittleFS has higher priority than SPIFFS + #if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) ) + #define USE_LITTLEFS true + #define USE_SPIFFS false + #elif defined(ARDUINO_ESP32C3_DEV) + // For core v1.0.6-, ESP32-C3 only supporting SPIFFS and EEPROM. To use v2.0.0+ for LittleFS + #define USE_LITTLEFS false + #define USE_SPIFFS true + #endif + + #if USE_LITTLEFS + // Use LittleFS + #include "FS.h" + + // Check cores/esp32/esp_arduino_version.h and cores/esp32/core_version.h + //#if ( ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(2, 0, 0) ) //(ESP_ARDUINO_VERSION_MAJOR >= 2) + #if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) ) + #if (_WIFIMGR_LOGLEVEL_ > 3) + #warning Using ESP32 Core 1.0.6 or 2.0.0+ + #endif + + // The library has been merged into esp32 core from release 1.0.6 + #include // https://github.com/espressif/arduino-esp32/tree/master/libraries/LittleFS + + #define FileFS LittleFS + #define FS_Name "LittleFS" + #else + #if (_WIFIMGR_LOGLEVEL_ > 3) + #warning Using ESP32 Core 1.0.5-. You must install LITTLEFS library + #endif + + // The library has been merged into esp32 core from release 1.0.6 + #include // https://github.com/lorol/LITTLEFS + #define FileFS LITTLEFS + #define FS_Name "LittleFS" + #endif + + #elif USE_SPIFFS + #include + #define FileFS SPIFFS + #define FS_Name "SPIFFS" + #else + // Use FFat + #include + #define FileFS FFat + #define FS_Name "FFat" + #endif + ////// + +#define LED_BUILTIN 2 +#define LED_ON HIGH +#define LED_OFF LOW + +#else + #include //https://github.com/esp8266/Arduino + //needed for library + #include + #include + + // From v1.1.0 + #include + ESP8266WiFiMulti wifiMulti; + + #define USE_LITTLEFS true + + #if USE_LITTLEFS + #include + FS* filesystem = &LittleFS; + #define FileFS LittleFS + #define FS_Name "LittleFS" + #else + FS* filesystem = &SPIFFS; + #define FileFS SPIFFS + #define FS_Name "SPIFFS" + #endif + ////// + + #define ESP_getChipId() (ESP.getChipId()) + + #define LED_ON LOW + #define LED_OFF HIGH +#endif + +// These defines must be put before #include +// to select where to store DoubleResetDetector's variable. +// For ESP32, You must select one to be true (EEPROM or SPIFFS) +// For ESP8266, You must select one to be true (RTC, EEPROM, SPIFFS or LITTLEFS) +// Otherwise, library will use default EEPROM storage +#ifdef ESP32 + + // These defines must be put before #include + // to select where to store DoubleResetDetector's variable. + // For ESP32, You must select one to be true (EEPROM or SPIFFS) + // Otherwise, library will use default EEPROM storage + #if USE_LITTLEFS + #define ESP_DRD_USE_LITTLEFS true + #define ESP_DRD_USE_SPIFFS false + #define ESP_DRD_USE_EEPROM false + #elif USE_SPIFFS + #define ESP_DRD_USE_LITTLEFS false + #define ESP_DRD_USE_SPIFFS true + #define ESP_DRD_USE_EEPROM false + #else + #define ESP_DRD_USE_LITTLEFS false + #define ESP_DRD_USE_SPIFFS false + #define ESP_DRD_USE_EEPROM true + #endif + +#else //ESP8266 + + // For DRD + // These defines must be put before #include + // to select where to store DoubleResetDetector's variable. + // For ESP8266, You must select one to be true (RTC, EEPROM, SPIFFS or LITTLEFS) + // Otherwise, library will use default EEPROM storage + #if USE_LITTLEFS + #define ESP_DRD_USE_LITTLEFS true + #define ESP_DRD_USE_SPIFFS false + #else + #define ESP_DRD_USE_LITTLEFS false + #define ESP_DRD_USE_SPIFFS true + #endif + + #define ESP_DRD_USE_EEPROM false + #define ESP8266_DRD_USE_RTC false +#endif + +#define DOUBLERESETDETECTOR_DEBUG false + +#include //https://github.com/khoih-prog/ESP_DoubleResetDetector + +// Number of seconds after reset during which a +// subseqent reset will be considered a double reset. +#define DRD_TIMEOUT 10 + +// RTC Memory Address for the DoubleResetDetector to use +#define DRD_ADDRESS 0 + + + +// From v1.1.0 +// You only need to format the filesystem once +//#define FORMAT_FILESYSTEM true +#define FORMAT_FILESYSTEM false + +#define MIN_AP_PASSWORD_SIZE 8 + +#define SSID_MAX_LEN 32 +//From v1.0.10, WPA2 passwords can be up to 63 characters long. +#define PASS_MAX_LEN 64 + +typedef struct +{ + char wifi_ssid[SSID_MAX_LEN]; + char wifi_pw [PASS_MAX_LEN]; +} WiFi_Credentials; + +typedef struct +{ + String wifi_ssid; + String wifi_pw; +} WiFi_Credentials_String; + +#define NUM_WIFI_CREDENTIALS 2 + +// Assuming max 491 chars +#define TZNAME_MAX_LEN 50 +#define TIMEZONE_MAX_LEN 50 + +typedef struct +{ + WiFi_Credentials WiFi_Creds [NUM_WIFI_CREDENTIALS]; + char TZ_Name[TZNAME_MAX_LEN]; // "America/Toronto" + char TZ[TIMEZONE_MAX_LEN]; // "EST5EDT,M3.2.0,M11.1.0" + uint16_t checksum; +} WM_Config; + + + +#define CONFIG_FILENAME F("/wifi_cred.dat") +////// + + + +// Use false if you don't like to display Available Pages in Information Page of Config Portal +// Comment out or use true to display Available Pages in Information Page of Config Portal +// Must be placed before #include +#define USE_AVAILABLE_PAGES true //false + +// From v1.0.10 to permit disable/enable StaticIP configuration in Config Portal from sketch. Valid only if DHCP is used. +// You'll loose the feature of dynamically changing from DHCP to static IP, or vice versa +// You have to explicitly specify false to disable the feature. +//#define USE_STATIC_IP_CONFIG_IN_CP false + +// Use false to disable NTP config. Advisable when using Cellphone, Tablet to access Config Portal. +// See Issue 23: On Android phone ConfigPortal is unresponsive (https://github.com/khoih-prog/ESP_WiFiManager/issues/23) +#define USE_ESP_WIFIMANAGER_NTP true + +// Just use enough to save memory. On ESP8266, can cause blank ConfigPortal screen +// if using too much memory +#define USING_AFRICA false +#define USING_AMERICA false +#define USING_ANTARCTICA false +#define USING_ASIA false +#define USING_ATLANTIC false +#define USING_AUSTRALIA false +#define USING_EUROPE true +#define USING_INDIAN false +#define USING_PACIFIC false +#define USING_ETC_GMT false + +// Use true to enable CloudFlare NTP service. System can hang if you don't have Internet access while accessing CloudFlare +// See Issue #21: CloudFlare link in the default portal (https://github.com/khoih-prog/ESP_WiFiManager/issues/21) +#define USE_CLOUDFLARE_NTP false + +// New in v1.0.11 +#define USING_CORS_FEATURE true + +//////////////////////////////////////////// + +// Use USE_DHCP_IP == true for dynamic DHCP IP, false to use static IP which you have to change accordingly to your network +#if (defined(USE_STATIC_IP_CONFIG_IN_CP) && !USE_STATIC_IP_CONFIG_IN_CP) + // Force DHCP to be true + #if defined(USE_DHCP_IP) + #undef USE_DHCP_IP + #endif + #define USE_DHCP_IP true +#else + // You can select DHCP or Static IP here + #define USE_DHCP_IP true + //#define USE_DHCP_IP false +#endif +