Solar Pool Heating Control

First off, I'm a rule machine novice, still learning how it works. So, I think I've bitten off a little more than I can chew with this project, but I'm pretty sure that if I can get some help and advice, my understanding of Rule Machine will be tremendously increased in the process.

The Goal: Use Rule Machine to heat my inground pool as much as possible using my Solar Pool Heating system.

The Problem: I can get a decent amount of heat from the solar system. However, it can cool the pool just as effectively as it can heat it. Meaning, when the system is under manual control and I forget that it is running, I can heat the pool up a few degrees during the day, and then cool it right back down again by leaving it running overnight! When it is sunny out, it absorbs solar radiation and heats the water, but when the sun isn't out, and the ambient temperature is lower than the pool water it just radiates heat and cools the water!

Compared to manual control, a very simple program to turn the solar system on in the afternoon and then off at night should be a step forward.

The Twist to Make it Interesting: However, here in Seattle, I'm really trying to get the most out of this system in the spring and fall when it might be sunny, but with an outdoor ambient temperature that is often lower than the pool temp setpoint (80 degrees). In this conditions it is little more complicated. If there is minimal solar radiation to absorbed, running the system can cause cooling. So, to really get good use of this system I need to understand and figure out how to control the system to heat the pool during parts of the year when the ambient temperature is below the pool set point of 80 degrees. Iā€™ve found that on REALLY sunny days, even down to 65 degrees, I can get heat.

The Hardware Setup:
-Zooz MultiRelays are setup to control the variable speed pool pump (lo, med, high speeds) and to operate all the pool valves.
-A Qubino Thermostat and a Qubino Multirelay are connected to temperature probes in the pool plumbing. Probe 1 Measures the water coming directly from the pool - I call this one Pool Temp. Probe 2 measures the water coming down from the solar heating system - I call this one Solar Temp.
-Ecowitt PWS measures outdoor temperature, illuminance, UV index, wind, precipitation, etc and reports it all to Hubitat.

My Current Rule Machine Rules:
So far, Iā€™ve made two rules, one to turn the system on, and one to turn the system off.

Turn On:
My thinking is that there must be an absolute minimum ambient temperature that is needed for heating to work. I donā€™t know yet what that is, but I presume that over time I will empirically figure it out. For now, I chose 55 degrees, which I suspect is quite a bit too low. Then, and I think more importantly, is illuminance. If itā€™s not sunny, no heat. Iā€™ve seen this sensor report as high as 100,000. I chose 40,000 as a starting point.

So, Iā€™ve set
Illuminance > 40,000
AND
Temperature > 55 degrees as predicate conditions.

Then, for the trigger event, Iā€™ve actually chosen a pool temp set point of 85 degrees and tell the system to trigger when the Pool Temp is < 85.

If that trigger is met, it opens the solar pool heating valve, waits 30 seconds and then turns on the pool pump.

(Or at least thatā€™s what I think this rule is doing)
Screen Shot 2021-09-14 at 2.42.15 PM

Turn Off
Now, do I even need a separate rule to turn off? This is one of the things that I donā€™t understand well about rule machine. If the trigger event of the Turn On rule is met, would the Turn On rule turn the valve off and turn the pump off?

Anyway, for the Turn off Rule, Iā€™ve set a predicate condition of the Solar Pool Heating being on. If its not on, why bother, right?
Then, if the solar heat is on, it is set to turn the system off if ANY of these conditions are met:
-its too cold, PWS temp < 54
-Pool is warm enough, Pool Temp > 85.5
-No sun, Illuminance < 38,000

If those conditions are met, it turns off the solar valve and turns off the pool pump. I have it turn off Pump Med and Pump Hi because I have another rule that turns the pump up to high if there is a large delta between Pool Temp and Solar Temp.

Screen Shot 2021-09-14 at 2.42.45 PM

====
Currently, this seems to work, but I have found some issues:
-there are times that I expect the system to be on and its not. It is as if the on rule isnā€™t firing all the times that it should.
-Do I actually need two rules?
-Clouds cause trouble. A cloud passes by, illuminance plummets, and the system shuts off. So, I can have these partly cloudy days where I can get heat, but the system spends all day short cycling on and off. Is there way to stop that? Iā€™ve thought of trying UV index instead of illuminance since clouds donā€™t filter UV light nearly as well as visible light.
-Iā€™d also love to be able to use the delta (as suggested by another user here) between Pool Temp and Pool Solar as a shut off condition. But, again, short cycling is an issue. It needs to let the system run for at least a few minutes before checking because right when the system starts it usually reads low until water starts coming in from the solar.

