Central Heating controller using the real time clock, PHY module for internet, 1-wire interface for temperature sensors, a system log and a configuration file

Dependencies:   net 1-wire lpc1768 crypto clock web fram log

/media/uploads/andrewboyson/heating.sch

/media/uploads/andrewboyson/heating.brd

/media/uploads/andrewboyson/eagle.epf

heating/radiator.c

Committer:
andrewboyson
Date:
2020-10-03
Revision:
96:18a3813bb4b5
Parent:
95:97621bfbedfa
Child:
97:84d58bf7a835

File content as of revision 96:18a3813bb4b5:

#include <stdint.h>
#include <string.h>
#include <stdbool.h>

#include "gpio.h"
#include "program.h"
#include "ds18b20.h"
#include "fram.h"
#include "radiator.h"
#include "clktime.h"
#include "clk.h"
#include "led.h"


#define RADIATOR_PUMP_DIR FIO2DIR(03) // P2.03 == p23;
#define RADIATOR_PUMP_PIN FIO2PIN(03)
#define RADIATOR_PUMP_SET FIO2SET(03)
#define RADIATOR_PUMP_CLR FIO2CLR(03)

static char      htgWinter;            static int iWinter;
static char      htgOverride;          static int iOverride;
static char*     hallRom;              static int iHallRom;
static uint8_t  overrideCancelHour;    static int iOverrideCancelHour;
static uint8_t  overrideCancelMinute;  static int iOverrideCancelMinute;
static  int16_t  nightTemperature;     static int iNightTemperature;
static  int16_t  frostTemperature;     static int iFrostTemperature;

bool     RadiatorGetWinter              () { return (bool)htgWinter;              } 
bool     RadiatorGetOverride            () { return (bool)htgOverride;            } 
uint16_t RadiatorGetHallDS18B20Value    () { return DS18B20ValueFromRom(hallRom); }
int      RadiatorGetOverrideCancelHour  () { return  (int)overrideCancelHour;     }
int      RadiatorGetOverrideCancelMinute() { return  (int)overrideCancelMinute;   }
int      RadiatorGetNightTemperature    () { return  (int)nightTemperature;       } 
int      RadiatorGetFrostTemperature    () { return  (int)frostTemperature;       } 

static void  setWinter              ( bool  value) { htgWinter            =     (char)value; FramWrite(iWinter,               1, &htgWinter           ); }
static void  setOverride            ( bool  value) { htgOverride          =     (char)value; FramWrite(iOverride,             1, &htgOverride         ); }
static void  setHallRom             ( char* value) { memcpy(hallRom,  value, 8);             FramWrite(iHallRom,              8,  hallRom             ); }
void RadiatorSetOverrideCancelHour  ( int   value) { overrideCancelHour   =  (uint8_t)value, FramWrite(iOverrideCancelHour,   1, &overrideCancelHour  ); }
void RadiatorSetOverrideCancelMinute( int   value) { overrideCancelMinute =  (uint8_t)value, FramWrite(iOverrideCancelMinute, 1, &overrideCancelMinute); }
void RadiatorSetNightTemperature    ( int   value) { nightTemperature     =  (int16_t)value; FramWrite(iNightTemperature,     2, &nightTemperature    ); }
void RadiatorSetFrostTemperature    ( int   value) { frostTemperature     =  (int16_t)value; FramWrite(iFrostTemperature,     2, &frostTemperature    ); }

