Browse Source

Merge pull request #1036 from poulch74/espurna-rtc

add complex support for RTC (ds3231 ds1307 etc)
rtc
Xose Pérez 5 years ago
committed by GitHub
parent
commit
4152caab93
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 386 additions and 1 deletions
  1. +1
    -0
      code/espurna/config/all.h
  2. +1
    -1
      code/espurna/config/arduino.h
  3. +58
    -0
      code/espurna/config/hardware.h
  4. +37
    -0
      code/espurna/config/rtc.h
  5. +7
    -0
      code/espurna/config/types.h
  6. +33
    -0
      code/espurna/ntp.ino
  7. +95
    -0
      code/espurna/rtc.ino
  8. +17
    -0
      code/espurna/rtc/README.md
  9. +55
    -0
      code/espurna/rtc/ds1307.h
  10. +52
    -0
      code/espurna/rtc/ds3231.h
  11. +30
    -0
      code/espurna/rtc/dummy.h

+ 1
- 0
code/espurna/config/all.h View File

@ -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"


+ 1
- 1
code/espurna/config/arduino.h View File

@ -89,7 +89,7 @@
//#define BLITZWOLF_BWSHP2
//#define BH_ONOFRE
//#define ITEAD_SONOFF_IFAN02
//#define SHAPEsp
//--------------------------------------------------------------------------------
// Features (values below are non-default values)
//--------------------------------------------------------------------------------


+ 58
- 0
code/espurna/config/hardware.h View File

@ -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
- 0
code/espurna/config/rtc.h View 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

+ 7
- 0
code/espurna/config/types.h View File

@ -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

+ 33
- 0
code/espurna/ntp.ino View File

@ -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
- 0
code/espurna/rtc.ino View 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
- 0
code/espurna/rtc/README.md View 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
- 0
code/espurna/rtc/ds1307.h View 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
- 0
code/espurna/rtc/ds3231.h View 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
- 0
code/espurna/rtc/dummy.h View 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;
}

Loading…
Cancel
Save