Anyway, I think Iā€™ve got a good setup here with sensors, motor control, pump control. Now its just figuring out how to best program rule machine

I think the best first step is to strip this system down a bit and get rid of all the "extra" data that's just complicating the issue.

Let's start with the rule to turn the system off. We'll start simple and then add some layers from there. Whoever told you to calculate the temp delta is spot on. As long as the temperature out of the heater is higher than what's going in, you should keep running the pump. I would start with a "simple conditional" to run a repeating action. If you're familiar with programming terminology, this essentially is a "while" loop. It will repeat a set of actions indefinately, as long as the condition is true. SO, it will look something like this...

IF (Solar Pool Heating ON) Repeat every 0:10:00
   Set variable-delta to (Solar Temp - Pool Temp)
   IF variable-delta < 0 AND variable-boolean is TRUE THEN
      Off:  Solar Pool Heating 
      Set variable-boolean to FALSE
      Exit Rule
   END-IF
   IF (variable-delta < 0) THEN
      Set variable-boolean to TRUE
   ELSE  Set variable-boolean to FALSE
   END-IF
END-REP

Line 1: Initiates the while loop. As long as the pool heating system is running, the rule will execute every 10 minutes.
Line 2: Calculating the temp difference tells you if the system is making heat or not.
Lines 3-7: If the system is heating, the conditions evaluates as FALSE and the the actions are not run. The first time the delta goes negative (losing heat), it will still evaluate as FALSE because the boolean should start out as false. If this is the second consecutive time that the rule has run and the delta is less than 0, the boolean will be TRUE, so the conditions will evaluate as TRUE and the actions will run. It will turn off the solar heating, reset the boolean, and exit the rule.
Lines 8-9: Sets the value of a boolean variable so that the heater must be losing heat for two consecutive iterations before the heating system is turned off.
Line 10: Resets the boolean if the heater starts making heat again.
Line 11: Ends the IF statement.
Line 12: Ends the repeating actions section.

For now, I would trigger this rule on whatever "switch" indicates that the pool heater is running. If you need to wait for a couple minutes after it starts to let the "cold" water in the heater cycle through, just put a "Wait for event: --> elapsed time: 0:05:00" in as the very first line. Feel free to adjust all the time delays based on your experience with the system and how quickly things react. Later, once you've got the ON rule working, you can include an action that will initiate the OFF rule.

Start with this, and use LOW speed. Once you get this rule working well, it can be made more complicated to run the pump on higher speeds. This will be based on the value of "variable-delta" increasing to some threshold.

Turning the pump ON is going to be more complicated. Perhaps the easiest (but least elegant) way would be to start the pump periodically and see if it makes heat or not.
A more elegant method will be to do exactly as you are proposing, but I expect that the illuminance and ambient temperature criteria are inversely related and there will need to be some math involved to make it work as you expect. For example, on a 55 degree day you may need an illuminance value of 75,000 to make heat, while on a 90 degree day you may be able to get by with 10,000. That will be a bit harder to figure out. You'll need to experimentally find the values for temperature and illuminance on the bottom end of the scale that still make heat. On the top end it might be simpler because, in theory, any day where the temperature is over 85 should "make heat" even with very low illuminance. Once you get the two extremes nailed down, you can establish a linear relationship between them. Then is should be a "simple" matter of comparing the current temperature and illuminance to the threshold values and starting the system if you are over the threshold. Rule machine can handle all of this, but it looks ugly on the backend.

1 Like

And after I wrote all of that, I realized I didn't even answer your questions...

  1. Logging is your friend when it comes to finding out while a rule is not triggering or running as expected. Lots of things can cause issues on this end. I'm still using RM4, so I'm not really familiar with predicate conditions and how that might impact triggers.

  2. Two rules are better than one in this case. It helps keep the logic in the rule simple and avoids alot of the IF condition1 Turn ON, ELSE-IF condition2 Turn OFF that gets messy really quickly.

  3. Once the system is turned on, the only thing that matters is the temperature delta. Using my rule example will help by requiring two consecutive iterations of the delta being less than zero to shut the system off and may help avoid transient conditions like clouds. Also, 0 may be too low...maybe you want to turn the system off if the delta is less than 5 degrees, for example.

  4. Using the delta is the best indicator of system performance. Adding a simple delay at startup should prevent false OFF commands.

This is awesome! I'm going to get this implemented ASAP. I really like this, an if/then loop that has a built in switch of sorts to allow the system to capture more data points before it actually decides to shut down. I love it.

