I was not able to test the following other than parts to check the logic of compiling and uncompiling the programs and whether the logic to turn a pin on or off works. My tests indicate that logic is working however I'm not sure of the file reading and writing.
I also tried to make it "do the appropriate thing" in the face of data errors. There were a few places where I was unsure as to what you were trying to accomplish so I just made a guess.
I did add to the program to include a pin number on the end. So the format is now:
Mon, Tues, Wed, Thur, Fri, Sat, Sun, H, H, M, M, on/off, pin number
By changing the program storage from a character string to the binary data structure, memory usage was reduced. If you increase the number of programs, the amount of memory used increases by less using the binary data structure over the character string storage.
This compiled with the Arduino IDE however Microsoft Visual Studio 2019 displayed errors which required that I use #defines for the day of week constants so that
const uint8_t SundayDOW = 0x01;
became
#define SundayDOW 0x01
, etc.
#include <iostream>
#include <string>
#include <FS.h> // File system library
#include <SPI.h> // Esp8266/Esp32 core library for Arduino environment
#include <SD.h> // SD card library
#include "time.h" /*C:\Users\User\AppData\Local\Arduino..\packages\ esp32\hardware\esp32\2.0.9\tools\ sdk\esp32\include\newlib\platform_include\*/
#include <WiFi.h> // This library allows an Arduino board to connect to the internet
#include <Wire.h> // Wiring library
const char *ssid = "your ssid";
const char *password = "password";
const char *ntpServerName = "pool.ntp.org";
const long gmtOffset_sec = 3600;
const int daylightOffset_sec = 3600;
const uint8_t SundayDOW = 0x01;
const uint8_t MondayDOW = 0x02;
const uint8_t TuesdayDOW = 0x04;
const uint8_t WednesdayDOW = 0x08;
const uint8_t ThursdayDOW = 0x10;
const uint8_t FridayDOW = 0x20;
const uint8_t SaturdayDOW = 0x40;
const uint8_t WeekEndDOW = SundayDOW | SaturdayDOW;
const uint8_t WeekWorkDOW = MondayDOW | TuesdayDOW | WednesdayDOW | ThursdayDOW | FridayDOW;
const uint8_t WeekEntireDOW = WeekWorkDOW | WeekEndDOW;
struct s_prog {
uint8_t daysofweek; uint8_t hourofday; uint8_t minuteofhour; uint8_t pinno; uint8_t pinoutput; } progs[] = {
{MondayDOW | TuesdayDOW | WednesdayDOW, 9, 0, 0, 1}, {WeekEntireDOW, 9, 1, 0, 0}, {MondayDOW, 18, 10, 0, 1}, {MondayDOW, 18, 15, 0, 0} };
int dcount = sizeof(progs)/sizeof(progs[0]);
const uint8_t usablepins[] = {0, 13, 14, 24, 25};
File myFile;
char fileName[] = "/programm.txt";
void setup() {
Serial.begin(115200);
for (int i = 0; i < sizeof(usablepins)/sizeof(usablepins[0]); i++) pinMode(usablepins[i], OUTPUT);
Serial.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
int i = 0;
while (i < 15 && WiFi.status() != WL_CONNECTED) {
i++;
Serial.print(".");
if (i == 15) {
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
Serial.println("WIFI disconnected");
break;
}
delay(500);
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println(" CONNECTED");
}
configTime(gmtOffset_sec, daylightOffset_sec, ntpServerName);
Serial.println("Initializing System");
if (!SD.begin(2)) { Serial.println("Card Mount Failed");
return;
}
char cardtype[16] = {0};
switch(SD.cardType()) {
case CARD_NONE:
Serial.println("No SD card attached");
return;
break;
case CARD_MMC:
strcpy(cardtype, "MMC");
break;
case CARD_SD:
strcpy(cardtype, "SDSC");
break;
case CARD_SDHC:
strcpy(cardtype, "SDHC");
break;
default:
strcpy(cardtype, "UNKNOWN");
break;
}
Serial.print("SD Card Type: ");
Serial.println(cardtype);
uint64_t cardSize = SD.cardSize() / (1024 * 1024);
Serial.printf("SD Card Size: %lluMB\n", cardSize);
Serial.println("initialisation done.");
writeToFile();
delay(2000);
readFromFile();
printFile();
}
void loop() {
loadProgramm();
delay(20000);
}
int compileprogram (const char program[16], struct s_prog *pgm) {
const uint8_t days[] = {MondayDOW, TuesdayDOW, WednesdayDOW, ThursdayDOW, FridayDOW, SaturdayDOW, SundayDOW};
uint8_t finish = 0;
struct s_prog jj = {0};
*pgm = jj;
for (int i = 0; program[i]; i++) {
switch (i) {
case 0: case 1: case 2: case 3: case 4: case 5: case 6: (program[i] == '1' && (pgm->daysofweek |= days[i]));
break;
case 7: case 8: pgm->hourofday = pgm->hourofday * 10 + program[i] - '0';
break;
case 9: case 10: pgm->minuteofhour = pgm->minuteofhour * 10 + program[i] - '0';
break;
case 11: (program[i] == '1' && (pgm->pinoutput = 1));
break;
case 12: pgm->pinno = pgm->pinno * 10 + program[i] - '0';
break;
case 13: pgm->pinno = pgm->pinno * 10 + program[i] - '0';
finish = 1;
break;
}
}
return finish;
}
char * uncompileprogram (char program[16], const struct s_prog pgm) {
const uint8_t days[] = {MondayDOW, TuesdayDOW, WednesdayDOW, ThursdayDOW, FridayDOW, SaturdayDOW, SundayDOW};
for (int i = 0; i < 14; i++) {
program[i] = '0';
switch (i) {
case 0: case 1: case 2: case 3: case 4: case 5: case 6: ((pgm.daysofweek & days[i]) && (program[i] = '1'));
break;
case 7: program[i] = (pgm.hourofday / 10) + '0';
break;
case 8: program[i] = (pgm.hourofday % 10) + '0';
break;
case 9: program[i] = (pgm.minuteofhour / 10) + '0';
break;
case 10: program[i] = (pgm.minuteofhour % 10) + '0';
break;
case 11: ((pgm.pinoutput == 1) && (program[i] = '1'));
break;
case 12: program[i] = (pgm.pinno / 10) + '0';
break;
case 13: program[i] = (pgm.pinno % 10) + '0';
program[i+1] = 0; break;
}
}
return program;
}
void writeToFile() {
myFile = SD.open("/programm.txt", FILE_WRITE);
if (myFile) {
char prog[16];
myFile.println(uncompileprogram (prog, progs[0]));
myFile.println(uncompileprogram (prog, progs[1]));
myFile.println(uncompileprogram (prog, progs[2]));
myFile.println(uncompileprogram (prog, progs[3]));
myFile.close();
Serial.println("Done writing to programm.txt");
} else {
Serial.println("Error opening programm.txt"); }
}
void readFromFile() {
if (!SD.exists("/programm.txt"))
Serial.println("programm.txt doesn't exist.");
Serial.println("Reading from programm.txt:");
myFile = SD.open("/programm.txt");
char inputString[16];
for (uint8_t d = 0, i = 0; myFile.available() && d < dcount; ) {
char inputChar = myFile.read(); if (inputChar == '\n') {
inputString[i] = 0; Serial.println(inputString);
compileprogram (inputString, progs + d);
if (i > 13) {
Serial.println("Incoming string longer than array allows");
Serial.print(" String No. "); Serial.print(d); Serial.print(" length ");
Serial.println(i);
}
d++;
i = 0;
} else if (i < 13) {
inputString[i] = inputChar; i++;
}
}
myFile.close();
Serial.println("Done reading file");
}
void printFile() {
char prog[16];
Serial.print("programma 0 = ");
Serial.println(uncompileprogram (prog, progs[0]));
Serial.print("programma 1 = ");
Serial.println(uncompileprogram (prog, progs[1]));
Serial.print("programma 2 = ");
Serial.println(uncompileprogram (prog, progs[2]));
Serial.print("programma 3 = ");
Serial.println(uncompileprogram (prog, progs[3]));
}
int checkpinok (uint8_t pinno) {
int i = 0;
for (i = 0; i < sizeof(usablepins)/sizeof(usablepins[0]); i++) {
if (pinno == usablepins[i]) break;
}
return i < sizeof(usablepins)/sizeof(usablepins[0]);
}
void checkProgram(const struct s_prog prog, struct tm timeInfo, int progNum) {
uint8_t thisday = (0x01 << timeInfo.tm_wday);
if ((prog.daysofweek & thisday) && prog.hourofday == timeInfo.tm_hour && prog.minuteofhour == timeInfo.tm_min && checkpinok(prog.pinno)) {
char progstr[16]; std::cout << "Output " << uncompileprogram(progstr, prog) << (prog.pinoutput ? " on\n" : " off\n");
std::cout << "Output " << progNum << (prog.pinoutput ? " set high\n" : " set low\n");
pinMode(prog.pinno, (prog.pinoutput ? HIGH : LOW));
} else {
std::cout << "Output " << progNum << " skipped\n";
}
}
void loadProgramm() {
struct tm timeInfo;
if (!getLocalTime(&timeInfo)) {
Serial.println("Failed to obtain time");
return;
}
for (int d = 0; d < dcount; d++) {
checkProgram(progs[d], timeInfo, d);
}
Serial.println("Done checking file");
}