Skip to content

Commit

Permalink
moved pids into pumps and mixer, hysteresis of boiler charging
Browse files Browse the repository at this point in the history
  • Loading branch information
Thomas Emmert committed Feb 8, 2015
1 parent 8f6f0d1 commit 20b50dd
Show file tree
Hide file tree
Showing 12 changed files with 139 additions and 105 deletions.
7 changes: 3 additions & 4 deletions cBoiler.cpp
Expand Up @@ -2,19 +2,18 @@

cBoiler::cBoiler(cRooms* Rooms_,cWarmWater* WarmWater_)
:Valve(PinValveBoilerOpen,PinValveBoilerClose),
pid( 1.05, 0.0, 10.5, REVERSE), //I= 0.063
TempCharge((&MPNumSys[0]),(&MPChanSys[idxTempBoilerCharge]),(&SysTempOffset[idxTempBoilerCharge])),
TempReserve1((&MPNumSys[0]),(&MPChanSys[idxTempBoilerReserve1]),(&SysTempOffset[idxTempBoilerReserve1])),
TempReserve2((&MPNumSys[0]),(&MPChanSys[idxTempBoilerReserve2]),(&SysTempOffset[idxTempBoilerReserve2])),
TempHead((&MPNumSys[0]),&MPChanSys[idxTempBoilerHead],(&SysTempOffset[idxTempBoilerHead])),
TempTop((&MPNumSys[0]),&MPChanSys[idxTempBoilerTop],(&SysTempOffset[idxTempBoilerTop])),
Pump(PinPumpBoiler)
Pump(PinPumpBoiler,1.05, 0.0, 10.5, REVERSE) //I= 0.063
{
Rooms = Rooms_;
WarmWater = WarmWater_;
ChargeMargin = DefaultChargeMargin;
// Set minimal Pump Power to 10%
pid.SetOutputLimits(0.1, 1);
Pump.SetOutputLimits(0.1, 1);
}

void cBoiler::getSP( JsonObject& root )
Expand Down Expand Up @@ -57,7 +56,7 @@ void cBoiler::getData( JsonObject& root )
root["BT3"] = TempReserve1.get();
root["BT4"] = TempReserve2.get();

root["BP"] = pid.get();
root["BP"] = Pump.get();
root["BncW"] = static_cast<int>( bneedChargeWarmWater);
root["BncH"] = static_cast<int>( bneedChargeHeating);
root["Bdisc"] = static_cast<int>( bDischarging);
Expand Down
22 changes: 16 additions & 6 deletions cBoiler.h
Expand Up @@ -60,16 +60,27 @@ class cBoiler
return bneedChargeHeating;
}

void charge(boolean bCharge, float TempChargeSource)
void charge(float TempHeatSource)
{
bCharging = bCharge;
boolean need = (bneedChargeWarmWater || bneedChargeHeating);

if (need) // if charging is needed, charging is fixed to true
bCharging = true;
else // Hysteresis
{
if (getSpTempCharge()+2 < TempHeatSource)
bCharging = true;
if (getSpTempCharge() > TempHeatSource)
bCharging = false;
}

Valve.set((bDischarging || bCharging)); // Open Valve if charging or discharging

if (bCharge) // Run Pump
Pump.setPower(pid.run(getSpTempCharge(), TempChargeSource));
if (bCharging) // Run Pump
Pump.run(getSpTempCharge(), TempHeatSource);
else // Stop Charging: Stop PID and Pump
Pump.setPower(pid.run());
Pump.run();

}

void discharge( boolean bNeedSourceBoiler )
Expand All @@ -87,7 +98,6 @@ class cBoiler

cValve Valve;
cPump Pump;
cPID pid;

// May become private again (debug)
cTempSensor TempCharge;
Expand Down
12 changes: 5 additions & 7 deletions cHeating.cpp
Expand Up @@ -146,24 +146,22 @@ void cHeating::selectSink( int Sink )
switch (Sink) {
case SiChargeWarmWater: {
Rooms.ChargeRooms(false);
Boiler.charge(true, TempSource);
Boiler.charge(TempSource);
break;
}
case SiChargeRooms: {
boolean ChargeBoilerAndRooms = (Burner.TempOperation.get() > Boiler.getSpTempCharge()) // Burner residual heat
||(Solar.TempFromCollector.get()-4 > Boiler.getSpTempCharge()); // Solar residual heat
Rooms.ChargeRooms(true, ChargeBoilerAndRooms);
Boiler.charge(ChargeBoilerAndRooms, TempSource);
Rooms.ChargeRooms(true);
Boiler.charge(TempSource);
break;
}
case SiChargeHeating: {
Rooms.ChargeRooms(false);
Boiler.charge(true, TempSource);
Boiler.charge(TempSource);
break;
}
case SiOff: default: {
Rooms.ChargeRooms(false);
Boiler.charge(false, TempSource);
Boiler.charge(TempSource);
break;
}
}
Expand Down
56 changes: 44 additions & 12 deletions cMixer.h
Expand Up @@ -4,26 +4,65 @@
#include "Arduino.h"

