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
Diff: heating/boiler.c
- Revision:
- 0:3c04f4b47041
- Child:
- 1:ccc66fdf858d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/heating/boiler.c Thu Jan 11 17:40:08 2018 +0000 @@ -0,0 +1,103 @@ +#include <string.h> +#include <stdint.h> +#include <stdbool.h> + +#include "peripherals.h" +#include "clock.h" +#include "ds18b20.h" +#include "fram.h" + +#define BOILER_PUMP_MASK 1UL << 4 // P2.4 == p22 +#define BOILER_CALL_MASK 1UL << 5 // P2.5 == p21 + +static char tankRom[8]; static int iTankRom; +static char outputRom[8]; static int iOutputRom; +static char returnRom[8]; static int iReturnRom; + + +static int32_t tankSetPoint; static int iTankSetPoint; +static int32_t tankHysteresis; static int iTankHysteresis; +static int32_t runOnResidual; static int iRunOnResidual; +static int32_t runOnTime; static int iRunOnTime; + +char* BoilerGetTankRom () { return tankRom; } +char* BoilerGetOutputRom () { return outputRom; } +char* BoilerGetReturnRom () { return returnRom; } +int BoilerGetTankSetPoint () { return (int) tankSetPoint; } +int BoilerGetTankHysteresis() { return (int) tankHysteresis; } +int BoilerGetRunOnResidual () { return (int) runOnResidual; } +int BoilerGetRunOnTime () { return (int) runOnTime; } + +void BoilerSetTankRom (char* value) { memcpy(tankRom, value, 8); FramWrite(iTankRom, 8, tankRom ); } +void BoilerSetOutputRom (char* value) { memcpy(outputRom, value, 8); FramWrite(iOutputRom, 8, outputRom ); } +void BoilerSetReturnRom (char* value) { memcpy(returnRom, value, 8); FramWrite(iReturnRom, 8, returnRom ); } +void BoilerSetTankSetPoint (int value) { tankSetPoint = (int32_t)value; FramWrite(iTankSetPoint, 4, &tankSetPoint ); } +void BoilerSetTankHysteresis (int value) { tankHysteresis = (int32_t)value; FramWrite(iTankHysteresis, 4, &tankHysteresis ); } +void BoilerSetRunOnResidual (int value) { runOnResidual = (int32_t)value; FramWrite(iRunOnResidual, 4, &runOnResidual ); } +void BoilerSetRunOnTime (int value) { runOnTime = (int32_t)value; FramWrite(iRunOnTime, 4, &runOnTime ); } + + +int BoilerInit() +{ + int address; + int32_t def4; + address = FramLoad( 8, tankRom, 0); if (address < 0) return -1; iTankRom = address; + address = FramLoad( 8, outputRom, 0); if (address < 0) return -1; iOutputRom = address; + address = FramLoad( 8, returnRom, 0); if (address < 0) return -1; iReturnRom = address; + def4 = 80; address = FramLoad( 4, &tankSetPoint, &def4); if (address < 0) return -1; iTankSetPoint = address; + def4 = 5; address = FramLoad( 4, &tankHysteresis, &def4); if (address < 0) return -1; iTankHysteresis = address; + def4 = 2; address = FramLoad( 4, &runOnResidual, &def4); if (address < 0) return -1; iRunOnResidual = address; + def4 = 360; address = FramLoad( 4, &runOnTime, &def4); if (address < 0) return -1; iRunOnTime = address; + + LPC_GPIO2->FIODIR |= BOILER_PUMP_MASK; //Set the direction to 1 == output + LPC_GPIO2->FIODIR |= BOILER_CALL_MASK; //Set the direction to 1 == output + + return 0; +} +bool BoilerPump = false; +bool BoilerCall = false; + +void BoilerMain() +{ + //Control boiler call + int tankTemp16ths = DS18B20ValueFromRom(tankRom); + if (DS18B20IsValidValue(tankTemp16ths)) //Ignore values which are likely to be wrong + { + int tankUpper16ths = tankSetPoint << 4; + int hysteresis16ths = tankHysteresis << 4; + int tankLower16ths = tankUpper16ths - hysteresis16ths; + + if (tankTemp16ths >= tankUpper16ths) BoilerCall = false; + if (tankTemp16ths <= tankLower16ths) BoilerCall = true; + } + if (BoilerCall) LPC_GPIO2->FIOSET = BOILER_CALL_MASK; + else LPC_GPIO2->FIOCLR = BOILER_CALL_MASK; + + //Control boiler circulation pump + int boilerOutput16ths = DS18B20ValueFromRom(outputRom); + int boilerReturn16ths = DS18B20ValueFromRom(returnRom); + int boilerResidual16ths = boilerOutput16ths - boilerReturn16ths; + int boilerTempsAreValid = DS18B20IsValidValue(boilerOutput16ths) && DS18B20IsValidValue(boilerReturn16ths); + + static int64_t offTimeNs; + if (BoilerCall) + { + BoilerPump = true; + offTimeNs = ClockNowNs(); + } + else + { + int64_t nowNs = ClockNowNs(); + int secondsSinceBoilerOff = (nowNs - offTimeNs) >> 20; + if (secondsSinceBoilerOff > runOnTime) BoilerPump = false; + if (boilerTempsAreValid) + { + int boilerStillSupplyingHeat = boilerResidual16ths > runOnResidual; + if (!boilerStillSupplyingHeat) BoilerPump = false; + } + } + + if (BoilerPump) LPC_GPIO2->FIOSET = BOILER_PUMP_MASK; + else LPC_GPIO2->FIOCLR = BOILER_PUMP_MASK; + +} \ No newline at end of file