Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Macro] Make your simple/dumb thermostat smarter!
#1
Here is a macro (in 2 parts) that I have been using for some time. The goal of this was to take a controllable thermostat that only has 1 setpoint, and make it better. Specifically:

1) Allow for an upper and lower setpoint, such that the temp will be maintained between them, switching modes as necessary.
2) Allow for a buffer around the setpoint, so that when the system comes on, it can run for a decent amount of time, and so there will be less cycling of the system.

To accomplish this, you'll need to use the variables driver to keep the setpoints and setpoint buffers. You'll also need to put triggers on the thermostat temp and modes. The macro takes a number of "actions" as a parameter, which should be obvious what they are and when you'd send them. The monikers and fields used should all be specified in the Literals section, so change it to your setup, and then modify as needed.

I'll be happy to answer questions about it, but expect my "support" of it to be very limited. I didn't post it here to give myself more work to do. ;-)

Below is the first half of the code. The 2nd half will be in the next post (forum limits prevented me from posting it all at once).
Code:
// CQC

Class=[NonFinal]
    ClassPath MEng.User.HvacControl;
    ParentClass MEng.Object;
EndClass;

Imports=
    MEng.System.CQC.Runtime.SimpleFldClient;
    MEng.System.CQC.Runtime.CQCLogger;
EndImports;

Literals=
    String HVAC_DRIVER_NAME("HVAC");
    String SETPOINT_FIELD("SetpointStat1");
    String TEMP_FIELD("TempStat1");
    String MODE_FIELD("ModeStat1");
    String COOLING("COOL");
    String HEATING("HEAT");
    String OFF("OFF");
    String COOL_ON_FIELD("CoolStage1Stat1");
    String HEAT_ON_FIELD("HeatStage1Stat1");
    
    String VARIABLE_DRIVER_NAME("MSVars");
    String UPPER_SETPOINT_FIELD("UpperSetpoint");
    String LOWER_SETPOINT_FIELD("LowerSetpoint");
    String SETPOINT_BUFFER_FIELD("SetpointBuffer");
EndLiterals;

Members=
    SimpleFldClient m_FldClient;
    CQCLogger m_Logger;
EndMembers;


