I tried to make ESP32Time set my T Beam clock from the GPS. The GPS works. The compiler tells me that the scope was not declared to run setTime() despite ESP32.h library being included in the program
I tried to do an end run around that by lifting the necessary code from the library and dropping it in my code. I discovered this pearl of information:
void setTime(int sc, int mn, int hr, int dy, int mt, int yr) //const
{
// seconds, minute, hour, day, month, year $ microseconds(optional)
// ie setTime(20, 34, 8, 1, 4, 2021) = 8:34:20 1/4/2021
struct tm t = {0, 0, 0, 0, 0, 0, 0, 0, 0}; // Initalize to all 0's
t.tm_year = yr - 1900; // This is year-1900, so 125 = 2025
t.tm_mon = mt - 1;
t.tm_mday = dy;
t.tm_hour = hr;
t.tm_min = mn;
t.tm_sec = sc;
time_t timeSinceEpoch = mktime(&t);
setTime(timeSinceEpoch);
}
note that the last line calls the function again, and setTime(timeSinceEpoch) requires a 32 bit integer. the compiler squawks about “too few arguments to function ‘void setTime(int, int, int, int, int, int)’
I can’t believe I am the first person to encounter this. I had to // that const because that also caused a failure to compile..
the entire code:
// T Beam Lora Gateway for FSBs 009H port /dev/ttyACMO 20250827
// TTD: MOUNT ALL, RTC_INT, TEST_PIN, GPS set time,
// add counters to bail on invalid GPS or LoRa
// dateUpdate(), setTimezone
#include "soc/soc.h" // Disable brownout problems
#include "soc/rtc_cntl_reg.h" // Disable brownout problems
#include <WiFi.h>
#include <Wire.h>
#include <SPI.h>
#include <FS.h>
#include <SD.h>
#include <LoRa.h> // Sandeepmistry
//#include <timeLib.h>
#include <ESP32Time.h>
#include <time.h> // ESP32Time
#include <TinyGPS++.h>
#include <HardwareSerial.h>
#include "RTClib.h"
RTC_DS3231 rtc;
#define RTC_INT_PIN 36 // the pin that is connected to SQW on the RTC
#define TEST_PIN 38 // middle pushbutton as system test
volatile bool setFSBtime;
byte FSBID = 0; // ID of the receiver
SPIClass* vspi = NULL; // VSPI LoRa
SPIClass* hspi = NULL; // HSPI SD
File dataFile; // filename variable for SD
char filename[] = "00000000.CSV"; // filename array for datalogger
char logString[] = "000000000000"; // string for the event log; may be one char too long.
#define HAS_SDCARD 1
#define SDCARD_MISO 04 // RED 02
#define SDCARD_CS 13 // YLO 13
#define SDCARD_SCLK 14 // ORG 14
#define SDCARD_MOSI 15 // YLO 15
bool getFilenameStatus = true;
#define I2C_SDA 21 // GRA 21
#define I2C_SCL 22 // VIO 22
#define ss 18 // VSPI CLK
#define rst 23 // VSPI MOSI
#define dio0 26 // LoRA IO
#define BAND 915E6 // 915E6 for North America
HardwareSerial GPSSerial(2);
#define GPS_RX_PIN 34
#define GPS_TX_PIN 12
TinyGPSPlus gps;
HardwareSerial SoundSerial(1); // YX-5300
#define Sound_RX_PIN -1 // Not required
#define Sound_TX_PIN 25 // WHT TO YX-5300 RX
int sw = 0;
#define CMD_SEL_DEV 0X09
#define DEV_TF 0X02
#define CMD_SET_VOLUME 0X06
#define CMD_PLAY_W_INDEX 0X03
#define CMD_PLAY_FOLDER_FILE 0X0f // 0x7E 06 0F 00 01 02 EF;( play folder 01/002.wav )
static unsigned int Send_buf[8] = { 0 }; // char string for YX-5300 commands
int folderArray[] = { 0, 1, 2, 3, 4, 5, 5, 5, 6, 6, 6, 6, 12, 13, 14,};
int filesPerFolderArray[] = { 15, 20, 30, 4, 6, 9, 9, 9, 25, 25, 25, 25, 29, 255, 74,};
/////////////////////////// Set these to suit your system and location /////////////////////
String hostname = "T Beam Gateway 09H3]";
const char* ssid = "ad5mb"; // "yourNetworkName";
const char* password = "sansuiau517"; // "yourNetworkPassword";
const char* ntpServer = "us.pool.ntp.org";
const char* timezone = "MST7MDT,M3.2.0,M11.1.0"; // https://leo.leung.xyz/wiki/Timezone
int localElevation = 1421; // elevation in meters
/////////////////////////////////////////////////////////////////////////////////////////
struct tm timeinfo;
int counter = 0; // Initialize variables to get and save LoRa data
int LoRarssi = 0;
float temperature_C; // Initialize variables to get and save Weather data
float temperature_F;
float pressure_hPa;
float Pressure;
float pressure_inHg;
float Humidity;
float seaLevelPressure_hPa;
float seaLevelPressure_inHg;
float dewpoint_F;
float dewpoint_C;
String fsbid;
String loRaMessage;
String alarmStatus;
String temperature;
String pressure;
String humidity;
String readingID;
//////////////////////////////////// RUN ONCE //////////////////////////////////////
void initWiFi()
{
WiFi.mode(WIFI_STA);
WiFi.setHostname(hostname.c_str()); // define hostname
Serial.print("WiFi Scan start ");
int n = WiFi.scanNetworks();
Serial.print("WiFi Scan done ");
if (n == 0)
{
Serial.println("no networks found");
} else
{
Serial.print(n);
Serial.println(" networks found");
Serial.println(" # | SSID | RSSI | CH | Encryption");
for (int i = 0; i < n; ++i) {
Serial.printf("%2d", i + 1);
Serial.print(" | ");
Serial.printf("%-32.32s", WiFi.SSID(i).c_str());
Serial.print(" | ");
Serial.printf("%4d", WiFi.RSSI(i));
Serial.print(" | ");
Serial.printf("%2d", WiFi.channel(i));
Serial.print(" | ");
switch (WiFi.encryptionType(i))
{
case WIFI_AUTH_OPEN:
Serial.print("open");
break;
case WIFI_AUTH_WEP:
Serial.print("WEP");
break;
case WIFI_AUTH_WPA_PSK:
Serial.print("WPA");
break;
case WIFI_AUTH_WPA2_PSK:
Serial.print("WPA2");
break;
case WIFI_AUTH_WPA_WPA2_PSK:
Serial.print("WPA+WPA2");
break;
case WIFI_AUTH_WPA2_ENTERPRISE:
Serial.print("WPA2-EAP");
break;
default:
Serial.print("unknown");
}
Serial.println();
delay(10);
}
WiFi.scanDelete();
Serial.println();
}
/////////////////////////////////////////////////////////////////////////
Serial.print("Connecting to ");
Serial.print(ssid);
Serial.println(":");
while (!WiFi.begin(ssid, password));
{
counter++;
Serial.print("WiFiv ");
Serial.print(counter);
Serial.print(F(" "));
delay(1000);
if (counter == 10)
{
counter = 0;
Serial.println();
Serial.print("WiFi AP ");
Serial.print(ssid);
Serial.println(" not available ");
return;
}
Serial.println();
}
}
void WiFiStationGotIP(WiFiEvent_t event, WiFiEventInfo_t info)
{
Serial.print("WiFiStationGotIP: ");
Serial.println(IPAddress(info.got_ip.ip_info.ip.addr));
return;
}
void initTime(String timezone) // stable
{
if (WiFi.status() == WL_CONNECTED)
{
Serial.println("initTime getting NTP time: ");
while (!getLocalTime(&timeinfo) && counter < 10) {
configTime(0, 0, ntpServer); // connect to NTP server, with 0 TZ offset
counter++;
Serial.print("NTPv ");
Serial.print(counter);
Serial.print(F(" "));
}
Serial.println();
if (getLocalTime(&timeinfo))
{
setTimezone(timezone);
Serial.print("LocalTime: ");
printLocalTime();
}
} else if (!getLocalTime(&timeinfo))
{
Serial.println("NTPv: readParseGPS");
Serial.println();
readParseGPS();
}
}
void setTimezone(String timezone) // stable
{
Serial.printf("Setting Timezone to %s\n", timezone.c_str());
setenv("TZ", timezone.c_str(), 1); // adjust the TZ. Clock settings are adjusted to show the new local time
tzset();
return;
}
void startLoRA() // stable 1 day = 86,400,000 milliseconds
{
LoRa.setPins(ss, rst, dio0); // Initialize LoRa transceiver module
while (!LoRa.begin(BAND) && counter < 10)
{
Serial.print("LoRav ");
counter++;
delay(500);
}
if (counter == 10)
{
counter = 0;
Serial.print("LoRav ");
Serial.println();
} else {
Serial.println("LoRa^");
Serial.println();
}
}
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> CALLED FUNCTIONS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<//
void setRTC()
{
Serial.print("setRTC(); ");
getLocalTime(&timeinfo);
rtc.adjust(DateTime(timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday,
timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec));
DateTime now = rtc.now();
Serial.print("RTC set to: ");
Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print('/');
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.print(now.second(), DEC);
} Serial.println();
void printLocalTime() // stable
{
if (!getLocalTime(&timeinfo))
{
Serial.println("Failed to obtain NTP time");
}
Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S Timezone %Z %z "); // Friday, April 15 2022 19:18:51 zone MDT -0600
Serial.println();
}
void readParseGPS()
{
if (GPSSerial.available())
{
while (GPSSerial.available() > 0)
gps.encode(GPSSerial.read());
}
if (gps.date.isUpdated())
{
Serial.print(F("GPS Year="));
Serial.print(gps.date.year());
Serial.print(F(" "));
Serial.print(F("GPS Month="));
Serial.print(gps.date.month());
Serial.print(F(" "));
Serial.print(F("GPS Day="));
Serial.println(gps.date.day());
}
if (gps.time.isUpdated())
{
Serial.print(F("Hour="));
Serial.print(gps.time.hour());
Serial.print(F(" "));
Serial.print(F("Minute="));
Serial.print(gps.time.minute());
Serial.print(F(" "));
Serial.print(F("Second="));
Serial.println(gps.time.second());
setTime(gps.time.second(),gps.time.minute(), gps.time.hour(), gps.date.day(), gps.date.month(), gps.date.year());
}
}
void setTime(int sc, int mn, int hr, int dy, int mt, int yr) //const
{
// seconds, minute, hour, day, month, year $ microseconds(optional)
// ie setTime(20, 34, 8, 1, 4, 2021) = 8:34:20 1/4/2021
struct tm t = {0, 0, 0, 0, 0, 0, 0, 0, 0}; // Initalize to all 0's
t.tm_year = yr - 1900; // This is year-1900, so 125 = 2025
t.tm_mon = mt - 1;
t.tm_mday = dy;
t.tm_hour = hr;
t.tm_min = mn;
t.tm_sec = sc;
time_t timeSinceEpoch = mktime(&t);
setTime(timeSinceEpoch);
}
//void IRAM_ATTR testPinSet()
//{
// sw = (6); = (1); //random(1, 15);
//}
void setRemotetime()
{
setFSBtime = true; // isr for midnight alarm
}
void dateUpdate() // Midnight FSB time Update
{
if (setFSBtime == true)
{
setFSBtime = false;
rtc.clearAlarm(1);
}
if (gps.time.isValid()) // first couple of times through the loop, gps not yet available
{
LoRa.beginPacket(); // send LoRa packet
LoRa.printf("Time: %.2d:%.2d:%.2d\n", gps.time.second(), gps.time.minute(), gps.time.hour());
LoRa.endPacket();
Serial.println("FSBs set to GPS time");
Serial.println("Midnight FSB time Update^ Alarm(1) cleared. setFSB time cleared");
}
}
////////////////////////////////////////////////////////////////////////////////////
void readParseLoRa() // Read LoRa packet and get the sensor readings
{
int packetSize = LoRa.parsePacket();
if (packetSize) {
Serial.print("Lora packet received: ");
Serial.print(packetSize);
Serial.println(" characters");
while (LoRa.available()) // Read packet
{
String LoRaData = LoRa.readString();
Serial.print(LoRaData);
int pos1 = LoRaData.indexOf('@');
int pos2 = LoRaData.indexOf('/');
int pos3 = LoRaData.indexOf('!');
int pos4 = LoRaData.indexOf('F');
int pos5 = LoRaData.indexOf('P');
int pos6 = LoRaData.indexOf('%');
fsbid = LoRaData.substring(0, pos1); // Get FSB ID
readingID = LoRaData.substring(pos1 + 1, pos2); // Get readingID
alarmStatus = LoRaData.substring(pos2 + 1, pos3); // Get alarmStatus
temperature = LoRaData.substring(pos3 + 1, pos4); // Get temperature
pressure = LoRaData.substring(pos4 + 1, pos5); // Get pressure
humidity = LoRaData.substring(pos5 + 1, LoRaData.length()); // Get humidity
}
LoRarssi = LoRa.packetRssi(); // Get RSSI
Serial.print(" LoRa RSSI: ");
Serial.println(LoRarssi);
Serial.print("alarmStatus = ");
Serial.print(alarmStatus);
Serial.print(" alarmStatus.toInt() = ");
Serial.println(alarmStatus.toInt());
Serial.println();
if (alarmStatus.toInt() != 0)
{
Serial.print("Alarm Triggered > ");
Serial.print(alarmStatus);
Serial.print(F(" "));
int sw = alarmStatus.toInt();
Serial.print("sw = ");
Serial.println(sw);
Serial.println();
alarmHandler(sw);
}
BME_280_conversions();
}
}
////////////////////////////////////////////////////////////////////////////////////
void alarmHandler(int sw)
{
logEvent(); // log event to SD card
playWAV(sw); // play appropriate sound file
}
void getFilename() //
{
if (getFilenameStatus == true)
{
getLocalTime(&timeinfo);
sprintf(filename, "%04d%02d%02d", timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday);
Serial.print("filename(): ");
Serial.println(filename);
Serial.println();
getFilenameStatus = false;
}
}
void logEvent()
{
getLocalTime(&timeinfo);
{
File dataFile = SD.open(filename, FILE_WRITE);
if (dataFile) // if the file is available, write to it:
{
sprintf(logString, "%02d,%02d,%02d,%02d", FSBID, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
dataFile.println(logString);
dataFile.close();
Serial.print("Event log string saved: ");
Serial.println(logString);
}
}
}
////////////////////////////////////
// YX5300 sound module functions ///
////////////////////////////////////
void playWAV(int sw)
{
int folder = folderArray[sw];
int filesPerFolder = filesPerFolderArray[sw];
randomFile(folder, filesPerFolder);
}
void randomFile(int folder, int filesPerFolder)
{
randomSeed(timeinfo.tm_sec);
sendCommand(CMD_PLAY_FOLDER_FILE, 0x0F0000 + (folder * 256) + (random(1, filesPerFolder)));
}
void sendCommand(uint8_t command, int16_t dat)
{
Send_buf[0] = 0x7e; // starting byte
Send_buf[1] = 0xff; // version
Send_buf[2] = 0x06; // the number of bytes of the command without starting byte and ending byte
Send_buf[3] = command; //
Send_buf[4] = 0x00; // 0x00 = no feedback, 0x01 = feedback
Send_buf[5] = (int8_t)(dat >> 8); // data high byte
Send_buf[6] = (int8_t)(dat); // data low byte
Send_buf[7] = 0xef; // ending byte
for (uint8_t i = 0; i < 8; i++)
{
SoundSerial.write(Send_buf[i]);
Serial.print(Send_buf[i], HEX);
}
Serial.println();
}
void BME_280_conversions()
{
temperature_C = (temperature.toInt());
Serial.print("Temperature C = ");
Serial.print(temperature_C);
Serial.println(" *C");
temperature_F = ((1.8 * temperature_C) + 32); // Convert Celcius temperature to Fahrenheit
Serial.print("Temperature F = ");
Serial.print(temperature_F);
Serial.println(" F");
Pressure = (pressure.toInt());
pressure_hPa = ((Pressure / 100.0F));
Serial.print("Pressure hPa = ");
Serial.print(pressure_hPa);
Serial.println(" hPa");
pressure_inHg = ((pressure_hPa / 100.0F) / 33.864); // Convert hectoPascals to inHg
Serial.print("Pressure inHG = ");
Serial.print(pressure_inHg);
Serial.println(" inHG");
Humidity = (humidity.toInt());
Serial.print("Humidity = ");
Serial.print(Humidity);
Serial.println(" %");
seaLevelPressure_hPa = pressure_hPa / pow(1.0 - 0.0065 * localElevation / (temperature_C + 273.15), 5.255);
Serial.print("Sea Level Pressure hPa = ");
Serial.print(seaLevelPressure_hPa);
Serial.println(" hPa");
seaLevelPressure_inHg = seaLevelPressure_hPa / 33.864;
Serial.print("Sea Level Pressure inHg = ");
Serial.print(seaLevelPressure_inHg);
Serial.println(" inHg");
dewpoint_F = 243.04 * (log(Humidity / 100) + ((17.625 * temperature_F) / (243.04 + temperature_F))) / (17.625 - log(Humidity / 100) - ((17.625 * temperature_F) / (243.04 + temperature_F)));
Serial.print("Dewpoint = ");
Serial.print(dewpoint_F);
Serial.println(" F");
dewpoint_C = ((temperature_F - 32) / 1.8); // Convert Fahrenheit temperature to Celcius
Serial.print("Dewpoint = ");
Serial.print(dewpoint_C);
Serial.println(" C");
Serial.println();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void setup()
{
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector
Serial.begin(115200);
Serial.println();
Serial.println("T Beam Gateway V009H"); // current status
// pinMode(TEST_PIN, INPUT);
// attachInterrupt(digitalPinToInterrupt(TEST_PIN), testPinSet, FALLING);
GPSSerial.begin(9600, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
pinMode(GPS_TX_PIN, OUTPUT); // TO GPS RX
pinMode(GPS_RX_PIN, INPUT); // FROM GPS TX
SoundSerial.begin(9600, SERIAL_8N1, Sound_RX_PIN, Sound_TX_PIN);
pinMode(Sound_TX_PIN, OUTPUT); // TO YX-5300 RX
sendCommand(CMD_SEL_DEV, DEV_TF); // Select the YX-5300 TF card
delay(200);
sendCommand(CMD_SET_VOLUME, 0x06001e); // set volume to mid range
delay(200);
randomSeed(timeinfo.tm_sec);
sendCommand(CMD_PLAY_W_INDEX, 0x030000 + random(1, 15)); // play on reset 1 of 15 files in TF card root
Serial.println();
vspi = new SPIClass(VSPI);
vspi->begin(SCK, MISO, MOSI, SS); // LoRa SPI
//loRa_SCLK 5 loRa_MISO 19 loRa_MOSI 27 loRa_SS 18
pinMode(SS, OUTPUT);
pinMode(SCK, OUTPUT);
pinMode(MOSI, OUTPUT);
pinMode(MISO, INPUT);
hspi = new SPIClass(HSPI);
pinMode(SDCARD_CS, OUTPUT);
hspi->begin(SDCARD_SCLK, SDCARD_MISO, SDCARD_MOSI, SDCARD_CS);
//SDCARD_SCLK 14 SDCARD_MISO 02 SDCARD_MOSI 15 SDCARD_CS 13
if (!SD.begin(SDCARD_CS))
{
Serial.println("SDv ");
Serial.println();
}
if (SD.begin())
{
Serial.println("SD^ ");
Serial.println();
uint32_t cardSize = SD.cardSize() / (1024 * 1024);
char outputString[2];
itoa(cardSize, outputString, 10);
Serial.print("Card Size = ^ ");
Serial.print(cardSize);
Serial.print(" mb ");
}
Wire.begin(I2C_SCL, I2C_SDA);
Serial.println("I2C scanner. Scanning ...");
byte count = 0;
for (byte i = 8; i < 120; i++)
{
Wire.beginTransmission(i);
if (Wire.endTransmission() == 0)
{
Serial.print("Found address: ");
Serial.print(i, DEC);
Serial.print(" (0x");
Serial.print(i, HEX);
Serial.println(")");
count++;
delay(1);
} // end of good response
} // end of for loop
Serial.print("Done.");
Serial.print("Found ");
Serial.print(count, DEC);
Serial.println(" device(s).");
Serial.println();
if (!rtc.begin())
{
Serial.println("RTCv");
Serial.println();
} else if (rtc.begin()) {
Serial.println("rtc.begin");
rtc.disable32K(); // disable the 32K Pin
pinMode(RTC_INT_PIN, INPUT); // attach an interrupt to the alarm
attachInterrupt(digitalPinToInterrupt(RTC_INT_PIN), setRemotetime, FALLING);
rtc.clearAlarm(1); // reset alarm 1, 2 flag on reboot & recompile
rtc.clearAlarm(2);
rtc.disableAlarm(2); // turn off alarm 2 at reboot
rtc.writeSqwPinMode(DS3231_OFF); // stop signals at SQW Pin
rtc.setAlarm1(DateTime(0, 0, 0, 0, 1, 0), DS3231_A1_Hour);
Serial.println("Alarm(1) set to trigger at midnight");
Serial.println();
}
initWiFi();
initTime(timezone); // MST https://leo.leung.xyz/wiki/Timezone
setRTC();
getFilenameStatus = true;
getFilename();
dateUpdate();
startLoRA();
Serial.println("Setup complete. Monitoring ");
Serial.println();
}
void loop()
{
readParseLoRa();
dateUpdate();
}