david_2018:
RTClib has a function to convert a DateTime variable to human readable form, the somewhat confusingly named .toString() because it returns a char* , not a String. You can specify a format for the date and time, the details of which are in the toString example sketch included with the library.
You will need to create a buffer to hold the return value from the function. Here is your sketch modified to use that instead of using Strings:
#include <SoftwareSerial.h>
#include "RTClib.h" // For Real Time Clock
#include "ThingSpeak.h"
#include "WiFiEsp.h"
#include "secrets.h"
#include "time.h"
#include <TimeLib.h>
#include <math.h>
#include "WiFiEspUdp.h"
#include <Timezone.h>
// Real time clock
RTC_DS3231 rtc;
char ssid[] = SECRET_SSID; // network SSID (name)
char pass[] = SECRET_PASS; // network password
int keyIndex = 0; // network key Index number (needed only for WEP)
WiFiEspClient client;
unsigned long myChannelNumber = SECRET_CH_ID; // Thingspeak channel ID
const char * myWriteAPIKey = SECRET_WRITE_APIKEY; // Thingspeak channel API key
int ThingSpeakResponse = 0;
// Timing-related variables
time_t UTCtime;
time_t nowUTC;
time_t nowLocal;
// Timezone rules for United Kingdom (London, Belfast)
TimeChangeRule BST = {"BST", Last, Sun, Mar, 1, 60}; // British Summer Time
TimeChangeRule GMT = {"GMT", Last, Sun, Oct, 2, 0}; // Standard Time
Timezone UK(BST, GMT);
void setup() {
// Initialize serial for output
Serial.begin(9600);
// Initialize DS3231 Real Time Clock
if (! rtc.begin()) {
Serial.println(F("Couldn't find RTC"));
while (1); // can't go further
}
// Initialize serial for ESP module
Serial1.begin(115200);
// Initialize ESP module
WiFi.init(&Serial1);
// Check for the presence of the shield
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println(F("WiFi shield not present"));
while (true);
}
// Initialize ThingSpeak
ThingSpeak.begin(client);
// Connect or reconnect to WiFi
if (WiFi.status() != WL_CONNECTED) {
Serial.print(F("Attempting to connect to SSID: "));
Serial.println(SECRET_SSID);
while (WiFi.status() != WL_CONNECTED) {
WiFi.begin(ssid, pass); // Connect to WPA/WPA2 network. Change this line if using open or WEP network
delay(5000);
}
}
// Set RTC time
rtc.adjust(DateTime(2020, 4, 2, 12, 0, 0)); // Set real time clock manually for testing purposes
nowUTC = rtc.now().unixtime(); // Get current unix timestamp from rtc
char buff[20]; //buffer for storing human-readable date and time
Serial.print(F("nowUTC: "));
Serial.println(nowUTC); // Correctly is 1585828800
Serial.print(F("Human readable: "));
Serial.println(datetimestring(buff, nowUTC)); // Correctly is 2020/04/02 12:00:00
nowLocal = UK.toLocal(nowUTC); // Convert time according to day light saving time rule
Serial.print(F("nowLocal: "));
Serial.println(nowLocal); // Should be 1585832400
Serial.print(F("Human readable: "));
Serial.println(datetimestring(buff, nowLocal)); // Should be 2020/04/02 13:00:00
}
void loop() {
// Set ThingSpeak fields with the values
ThingSpeak.setField(1, 1);
// Set ThingSpeak channel status
ThingSpeak.setStatus("Testing");
// Write to the ThingSpeak channel
//ThingSpeakResponse = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
}
// Function to return date and time in human readable form
// format "yyyy/mm/dd hh:mm:ss"
// must declare dest[] as 20 char or larger
char * datetimestring(char * dest, DateTime datetime) {
static const char datetimeTemplate[] PROGMEM = "YYYY/MM/DD hh:mm:ss"; //stored in PROGMEM to save space in ram
strcpy_P(dest, datetimeTemplate); //copy template to buffer
return (datetime.toString(dest));
}
Thank you so much david_2018, that did it! I did not know that a String goes out of scope if it's local to a function - every day is school day. Thanks odometer, too, I'll implement your suggestion.
I still cannot quite get my head around the observations I have made earlier though. I guess it had to do with the fact that the datetimestring() function was used just before the lines that just 'appeared' to affect the result (when, in fact, it was the memory being screwed up by my datetimestring() function? And maybe it didn't become apparent earlier in the code where it had already been used because the Thingspeak update is more memory-intensive?). If you feel like explaining it in a bit more detail, I'd appreciate that because I like to learn from my mistakes. If not, that's fine too. Thanks again!