Methods=[Public,Final]

    Constructor()
    Begin
    EndConstructor;

    Method Start([In] MEng.String action) Returns Int4
    Begin
        Locals=
            Int4 actualSetpoint;
            Int4 actualTemp;
            Int4 upperSetpoint;
            Int4 lowerSetpoint;
            Int4 setpointBuffer;
            Int4 newSetpoint;
            String currentMode;
            Int4 distanceToUpper;
            Int4 distanceToLower;
        EndLocals;
        
        actualSetpoint := m_FldClient.ReadIntField(HVAC_DRIVER_NAME, SETPOINT_FIELD);
        upperSetpoint := m_FldClient.ReadIntField(VARIABLE_DRIVER_NAME, UPPER_SETPOINT_FIELD);
        lowerSetpoint := m_FldClient.ReadIntField(VARIABLE_DRIVER_NAME, LOWER_SETPOINT_FIELD);
        currentMode := m_FldClient.ReadStringField(HVAC_DRIVER_NAME, MODE_FIELD);
        actualTemp := m_FldClient.ReadIntField(HVAC_DRIVER_NAME, TEMP_FIELD);
        setpointBuffer := m_FldClient.ReadIntField(VARIABLE_DRIVER_NAME, SETPOINT_BUFFER_FIELD);
        
        If (action = "UPPER_INC")
            m_Logger.LogMsg2("[HVAC Macro] Incrementing upper setpoint. Upper [%(1)]  Actual [%(2)]", upperSetpoint + 1, actualSetpoint + 1);

            m_FldClient.WriteIntField(VARIABLE_DRIVER_NAME, UPPER_SETPOINT_FIELD, upperSetpoint + 1);
            If (currentMode = COOLING)
                m_FldClient.WriteIntField(HVAC_DRIVER_NAME, SETPOINT_FIELD, actualSetpoint + 1);
            EndIf;
        ElseIf (action = "UPPER_DEC")
            m_Logger.LogMsg2("[HVAC Macro] Decrementing upper setpoint. Upper [%(1)]  Actual [%(2)]", upperSetpoint - 1, actualSetpoint - 1);
            m_FldClient.WriteIntField(VARIABLE_DRIVER_NAME, UPPER_SETPOINT_FIELD, upperSetpoint - 1);
            If (currentMode = COOLING)
                m_FldClient.WriteIntField(HVAC_DRIVER_NAME, SETPOINT_FIELD, actualSetpoint - 1);
            EndIf;
        ElseIf (action = "LOWER_INC")
            m_Logger.LogMsg2("[HVAC Macro] Incrementing lower setpoint. Upper [%(1)]  Actual [%(2)]", lowerSetpoint + 1, actualSetpoint + 1);

            m_FldClient.WriteIntField(VARIABLE_DRIVER_NAME, LOWER_SETPOINT_FIELD, lowerSetpoint + 1);
            If (currentMode = HEATING)
                m_FldClient.WriteIntField(HVAC_DRIVER_NAME, SETPOINT_FIELD, actualSetpoint + 1);
            EndIf;
        ElseIf (action = "LOWER_DEC")
            m_Logger.LogMsg2("[HVAC Macro] Decrementing lower setpoint. Upper [%(1)]  Actual [%(2)]", lowerSetpoint - 1, actualSetpoint - 1);
            m_FldClient.WriteIntField(VARIABLE_DRIVER_NAME, LOWER_SETPOINT_FIELD, lowerSetpoint - 1);
            If (currentMode = HEATING)
                m_FldClient.WriteIntField(HVAC_DRIVER_NAME, SETPOINT_FIELD, actualSetpoint - 1);
            EndIf;    
        ElseIf (action = "START")
            // We've just been enabled...so check the current conditions and set appropriate
            // values for setpoint and heat/cool mode.
            // First, figure out what mode we SHOULD be in.
            distanceToUpper := (upperSetpoint - actualTemp);
            distanceToLower := (actualTemp - lowerSetpoint);            
            
            If (distanceToUpper < distanceToLower)
                // Closest to the upper setpoint, so set to COOL
                If (currentMode = HEATING)
                    m_FldClient.WriteStringField(HVAC_DRIVER_NAME, MODE_FIELD, OFF);
                EndIf;
                newSetpoint := upperSetpoint + setpointBuffer;
                m_FldClient.WriteIntField(HVAC_DRIVER_NAME, SETPOINT_FIELD, newSetpoint);
                If (m_FldClient.ReadStringField(HVAC_DRIVER_NAME, MODE_FIELD) = OFF)
                    m_FldClient.WriteStringField(HVAC_DRIVER_NAME, MODE_FIELD, COOLING);
                EndIf;
                m_Logger.LogMsg("[HVAC Macro] Control enabled, setting mode to COOL");                    
            Else            
                // Closest to the lower setpoint, so set to HEAT
                If (currentMode = COOLING)
                    m_FldClient.WriteStringField(HVAC_DRIVER_NAME, MODE_FIELD, OFF);
                EndIf;
                newSetpoint := (lowerSetpoint - setpointBuffer) - 1;
                m_FldClient.WriteIntField(HVAC_DRIVER_NAME, SETPOINT_FIELD, newSetpoint);
                If (m_FldClient.ReadStringField(HVAC_DRIVER_NAME, MODE_FIELD) = OFF)
                    m_FldClient.WriteStringField(HVAC_DRIVER_NAME, MODE_FIELD, HEATING);
                EndIf;
                m_Logger.LogMsg("[HVAC Macro] Control enabled, setting mode to HEAT");  
            
            EndIf;
          
        ElseIf (action = "TEMP")
            // The temp has changed, so check and see if we need to change the mode from heat to cool
            // or vice versa.
            If (((upperSetpoint - actualTemp) <= setpointBuffer) && (currentMode = HEATING))
                // We're within the buffer of the upper setpoint, but we're set to heat,
                // so switch to cooling.
                // First set it to OFF so we can change the setpoint
                // without causing the system to come on.
                m_FldClient.WriteStringField(HVAC_DRIVER_NAME, MODE_FIELD, OFF);
                newSetpoint := upperSetpoint + setpointBuffer;
                m_FldClient.WriteIntField(HVAC_DRIVER_NAME, SETPOINT_FIELD, newSetpoint);
                m_FldClient.WriteStringField(HVAC_DRIVER_NAME, MODE_FIELD, COOLING);
                m_Logger.LogMsg("[HVAC Macro] Switching from HEAT to COOL Mode");
            ElseIf (((actualTemp - lowerSetpoint) <= setpointBuffer) && (currentMode = COOLING))
                // We're within the buffer of the lower setpoint, but we're set to cool,
                // so switch to heating.
                // First set it to OFF so we can change the setpoint
                // without causing the system to come on.
                m_FldClient.WriteStringField(HVAC_DRIVER_NAME, MODE_FIELD, OFF);
                newSetpoint := (lowerSetpoint - setpointBuffer) - 1;
                m_FldClient.WriteIntField(HVAC_DRIVER_NAME, SETPOINT_FIELD, newSetpoint);
                m_FldClient.WriteStringField(HVAC_DRIVER_NAME, MODE_FIELD, HEATING);
                m_Logger.LogMsg("[HVAC Macro] Switching from COOL to HEAT Mode");
            EndIf;
