mirror of
https://github.com/thooge/esp32-nmea2000-obp60.git
synced 2026-02-11 07:03:07 +01:00
Add more functionality for time and date synchrinisation
This commit is contained in:
@@ -49,8 +49,10 @@ void sensorTask(void *param){
|
|||||||
|
|
||||||
// Init sensor stuff
|
// Init sensor stuff
|
||||||
bool oneWire_ready = false; // 1Wire initialized and ready to use
|
bool oneWire_ready = false; // 1Wire initialized and ready to use
|
||||||
|
bool iRTC_ready = false; // Software RTC initialized and ready to use
|
||||||
bool RTC_ready = false; // DS1388 initialized and ready to use
|
bool RTC_ready = false; // DS1388 initialized and ready to use
|
||||||
bool GPS_ready = false; // GPS initialized and ready to use
|
bool GPS_ready = false; // GPS initialized and ready to use
|
||||||
|
bool N2K_GPS_ready = false; // GPS time on N2K bus
|
||||||
bool BME280_ready = false; // BME280 initialized and ready to use
|
bool BME280_ready = false; // BME280 initialized and ready to use
|
||||||
bool BMP280_ready = false; // BMP280 initialized and ready to use
|
bool BMP280_ready = false; // BMP280 initialized and ready to use
|
||||||
bool BMP180_ready = false; // BMP180 initialized and ready to use
|
bool BMP180_ready = false; // BMP180 initialized and ready to use
|
||||||
@@ -382,6 +384,7 @@ void sensorTask(void *param){
|
|||||||
if (getLocalTime(&timeinfo)) {
|
if (getLocalTime(&timeinfo)) {
|
||||||
api->getLogger()->logDebug(GwLog::LOG,"NTP time: %04d-%02d-%02d %02d:%02d:%02d UTC", timeinfo.tm_year+1900, timeinfo.tm_mon+1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
|
api->getLogger()->logDebug(GwLog::LOG,"NTP time: %04d-%02d-%02d %02d:%02d:%02d UTC", timeinfo.tm_year+1900, timeinfo.tm_mon+1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
|
||||||
rtc.setTimeStruct(timeinfo);
|
rtc.setTimeStruct(timeinfo);
|
||||||
|
iRTC_ready = true;
|
||||||
sensors.rtcValid = true;
|
sensors.rtcValid = true;
|
||||||
} else {
|
} else {
|
||||||
api->getLogger()->logDebug(GwLog::LOG,"NTP time fetch failed!");
|
api->getLogger()->logDebug(GwLog::LOG,"NTP time fetch failed!");
|
||||||
@@ -400,7 +403,7 @@ void sensorTask(void *param){
|
|||||||
if (millis() > starttime0 + 100)
|
if (millis() > starttime0 + 100)
|
||||||
{
|
{
|
||||||
starttime0 = millis();
|
starttime0 = millis();
|
||||||
// Send NMEA0183 GPS data on several bus systems all 100ms
|
// Send NMEA0183 GPS data on several bus systems (N2K an 0183) all 100ms
|
||||||
if (GPS_ready == true && hdop->value <= hdopAccuracy)
|
if (GPS_ready == true && hdop->value <= hdopAccuracy)
|
||||||
{
|
{
|
||||||
SNMEA0183Msg NMEA0183Msg;
|
SNMEA0183Msg NMEA0183Msg;
|
||||||
@@ -412,9 +415,55 @@ void sensorTask(void *param){
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If RTC DS1388 ready, then copy GPS data to RTC all 5min
|
/*
|
||||||
|
Time set logic for RTC and N2K
|
||||||
|
###############################
|
||||||
|
|
||||||
|
iRTC = Software RTC updatetd with NTP via internet
|
||||||
|
RTC = RTC chip on PCB
|
||||||
|
GPS = GPS Receiver on PCB
|
||||||
|
N2K = GPS time on N2K od 183 bus
|
||||||
|
0 = device not ready
|
||||||
|
1 = device ready
|
||||||
|
X = undependend
|
||||||
|
() = source for set time N2K
|
||||||
|
-> = set RTC via iRTC
|
||||||
|
<- = set RTC via GPS
|
||||||
|
|
||||||
|
iRTC RTC GPS N2K
|
||||||
|
0 0 0 (1)
|
||||||
|
0 0 (1) (X)
|
||||||
|
0 (1) 0 (X)
|
||||||
|
0 1 <-(1) (X)
|
||||||
|
(1) 0 0 (X)
|
||||||
|
1 0 (1) (X)
|
||||||
|
1 ->(1) 0 (X)
|
||||||
|
1 1 <-(1) (X)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// If RTC DS1388 ready, then copy iRTC and GPS data to RTC all 5min
|
||||||
if(millis() > starttime11 + 5*60*1000){
|
if(millis() > starttime11 + 5*60*1000){
|
||||||
starttime11 = millis();
|
starttime11 = millis();
|
||||||
|
// Set RTC chip via iRTC (NTP)
|
||||||
|
if(iRTC_ready == true && RTC_ready == true && GPS_ready == false){
|
||||||
|
GwApi::Status status;
|
||||||
|
api->getStatus(status);
|
||||||
|
// Check WiFi connection
|
||||||
|
if (status.wifiClientConnected) {
|
||||||
|
sensors.rtcTime = rtc.getTimeStruct(); // Get time from software RTC (iRTC)
|
||||||
|
DateTime now = DateTime(
|
||||||
|
sensors.rtcTime.tm_year + 1900,
|
||||||
|
sensors.rtcTime.tm_mon + 1,
|
||||||
|
sensors.rtcTime.tm_mday,
|
||||||
|
sensors.rtcTime.tm_hour,
|
||||||
|
sensors.rtcTime.tm_min,
|
||||||
|
sensors.rtcTime.tm_sec
|
||||||
|
);
|
||||||
|
ds1388.adjust(now);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set RTC chip via internal GPS
|
||||||
if(rtcOn == "DS1388" && RTC_ready == true && GPS_ready == true){
|
if(rtcOn == "DS1388" && RTC_ready == true && GPS_ready == true){
|
||||||
api->getBoatDataValues(3,valueList);
|
api->getBoatDataValues(3,valueList);
|
||||||
if(gpsdays->valid && gpsseconds->valid && hdop->valid){
|
if(gpsdays->valid && gpsseconds->valid && hdop->valid){
|
||||||
@@ -422,40 +471,33 @@ void sensorTask(void *param){
|
|||||||
// sample input: date = "Dec 26 2009", time = "12:34:56"
|
// sample input: date = "Dec 26 2009", time = "12:34:56"
|
||||||
// ds1388.adjust(DateTime("Dec 26 2009", "12:34:56"));
|
// ds1388.adjust(DateTime("Dec 26 2009", "12:34:56"));
|
||||||
DateTime adjusttime(ts);
|
DateTime adjusttime(ts);
|
||||||
api->getLogger()->logDebug(GwLog::LOG,"Adjust RTC time: %04d/%02d/%02d %02d:%02d:%02d",adjusttime.year(), adjusttime.month(), adjusttime.day(), adjusttime.hour(), adjusttime.minute(), adjusttime.second());
|
api->getLogger()->logDebug(GwLog::LOG,"Adjust RTC time via internal GPS: %04d/%02d/%02d %02d:%02d:%02d",adjusttime.year(), adjusttime.month(), adjusttime.day(), adjusttime.hour(), adjusttime.minute(), adjusttime.second());
|
||||||
// Adjust RTC time as unix time value
|
// Adjust RTC time as unix time value
|
||||||
ds1388.adjust(adjusttime);
|
ds1388.adjust(adjusttime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send 1Wire data for all temperature sensors all 2s
|
// Set RTC chip via N2K or 183 in case the internal GPS is off (only one time)
|
||||||
if(millis() > starttime13 + 2000 && String(oneWireOn) == "DS18B20" && oneWire_ready == true){
|
if(N2K_GPS_ready == false && RTC_ready == true && GPS_ready == false){
|
||||||
starttime13 = millis();
|
api->getBoatDataValues(3,valueList);
|
||||||
float tempC;
|
if(gpsdays->valid && gpsseconds->valid && hdop->valid){
|
||||||
ds18b20.requestTemperatures(); // Collect all temperature values (max.8)
|
long ts = tNMEA0183Msg::daysToTime_t(gpsdays->value - (30*365+7))+floor(gpsseconds->value); // Adjusted to reference year 2000 (-30 years and 7 days for switch years)
|
||||||
for(int i=0;i<numberOfDevices; i++){
|
// sample input: date = "Dec 26 2009", time = "12:34:56"
|
||||||
// Send only one 1Wire data per loop step (time reduction)
|
// ds1388.adjust(DateTime("Dec 26 2009", "12:34:56"));
|
||||||
if(i == loopCounter % numberOfDevices){
|
DateTime adjusttime(ts);
|
||||||
if(ds18b20.getAddress(tempDeviceAddress, i)){
|
api->getLogger()->logDebug(GwLog::LOG,"Adjust RTC time via N2K/183: %04d/%02d/%02d %02d:%02d:%02d",adjusttime.year(), adjusttime.month(), adjusttime.day(), adjusttime.hour(), adjusttime.minute(), adjusttime.second());
|
||||||
// Read temperature value in Celsius
|
// Adjust RTC time as unix time value
|
||||||
tempC = ds18b20.getTempC(tempDeviceAddress);
|
ds1388.adjust(adjusttime);
|
||||||
}
|
// N2K GPS time ready
|
||||||
// Send to NMEA200 bus for each sensor with instance number
|
N2K_GPS_ready = true;
|
||||||
if(!isnan(tempC)){
|
}
|
||||||
sensors.onewireTemp[i] = tempC; // Save values in SensorData
|
|
||||||
api->getLogger()->logDebug(GwLog::DEBUG,"DS18B20-%1d Temp: %.1f",i,tempC);
|
|
||||||
SetN2kPGN130316(N2kMsg, 0, i, N2kts_OutsideTemperature, CToKelvin(tempC), N2kDoubleNA);
|
|
||||||
api->sendN2kMessage(N2kMsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
loopCounter++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get current RTC date and time all 500ms
|
// Send RTC date and time to N2K all 500ms
|
||||||
if (millis() > starttime12 + 500) {
|
if (millis() > starttime12 + 500) {
|
||||||
starttime12 = millis();
|
starttime12 = millis();
|
||||||
|
// Send date and time from RTC chip
|
||||||
if (rtcOn == "DS1388" && RTC_ready) {
|
if (rtcOn == "DS1388" && RTC_ready) {
|
||||||
DateTime dt = ds1388.now();
|
DateTime dt = ds1388.now();
|
||||||
sensors.rtcTime.tm_year = dt.year() - 1900; // Save values in SensorData
|
sensors.rtcTime.tm_year = dt.year() - 1900; // Save values in SensorData
|
||||||
@@ -481,21 +523,62 @@ void sensorTask(void *param){
|
|||||||
}
|
}
|
||||||
// N2K sysTime is double in n2klib
|
// N2K sysTime is double in n2klib
|
||||||
double sysTime = (dt.hour() * 3600) + (dt.minute() * 60) + dt.second();
|
double sysTime = (dt.hour() * 3600) + (dt.minute() * 60) + dt.second();
|
||||||
// WHY? isnan should always fail here
|
if(!isnan(daysAt1970) && !isnan(sysTime)){
|
||||||
//if(!isnan(daysAt1970) && !isnan(sysTime)){
|
|
||||||
//api->getLogger()->logDebug(GwLog::LOG,"RTC time: %04d/%02d/%02d %02d:%02d:%02d",sensors.rtcTime.tm_year+1900,sensors.rtcTime.tm_mon, sensors.rtcTime.tm_mday, sensors.rtcTime.tm_hour, sensors.rtcTime.tm_min, sensors.rtcTime.tm_sec);
|
//api->getLogger()->logDebug(GwLog::LOG,"RTC time: %04d/%02d/%02d %02d:%02d:%02d",sensors.rtcTime.tm_year+1900,sensors.rtcTime.tm_mon, sensors.rtcTime.tm_mday, sensors.rtcTime.tm_hour, sensors.rtcTime.tm_min, sensors.rtcTime.tm_sec);
|
||||||
//api->getLogger()->logDebug(GwLog::LOG,"Send PGN126992: %10d %10d",daysAt1970, (uint16_t)sysTime);
|
//api->getLogger()->logDebug(GwLog::LOG,"Send PGN126992: %10d %10d",daysAt1970, (uint16_t)sysTime);
|
||||||
SetN2kPGN126992(N2kMsg,0,daysAt1970,sysTime,N2ktimes_LocalCrystalClock);
|
SetN2kPGN126992(N2kMsg,0,daysAt1970,sysTime,N2ktimes_LocalCrystalClock);
|
||||||
api->sendN2kMessage(N2kMsg);
|
api->sendN2kMessage(N2kMsg);
|
||||||
// }
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Send date and time from software RTC (iRTC)
|
||||||
|
if (iRTC_ready == true && RTC_ready == false && GPS_ready == false) {
|
||||||
|
// Use internal RTC feature
|
||||||
|
sensors.rtcTime = rtc.getTimeStruct(); // Save software RTC values in SensorData
|
||||||
|
// TODO implement daysAt1970 and sysTime as methods of DateTime
|
||||||
|
const short daysOfYear[12] = {0,31,59,90,120,151,181,212,243,273,304,334};
|
||||||
|
uint16_t switchYear = ((sensors.rtcTime.tm_year-1)-1968)/4 - ((sensors.rtcTime.tm_year-1)-1900)/100 + ((sensors.rtcTime.tm_year-1)-1600)/400;
|
||||||
|
long daysAt1970 = (sensors.rtcTime.tm_year-1970)*365 + switchYear + daysOfYear[sensors.rtcTime.tm_mon-1] + sensors.rtcTime.tm_mday-1;
|
||||||
|
// If switch year then add one day
|
||||||
|
if ((sensors.rtcTime.tm_mon > 2) && (sensors.rtcTime.tm_year % 4 == 0 && (sensors.rtcTime.tm_year % 100 != 0 || sensors.rtcTime.tm_year % 400 == 0))) {
|
||||||
|
daysAt1970 += 1;
|
||||||
|
}
|
||||||
|
// N2K sysTime is double in n2klib
|
||||||
|
double sysTime = (sensors.rtcTime.tm_hour * 3600) + (sensors.rtcTime.tm_min * 60) + sensors.rtcTime.tm_sec;
|
||||||
|
if(!isnan(daysAt1970) && !isnan(sysTime)){
|
||||||
|
//api->getLogger()->logDebug(GwLog::LOG,"RTC time: %04d/%02d/%02d %02d:%02d:%02d",sensors.rtcTime.tm_year+1900,sensors.rtcTime.tm_mon, sensors.rtcTime.tm_mday, sensors.rtcTime.tm_hour, sensors.rtcTime.tm_min, sensors.rtcTime.tm_sec);
|
||||||
|
//api->getLogger()->logDebug(GwLog::LOG,"Send PGN126992: %10d %10d",daysAt1970, (uint16_t)sysTime);
|
||||||
|
SetN2kPGN126992(N2kMsg,0,daysAt1970,sysTime,N2ktimes_LocalCrystalClock);
|
||||||
|
api->sendN2kMessage(N2kMsg);
|
||||||
}
|
}
|
||||||
} else if (sensors.rtcValid) {
|
|
||||||
// use internal rtc feature
|
|
||||||
sensors.rtcTime = rtc.getTimeStruct();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send supply voltage value all 1s
|
// Send 1Wire data for all temperature sensors to N2K all 2s
|
||||||
|
if(millis() > starttime13 + 2000 && String(oneWireOn) == "DS18B20" && oneWire_ready == true){
|
||||||
|
starttime13 = millis();
|
||||||
|
float tempC;
|
||||||
|
ds18b20.requestTemperatures(); // Collect all temperature values (max.8)
|
||||||
|
for(int i=0;i<numberOfDevices; i++){
|
||||||
|
// Send only one 1Wire data per loop step (time reduction)
|
||||||
|
if(i == loopCounter % numberOfDevices){
|
||||||
|
if(ds18b20.getAddress(tempDeviceAddress, i)){
|
||||||
|
// Read temperature value in Celsius
|
||||||
|
tempC = ds18b20.getTempC(tempDeviceAddress);
|
||||||
|
}
|
||||||
|
// Send to NMEA200 bus for each sensor with instance number
|
||||||
|
if(!isnan(tempC)){
|
||||||
|
sensors.onewireTemp[i] = tempC; // Save values in SensorData
|
||||||
|
api->getLogger()->logDebug(GwLog::DEBUG,"DS18B20-%1d Temp: %.1f",i,tempC);
|
||||||
|
SetN2kPGN130316(N2kMsg, 0, i, N2kts_OutsideTemperature, CToKelvin(tempC), N2kDoubleNA);
|
||||||
|
api->sendN2kMessage(N2kMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loopCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send supply voltage value to N2K all 1s
|
||||||
if(millis() > starttime5 + 1000 && String(powsensor1) == "off"){
|
if(millis() > starttime5 + 1000 && String(powsensor1) == "off"){
|
||||||
starttime5 = millis();
|
starttime5 = millis();
|
||||||
float rawVoltage = 0; // Default value
|
float rawVoltage = 0; // Default value
|
||||||
@@ -565,7 +648,7 @@ void sensorTask(void *param){
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send data from environment sensor all 2s
|
// Send data from environment sensor to N2K all 2s
|
||||||
if(millis() > starttime6 + 2000){
|
if(millis() > starttime6 + 2000){
|
||||||
starttime6 = millis();
|
starttime6 = millis();
|
||||||
unsigned char TempSource = 2; // Inside temperature
|
unsigned char TempSource = 2; // Inside temperature
|
||||||
@@ -630,7 +713,7 @@ void sensorTask(void *param){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send rotation angle all 500ms
|
// Send rotation angle to N2K all 500ms
|
||||||
if(millis() > starttime7 + 500){
|
if(millis() > starttime7 + 500){
|
||||||
starttime7 = millis();
|
starttime7 = millis();
|
||||||
double rotationAngle=0;
|
double rotationAngle=0;
|
||||||
@@ -678,7 +761,7 @@ void sensorTask(void *param){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send battery power value all 1s
|
// Send battery power value to N2K all 1s
|
||||||
if(millis() > starttime8 + 1000 && (String(powsensor1) == "INA219" || String(powsensor1) == "INA226")){
|
if(millis() > starttime8 + 1000 && (String(powsensor1) == "INA219" || String(powsensor1) == "INA226")){
|
||||||
starttime8 = millis();
|
starttime8 = millis();
|
||||||
if(String(powsensor1) == "INA226" && INA226_1_ready == true){
|
if(String(powsensor1) == "INA226" && INA226_1_ready == true){
|
||||||
@@ -720,7 +803,7 @@ void sensorTask(void *param){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send solar power value all 1s
|
// Send solar power value to N2K all 1s
|
||||||
if(millis() > starttime9 + 1000 && (String(powsensor2) == "INA219" || String(powsensor2) == "INA226")){
|
if(millis() > starttime9 + 1000 && (String(powsensor2) == "INA219" || String(powsensor2) == "INA226")){
|
||||||
starttime9 = millis();
|
starttime9 = millis();
|
||||||
if(String(powsensor2) == "INA226" && INA226_2_ready == true){
|
if(String(powsensor2) == "INA226" && INA226_2_ready == true){
|
||||||
@@ -750,7 +833,7 @@ void sensorTask(void *param){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send generator power value all 1s
|
// Send generator power value to N2K all 1s
|
||||||
if(millis() > starttime10 + 1000 && (String(powsensor3) == "INA219" || String(powsensor3) == "INA226")){
|
if(millis() > starttime10 + 1000 && (String(powsensor3) == "INA219" || String(powsensor3) == "INA226")){
|
||||||
starttime10 = millis();
|
starttime10 = millis();
|
||||||
if(String(powsensor3) == "INA226" && INA226_3_ready == true){
|
if(String(powsensor3) == "INA226" && INA226_3_ready == true){
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ typedef struct{
|
|||||||
double rotationAngle = 0; // Rotation angle in radiant
|
double rotationAngle = 0; // Rotation angle in radiant
|
||||||
bool validRotAngle = false; // Valid flag magnet present for rotation sensor
|
bool validRotAngle = false; // Valid flag magnet present for rotation sensor
|
||||||
struct tm rtcTime; // UTC time from internal RTC
|
struct tm rtcTime; // UTC time from internal RTC
|
||||||
bool rtcValid = false;
|
bool rtcValid = false; // Internal RTC chip
|
||||||
int sunsetHour = 0;
|
int sunsetHour = 0;
|
||||||
int sunsetMinute = 0;
|
int sunsetMinute = 0;
|
||||||
int sunriseHour = 0;
|
int sunriseHour = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user