Also, your explanation of it is an order of magnitude easier to follow than the manual for RM is. I've tried reading that, but am always left scratching my head. It is NOT written for those of us that only have a PhD in Molecular Biology.

I hope it works! I'm still a novice with RM myself.

You could modify this in the future using a number variable instead of a boolean. You would simply add or subtract to the number variable each iteration and only turn the heater off when it reaches a predetermined value of 10, for example. This would allow you to shorten the repeating interval if you needed. Although you would need to add more logic to keep the value of your variable from going less than 0.

RM is incredibly powerful but relies on users having some familiarity with the terms and basic functions used in logic systems (ie. programming knowledge). Once you've grasped the concept of IF, ELSE-IF, ELSE, END-IF, things get easier.

That said, the simpler you can make your rules, the better. They will run faster and more predictably. Not every rule needs predicate conditions or lengthy IF statements. Most experienced users will tend to provide guidance in this direction. The HE crew have also put together the Basic Rule app for just this purpose.

I tried making this rule in RM 5 and quickly realized I don't have the foggiest idea how to get started, but following the logic of what you sketched out, this is what I came up with:

I feel like I ALMOST have it.

Two issues:

  1. I'm not sure that the repeat is in the correct place, or that I did that correctly
  2. It looks like the private boolean is starting off as true instead of false. does that matter? I think it will just fix itself once it starts running?

Let me see if I can make some virtual devices and create this rule. Might take some time so hopefully get to it tomorrow...

Ok...I couldn't wait...

I updated the structure a bit based on your screenshot, trying to keep mine as consistent with yours as possible.

First, because you are using private boolean instead of a hub or local variable, I had to set it as false right off the get-go and could then remove that action from inside the repeating portion. Private boolean always starts as true and no way to change it outside of the rule actions. Perhaps easier to use a local variable, but either is acceptable.

Second, for a WHILE loop, the repeating actions needs to use a simple conditional. Note that mine does not have a THEN in it. When I tried to end the rule with an END-REP, the UI didn't give me the option. I had to choose "Insert Action Before" and select the action immediately after the line with the IF ... Repeat Every... then choose conditional action then END-REP. Then I could cut it and paste it at the end of the rule.

The rest of the rule should be as noted previously.

and poof, a miracle occurs:
image

I'm not sure I can reproduce this, but it looks like I have it!

Maybe not, that rule never seemed to shut it off. So, I'm trying these modifications:
image

I tested my rule and it seemed to work fine. If your screenshot was taken around the time you were testing, it won't shut the heater off because the temp of the solar heater is more than 5 deg. hotter than the pool. That makes the IF condition false and the action to turn the heater off is skipped. If you haven't deleted this rule, I would run it with all logging options turned on and see what is causing the problem. I shortened my repeat interval to 10 seconds to help speed things up when I tested mine.

I should mention that even after the Solar Pool Heater switch was turned off (and the rule was exited) it executed one more iteration. However, the only action run was the first line. After that all actions were skipped because the switch (Solar Pool Heating) was off and the simple condition was false.

If that rule doesn't work as intended either, I would create a boolean-type hub variable and use that instead of the private boolean. For some reason it seems that the private boolean "resets" itself to true when I believe it should have been left as false.

Still not seeing it turn off

This is how I have it currently setup:

I'm getting this in my logs:
java.lang.NullPointerException: null on line 6905 (method periodicHandler)

So, it seems to me that the trigger event is not working?

I tried to delete the trigger, and hubitat spat out another error. so, I thought, maybe all my hacking and revising of this rule just screwed up its innards (serious technospeak). So, I recreated the rule from scratch, installed it, and now, it SEEMS to be working!

well, it worked once.


Had to make one more change. I added in "Set Check2x to false" in line 4 to reset to boolean to false after the rule has triggered the solar to turn off. Otherwise, it would remain true and the next time the rule ran it would immediately shut the system back down because the return water hadn't had a chance to become warm enough to not trigger shut down.

Soooooo, now what I'm thinking is that I would like my turn on rule to be aware of the shut down rule.

Meaning, if the Temp Delta rule has recently shut off the solar heating because the return temp wasn't high enough to be worth running it, i'd like the system to not try turning the system back on for at least 30-60 minutes or something.

It looks like this can be done by using this same "Check2x" Variable in my turn on rule. But, I also think that I'll need to remove the "Set Check2x to false" in line 4 and instead have my turn on rule make that change.

I'm going to rename that variable to something that will be more meaningful and take a stab at this!

This is FUN!

Thanks for bearing with me as a I work through this problem!

Sorry it's not working for you. There's nothing out of place that I can see. Maybe someone with a bit more experience will see something.