From 13ddf853edaa8390ec4b8b87699694ea7e8f07b8 Mon Sep 17 00:00:00 2001 From: mattbk Date: Thu, 31 Aug 2023 11:52:11 -0500 Subject: [PATCH 1/9] Use a dropdown for program setting. --- vulpes/src/main.cpp | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/vulpes/src/main.cpp b/vulpes/src/main.cpp index b840c45..7874087 100644 --- a/vulpes/src/main.cpp +++ b/vulpes/src/main.cpp @@ -55,17 +55,13 @@ const char index_html[] PROGMEM = R"rawliteral(
inputString (current value %inputString%):
- - Seconds between flash (current value %inputInt%):
- + + Sending program: +
+ inputFloat (current value %inputFloat%):
@@ -144,7 +140,7 @@ void writeFile(fs::FS &fs, const char * path, const char * message){ file.close(); } -// Replaces placeholder with stored values +// Replaces placeholder in web UI with stored values String processor(const String& var){ //Serial.println(var); if(var == "inputString"){ @@ -365,14 +361,14 @@ void loop() { // float yourInputFloat = readFile(SPIFFS, "/inputFloat.txt").toFloat(); // if you want to send code, and it's not sending, then start it up - if((yourInputInt != 0) & (morseLed.IsRunning() == false)){ + if((yourInputInt == 1) & (morseLed.IsRunning() == false)){ //jled morseLed.Reset().Update(); //morse.send("CQ CQ CQ DE W1CDN K"); //etherkit morse //telegraph26.send("CQ CQ CQ DE W1CDN K"); //telegraph // if you want to send code, and it is sending, keep sending - } else if((yourInputInt != 0) & (morseLed.IsRunning() == true)){ + } else if((yourInputInt == 1) & (morseLed.IsRunning() == true)){ morseLed.Update(); // if you don't want to send code } else { -- 2.30.2 From b0be20087c007af8acd6595b9a91cdc51d659f03 Mon Sep 17 00:00:00 2001 From: mattbk Date: Thu, 31 Aug 2023 20:41:24 -0500 Subject: [PATCH 2/9] Add option for cycle send and clean up a bit. --- vulpes/src/main.cpp | 68 +++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 40 deletions(-) diff --git a/vulpes/src/main.cpp b/vulpes/src/main.cpp index 7874087..3aba681 100644 --- a/vulpes/src/main.cpp +++ b/vulpes/src/main.cpp @@ -34,15 +34,15 @@ const char* ssid = WIFI_SSID; const char* password = WIFI_PASSWORD; const char* PARAM_STRING = "inputString"; -const char* PARAM_INT = "inputInt"; +const char* PARAM_SEND = "inputSend"; const char* PARAM_FLOAT = "inputFloat"; // Global variables String yourInputString; -int yourInputInt; +int yourInputSend; float yourInputFloat; -// HTML web page to handle 3 input fields (inputString, inputInt, inputFloat) +// HTML web page to handle 3 input fields (inputString, inputSend, inputFloat) const char index_html[] PROGMEM = R"rawliteral( ESP Input Form @@ -57,9 +57,10 @@ const char index_html[] PROGMEM = R"rawliteral( inputString (current value %inputString%):
Sending program: - + - +
inputFloat (current value %inputFloat%):
@@ -101,7 +102,7 @@ bool toggle_gpio_26(void *) { // defaults // String yourInputString; -// int yourInputInt; +// int yourInputSend; // float yourInputFloat; void notFound(AsyncWebServerRequest *request) { @@ -146,8 +147,8 @@ String processor(const String& var){ if(var == "inputString"){ return readFile(SPIFFS, "/inputString.txt"); } - else if(var == "inputInt"){ - return readFile(SPIFFS, "/inputInt.txt"); + else if(var == "inputSend"){ + return readFile(SPIFFS, "/inputSend.txt"); } else if(var == "inputFloat"){ return readFile(SPIFFS, "/inputFloat.txt"); @@ -283,7 +284,7 @@ void setup() { // Read in existing data yourInputString = readFile(SPIFFS, "/inputString.txt"); - yourInputInt = readFile(SPIFFS, "/inputInt.txt").toInt(); + yourInputSend = readFile(SPIFFS, "/inputSend.txt").toInt(); yourInputFloat = readFile(SPIFFS, "/inputFloat.txt").toFloat(); WiFi.mode(WIFI_STA); @@ -310,11 +311,11 @@ void setup() { writeFile(SPIFFS, "/inputString.txt", inputMessage.c_str()); yourInputString = inputMessage; } - // GET inputInt value on /get?inputInt= - if (request->hasParam(PARAM_INT)) { - inputMessage = request->getParam(PARAM_INT)->value(); - writeFile(SPIFFS, "/inputInt.txt", inputMessage.c_str()); - yourInputInt = inputMessage.toInt(); + // GET inputSend value on /get?inputSend= + if (request->hasParam(PARAM_SEND)) { + inputMessage = request->getParam(PARAM_SEND)->value(); + writeFile(SPIFFS, "/inputSend.txt", inputMessage.c_str()); + yourInputSend = inputMessage.toInt(); } // GET inputFloat value on /get?inputFloat= if (request->hasParam(PARAM_FLOAT)) { @@ -327,10 +328,6 @@ void setup() { // } request->send(200, "text/plain", inputMessage); - // // Update data from files - // String yourInputString = readFile(SPIFFS, "/inputString.txt"); - // int yourInputInt = readFile(SPIFFS, "/inputInt.txt").toInt(); - // float yourInputFloat = readFile(SPIFFS, "/inputFloat.txt").toFloat(); }); server.onNotFound(notFound); server.begin(); @@ -356,20 +353,25 @@ void loop() { //arduinomorse //sender.continueSending(); - //String yourInputString = readFile(SPIFFS, "/inputString.txt"); - //int yourInputInt = readFile(SPIFFS, "/inputInt.txt").toInt(); - // float yourInputFloat = readFile(SPIFFS, "/inputFloat.txt").toFloat(); - - // if you want to send code, and it's not sending, then start it up - if((yourInputInt == 1) & (morseLed.IsRunning() == false)){ + // if you want to send continuous code, and it's not sending, then start it up + if((yourInputSend == 1) & (morseLed.IsRunning() == false)){ //jled morseLed.Reset().Update(); //morse.send("CQ CQ CQ DE W1CDN K"); //etherkit morse //telegraph26.send("CQ CQ CQ DE W1CDN K"); //telegraph - // if you want to send code, and it is sending, keep sending - } else if((yourInputInt == 1) & (morseLed.IsRunning() == true)){ + // if you want to send continuous code, and it is sending, keep sending + } else if((yourInputSend == 1) & (morseLed.IsRunning() == true)){ morseLed.Update(); + + // if you want to send cycle code and it is sending, keep sending + } else if((yourInputSend == 2) & (morseLed.IsRunning() == true)){ + morseLed.Update(); + + // if you want to send cycle code and it's not sending, then start it up + } else if((yourInputSend == 2) & (morseLed.IsRunning() == true)){ + morseLed.Reset().Update(); + // if you don't want to send code } else { // stop sending and make sure the pin is off @@ -394,18 +396,4 @@ void loop() { // output26State = "off"; // } - -// // To access your stored values on inputString, inputInt, inputFloat -// String yourInputString = readFile(SPIFFS, "/inputString.txt"); -// Serial.print("*** Your inputString: "); -// Serial.println(yourInputString); - -// int yourInputInt = readFile(SPIFFS, "/inputInt.txt").toInt(); -// Serial.print("*** Your inputInt: "); -// Serial.println(yourInputInt); - -// float yourInputFloat = readFile(SPIFFS, "/inputFloat.txt").toFloat(); -// Serial.print("*** Your inputFloat: "); -// Serial.println(yourInputFloat); -// delay(5000); } \ No newline at end of file -- 2.30.2 From 50eaf8e973d8b7a64c5aaf20d4efb3a2617f8448 Mon Sep 17 00:00:00 2001 From: mattbk Date: Thu, 31 Aug 2023 21:35:49 -0500 Subject: [PATCH 3/9] Snapshot. --- vulpes/src/main.cpp | 124 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 105 insertions(+), 19 deletions(-) diff --git a/vulpes/src/main.cpp b/vulpes/src/main.cpp index 3aba681..7c48b99 100644 --- a/vulpes/src/main.cpp +++ b/vulpes/src/main.cpp @@ -35,11 +35,15 @@ const char* password = WIFI_PASSWORD; const char* PARAM_STRING = "inputString"; const char* PARAM_SEND = "inputSend"; +const char* PARAM_WPM = "inputWPM"; +const char* PARAM_MSG = "inputMsg"; const char* PARAM_FLOAT = "inputFloat"; // Global variables String yourInputString; int yourInputSend; +int yourInputWPM; +int yourInputMsg; float yourInputFloat; // HTML web page to handle 3 input fields (inputString, inputSend, inputFloat) @@ -56,13 +60,25 @@ const char index_html[] PROGMEM = R"rawliteral(
inputString (current value %inputString%):
- Sending program: + Sending program (cycle doesn't work yet):
+ + Message: +
+ WPM (current value %inputWPM%): (doesn't work yet)
+ inputFloat (current value %inputFloat%):
@@ -100,11 +116,6 @@ bool toggle_gpio_26(void *) { return true; // keep timer active? true } -// defaults -// String yourInputString; -// int yourInputSend; -// float yourInputFloat; - void notFound(AsyncWebServerRequest *request) { request->send(404, "text/plain", "Not found"); } @@ -150,6 +161,12 @@ String processor(const String& var){ else if(var == "inputSend"){ return readFile(SPIFFS, "/inputSend.txt"); } + else if(var == "inputWPM"){ + return readFile(SPIFFS, "/inputWPM.txt"); + } + else if(var == "inputMsg"){ + return readFile(SPIFFS, "/inputMsg.txt"); + } else if(var == "inputFloat"){ return readFile(SPIFFS, "/inputFloat.txt"); } @@ -244,9 +261,29 @@ class MorseEffect : public jled::BrightnessEvaluator { // Speed is milliseconds per dit, which is 1000 * (60 / (50 * WPM)) // 60 is 20 wpm, 120 is 10 wpm, 90 is 15 wpm, etc. // https://morsecode.world/international/timing.html -MorseEffect morseEffect("CQ CQ CQ DE W1CDN", 120); -auto morseLed = - JLed(output26).UserFunc(&morseEffect).DelayAfter(2000).Forever(); +int wpm = 10; +int ms_per_dit = 120; //1000 * (60 / (50 * wpm)); +int word_space_ms = ms_per_dit * 7; +// Hardcoding these for now, will come back and make it more flexible. +MorseEffect morseEffect("CQ CQ CQ DE W1CDN", ms_per_dit); +MorseEffect morseEffectMOE("MOE", ms_per_dit); +MorseEffect morseEffectMOI("MOI", ms_per_dit); +MorseEffect morseEffectMOS("MOS", ms_per_dit); +MorseEffect morseEffectMOH("MOH", ms_per_dit); +MorseEffect morseEffectMO5("MO5", ms_per_dit); + +auto morseCQ = + JLed(output26).UserFunc(&morseEffect).DelayAfter(word_space_ms).Forever(); +auto morseMOE = + JLed(output26).UserFunc(&morseEffectMOE).DelayAfter(word_space_ms).Forever(); +auto morseMOI = + JLed(output26).UserFunc(&morseEffectMOI).DelayAfter(word_space_ms).Forever(); +auto morseMOS = + JLed(output26).UserFunc(&morseEffectMOS).DelayAfter(word_space_ms).Forever(); +auto morseMOH = + JLed(output26).UserFunc(&morseEffectMOH).DelayAfter(word_space_ms).Forever(); +auto morseMO5 = + JLed(output26).UserFunc(&morseEffectMO5).DelayAfter(word_space_ms).Forever(); //================================================================================ // setup(): stuff that only gets done once, after power up (KB1OIQ's description) @@ -282,9 +319,29 @@ void setup() { } //#endif + // Make sure files exist, maybe with defaults here + // if(SPIFFS.exists("/inputString.txt") == 0){ + // writeFile(SPIFFS, "/inputString.txt", "CQ"); + // } + // if(SPIFFS.exists("/inputSend.txt") == 0){ + // writeFile(SPIFFS, "/inputSend.txt", "0"); + // } + // if(SPIFFS.exists("/inputWPM.txt") == 0){ + // writeFile(SPIFFS, "/inputWPM.txt", "10"); + // } + // if(SPIFFS.exists("/inputMsg.txt") == 0){ + // writeFile(SPIFFS, "/inputMsg.txt", "0"); + // } + // if(SPIFFS.exists("/inputFloat.txt") == 0){ + // writeFile(SPIFFS, "/inputFloat.txt", "1.1"); + // } + + // Read in existing data yourInputString = readFile(SPIFFS, "/inputString.txt"); yourInputSend = readFile(SPIFFS, "/inputSend.txt").toInt(); + yourInputWPM = readFile(SPIFFS, "/inputWPM.txt").toInt(); + yourInputMsg = readFile(SPIFFS, "/inputMsg.txt").toInt(); yourInputFloat = readFile(SPIFFS, "/inputFloat.txt").toFloat(); WiFi.mode(WIFI_STA); @@ -317,6 +374,18 @@ void setup() { writeFile(SPIFFS, "/inputSend.txt", inputMessage.c_str()); yourInputSend = inputMessage.toInt(); } + // GET inputWPM value on /get?inputWPM= + if (request->hasParam(PARAM_WPM)) { + inputMessage = request->getParam(PARAM_WPM)->value(); + writeFile(SPIFFS, "/inputWPM.txt", inputMessage.c_str()); + yourInputWPM = inputMessage.toInt(); + } + // GET inputMsg value on /get?inputMsg= + if (request->hasParam(PARAM_MSG)) { + inputMessage = request->getParam(PARAM_MSG)->value(); + writeFile(SPIFFS, "/inputMsg.txt", inputMessage.c_str()); + yourInputMsg = inputMessage.toInt(); + } // GET inputFloat value on /get?inputFloat= if (request->hasParam(PARAM_FLOAT)) { inputMessage = request->getParam(PARAM_FLOAT)->value(); @@ -353,31 +422,48 @@ void loop() { //arduinomorse //sender.continueSending(); + // See which message we are sending + auto morseToSend = JLed(output26); + if(yourInputMsg == 0){ + morseToSend = morseCQ; + } else if(yourInputMsg == 1){ + morseToSend = morseMOE; + } else if(yourInputMsg == 2){ + morseToSend = morseMOI; + } else if(yourInputMsg == 3){ + morseToSend = morseMOS; + } else if(yourInputMsg == 4){ + morseToSend = morseMOH; + } else if(yourInputMsg == 5){ + morseToSend = morseMO5; + } + + // if you want to send continuous code, and it's not sending, then start it up - if((yourInputSend == 1) & (morseLed.IsRunning() == false)){ + if((yourInputSend == 1) & (morseCQ.IsRunning() == false)){ //jled - morseLed.Reset().Update(); + morseCQ.Reset().Update(); //morse.send("CQ CQ CQ DE W1CDN K"); //etherkit morse //telegraph26.send("CQ CQ CQ DE W1CDN K"); //telegraph // if you want to send continuous code, and it is sending, keep sending - } else if((yourInputSend == 1) & (morseLed.IsRunning() == true)){ - morseLed.Update(); + } else if((yourInputSend == 1) & (morseCQ.IsRunning() == true)){ + morseCQ.Update(); // if you want to send cycle code and it is sending, keep sending - } else if((yourInputSend == 2) & (morseLed.IsRunning() == true)){ - morseLed.Update(); + } else if((yourInputSend == 2) & (morseCQ.IsRunning() == true)){ + morseCQ.Update(); // if you want to send cycle code and it's not sending, then start it up - } else if((yourInputSend == 2) & (morseLed.IsRunning() == true)){ - morseLed.Reset().Update(); + } else if((yourInputSend == 2) & (morseCQ.IsRunning() == true)){ + morseCQ.Reset().Update(); // if you don't want to send code } else { // stop sending and make sure the pin is off - morseLed.Stop(JLed::eStopMode::FULL_OFF).Update(); + morseCQ.Stop(JLed::eStopMode::FULL_OFF).Update(); } - morseLed.Update(); + morseCQ.Update(); -- 2.30.2 From cc4d798a03ae4fb38b729cd37ad32e9273d039b0 Mon Sep 17 00:00:00 2001 From: mattbk Date: Thu, 31 Aug 2023 23:09:21 -0500 Subject: [PATCH 4/9] Get back to working. --- vulpes/src/main.cpp | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/vulpes/src/main.cpp b/vulpes/src/main.cpp index 7c48b99..e782b69 100644 --- a/vulpes/src/main.cpp +++ b/vulpes/src/main.cpp @@ -60,14 +60,14 @@ const char index_html[] PROGMEM = R"rawliteral(
inputString (current value %inputString%):
- Sending program (cycle doesn't work yet): + Sending program (cycle doesn't work yet) (current %inputSend%):
- Message: + Message (current %inputMsg%):
- WPM (current value %inputWPM%): (doesn't work yet)
+ inputFloat (current value %inputFloat%):
@@ -265,7 +265,7 @@ int wpm = 10; int ms_per_dit = 120; //1000 * (60 / (50 * wpm)); int word_space_ms = ms_per_dit * 7; // Hardcoding these for now, will come back and make it more flexible. -MorseEffect morseEffect("CQ CQ CQ DE W1CDN", ms_per_dit); +MorseEffect morseEffectCQ("CQ CQ CQ DE W1CDN", ms_per_dit); MorseEffect morseEffectMOE("MOE", ms_per_dit); MorseEffect morseEffectMOI("MOI", ms_per_dit); MorseEffect morseEffectMOS("MOS", ms_per_dit); @@ -273,7 +273,7 @@ MorseEffect morseEffectMOH("MOH", ms_per_dit); MorseEffect morseEffectMO5("MO5", ms_per_dit); auto morseCQ = - JLed(output26).UserFunc(&morseEffect).DelayAfter(word_space_ms).Forever(); + JLed(output26).UserFunc(&morseEffectCQ).DelayAfter(word_space_ms).Forever(); auto morseMOE = JLed(output26).UserFunc(&morseEffectMOE).DelayAfter(word_space_ms).Forever(); auto morseMOI = @@ -423,20 +423,19 @@ void loop() { //sender.continueSending(); // See which message we are sending - auto morseToSend = JLed(output26); - if(yourInputMsg == 0){ - morseToSend = morseCQ; - } else if(yourInputMsg == 1){ - morseToSend = morseMOE; - } else if(yourInputMsg == 2){ - morseToSend = morseMOI; - } else if(yourInputMsg == 3){ - morseToSend = morseMOS; - } else if(yourInputMsg == 4){ - morseToSend = morseMOH; - } else if(yourInputMsg == 5){ - morseToSend = morseMO5; - } + // if(yourInputMsg == 0){ + // morseToSend = JLed(output26).UserFunc(&morseEffectCQ).DelayAfter(word_space_ms).Forever(); + // } else if(yourInputMsg == 1){ + // morseToSend = morseMOE; + // } else if(yourInputMsg == 2){ + // morseToSend = morseMOI; + // } else if(yourInputMsg == 3){ + // morseToSend = morseMOS; + // } else if(yourInputMsg == 4){ + // morseToSend = morseMOH; + // } else if(yourInputMsg == 5){ + // morseToSend = morseMO5; + // } // if you want to send continuous code, and it's not sending, then start it up -- 2.30.2 From 6af5dfcd0ea2b6b4f4970038cfbf68b45058af83 Mon Sep 17 00:00:00 2001 From: mattbk Date: Fri, 1 Sep 2023 09:39:00 -0500 Subject: [PATCH 5/9] Choose message to send. This only works after you submit the webform again. More work needed so it works on start. --- vulpes/src/main.cpp | 56 ++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/vulpes/src/main.cpp b/vulpes/src/main.cpp index e782b69..b43dc87 100644 --- a/vulpes/src/main.cpp +++ b/vulpes/src/main.cpp @@ -43,7 +43,8 @@ const char* PARAM_FLOAT = "inputFloat"; String yourInputString; int yourInputSend; int yourInputWPM; -int yourInputMsg; +int yourInputMsg = 0; +int yourInputMsg_old = 0; // to save previous state and check changes float yourInputFloat; // HTML web page to handle 3 input fields (inputString, inputSend, inputFloat) @@ -284,6 +285,7 @@ auto morseMOH = JLed(output26).UserFunc(&morseEffectMOH).DelayAfter(word_space_ms).Forever(); auto morseMO5 = JLed(output26).UserFunc(&morseEffectMO5).DelayAfter(word_space_ms).Forever(); +auto morseToSend = JLed(output26); // set this up to overwrite later in loop() //================================================================================ // setup(): stuff that only gets done once, after power up (KB1OIQ's description) @@ -384,6 +386,8 @@ void setup() { if (request->hasParam(PARAM_MSG)) { inputMessage = request->getParam(PARAM_MSG)->value(); writeFile(SPIFFS, "/inputMsg.txt", inputMessage.c_str()); + // save previous state + yourInputMsg_old = yourInputMsg; yourInputMsg = inputMessage.toInt(); } // GET inputFloat value on /get?inputFloat= @@ -423,46 +427,50 @@ void loop() { //sender.continueSending(); // See which message we are sending - // if(yourInputMsg == 0){ - // morseToSend = JLed(output26).UserFunc(&morseEffectCQ).DelayAfter(word_space_ms).Forever(); - // } else if(yourInputMsg == 1){ - // morseToSend = morseMOE; - // } else if(yourInputMsg == 2){ - // morseToSend = morseMOI; - // } else if(yourInputMsg == 3){ - // morseToSend = morseMOS; - // } else if(yourInputMsg == 4){ - // morseToSend = morseMOH; - // } else if(yourInputMsg == 5){ - // morseToSend = morseMO5; - // } + // Only do this when the message has been updated. + if(yourInputMsg != yourInputMsg_old){ + morseToSend.Stop(JLed::eStopMode::FULL_OFF).Update(); + if(yourInputMsg == 0){ + morseToSend = morseCQ; + } else if(yourInputMsg == 1){ + morseToSend = morseMOE; + } else if(yourInputMsg == 2){ + morseToSend = morseMOI; + } else if(yourInputMsg == 3){ + morseToSend = morseMOS; + } else if(yourInputMsg == 4){ + morseToSend = morseMOH; + } else if(yourInputMsg == 5){ + morseToSend = morseMO5; + } + } // if you want to send continuous code, and it's not sending, then start it up - if((yourInputSend == 1) & (morseCQ.IsRunning() == false)){ + if((yourInputSend == 1) & (morseToSend.IsRunning() == false)){ //jled - morseCQ.Reset().Update(); + morseToSend.Reset().Update(); //morse.send("CQ CQ CQ DE W1CDN K"); //etherkit morse //telegraph26.send("CQ CQ CQ DE W1CDN K"); //telegraph // if you want to send continuous code, and it is sending, keep sending - } else if((yourInputSend == 1) & (morseCQ.IsRunning() == true)){ - morseCQ.Update(); + } else if((yourInputSend == 1) & (morseToSend.IsRunning() == true)){ + morseToSend.Update(); // if you want to send cycle code and it is sending, keep sending - } else if((yourInputSend == 2) & (morseCQ.IsRunning() == true)){ - morseCQ.Update(); + } else if((yourInputSend == 2) & (morseToSend.IsRunning() == true)){ + morseToSend.Update(); // if you want to send cycle code and it's not sending, then start it up - } else if((yourInputSend == 2) & (morseCQ.IsRunning() == true)){ - morseCQ.Reset().Update(); + } else if((yourInputSend == 2) & (morseToSend.IsRunning() == true)){ + morseToSend.Reset().Update(); // if you don't want to send code } else { // stop sending and make sure the pin is off - morseCQ.Stop(JLed::eStopMode::FULL_OFF).Update(); + morseToSend.Stop(JLed::eStopMode::FULL_OFF).Update(); } - morseCQ.Update(); + morseToSend.Update(); -- 2.30.2 From 20e075d29dd048bd00ca6054b46c1ad49a06b12a Mon Sep 17 00:00:00 2001 From: mattbk Date: Fri, 1 Sep 2023 10:01:49 -0500 Subject: [PATCH 6/9] Send previous message on startup. --- vulpes/src/main.cpp | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/vulpes/src/main.cpp b/vulpes/src/main.cpp index b43dc87..6fbb5e6 100644 --- a/vulpes/src/main.cpp +++ b/vulpes/src/main.cpp @@ -43,8 +43,8 @@ const char* PARAM_FLOAT = "inputFloat"; String yourInputString; int yourInputSend; int yourInputWPM; -int yourInputMsg = 0; -int yourInputMsg_old = 0; // to save previous state and check changes +int yourInputMsg; +int yourInputMsg_old; // to save previous state and check changes float yourInputFloat; // HTML web page to handle 3 input fields (inputString, inputSend, inputFloat) @@ -285,7 +285,7 @@ auto morseMOH = JLed(output26).UserFunc(&morseEffectMOH).DelayAfter(word_space_ms).Forever(); auto morseMO5 = JLed(output26).UserFunc(&morseEffectMO5).DelayAfter(word_space_ms).Forever(); -auto morseToSend = JLed(output26); // set this up to overwrite later in loop() +auto morseToSend = morseCQ; // set this up to overwrite later //================================================================================ // setup(): stuff that only gets done once, after power up (KB1OIQ's description) @@ -346,6 +346,23 @@ void setup() { yourInputMsg = readFile(SPIFFS, "/inputMsg.txt").toInt(); yourInputFloat = readFile(SPIFFS, "/inputFloat.txt").toFloat(); + + // On restart, keep doing what you were doing before + yourInputMsg_old = yourInputMsg; + if(yourInputMsg == 0){ + morseToSend = morseCQ; + } else if(yourInputMsg == 1){ + morseToSend = morseMOE; + } else if(yourInputMsg == 2){ + morseToSend = morseMOI; + } else if(yourInputMsg == 3){ + morseToSend = morseMOS; + } else if(yourInputMsg == 4){ + morseToSend = morseMOH; + } else if(yourInputMsg == 5){ + morseToSend = morseMO5; + } + WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); if (WiFi.waitForConnectResult() != WL_CONNECTED) { -- 2.30.2 From bfc43443b44eeb52a774b2130cab2b0145634997 Mon Sep 17 00:00:00 2001 From: mattbk Date: Fri, 1 Sep 2023 14:15:54 -0500 Subject: [PATCH 7/9] Clarify some things. --- vulpes/src/main.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/vulpes/src/main.cpp b/vulpes/src/main.cpp index 6fbb5e6..0dc2bf3 100644 --- a/vulpes/src/main.cpp +++ b/vulpes/src/main.cpp @@ -61,24 +61,24 @@ const char index_html[] PROGMEM = R"rawliteral( inputString (current value %inputString%):
- Sending program (cycle doesn't work yet) (current %inputSend%): + Sending program (cycle doesn't work yet) (current value: %inputSend%):
- Message (current %inputMsg%): + Message (current value %inputMsg%):
- + WPM (current value %inputWPM%): (doesn't work yet)
inputFloat (current value %inputFloat%):
@@ -262,8 +262,8 @@ class MorseEffect : public jled::BrightnessEvaluator { // Speed is milliseconds per dit, which is 1000 * (60 / (50 * WPM)) // 60 is 20 wpm, 120 is 10 wpm, 90 is 15 wpm, etc. // https://morsecode.world/international/timing.html -int wpm = 10; -int ms_per_dit = 120; //1000 * (60 / (50 * wpm)); +float wpm = 10; +float ms_per_dit = 1000 * (60 / (50 * wpm)); int word_space_ms = ms_per_dit * 7; // Hardcoding these for now, will come back and make it more flexible. MorseEffect morseEffectCQ("CQ CQ CQ DE W1CDN", ms_per_dit); @@ -446,7 +446,7 @@ void loop() { // See which message we are sending // Only do this when the message has been updated. if(yourInputMsg != yourInputMsg_old){ - morseToSend.Stop(JLed::eStopMode::FULL_OFF).Update(); + //morseToSend.Stop(JLed::eStopMode::FULL_OFF).Update(); if(yourInputMsg == 0){ morseToSend = morseCQ; } else if(yourInputMsg == 1){ -- 2.30.2 From 7d673fe70c09b0473e8cd7aa5955fdc637cf358b Mon Sep 17 00:00:00 2001 From: mattbk Date: Sat, 2 Sep 2023 18:35:08 -0500 Subject: [PATCH 8/9] Stub out RTC integration. --- vulpes/platformio.ini | 4 +- vulpes/src/main.cpp | 196 ++++++++++++++++++++++++++++-------------- 2 files changed, 136 insertions(+), 64 deletions(-) diff --git a/vulpes/platformio.ini b/vulpes/platformio.ini index ace10bd..ce3e1cb 100644 --- a/vulpes/platformio.ini +++ b/vulpes/platformio.ini @@ -18,5 +18,7 @@ lib_deps = me-no-dev/ESP Async WebServer@^1.2.3 contrem/arduino-timer@^3.0.1 kj7rrv/Telegraph@^1.0.0 - ;etherkit/Etherkit Morse@^1.1.2 jandelgado/JLed@^4.13.0 + adafruit/RTClib@^2.1.1 + adafruit/Adafruit BusIO@^1.14.3 + ;jchristensen/DS3232RTC@^2.0.1 diff --git a/vulpes/src/main.cpp b/vulpes/src/main.cpp index 0dc2bf3..8184420 100644 --- a/vulpes/src/main.cpp +++ b/vulpes/src/main.cpp @@ -17,18 +17,22 @@ #include #include #include -#include +// #include //#include //arduino morse //#include //etherkit morse #include // jled #include "jled/morse.h" //jled -//#include "morse_effect.h" // jled +#include // for DS3231 +#include // for DS3231 +//#include //for DS3231 // download zip from https://github.com/me-no-dev/ESPAsyncWebServer and install. #include AsyncWebServer server(80); +RTC_DS3231 rtc; + // Read from config.h const char* ssid = WIFI_SSID; const char* password = WIFI_PASSWORD; @@ -38,6 +42,7 @@ const char* PARAM_SEND = "inputSend"; const char* PARAM_WPM = "inputWPM"; const char* PARAM_MSG = "inputMsg"; const char* PARAM_FLOAT = "inputFloat"; +const char* PARAM_TIME = "inputTimeUnix"; // Global variables String yourInputString; @@ -46,6 +51,7 @@ int yourInputWPM; int yourInputMsg; int yourInputMsg_old; // to save previous state and check changes float yourInputFloat; +String yourInputTime; //to keep time // HTML web page to handle 3 input fields (inputString, inputSend, inputFloat) const char index_html[] PROGMEM = R"rawliteral( @@ -80,10 +86,15 @@ const char index_html[] PROGMEM = R"rawliteral( WPM (current value %inputWPM%): (doesn't work yet)
+ Time Unix:
+ inputFloat (current value %inputFloat%):
+ )rawliteral"; // Auxiliary variables to store the current output state @@ -91,7 +102,7 @@ String output26State = "off"; String output27State = "off"; // Assign output variables to GPIO pins -const int output26 = 26; +const int output26 = 32;//26 for LED; //32 for transmitter keyer const int output27 = 27; // Timers @@ -106,16 +117,16 @@ bool toggle_led(void *) { } // Toggle GPIO pin (LED or relay) -bool toggle_gpio_26(void *) { - if(output26State == "off"){ - output26State = "on"; - digitalWrite(output26, HIGH); - } else { - output26State = "off"; - digitalWrite(output26, LOW); - } - return true; // keep timer active? true -} +// bool toggle_gpio_26(void *) { +// if(output26State == "off"){ +// output26State = "on"; +// digitalWrite(output26, HIGH); +// } else { +// output26State = "off"; +// digitalWrite(output26, LOW); +// } +// return true; // keep timer active? true +// } void notFound(AsyncWebServerRequest *request) { request->send(404, "text/plain", "Not found"); @@ -174,65 +185,65 @@ String processor(const String& var){ return String(); } -// vvvvv Modify some functions from KB1OIQ's controller. -// This section hasn't been tested on the hardware. +// // vvvvv Modify some functions from KB1OIQ's controller. +// // This section hasn't been tested on the hardware. -//int dit_len = 60 ; //milliseconds; https://morsecode.world/international/timing.html +// //int dit_len = 60 ; //milliseconds; https://morsecode.world/international/timing.html -//================================================================================ -// stop_26(): set GPIO 26 to LOW. Used for dot(), dash(). -//================================================================================ -bool stop_26(void *){ - output26State = "off"; - digitalWrite(output26, LOW); - return false; // keep timer active? true -} +// //================================================================================ +// // stop_26(): set GPIO 26 to LOW. Used for dot(), dash(). +// //================================================================================ +// bool stop_26(void *){ +// output26State = "off"; +// digitalWrite(output26, LOW); +// return false; // keep timer active? true +// } -//================================================================================ -// dit(): transmit a single dit -//================================================================================ -void dit(int dit_len = 1000) { - output26State = "on"; - digitalWrite(output26, HIGH); - timer.in(dit_len, stop_26); -} +// //================================================================================ +// // dit(): transmit a single dit +// //================================================================================ +// void dit(int dit_len = 1000) { +// output26State = "on"; +// digitalWrite(output26, HIGH); +// timer.in(dit_len, stop_26); +// } -//================================================================================ -// dah(): transmit a single dah -//================================================================================ -void dah(int dit_len = 1000) { - output26State = "on"; - digitalWrite(output26, HIGH); - timer.in(dit_len * 3, stop_26); -} +// //================================================================================ +// // dah(): transmit a single dah +// //================================================================================ +// void dah(int dit_len = 1000) { +// output26State = "on"; +// digitalWrite(output26, HIGH); +// timer.in(dit_len * 3, stop_26); +// } -//================================================================================ -// char_space()): transmit a character space -//================================================================================ -// A function that does nothing except (hopefully) block the timer. -bool empty(void *) { - return false; - } +// //================================================================================ +// // char_space()): transmit a character space +// //================================================================================ +// // A function that does nothing except (hopefully) block the timer. +// bool empty(void *) { +// return false; +// } -void char_space(int dit_len = 1000) { +// void char_space(int dit_len = 1000) { - timer.in(dit_len, empty); -} +// timer.in(dit_len, empty); +// } -void k(){ - Serial.println("K"); - dah(); - char_space(); - dit(); - char_space(); - dah(); -} +// void k(){ +// Serial.println("K"); +// dah(); +// char_space(); +// dit(); +// char_space(); +// dah(); +// } -// ^^^^ +// // ^^^^ -//telegraph -//Telegraph telegraph(LED_BUILTIN, 10, HIGH); -Telegraph telegraph26(output26, 10, HIGH); +// //telegraph +// //Telegraph telegraph(LED_BUILTIN, 10, HIGH); +// Telegraph telegraph26(output26, 10, HIGH); //arduinomorse //LEDMorseSender sender(LED_BUILTIN); @@ -265,7 +276,7 @@ class MorseEffect : public jled::BrightnessEvaluator { float wpm = 10; float ms_per_dit = 1000 * (60 / (50 * wpm)); int word_space_ms = ms_per_dit * 7; -// Hardcoding these for now, will come back and make it more flexible. +// Hardcoding messages and WPM for now, will come back and make it more flexible. MorseEffect morseEffectCQ("CQ CQ CQ DE W1CDN", ms_per_dit); MorseEffect morseEffectMOE("MOE", ms_per_dit); MorseEffect morseEffectMOI("MOI", ms_per_dit); @@ -287,12 +298,48 @@ auto morseMO5 = JLed(output26).UserFunc(&morseEffectMO5).DelayAfter(word_space_ms).Forever(); auto morseToSend = morseCQ; // set this up to overwrite later + +// format and print a time_t value +// void printTime(time_t t) +// { +// char buf[25]; +// char m[4]; // temporary storage for month string (DateStrings.cpp uses shared buffer) +// strcpy(m, monthShortStr(month(t))); +// sprintf(buf, "%.2d:%.2d:%.2d %s %.2d %s %d", +// hour(t), minute(t), second(t), dayShortStr(weekday(t)), day(t), m, year(t)); +// Serial.println(buf); +// } + //================================================================================ // setup(): stuff that only gets done once, after power up (KB1OIQ's description) //================================================================================ void setup() { Serial.begin(115200); + // https://github.com/JChristensen/DS3232RTC/blob/master/examples/TimeRTC/TimeRTC.ino + // rtc.begin(); + // setSyncProvider(rtc.get); // the function to get the time from the RTC + // if(timeStatus() != timeSet) + // Serial.println("Unable to sync with the RTC"); + // else + // Serial.println("RTC has set the system time"); + + if (! rtc.begin()) { + Serial.println("Couldn't find RTC"); + Serial.flush(); + while (1) delay(10); + } + + if (rtc.lostPower()) { + Serial.println("RTC lost power, let's set the time!"); + // When time needs to be set on a new device, or after a power loss, the + // following line sets the RTC to the date & time this sketch was compiled + rtc.adjust(DateTime(__DATE__, __TIME__)); + // This line sets the RTC with an explicit date & time, for example to set + // January 21, 2014 at 3am you would call: + //rtc.adjust(DateTime(2023, 9, 2, 17, 32, 0)); + } + // Timer example, blink main LED pinMode(LED_BUILTIN, OUTPUT); // set LED pin to OUTPUT // call the toggle_led function every 10000 millis (10 second) @@ -407,6 +454,12 @@ void setup() { yourInputMsg_old = yourInputMsg; yourInputMsg = inputMessage.toInt(); } + // GET inputTimeUnix value on /get?inputTimeUnix= + if (request->hasParam(PARAM_TIME)) { + inputMessage = request->getParam(PARAM_TIME)->value(); + yourInputTime = inputMessage; + Serial.println(yourInputTime); + } // GET inputFloat value on /get?inputFloat= if (request->hasParam(PARAM_FLOAT)) { inputMessage = request->getParam(PARAM_FLOAT)->value(); @@ -440,6 +493,23 @@ void loop() { time_until_start.tick(); timer.tick(); + DateTime now = rtc.now(); + // Serial.print(now.year(), DEC); + // Serial.print('/'); + // Serial.print(now.month(), DEC); + // Serial.print('/'); + // Serial.print(now.day(), DEC); + // Serial.print(" ("); + // Serial.print(now.dayOfTheWeek()); + // Serial.print(") "); + // Serial.print(now.hour(), DEC); + // Serial.print(':'); + // Serial.print(now.minute(), DEC); + // Serial.print(':'); + // Serial.print(now.second(), DEC); + // Serial.println(); + + //arduinomorse //sender.continueSending(); -- 2.30.2 From 736109b9b0b1c729d146533758d3c8bb0f8d1990 Mon Sep 17 00:00:00 2001 From: mattbk Date: Sat, 2 Sep 2023 18:48:40 -0500 Subject: [PATCH 9/9] Revert "Stub out RTC integration." This reverts commit 7d673fe70c09b0473e8cd7aa5955fdc637cf358b. --- vulpes/platformio.ini | 4 +- vulpes/src/main.cpp | 196 ++++++++++++++---------------------------- 2 files changed, 64 insertions(+), 136 deletions(-) diff --git a/vulpes/platformio.ini b/vulpes/platformio.ini index ce3e1cb..ace10bd 100644 --- a/vulpes/platformio.ini +++ b/vulpes/platformio.ini @@ -18,7 +18,5 @@ lib_deps = me-no-dev/ESP Async WebServer@^1.2.3 contrem/arduino-timer@^3.0.1 kj7rrv/Telegraph@^1.0.0 + ;etherkit/Etherkit Morse@^1.1.2 jandelgado/JLed@^4.13.0 - adafruit/RTClib@^2.1.1 - adafruit/Adafruit BusIO@^1.14.3 - ;jchristensen/DS3232RTC@^2.0.1 diff --git a/vulpes/src/main.cpp b/vulpes/src/main.cpp index 8184420..0dc2bf3 100644 --- a/vulpes/src/main.cpp +++ b/vulpes/src/main.cpp @@ -17,22 +17,18 @@ #include #include #include -// #include +#include //#include //arduino morse //#include //etherkit morse #include // jled #include "jled/morse.h" //jled -#include // for DS3231 -#include // for DS3231 -//#include //for DS3231 +//#include "morse_effect.h" // jled // download zip from https://github.com/me-no-dev/ESPAsyncWebServer and install. #include AsyncWebServer server(80); -RTC_DS3231 rtc; - // Read from config.h const char* ssid = WIFI_SSID; const char* password = WIFI_PASSWORD; @@ -42,7 +38,6 @@ const char* PARAM_SEND = "inputSend"; const char* PARAM_WPM = "inputWPM"; const char* PARAM_MSG = "inputMsg"; const char* PARAM_FLOAT = "inputFloat"; -const char* PARAM_TIME = "inputTimeUnix"; // Global variables String yourInputString; @@ -51,7 +46,6 @@ int yourInputWPM; int yourInputMsg; int yourInputMsg_old; // to save previous state and check changes float yourInputFloat; -String yourInputTime; //to keep time // HTML web page to handle 3 input fields (inputString, inputSend, inputFloat) const char index_html[] PROGMEM = R"rawliteral( @@ -86,15 +80,10 @@ const char index_html[] PROGMEM = R"rawliteral( WPM (current value %inputWPM%): (doesn't work yet)
- Time Unix:
- inputFloat (current value %inputFloat%):
- )rawliteral"; // Auxiliary variables to store the current output state @@ -102,7 +91,7 @@ String output26State = "off"; String output27State = "off"; // Assign output variables to GPIO pins -const int output26 = 32;//26 for LED; //32 for transmitter keyer +const int output26 = 26; const int output27 = 27; // Timers @@ -117,16 +106,16 @@ bool toggle_led(void *) { } // Toggle GPIO pin (LED or relay) -// bool toggle_gpio_26(void *) { -// if(output26State == "off"){ -// output26State = "on"; -// digitalWrite(output26, HIGH); -// } else { -// output26State = "off"; -// digitalWrite(output26, LOW); -// } -// return true; // keep timer active? true -// } +bool toggle_gpio_26(void *) { + if(output26State == "off"){ + output26State = "on"; + digitalWrite(output26, HIGH); + } else { + output26State = "off"; + digitalWrite(output26, LOW); + } + return true; // keep timer active? true +} void notFound(AsyncWebServerRequest *request) { request->send(404, "text/plain", "Not found"); @@ -185,65 +174,65 @@ String processor(const String& var){ return String(); } -// // vvvvv Modify some functions from KB1OIQ's controller. -// // This section hasn't been tested on the hardware. +// vvvvv Modify some functions from KB1OIQ's controller. +// This section hasn't been tested on the hardware. -// //int dit_len = 60 ; //milliseconds; https://morsecode.world/international/timing.html +//int dit_len = 60 ; //milliseconds; https://morsecode.world/international/timing.html -// //================================================================================ -// // stop_26(): set GPIO 26 to LOW. Used for dot(), dash(). -// //================================================================================ -// bool stop_26(void *){ -// output26State = "off"; -// digitalWrite(output26, LOW); -// return false; // keep timer active? true -// } +//================================================================================ +// stop_26(): set GPIO 26 to LOW. Used for dot(), dash(). +//================================================================================ +bool stop_26(void *){ + output26State = "off"; + digitalWrite(output26, LOW); + return false; // keep timer active? true +} -// //================================================================================ -// // dit(): transmit a single dit -// //================================================================================ -// void dit(int dit_len = 1000) { -// output26State = "on"; -// digitalWrite(output26, HIGH); -// timer.in(dit_len, stop_26); -// } +//================================================================================ +// dit(): transmit a single dit +//================================================================================ +void dit(int dit_len = 1000) { + output26State = "on"; + digitalWrite(output26, HIGH); + timer.in(dit_len, stop_26); +} -// //================================================================================ -// // dah(): transmit a single dah -// //================================================================================ -// void dah(int dit_len = 1000) { -// output26State = "on"; -// digitalWrite(output26, HIGH); -// timer.in(dit_len * 3, stop_26); -// } +//================================================================================ +// dah(): transmit a single dah +//================================================================================ +void dah(int dit_len = 1000) { + output26State = "on"; + digitalWrite(output26, HIGH); + timer.in(dit_len * 3, stop_26); +} -// //================================================================================ -// // char_space()): transmit a character space -// //================================================================================ -// // A function that does nothing except (hopefully) block the timer. -// bool empty(void *) { -// return false; -// } +//================================================================================ +// char_space()): transmit a character space +//================================================================================ +// A function that does nothing except (hopefully) block the timer. +bool empty(void *) { + return false; + } -// void char_space(int dit_len = 1000) { +void char_space(int dit_len = 1000) { -// timer.in(dit_len, empty); -// } + timer.in(dit_len, empty); +} -// void k(){ -// Serial.println("K"); -// dah(); -// char_space(); -// dit(); -// char_space(); -// dah(); -// } +void k(){ + Serial.println("K"); + dah(); + char_space(); + dit(); + char_space(); + dah(); +} -// // ^^^^ +// ^^^^ -// //telegraph -// //Telegraph telegraph(LED_BUILTIN, 10, HIGH); -// Telegraph telegraph26(output26, 10, HIGH); +//telegraph +//Telegraph telegraph(LED_BUILTIN, 10, HIGH); +Telegraph telegraph26(output26, 10, HIGH); //arduinomorse //LEDMorseSender sender(LED_BUILTIN); @@ -276,7 +265,7 @@ class MorseEffect : public jled::BrightnessEvaluator { float wpm = 10; float ms_per_dit = 1000 * (60 / (50 * wpm)); int word_space_ms = ms_per_dit * 7; -// Hardcoding messages and WPM for now, will come back and make it more flexible. +// Hardcoding these for now, will come back and make it more flexible. MorseEffect morseEffectCQ("CQ CQ CQ DE W1CDN", ms_per_dit); MorseEffect morseEffectMOE("MOE", ms_per_dit); MorseEffect morseEffectMOI("MOI", ms_per_dit); @@ -298,48 +287,12 @@ auto morseMO5 = JLed(output26).UserFunc(&morseEffectMO5).DelayAfter(word_space_ms).Forever(); auto morseToSend = morseCQ; // set this up to overwrite later - -// format and print a time_t value -// void printTime(time_t t) -// { -// char buf[25]; -// char m[4]; // temporary storage for month string (DateStrings.cpp uses shared buffer) -// strcpy(m, monthShortStr(month(t))); -// sprintf(buf, "%.2d:%.2d:%.2d %s %.2d %s %d", -// hour(t), minute(t), second(t), dayShortStr(weekday(t)), day(t), m, year(t)); -// Serial.println(buf); -// } - //================================================================================ // setup(): stuff that only gets done once, after power up (KB1OIQ's description) //================================================================================ void setup() { Serial.begin(115200); - // https://github.com/JChristensen/DS3232RTC/blob/master/examples/TimeRTC/TimeRTC.ino - // rtc.begin(); - // setSyncProvider(rtc.get); // the function to get the time from the RTC - // if(timeStatus() != timeSet) - // Serial.println("Unable to sync with the RTC"); - // else - // Serial.println("RTC has set the system time"); - - if (! rtc.begin()) { - Serial.println("Couldn't find RTC"); - Serial.flush(); - while (1) delay(10); - } - - if (rtc.lostPower()) { - Serial.println("RTC lost power, let's set the time!"); - // When time needs to be set on a new device, or after a power loss, the - // following line sets the RTC to the date & time this sketch was compiled - rtc.adjust(DateTime(__DATE__, __TIME__)); - // This line sets the RTC with an explicit date & time, for example to set - // January 21, 2014 at 3am you would call: - //rtc.adjust(DateTime(2023, 9, 2, 17, 32, 0)); - } - // Timer example, blink main LED pinMode(LED_BUILTIN, OUTPUT); // set LED pin to OUTPUT // call the toggle_led function every 10000 millis (10 second) @@ -454,12 +407,6 @@ void setup() { yourInputMsg_old = yourInputMsg; yourInputMsg = inputMessage.toInt(); } - // GET inputTimeUnix value on /get?inputTimeUnix= - if (request->hasParam(PARAM_TIME)) { - inputMessage = request->getParam(PARAM_TIME)->value(); - yourInputTime = inputMessage; - Serial.println(yourInputTime); - } // GET inputFloat value on /get?inputFloat= if (request->hasParam(PARAM_FLOAT)) { inputMessage = request->getParam(PARAM_FLOAT)->value(); @@ -493,23 +440,6 @@ void loop() { time_until_start.tick(); timer.tick(); - DateTime now = rtc.now(); - // Serial.print(now.year(), DEC); - // Serial.print('/'); - // Serial.print(now.month(), DEC); - // Serial.print('/'); - // Serial.print(now.day(), DEC); - // Serial.print(" ("); - // Serial.print(now.dayOfTheWeek()); - // Serial.print(") "); - // Serial.print(now.hour(), DEC); - // Serial.print(':'); - // Serial.print(now.minute(), DEC); - // Serial.print(':'); - // Serial.print(now.second(), DEC); - // Serial.println(); - - //arduinomorse //sender.continueSending(); -- 2.30.2