Integrate RTC chip #16

Merged
W1CDN merged 5 commits from add-rtc into main 2023-09-03 11:00:47 -05:00
2 changed files with 168 additions and 70 deletions

View File

@ -10,13 +10,20 @@
[env:esp32doit-devkit-v1] [env:esp32doit-devkit-v1]
platform = espressif32 platform = espressif32
;build_flags =
; -std=c++11
; -std=gnu++11
board = esp32doit-devkit-v1 board = esp32doit-devkit-v1
framework = arduino framework = arduino
upload_speed = 921600
monitor_speed = 115200 monitor_speed = 115200
lib_deps = lib_deps =
me-no-dev/AsyncTCP@^1.1.1 me-no-dev/AsyncTCP@^1.1.1
me-no-dev/ESP Async WebServer@^1.2.3 me-no-dev/ESP Async WebServer@^1.2.3
contrem/arduino-timer@^3.0.1 contrem/arduino-timer@^3.0.1
kj7rrv/Telegraph@^1.0.0 kj7rrv/Telegraph@^1.0.0
;etherkit/Etherkit Morse@^1.1.2
jandelgado/JLed@^4.13.0 jandelgado/JLed@^4.13.0
;adafruit/RTClib@^2.1.1
https://github.com/adafruit/RTClib.git ; >=2.1.2
adafruit/Adafruit BusIO@^1.14.3
;jchristensen/DS3232RTC@^2.0.1

View File