#include "cLFPWM.h"
#include <PID_v1.h>

class cMixer
class cMixer : public PID
{
public:
/// Creates the mixer
cMixer(int pinOpen_, int pinClose_):PWM(5000){
cMixer(int pinOpen_, int pinClose_,double p, double i, double d, int mode):
PWM(5000),
PID(&Is, &Power, &Setpoint, p, i, d, mode)
{
pinOpen = pinOpen_;
pinMode(pinOpen, OUTPUT);

pinClose = pinClose_;
pinMode(pinClose, OUTPUT);
};

Is = 0;
Power = 0;
Setpoint = 0;
}

/// Set the power in percent
/** Drives the mixer with a certain power (abs) into a direction (sign: open or close)
\param Power the desired power in percent */
void run(double Power)
void run(double Power_)
{
boolean direction = (Power>=0);
Power = Power_;
SetMode(MANUAL);
Compute();

run();
}

double run(double Setpoint_, double Is_)
{
Is = Is_;
Setpoint = Setpoint_;
SetMode(AUTOMATIC);
Compute();

run();

return Power;
}

double get(void){return Power;}

private:
cLFPWM PWM;
int pinOpen;
int pinClose;

double Is;
double Setpoint;
double Power;

void run()
{
boolean direction = (Power>=0);
// Check PWM and hysteresis
if(PWM.get(abs(Power))&&(abs(Power)> 0.0)) {
// Drive in direction
Expand All @@ -36,13 +75,6 @@ class cMixer
digitalWrite(pinOpen, HIGH);
}
}

//float get(void){return PWM.getPower();}

private:
cLFPWM PWM;
int pinOpen;
int pinClose;
};

#endif
49 changes: 38 additions & 11 deletions cPump.h
Expand Up @@ -4,42 +4,69 @@
#include "Arduino.h"
#include "PinDefinitions.h"
#include "cLFPWM.h"
#include <cPID.h>
#include <PID_v1.h>

#define PWMPeriod 2000

