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:
- 2021-01-16
- Revision:
- 102:d7bc31f0ac6e
- Parent:
- 99:84c3273dc77f
File content as of revision 102:d7bc31f0ac6e:
#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 bool htgOverride = false; static char htgWinter; static int iWinter; 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 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 v) { htgWinter = (char)v; FramWrite(iWinter, 1, &htgWinter ); } static void setHallRom ( char* v) { memcpy(hallRom, v, 8); FramWrite(iHallRom, 8, hallRom ); } void RadiatorSetOverrideCancelHour ( int v) { if (v > 23 || v < 0) v = 0; overrideCancelHour = (uint8_t)v, FramWrite(iOverrideCancelHour, 1, &overrideCancelHour ); } void RadiatorSetOverrideCancelMinute( int v) { if (v > 59 || v < 0) v = 0; overrideCancelMinute = (uint8_t)v, FramWrite(iOverrideCancelMinute, 1, &overrideCancelMinute); } void RadiatorSetNightTemperature ( int v) { if (v > 99 || v < 0) v = 0; nightTemperature = (int16_t)v; FramWrite(iNightTemperature, 2, &nightTemperature ); } void RadiatorSetFrostTemperature ( int v) { if (v > 99 || v < 0) v = 0; frostTemperature = (int16_t)v; 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 static bool nightTooCold = false; static bool frostTooCold = false; if (DS18B20IsValidValue(hallTemp16ths)) { if (hallTemp16ths < frostTemp16ths) frostTooCold = true; if (hallTemp16ths > frostTemp16ths) frostTooCold = false; if (hallTemp16ths < nightTemp16ths) nightTooCold = true; //Set at 289 (18.06) rather than 288 (18.00) if (hallTemp16ths > nightTemp16ths) nightTooCold = false;//Reset at 287 (17.94). This prevent it following the flashing. } outputBeforeOverride = (htgWinter && ProgramTimerOutput) || (htgWinter && nightTooCold) || frostTooCold; } 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) htgOverride = false; cancelWasDue = cancelIsDue; } //Remove override if no longer required static bool previousOutput = false; if (previousOutput != outputBeforeOverride && htgOverride) htgOverride = 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) htgOverride = false; //Adjust the override to leave the heat as it was - off or on. } else //Winter -> Summer { htgOverride = false; //turn off the heat. } } makeOutputWithOverride(); } void RadiatorSetOverride(bool value) { htgOverride = 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; FramAllocate(1); //Spare byte 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 output as it uses that information makeOutputWithOverride(); //Pump output if (RadiatorPump) RADIATOR_PUMP_SET; else RADIATOR_PUMP_CLR; }