@ -17,18 +17,23 @@
#include <SPIFFS.h> #include <SPIFFS.h>
#include <Preferences.h> #include <Preferences.h>
#include <arduino-timer.h> #include <arduino-timer.h>
#include <Telegraph.h> // #include <Telegraph.h>
//#include <morse.h> //arduino morse //#include <morse.h> //arduino morse
//#include <Morse.h> //etherkit morse //#include <Morse.h> //etherkit morse
#include <jled.h> // jled #include <jled.h> // jled
#include "jled/morse.h" //jled #include "jled/morse.h" //jled
//#include "morse_effect.h" // jled #include <Adafruit_BusIO_Register.h> // for DS3231
#include <RTClib.h> // for DS3231
//#include <DS3232RTC.h> //for DS3231
//#include <sstream>
// download zip from https://github.com/me-no-dev/ESPAsyncWebServer and install. // download zip from https://github.com/me-no-dev/ESPAsyncWebServer and install.
#include <ESPAsyncWebServer.h> #include <ESPAsyncWebServer.h>
AsyncWebServer server(80); AsyncWebServer server(80);
RTC_DS3231 rtc; // set up RTC
// Read from config.h // Read from config.h
const char* ssid = WIFI_SSID; const char* ssid = WIFI_SSID;
const char* password = WIFI_PASSWORD; const char* password = WIFI_PASSWORD;
@ -38,6 +43,7 @@ const char* PARAM_SEND = "inputSend";
const char* PARAM_WPM = "inputWPM"; const char* PARAM_WPM = "inputWPM";
const char* PARAM_MSG = "inputMsg"; const char* PARAM_MSG = "inputMsg";
const char* PARAM_FLOAT = "inputFloat"; const char* PARAM_FLOAT = "inputFloat";
const char* PARAM_TIME = "inputTimeUnix";
// Global variables // Global variables
String yourInputString; String yourInputString;
@ -46,6 +52,7 @@ int yourInputWPM;
int yourInputMsg; int yourInputMsg;
int yourInputMsg_old; // to save previous state and check changes int yourInputMsg_old; // to save previous state and check changes
float yourInputFloat; float yourInputFloat;
uint32_t yourInputTime; //to keep time
// HTML web page to handle 3 input fields (inputString, inputSend, inputFloat) // HTML web page to handle 3 input fields (inputString, inputSend, inputFloat)
const char index_html[] PROGMEM = R"rawliteral( const char index_html[] PROGMEM = R"rawliteral(
@ -53,12 +60,11 @@ const char index_html[] PROGMEM = R"rawliteral(
<title>ESP Input Form</title> <title>ESP Input Form</title>
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<script> <script>
function submitMessage() { var putDate = function(form) {
<!--alert("Saved value to ESP SPIFFS");--> form.inputTimeUnix.value = Math.floor(Date.now() / 1000);
setTimeout(function(){ document.location.reload(false); }, 500); };
}
</script></head><body> </script></head><body>
<form action="/get" target="hidden-form"> <form action="/get" target="hidden-form" onsubmit="putDate(this);">
inputString (current value %inputString%): <input type="text" name="inputString" value=%inputString%><br> inputString (current value %inputString%): <input type="text" name="inputString" value=%inputString%><br>
Sending program (cycle doesn't work yet) (current value: <b>%inputSend%</b>): Sending program (cycle doesn't work yet) (current value: <b>%inputSend%</b>):
@ -80,8 +86,11 @@ const char index_html[] PROGMEM = R"rawliteral(
WPM (current value %inputWPM%): <input type="number " name="inputWPM" value = %inputWPM%> (doesn't work yet)<br> WPM (current value %inputWPM%): <input type="number " name="inputWPM" value = %inputWPM%> (doesn't work yet)<br>
Current time (UTC): %inputTimeUnix%
<input type="hidden" name="inputTimeUnix" id="js_time_unix"><br>
inputFloat (current value %inputFloat%): <input type="number " name="inputFloat" value = %inputFloat%><br> inputFloat (current value %inputFloat%): <input type="number " name="inputFloat" value = %inputFloat%><br>
<input type="submit" value="Submit" onclick="submitMessage()"> <input type="submit" value="Submit"">
</form> </form>
<iframe style="display:none" name="hidden-form"></iframe> <iframe style="display:none" name="hidden-form"></iframe>
</body></html>)rawliteral"; </body></html>)rawliteral";
@ -91,7 +100,7 @@ String output26State = "off";
String output27State = "off"; String output27State = "off";
// Assign output variables to GPIO pins // 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; const int output27 = 27;
// Timers // Timers
@ -106,16 +115,16 @@ bool toggle_led(void *) {
} }
// Toggle GPIO pin (LED or relay) // Toggle GPIO pin (LED or relay)
bool toggle_gpio_26(void *) { // bool toggle_gpio_26(void *) {
if(output26State == "off"){ // if(output26State == "off"){
output26State = "on"; // output26State = "on";
digitalWrite(output26, HIGH); // digitalWrite(output26, HIGH);
} else { // } else {
output26State = "off"; // output26State = "off";
digitalWrite(output26, LOW); // digitalWrite(output26, LOW);
} // }
return true; // keep timer active? true // return true; // keep timer active? true
} // }
void notFound(AsyncWebServerRequest *request) { void notFound(AsyncWebServerRequest *request) {
request->send(404, "text/plain", "Not found"); request->send(404, "text/plain", "Not found");
@ -170,69 +179,71 @@ String processor(const String& var){
} }
else if(var == "inputFloat"){ else if(var == "inputFloat"){
return readFile(SPIFFS, "/inputFloat.txt"); return readFile(SPIFFS, "/inputFloat.txt");
} else if(var == "inputTimeUnix"){
return rtc.now().timestamp();
} }
return String(); return String();
} }
// vvvvv Modify some functions from KB1OIQ's controller. // // vvvvv Modify some functions from KB1OIQ's controller.
// This section hasn't been tested on the hardware. // // 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(). // // stop_26(): set GPIO 26 to LOW. Used for dot(), dash().
//================================================================================ // //================================================================================
bool stop_26(void *){ // bool stop_26(void *){
output26State = "off"; // output26State = "off";
digitalWrite(output26, LOW); // digitalWrite(output26, LOW);
return false; // keep timer active? true // return false; // keep timer active? true
} // }
//================================================================================ // //================================================================================
// dit(): transmit a single dit // // dit(): transmit a single dit
//================================================================================ // //================================================================================
void dit(int dit_len = 1000) { // void dit(int dit_len = 1000) {
output26State = "on"; // output26State = "on";
digitalWrite(output26, HIGH); // digitalWrite(output26, HIGH);
timer.in(dit_len, stop_26); // timer.in(dit_len, stop_26);
} // }
//================================================================================ // //================================================================================
// dah(): transmit a single dah // // dah(): transmit a single dah
//================================================================================ // //================================================================================
void dah(int dit_len = 1000) { // void dah(int dit_len = 1000) {
output26State = "on"; // output26State = "on";
digitalWrite(output26, HIGH); // digitalWrite(output26, HIGH);
timer.in(dit_len * 3, stop_26); // timer.in(dit_len * 3, stop_26);
} // }
//================================================================================ // //================================================================================
// char_space()): transmit a character space // // char_space()): transmit a character space
//================================================================================ // //================================================================================
// A function that does nothing except (hopefully) block the timer. // // A function that does nothing except (hopefully) block the timer.
bool empty(void *) { // bool empty(void *) {
return false; // 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(){ // void k(){
Serial.println("K"); // Serial.println("K");
dah(); // dah();
char_space(); // char_space();
dit(); // dit();
char_space(); // char_space();
dah(); // dah();
} // }
// ^^^^ // // ^^^^
//telegraph // //telegraph
//Telegraph telegraph(LED_BUILTIN, 10, HIGH); // //Telegraph telegraph(LED_BUILTIN, 10, HIGH);
Telegraph telegraph26(output26, 10, HIGH); // Telegraph telegraph26(output26, 10, HIGH);
//arduinomorse //arduinomorse
//LEDMorseSender sender(LED_BUILTIN); //LEDMorseSender sender(LED_BUILTIN);
@ -265,7 +276,7 @@ class MorseEffect : public jled::BrightnessEvaluator {
float wpm = 10; float wpm = 10;
float ms_per_dit = 1000 * (60 / (50 * wpm)); float ms_per_dit = 1000 * (60 / (50 * wpm));
int word_space_ms = ms_per_dit * 7; 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 morseEffectCQ("CQ CQ CQ DE W1CDN", ms_per_dit);
MorseEffect morseEffectMOE("MOE", ms_per_dit); MorseEffect morseEffectMOE("MOE", ms_per_dit);
MorseEffect morseEffectMOI("MOI", ms_per_dit); MorseEffect morseEffectMOI("MOI", ms_per_dit);
@ -287,12 +298,48 @@ auto morseMO5 =
JLed(output26).UserFunc(&morseEffectMO5).DelayAfter(word_space_ms).Forever(); JLed(output26).UserFunc(&morseEffectMO5).DelayAfter(word_space_ms).Forever();
auto morseToSend = morseCQ; // set this up to overwrite later 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) // setup(): stuff that only gets done once, after power up (KB1OIQ's description)
//================================================================================ //================================================================================
void setup() { void setup() {
Serial.begin(115200); 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 // Timer example, blink main LED
pinMode(LED_BUILTIN, OUTPUT); // set LED pin to OUTPUT pinMode(LED_BUILTIN, OUTPUT); // set LED pin to OUTPUT
// call the toggle_led function every 10000 millis (10 second) // call the toggle_led function every 10000 millis (10 second)
@ -407,6 +454,33 @@ void setup() {
yourInputMsg_old = yourInputMsg; yourInputMsg_old = yourInputMsg;
yourInputMsg = inputMessage.toInt(); yourInputMsg = inputMessage.toInt();
} }
// GET inputTimeUnix value on <ESP_IP>/get?inputTimeUnix=<inputMessage>
if (request->hasParam(PARAM_TIME)) {
inputMessage = request->getParam(PARAM_TIME)->value();
Serial.println(inputMessage);
//https://stackoverflow.com/a/22733127/2152245
yourInputTime = atol(inputMessage.c_str());
Serial.println(yourInputTime);
// update the RTC time
rtc.adjust(DateTime(yourInputTime));
;
DateTime now = rtc.now();
Serial.print("UTC time from browser: ");
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();
}
// GET inputFloat value on <ESP_IP>/get?inputFloat=<inputMessage> // GET inputFloat value on <ESP_IP>/get?inputFloat=<inputMessage>
if (request->hasParam(PARAM_FLOAT)) { if (request->hasParam(PARAM_FLOAT)) {
inputMessage = request->getParam(PARAM_FLOAT)->value(); inputMessage = request->getParam(PARAM_FLOAT)->value();
@ -440,6 +514,23 @@ void loop() {
time_until_start.tick(); time_until_start.tick();
timer.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 //arduinomorse
//sender.continueSending(); //sender.continueSending();