class cPump
class cPump : public PID
{
public:
/// Creates a pump object with a certain pin.
/** The power of the pump is set to zero by default.*/
/** \param PinPump the pin used to drive the Pump*/
/** \param Power the power the pump in percent*/
cPump(int PinPump_,float p= 0.0, float i= 0.0, float d= 0.0, double Power = 0.0):
cPump(int PinPump_,float p, float i, float d, int mode, double Power = 0.0):
PWM(PWMPeriod),
pid(p, i, d, DIRECT)
PID(&Is, &Power, &Setpoint, p, i, d, mode)
{
PinPump = PinPump_;
pinMode(PinPump, OUTPUT);
setPower(Power);

Is = 0;
Power = 0;
Setpoint = 0;

run();
}

/// Set the power of the pump in percent
/** Set the power of the pump in percent and execute
\param Value of the desired power in percent*/
void setPower( double Power )
\param Power_ in percent*/
double run(double Power_ = 0.0)
{
Power = Power_;
SetMode(MANUAL);

Compute();
// Pump is running if switching time of PWM is not yet exceeded
digitalWrite(PinPump, !PWM.get(Power)); // Pump switched on if true and off if false
return Power;
}
/// Regulate the power by pid controller
/** Update setpoint and is value, then execute pid controller and set pump
\param Setpoint_ update Setpoint value
\param Is_ update Is value*/
double run(double Setpoint_, double Is_)
{
// Limit Power
Power = max(min(Power,1.0),0.0);
Is = Is_;
Setpoint = Setpoint_;
SetMode(AUTOMATIC);

Compute();
// Pump is running if switching time of PWM is not yet exceeded
digitalWrite(PinPump, !PWM.get(Power)); // Pump switched on if true and off if false
return Power;
}

cPID pid;
double get(void)
{
return Power;
}

private:
int PinPump;
double Is;
double Setpoint;
double Power;

cLFPWM PWM;

Expand Down
52 changes: 15 additions & 37 deletions cRooms.cpp
Expand Up @@ -4,16 +4,14 @@ cRooms::cRooms( void ):
IsTempHeatingLead((&MPNumSys[0]),(&MPChanSys[idxTempHeatingLead]),(&SysTempOffset[idxTempHeatingLead])),
IsTempHeatingReturn((&MPNumSys[0]),(&MPChanSys[idxTempHeatingReturn]),(&SysTempOffset[idxTempHeatingReturn])),
TempOutside((&MPNumSys[0]),(&MPChanSys[idxTempOutside]),(&SysTempOffset[idxTempOutside])),
PIDPump( 0.5, 0.0, 0.0, DIRECT),
PIDMixer( 0.2, 0.0, 2.0, DIRECT),
Pump(PinPumpHeating,0.5, 0.0, 0.0, DIRECT),
Mixer(PinMixerOpen,PinMixerClose)
Pump(PinPumpHeating,0.5, 0.0, 0.0, DIRECT, 0.0),
Mixer(PinMixerOpen,PinMixerClose, 0.2, 0.0, 2.0, DIRECT)
{
SetType = Normal;
// Initialize PID controllers for pumps
PIDPump.SetOutputLimits(0.3, 1.0);
PIDMixer.SetOutputLimits(-1.0, 1.0);
PIDMixer.SetSampleTime(500);
Pump.SetOutputLimits(0.3, 1.0);
Mixer.SetOutputLimits(-1.0, 1.0);
Mixer.SetSampleTime(500);

dMaxDiff =0;
dMaxSp = 0;
Expand Down Expand Up @@ -75,39 +73,21 @@ void cRooms::initDefaultSetpoint()
}


void cRooms::ChargeRooms( boolean ChargeRooms, boolean BoilerCharges )
void cRooms::ChargeRooms( boolean ChargeRooms )
{
dSpTempHeatingLead = getSpHeating();
dIsTempHeatingLead = IsTempHeatingLead.get();
dSpTempHeatingReturn = getSpHeating()-DiffTempHeatingLeadReturn;
dIsTempHeatingReturn = IsTempHeatingReturn.get();
double SpTempHeatingReturn = getSpHeating()-DiffTempHeatingLeadReturn;

if (ChargeRooms)
{

// Run Mixer and PID
Mixer.run(PIDMixer.run(dSpTempHeatingLead, dIsTempHeatingLead));

// Run heating pump and PID
if (BoilerCharges)
{
// If Boiler is charged, run heating pump at full speed.
// The Boiler is collecting the remaining heat from the source.
PIDPump.run();
Pump.setPower(1.0);
}
else
{
Pump.setPower(PIDPump.run(dSpTempHeatingReturn, dIsTempHeatingReturn));
}
// Run Pump and Mixer
Mixer.run(getSpHeating(), IsTempHeatingLead.get());
Pump.run(SpTempHeatingReturn, IsTempHeatingReturn.get());
}
else
{
// Stop Pump Heating and PID
PIDPump.run();
Pump.setPower(0.0);
// Stop mixer PID and run Mixer to closed position
PIDMixer.run();
// Stop Pump Heating
Pump.run(0.0);
// Close Mixer
Mixer.run(-1.0);
}
}
Expand Down Expand Up @@ -202,7 +182,6 @@ int cRooms::setOffsetTime( JsonObject& root )
return 0;
}


void cRooms::getOffsetTemp( JsonObject& root )
{
JsonArray& temps = root.createNestedArray("RTs");
Expand All @@ -222,7 +201,6 @@ void cRooms::getOffsetTemp( JsonObject& root )
}
}


int cRooms::setOffsetTemp( JsonObject& root )
{
if(root.containsKey("RTs")) {
Expand Down Expand Up @@ -338,6 +316,6 @@ void cRooms::getData( JsonObject& root )

root["RTitoR"] = IsTempHeatingLead.get();
root["RTitoSys"] = IsTempHeatingReturn.get();
root["RP"] = PIDPump.get();
root["RM"] = PIDMixer.get();
root["RP"] = Pump.get();
root["RM"] = Mixer.get();
}

0 comments on commit 20b50dd

Please sign in to comment.