static bool outputBeforeOverride = false;
static void makeOutputBeforeOverride()
{
    //See if the temperature is too low
    int  hallTemp16ths = DS18B20ValueFromRom(hallRom);
    int nightTemp16ths = nightTemperature << 4;
    int frostTemp16ths = frostTemperature << 4;

    static bool tooCold = false; //This is static to ride through invalid temperature reads
    if (DS18B20IsValidValue(hallTemp16ths))
    {
        tooCold = hallTemp16ths < frostTemp16ths;
        if (htgWinter) tooCold |= hallTemp16ths < nightTemp16ths;
    }
    
    outputBeforeOverride = (htgWinter && ProgramTimerOutput) || tooCold;
}
static void autoCancelOverride()
{
    
    //Remove override at 11pm
    if (ClkTimeIsSet())
    {
        struct tm tm;
        ClkNowTmLocal(&tm);
        static bool cancelWasDue = false;
        bool cancelIsDue = tm.tm_hour == overrideCancelHour && tm.tm_min == overrideCancelMinute;
        if (cancelIsDue && !cancelWasDue && htgOverride) setOverride(false);
        cancelWasDue = cancelIsDue;
    }
    
    //Remove override if no longer required
    static bool previousOutput = false;
    if (previousOutput != outputBeforeOverride && htgOverride) setOverride(false);
    previousOutput = outputBeforeOverride;
}
bool RadiatorPump = false;
static void makeOutputWithOverride()
{
    RadiatorPump = htgOverride ? !outputBeforeOverride : outputBeforeOverride ;
}

void RadiatorSetWinter(bool value) //Summer is false, Winter is true
{
    if (htgWinter == (char)value) return; //Ignore no change
    setWinter(value);                     //Change to the new value
    
    bool prevOutputBeforeOverride = outputBeforeOverride;
    makeOutputBeforeOverride();
    
    if (htgOverride) //Only deal with an override that is already set; if it wasn't set don't change it
    {
        if (htgWinter) //Summer -> Winter
        {
            if (outputBeforeOverride != prevOutputBeforeOverride) setOverride(0); //Adjust the override to leave the heat as it was - off or on.
        }
        else //Winter -> Summer
        {
            setOverride(0); //turn off the heat.
        }
    }
        
    makeOutputWithOverride();
}
void RadiatorSetOverride(bool value)
{
    setOverride(value);
    makeOutputBeforeOverride();
    makeOutputWithOverride(); }

void RadiatorChgWinter  (){ RadiatorSetWinter  (!RadiatorGetWinter  ()); }
void RadiatorChgOverride(){ RadiatorSetOverride(!RadiatorGetOverride()); }

int RadiatorInit()
{
    hallRom = DS18B20Roms + 8 * DS18B20RomCount;
    DS18B20RomSetters[DS18B20RomCount] = setHallRom;
    DS18B20RomNames[DS18B20RomCount] = "Hall";
    DS18B20RomCount++;

    int  address;
    int8_t  def1;
    int16_t def2;
    def1 =  0; address = FramLoad( 1, &htgWinter,            &def1); if (address < 0) return -1; iWinter               = address; 
    def1 =  0; address = FramLoad( 1, &htgOverride,          &def1); if (address < 0) return -1; iOverride             = address; 
               address = FramLoad( 8,  hallRom,                  0); if (address < 0) return -1; iHallRom              = address;
    def1 = 23; address = FramLoad( 1, &overrideCancelHour,   &def1); if (address < 0) return -1; iOverrideCancelHour   = address;
    def1 =  0; address = FramLoad( 1, &overrideCancelMinute, &def1); if (address < 0) return -1; iOverrideCancelMinute = address;
                            FramAllocate(2); //Spare two bytes
    def2 = 15; address = FramLoad( 2, &nightTemperature,     &def2); if (address < 0) return -1; iNightTemperature     = address; 
    def2 =  8; address = FramLoad( 2, &frostTemperature,     &def2); if (address < 0) return -1; iFrostTemperature     = address; 
    
    RADIATOR_PUMP_DIR = 1; //Set the direction to 1 == output
    
    return 0;
}
void RadiatorMain()
{
    //Make the radiator output
    makeOutputBeforeOverride();
    autoCancelOverride(); //Do this after making the outputt as it uses that information
    makeOutputWithOverride();
    
    //Pump output
    if (RadiatorPump) RADIATOR_PUMP_SET;
    else              RADIATOR_PUMP_CLR;

}