Reply
#2
Paste this directly after the stuff above.

Code:
Else
            // Called only because the HVAC has come on or off.
            If (currentMode = COOLING)
                // Ok, the "cool" is on.  So, we have to compare the setpoints and the desired
                // setpoints to see if they need adjusting.
                m_Logger.LogMsg2("[HVAC Macro] Cooling on or off. Actual setpoint [%(1)]  Temp [%(2)]", actualSetpoint, actualTemp);
                
                // We're here if the HVAC just came on or went off.  If it came on, then reset the setpoint
                // to the lower value.  
                //If ((upperSetpoint + setpointBuffer) <= actualTemp)
                If (m_FldClient.ReadBoolField(HVAC_DRIVER_NAME, COOL_ON_FIELD))
                    // If so, then reset the actual setpoint to be the upper setpoint
                    // minus the setpoint buffer amount
                    newSetpoint := (upperSetpoint - setpointBuffer) - 1;
                    
                    If (actualSetpoint != newSetpoint)
                        m_Logger.LogMsg1("[HVAC Macro] Upper limit reached.  Resetting setpoint to [%(1)].", newSetpoint);
                        m_FldClient.WriteIntField(HVAC_DRIVER_NAME, SETPOINT_FIELD, newSetpoint);
                    EndIf;        
                Else    
                // Otherwise, the HVAC just went off, so reset the setpoint higher.
                //If ((upperSetpoint - actualTemp) >= setpointBuffer)
                    // If so, then reset the actual setpoint to be the upper setpoint
                    // plus the setpoint buffer amount
                    newSetpoint := upperSetpoint + (setpointBuffer - 1);
                    If (actualSetpoint != newSetpoint)
                        m_Logger.LogMsg1("[HVAC Macro] Lower limit reached.  Resetting setpoint to [%(1)].", newSetpoint);
                        m_FldClient.WriteIntField(HVAC_DRIVER_NAME, SETPOINT_FIELD, newSetpoint);
                    EndIf;
                EndIf;
            ElseIf (currentMode = HEATING)
                // Ok, the "heat" is on.  So, we have to compare the setpoints and the desired
                // setpoints to see if they need adjusting.
                m_Logger.LogMsg2("[HVAC Macro] Heating on or off. Actual setpoint [%(1)]  Temp [%(2)]", actualSetpoint, actualTemp);
                
                // We're here if the HVAC just came on or went off.  
                If (m_FldClient.ReadBoolField(HVAC_DRIVER_NAME, HEAT_ON_FIELD))
                    // Heat is ON, so reset the actual setpoint to be the upper setpoint
                    // plus the setpoint buffer amount
                    newSetpoint := (lowerSetpoint + setpointBuffer);
                    
                    If (actualSetpoint != newSetpoint)
                        m_Logger.LogMsg1("[HVAC Macro] Resetting setpoint to [%(1)].", newSetpoint);
                        m_FldClient.WriteIntField(HVAC_DRIVER_NAME, SETPOINT_FIELD, newSetpoint);
                    EndIf;        
                Else    
                    // Otherwise, the HVAC just went off, so reset the setpoint lower.
                    newSetpoint := lowerSetpoint - setpointBuffer;
                    If (actualSetpoint != newSetpoint)
                        m_Logger.LogMsg1("[HVAC Macro] Resetting setpoint to [%(1)].", newSetpoint);
                        m_FldClient.WriteIntField(HVAC_DRIVER_NAME, SETPOINT_FIELD, newSetpoint);
                    EndIf;
                EndIf;
            
            
            EndIf;
        EndIf;
        Return 0;
    EndMethod;

EndMethods;
Reply


Possibly Related Threads...
Thread Author Replies Views Last Post
  Looking for 48x48 png HVAC/thermostat/AC icon SamVimes2 3 7,755 12-20-2009, 10:56 PM
Last Post: Sendero

Forum Jump:


Users browsing this thread: 1 Guest(s)