Skip to content

Commit

Permalink
RTC auto calibration
Browse files Browse the repository at this point in the history
  • Loading branch information
dlyubimov committed Jul 10, 2017
1 parent a47cdef commit d622633
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 11 deletions.
8 changes: 7 additions & 1 deletion Hydra_EVSE/Hydra_EVSE.h
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,10 @@ typedef struct calib_struct {
// eprom persistence format signature (usually minimally compatible SW_VERSION):
// 2.4.1
#define PERSIST_SIG 241

// debug to reset eprom
//#define PERSIST_SIG -1

#define EEPROM_OFFSET 0

struct persisted_struct {
Expand All @@ -491,7 +495,9 @@ struct persisted_struct {
event_struct events[EVENT_COUNT];
calib_struct calib;

persisted_struct() {
RTCModel rtc;

persisted_struct() : rtc(0.5) {
eepromRead();
validate();
}
Expand Down
6 changes: 5 additions & 1 deletion Hydra_EVSE/Hydra_EVSE.ino
Original file line number Diff line number Diff line change
Expand Up @@ -1171,9 +1171,13 @@ void doClockMenu(boolean initialize)
// The underlying system clock is always winter time.
// Note that setting the time during the repeated hour in
// the fall will assume winter time - the hour will NOT repeat.
// if (enable_dst) toSet = dst.toUTC(toSet);

time_t oldTime = now;
setTime(toSet);
RTC.set(toSet);
RTC.setCalibration(persisted.rtc.update(toSet, toSet-oldTime));
persisted.eepromWrite();

doMenuFunc = doMenu;
inMenu = false; // exit all menus
display.clear();
Expand Down
58 changes: 49 additions & 9 deletions Hydra_EVSE/onlineSum.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@
#ifndef ___ONLINESUM_H___
#define ___ONLINESUM_H___

#include "Arduino.h"

///////////////////////////////////////////////////////////////////
// Exponentially Weighted Average summarizer for irregularly sampled data.
// References:
// References:
// http://tdunning.blogspot.com/2011/03/exponentially-weighted-averaging-for.html
// My mods for the updates-in-the past (ensures no NaNs created regardless of updates order):
// http://weatheringthrutechdays.blogspot.com/2011/04/follow-up-for-mean-summarizer-post.html
Expand All @@ -32,15 +34,17 @@
template <class T>
class EWASum {

friend class RTCModel;

T alpha;
T w, s, tn;

public:
// tHalfWeightPeriod is the amount of t (timeline point) in the past at which the observation is
// exponentially weighed at exactly 0.5 vs. any observation right now. Since it is weighed
// exponentially rather than linearly, observations at full period still do have a nonzero weight,
// and in general with this summarizer most recent observations are being discounted at fastest

// tHalfWeightPeriod is the amount of t (timeline point) in the past at which the observation is
// exponentially weighed at exactly 0.5 vs. any observation right now. Since it is weighed
// exponentially rather than linearly, observations at full period still do have a nonzero weight,
// and in general with this summarizer most recent observations are being discounted at fastest
// weight but never actually discounted completely (indefinite history), down to the precision of
// the arithmetics. At full period the weights are thus still coming in at exp(-2) = 0.135 (13.5%).
EWASum(T tHalfWeightPeriod) : alpha(-tHalfWeightPeriod / log((T)0.5)) {
Expand Down Expand Up @@ -72,14 +76,50 @@ void EWASum<T>::update(T x, T t) {

template <class T>
T EWASum<T>::ewa() {
// In this sum, weights low enough should not happen, as we never discount the most recent weight,
// which is at least one. So w>= 1 if there were at least one sample; and w = exactly 0 if there
// are no samples at all. With no samples, we just return 0.
// In this sum, weights low enough should not happen, as we never discount the most recent weight,
// which is at least one. So w>= 1 if there were at least one sample; and w = exactly 0 if there
// are no samples at all. With no samples, we just return 0.
return (abs(w) < 1e-6) ? 0 : s / w;
}

// On Arduino, double seems to be the same as float and take 4 bytes!
typedef EWASum<double> EWASumD;
typedef EWASum<float> EWASumF;

#define RTC_CALIB_PERIOD SECS_PER_DAY

// RTC model
class RTCModel {

protected:

EWASumD ewa;
char calib, calibErr;
double initCalibRate, rate, dn;

public:

// for PT7C4311WEX, actual rate to add seconds per day seems to be 0.35, and to delete seconds is 0.175.
// in simulations, 0.5 seems to be a good initial value.
// half rate period should be in seconds, e.g., 2* SECS_PER_WEEK seems to be a good value.
RTCModel(double initCalibRate);

// update model after time adjustment: t is the time after adjustment (in seconds, e.g. what now() returns),
// and adjustmentn is number of seconds added. E.g., if we moved clock forward, we wanted to add seconds (+),
// and if we moved clock backwards, we wanted to remove extra seconds (-). Adjustment is absolute value of
// adjustment given by a human thru the clock menu (NOT weighted per day!). Returns new calibration value
// to use in the rtc chip.
char update(double t, double adjustment);

// get current calibration value.
char getCalib() {
return calib;
}

void reset();



};

#endif // ___ONLINESUM_H___

0 comments on commit d622633

Please sign in to comment.