mirror of
https://github.com/xoseperez/espurna.git
synced 2026-03-03 06:54:16 +01:00
add RTC support (ds3231 ds1307 etc)
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
#include "general.h"
|
||||
#include "prototypes.h"
|
||||
#include "sensors.h"
|
||||
#include "rtc.h"
|
||||
#include "dependencies.h"
|
||||
#include "progmem.h"
|
||||
#include "debug.h"
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
//#define BLITZWOLF_BWSHP2
|
||||
//#define BH_ONOFRE
|
||||
//#define ITEAD_SONOFF_IFAN02
|
||||
|
||||
//#define SHAPEsp
|
||||
//--------------------------------------------------------------------------------
|
||||
// Features (values below are non-default values)
|
||||
//--------------------------------------------------------------------------------
|
||||
|
||||
@@ -990,7 +990,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef NTP_UPDATE_INTERVAL
|
||||
#define NTP_UPDATE_INTERVAL 1800 // NTP check every 30 minutes
|
||||
#define NTP_UPDATE_INTERVAL 180 // NTP check every 30 minutes
|
||||
#endif
|
||||
|
||||
#ifndef NTP_START_DELAY
|
||||
|
||||
@@ -112,6 +112,14 @@
|
||||
#define I2C_SDA_PIN 12 // D6
|
||||
#define I2C_SCL_PIN 14 // D5
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// RTC_SUPPORT example
|
||||
// -----------------------------------------------------------------------------
|
||||
//#define RTC_SUPPORT 1 // for test
|
||||
//#define RTC_PROVIDER RTC_PROVIDER_DS1307 // for test
|
||||
//#define RTC_RECOVERY_CNT 3 // 0 no recovery default 10
|
||||
//#define RTC_NTP_SYNC_ENA 1 // 0 rtc not synced with ntp default 1
|
||||
|
||||
#elif defined(WEMOS_D1_TARPUNA_SHIELD)
|
||||
|
||||
// Info
|
||||
@@ -2595,6 +2603,56 @@
|
||||
#define NETBIOS_SUPPORT 1
|
||||
#define SSDP_SUPPORT 1
|
||||
|
||||
#elif defined(SHAPEsp)
|
||||
|
||||
// Info
|
||||
#define MANUFACTURER "POULCH74"
|
||||
#define DEVICE "SHAPEsp"
|
||||
|
||||
// Buttons
|
||||
|
||||
//#define BUTTON1_PIN 2
|
||||
//#define BUTTON1_MODE BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH | BUTTON_ONCE
|
||||
//#define BUTTON1_PRESS BUTTON_MODE_TOGGLE
|
||||
//#define BUTTON1_CLICK BUTTON_MODE_TOGGLE
|
||||
//#define BUTTON1_DBLCLICK BUTTON_MODE_TOGGLE
|
||||
//#define BUTTON1_LNGCLICK BUTTON_MODE_TOGGLE
|
||||
//#define BUTTON1_LNGLNGCLICK BUTTON_MODE_TOGGLE
|
||||
|
||||
//#define BUTTON1_RELAY 1
|
||||
|
||||
// Relays
|
||||
//#define RELAY1_PIN 14
|
||||
//#define RELAY1_PIN2 12
|
||||
//#define RELAY1_PINP 13 // GPIO_NONE to leave it unused, so no pulse on start valve (autostop not used)
|
||||
//#define RELAY1_TYPE RELAY_TYPE_HBRIDGE
|
||||
// pulse duration for pinP pulse to start valve
|
||||
//#define RELAY1_HBPULSE 100
|
||||
|
||||
// Relays
|
||||
//#define RELAY2_PIN 98 // fake pin for relay
|
||||
//#define RELAY2_TYPE RELAY_TYPE_BTNRESET
|
||||
//#define RELAY2_BUTTON 1
|
||||
|
||||
// LEDs
|
||||
#define LED1_PIN 2 //15 to free pin 2 which can be used for dallas support or water sensor for example
|
||||
#define LED1_PIN_INVERSE 1
|
||||
|
||||
#define I2C_SDA_PIN 4
|
||||
#define I2C_SCL_PIN 5
|
||||
|
||||
//#define ADC_MODE_VALUE ADC_VCC_CUSTOM
|
||||
//#define ADC_VCC_CUSTOM_MUL (15.63)
|
||||
//#define ADC_VCC_CUSTOM_ADD (0)
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// RTC_SUPPORT
|
||||
// -----------------------------------------------------------------------------
|
||||
#define RTC_SUPPORT 1 // for test
|
||||
#define RTC_PROVIDER RTC_PROVIDER_DS3231 // for test
|
||||
#define RTC_RECOVERY_CNT 3 // 0 no recovery
|
||||
#define RTC_NTP_SYNC_ENA 1 // 0 rtc not synced with ntp
|
||||
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
37
code/espurna/config/rtc.h
Normal file
37
code/espurna/config/rtc.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
|
||||
RTC support module
|
||||
|
||||
Copyright (C) 2018 by Pavel Chauzov <poulch at mail dot ru>
|
||||
|
||||
*/
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// RTC3231_SUPPORT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#ifndef RTC_SUPPORT
|
||||
#define RTC_SUPPORT 0 // enable battery backed RTC for ntp
|
||||
#define RTC_PROVIDER RTC_DUMMY
|
||||
#endif
|
||||
|
||||
#ifndef RTC_RECOVERY_CNT
|
||||
#define RTC_RECOVERY_CNT 10 // 0 no recovery
|
||||
#endif
|
||||
|
||||
#ifndef RTC_NTP_SYNC_ENA
|
||||
#define RTC_NTP_SYNC_ENA 1 // enable sync RTC on NTP sync success
|
||||
#endif
|
||||
|
||||
|
||||
#if RTC_SUPPORT
|
||||
|
||||
#if RTC_PROVIDER == RTC_PROVIDER_DS3231
|
||||
#include "../rtc/ds3231.h"
|
||||
#elif RTC_PROVIDER == RTC_PROVIDER_DS1307
|
||||
#include "../rtc/ds1307.h"
|
||||
#else
|
||||
#include "../rtc/dummy.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -301,3 +301,10 @@
|
||||
#define MAGNITUDE_GEIGER_SIEVERT 24
|
||||
|
||||
#define MAGNITUDE_MAX 25
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// RTC providers
|
||||
//-----------------------------------------------------------------------------
|
||||
#define RTC_PROVIDER_DUMMY 0
|
||||
#define RTC_PROVIDER_DS3231 1
|
||||
#define RTC_PROVIDER_DS1307 2
|
||||
|
||||
@@ -17,6 +17,11 @@ unsigned long _ntp_start = 0;
|
||||
bool _ntp_update = false;
|
||||
bool _ntp_configure = false;
|
||||
|
||||
#if RTC_SUPPORT && RTC_NTP_SYNC_ENA
|
||||
bool _rtc_update = false;
|
||||
#endif
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// NTP
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -44,6 +49,12 @@ void _ntpStart() {
|
||||
_ntp_start = 0;
|
||||
|
||||
NTP.begin(getSetting("ntpServer", NTP_SERVER));
|
||||
|
||||
#if RTC_SUPPORT
|
||||
// set alter sync provider. two attempts for NTP synchro at start occure...
|
||||
setSyncProvider(ntp_getTime);
|
||||
#endif
|
||||
|
||||
NTP.setInterval(NTP_SYNC_INTERVAL, NTP_UPDATE_INTERVAL);
|
||||
NTP.setNTPTimeout(NTP_TIMEOUT);
|
||||
_ntpConfigure();
|
||||
@@ -90,6 +101,11 @@ void _ntpUpdate() {
|
||||
|
||||
if (ntpSynced()) {
|
||||
time_t t = now();
|
||||
#if RTC_SUPPORT && RTC_NTP_SYNC_ENA
|
||||
// sync/update rtc here!!!!!!!!!!!!
|
||||
if(_rtc_update) setTime_rtc(t);
|
||||
#endif
|
||||
|
||||
DEBUG_MSG_P(PSTR("[NTP] UTC Time : %s\n"), (char *) ntpDateTime(ntpLocal2UTC(t)).c_str());
|
||||
DEBUG_MSG_P(PSTR("[NTP] Local Time: %s\n"), (char *) ntpDateTime(t).c_str());
|
||||
}
|
||||
@@ -167,13 +183,24 @@ void ntpSetup() {
|
||||
} else if (error == invalidAddress) {
|
||||
DEBUG_MSG_P(PSTR("[NTP] Error: Invalid NTP server address\n"));
|
||||
}
|
||||
_ntp_update = false;
|
||||
} else {
|
||||
_ntp_update = true;
|
||||
#if RTC_SUPPORT && RTC_NTP_SYNC_ENA
|
||||
_rtc_update = true;
|
||||
#endif
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
wifiRegister([](justwifi_messages_t code, char * parameter) {
|
||||
if (code == MESSAGE_CONNECTED) _ntp_start = millis() + NTP_START_DELAY;
|
||||
#if RTC_SUPPORT
|
||||
// system time from local RTC, but still try recovery if enabled (without success)
|
||||
else
|
||||
if(code == MESSAGE_ACCESSPOINT_CREATED) _ntp_start = millis() + NTP_START_DELAY;
|
||||
#endif
|
||||
|
||||
});
|
||||
|
||||
#if WEB_SUPPORT
|
||||
@@ -184,6 +211,12 @@ void ntpSetup() {
|
||||
|
||||
// Register loop
|
||||
espurnaRegisterLoop(_ntpLoop);
|
||||
|
||||
#if RTC_SUPPORT
|
||||
#if TERMINAL_SUPPORT
|
||||
_rtcInitCommands();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
95
code/espurna/rtc.ino
Normal file
95
code/espurna/rtc.ino
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
|
||||
RTC support module
|
||||
|
||||
Copyright (C) 2018 by Pavel Chauzov <poulch at mail dot ru>
|
||||
|
||||
in debug terminal - RTC return current rtc time
|
||||
- RTC YYYY-MM-DD DoW HH:MM:SS setup rtc
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#if RTC_SUPPORT
|
||||
|
||||
static int _rtc_recovery = 0;
|
||||
|
||||
static time_t ntp_getTime() {
|
||||
time_t tm = 0;
|
||||
if(_rtc_recovery == 0) { tm = NTP.getTime(); }
|
||||
if((_rtc_recovery !=0) || (tm == 0)) {
|
||||
_rtc_recovery++;
|
||||
tm = getTime_rtc();
|
||||
// signal ntp loop to update clock but not rtc...
|
||||
_ntp_update = true;
|
||||
#if RTC_SUPPORT && RTC_NTP_SYNC_ENA
|
||||
_rtc_update = false;
|
||||
#endif
|
||||
}
|
||||
if(_rtc_recovery > RTC_RECOVERY_CNT) { _rtc_recovery = RTC_RECOVERY_CNT ? 0:1; }
|
||||
DEBUG_MSG_P(PSTR("[NTP] RTC Time : %s\n"), (char *) ntpDateTime(tm).c_str());
|
||||
return tm;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Settings
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#if TERMINAL_SUPPORT
|
||||
|
||||
String _rtc_getValue(String data, char sep, int idx) {
|
||||
int found = 0;
|
||||
int si[] = {0, -1};
|
||||
int maxi = data.length()-1;
|
||||
|
||||
for(int i=0; i<=maxi && found<=idx; i++) {
|
||||
if(data.charAt(i)==sep || i==maxi) {
|
||||
found++;
|
||||
si[0] = si[1]+1;
|
||||
si[1] = (i == maxi) ? i+1 : i;
|
||||
}
|
||||
}
|
||||
return found>idx ? data.substring(si[0], si[1]) : "0";
|
||||
}
|
||||
|
||||
void _rtcInitCommands() {
|
||||
|
||||
settingsRegisterCommand(F("RTC"), [](Embedis* e) {
|
||||
String rtc;
|
||||
time_t t;
|
||||
tmElements_t tm;
|
||||
if (e->argc == 1) {
|
||||
t = getTime_rtc();
|
||||
DEBUG_MSG_P(PSTR("[NTP] GET RTC Local Time: %s\n"), (char *) ntpDateTime(t).c_str());
|
||||
}
|
||||
|
||||
if (e->argc > 3) {
|
||||
String sdate = String(e->argv[1]);
|
||||
String sdow = String(e->argv[2]);
|
||||
String stime = String(e->argv[3]);
|
||||
|
||||
tm.Second = _rtc_getValue(stime,':',2).toInt();
|
||||
tm.Minute = _rtc_getValue(stime,':',1).toInt();
|
||||
tm.Hour = _rtc_getValue(stime,':',0).toInt();
|
||||
|
||||
tm.Wday = sdow.toInt();
|
||||
|
||||
tm.Day = _rtc_getValue(sdate,'-',2).toInt();
|
||||
tm.Month = _rtc_getValue(sdate,'-',1).toInt();
|
||||
tm.Year = y2kYearToTm(_rtc_getValue(sdate,'-',0).toInt()-2000);
|
||||
|
||||
t = makeTime(tm);
|
||||
setTime_rtc(t);
|
||||
setTime(t);
|
||||
|
||||
DEBUG_MSG_P(PSTR("[NTP] SET RTC Local Time: %s\n"), (char *) ntpDateTime(t).c_str());
|
||||
}
|
||||
DEBUG_MSG_P(PSTR("+OK\n"));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
#endif // TERMINAL_SUPPORT
|
||||
|
||||
|
||||
#endif
|
||||
17
code/espurna/rtc/README.md
Normal file
17
code/espurna/rtc/README.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# RTC support module
|
||||
|
||||
## commands in debug terminal
|
||||
- RTC return current rtc time
|
||||
- RTC YYYY-MM-DD DoW HH:MM:SS setup rtc
|
||||
|
||||
## defines to enable support for modules in hardware.h
|
||||
- #define RTC_SUPPORT 0/1 enable/disable RTC support
|
||||
- #define RTC_PROVIDER RTC_PROVIDER_DS3231 etc... spec which rtc ic to use
|
||||
- #define RTC_RECOVERY_CNT 10(def) // 0 no attempt to switch back to NTP time
|
||||
- #define RTC_NTP_SYNC_ENA 0/1 // 0 independed rtc, not synced with ntp,
|
||||
1 rtc synced with ntp on ntp success
|
||||
## to add new rtc ic support
|
||||
- see ds3231.h as example, create your_ic.h file and write two
|
||||
functions time_t getTime_rtc() and uint8_t setTime_rtc(time_t nt)
|
||||
- define your provider constant in config/types.h
|
||||
- add your provider section in config/rtc.h
|
||||
55
code/espurna/rtc/ds1307.h
Normal file
55
code/espurna/rtc/ds1307.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
|
||||
ds1307 support module
|
||||
|
||||
not tested but it almost similar to ds3231, so it maybe work
|
||||
|
||||
Copyright (C) 2018 by Pavel Chauzov <poulch at mail dot ru>
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#undef I2C_SUPPORT
|
||||
#define I2C_SUPPORT 1 // Explicitly request I2C support.
|
||||
|
||||
#include <TimeLib.h>
|
||||
|
||||
#define DS1307ADDR 0x68
|
||||
|
||||
#define _bcdToDec(val) ((uint8_t) ((val / 16 * 10) + (val % 16)))
|
||||
#define _decToBcd(val) ((uint8_t) ((val / 10 * 16) + (val % 10)))
|
||||
|
||||
time_t getTime_rtc() {
|
||||
uint8_t data[7];
|
||||
tmElements_t tm;
|
||||
|
||||
i2c_write_uint8(DS1307ADDR,0);
|
||||
i2c_read_buffer(DS1307ADDR, data, 7);
|
||||
tm.Second = _bcdToDec(data[0]);
|
||||
tm.Minute = _bcdToDec(data[1]);
|
||||
tm.Hour = _bcdToDec(data[2]);
|
||||
tm.Wday = _bcdToDec(data[3]);
|
||||
tm.Day = _bcdToDec(data[4]);
|
||||
tm.Month = _bcdToDec(data[5]);
|
||||
tm.Year = y2kYearToTm(_bcdToDec(data[6]));
|
||||
|
||||
return makeTime(tm);
|
||||
}
|
||||
|
||||
uint8_t setTime_rtc(time_t nt) {
|
||||
uint8_t data[8];
|
||||
tmElements_t ct;
|
||||
breakTime(nt, ct);
|
||||
|
||||
data[0] = 0;
|
||||
data[1] = _decToBcd(ct.Second);
|
||||
data[2] = _decToBcd(ct.Minute);
|
||||
data[3] = _decToBcd(ct.Hour);
|
||||
data[4] = _decToBcd(ct.Wday);
|
||||
data[5] = _decToBcd(ct.Day);
|
||||
data[6] = _decToBcd(ct.Month);
|
||||
data[7] = _decToBcd(tmYearToY2k(ct.Year));
|
||||
uint8_t s = i2c_write_buffer(DS1307ADDR, data, 8);
|
||||
return s;
|
||||
}
|
||||
52
code/espurna/rtc/ds3231.h
Normal file
52
code/espurna/rtc/ds3231.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
ds3231 support module
|
||||
|
||||
Copyright (C) 2018 by Pavel Chauzov <poulch at mail dot ru>
|
||||
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#undef I2C_SUPPORT
|
||||
#define I2C_SUPPORT 1 // Explicitly request I2C support.
|
||||
|
||||
#include <TimeLib.h>
|
||||
|
||||
|
||||
#define DS3231ADDR 0x68
|
||||
|
||||
#define _bcdToDec(val) ((uint8_t) ((val / 16 * 10) + (val % 16)))
|
||||
#define _decToBcd(val) ((uint8_t) ((val / 10 * 16) + (val % 10)))
|
||||
|
||||
time_t getTime_rtc() {
|
||||
uint8_t data[7];
|
||||
tmElements_t tm;
|
||||
|
||||
i2c_write_uint8(DS3231ADDR,0);
|
||||
i2c_read_buffer(DS3231ADDR, data, 7);
|
||||
tm.Second = _bcdToDec(data[0]);
|
||||
tm.Minute = _bcdToDec(data[1]);
|
||||
tm.Hour = _bcdToDec(data[2]);
|
||||
tm.Wday = _bcdToDec(data[3]);
|
||||
tm.Day = _bcdToDec(data[4]);
|
||||
tm.Month = _bcdToDec(data[5]);
|
||||
tm.Year = y2kYearToTm(_bcdToDec(data[6]));
|
||||
|
||||
return makeTime(tm);
|
||||
}
|
||||
|
||||
uint8_t setTime_rtc(time_t nt) {
|
||||
uint8_t data[8];
|
||||
tmElements_t ct;
|
||||
breakTime(nt, ct);
|
||||
|
||||
data[0] = 0;
|
||||
data[1] = _decToBcd(ct.Second);
|
||||
data[2] = _decToBcd(ct.Minute);
|
||||
data[3] = _decToBcd(ct.Hour);
|
||||
data[4] = _decToBcd(ct.Wday);
|
||||
data[5] = _decToBcd(ct.Day);
|
||||
data[6] = _decToBcd(ct.Month);
|
||||
data[7] = _decToBcd(tmYearToY2k(ct.Year));
|
||||
uint8_t s = i2c_write_buffer(DS3231ADDR, data, 8);
|
||||
return s;
|
||||
}
|
||||
30
code/espurna/rtc/dummy.h
Normal file
30
code/espurna/rtc/dummy.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
|
||||
dummyRTC support module
|
||||
|
||||
Copyright (C) 2018 by Pavel Chauzov <poulch at mail dot ru>
|
||||
|
||||
*/
|
||||
#include <TimeLib.h>
|
||||
|
||||
#define _bcdToDec(val) ((uint8_t) ((val / 16 * 10) + (val % 16)))
|
||||
#define _decToBcd(val) ((uint8_t) ((val / 10 * 16) + (val % 10)))
|
||||
|
||||
time_t getTime_rtc() {
|
||||
|
||||
tmElements_t tm;
|
||||
|
||||
tm.Second = _bcdToDec(1);
|
||||
tm.Minute = _bcdToDec(0);
|
||||
tm.Hour = _bcdToDec(0);
|
||||
tm.Wday = _bcdToDec(0);
|
||||
tm.Day = _bcdToDec(1);
|
||||
tm.Month = _bcdToDec(1);
|
||||
tm.Year = y2kYearToTm(16);
|
||||
|
||||
return makeTime(tm);
|
||||
}
|
||||
|
||||
uint8_t setTime_rtc(time_t nt) {
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user