bryandowen
Posts: 6
Joined: Mon Feb 01, 2016 1:14 am

Temperature trending with DS18b20

Mon Feb 19, 2018 6:03 am

Fair warning: This is a long-ish one with a bit of background, and is more of a "help me think about this idea" question, and less of a "has anybody run into this very specific implementation issue" question.

I'm evolving a hot tub controller project, which consists of:
  • An 80s-era Cal Spas hot tub (pretty easy to understand and work on, all mechanical switches, etc.)
  • Raspberry Pi 2
  • WiFi dongle to attach to my home WiFi network
  • DS18b20 waterproof thermometer (up over the edge of the hot tub, hanging in the water)
  • An 8-channel 5V relay module, spliced in parallel (considering switching to series) into the "top side" control dials (Jets, Heater, Lights, Cold air blower, Hot air blower)
  • A couple of ThingSpeak data logging channels - one for (upward) data logging, one for (downward) commands
The controller app is written in Python, and I use the Linux virtual device method to read the DS18b20 temperature.

Algorithm-wise: I read the temperature every 60-ish seconds, make sure the temp hasn't exceeded my safety threshold (104 degrees), log the temperature to ThingSpeak, then make a decision based on (a) whether the hot tub is heating or cooling, and (b) the rate of heating or cooling.

If the hot tub is cooling (heater not on), I look at the rate of cooling:
  • If cooling > 6 degrees per hour, alert and go into "safe mode" (no longer attempt to automatically regulate temperature) -- see heating < 1 degree per hour (below) for explanation of why
  • If cooling 2-6 degrees per hour, alert that the cover is likely open (cooling quicker than normal)
  • If cooling between 0 and 2 degrees per hour, this is normal
  • If actually warming, throw an alert and go into "safe mode" (because I don't know what's going on) <-- overly-safe? considering backing away from this
If the hot tub is heating (heater on), I look at the rate of heating:
  • If heating > 9 degrees per hour, alert and go into "safe mode" (because I don't know what's going on; my hot tub doesn't heat this fast under normal conditions)
  • f heating 5-8 degrees per hour, this is normal (6.4 is average)
  • If heating 1-5 degrees per hour, alert that the cover is likely open (heating slower than normal)
  • If heating < 1 degree per hour, alert and go into "safe mode" -- Two misuse cases:
    1. There's a mechanical over-temp switch that pops and causes circulation pump to run, but shuts off the heater element; this over-temp switch is erratic and I don't want to run the circulation pump forever if I'm not heating.
    2. If the DS18b20 is pulled out of the water, we have no idea whether we're properly heating. The apparent temperature drops rapidly in this case. My wife may or may not have accidentally done exactly this the first day I started heating under RPi automation.
After those checks, if I'm not in "safe mode", I look at the current temperature and measure it against my "target temperature" (which I set through a ThingSpeak "command" channel). I give 0.5 degrees slop plus-or-minus. In other words, if the target is 102.0, my regulation window is 101.5 to 102.5 degrees. The algorithm (in Python) is quite simple:

Code: Select all

    if currentTemp < targetTemp - tempSlop: # 102.0 - 0.5 = 101.5
        heaterOn()
    elif currentTemp > targetTemp + tempSlop: # 102.0 + 0.5 = 102.5
        heaterOff()

This is all happy goodness. I *love* this project, and it tickles me whenever I hear it kick on and off.

The wrinkles:

Once in a while it'll kick into "safe mode" when nothing's really gone wrong. This is due to the sensitivity of the readings coming out of the DS18b20, and my ability to "smooth" them. Its apparent resolution is something like 0.11 degrees (Fahrenheit). It always jumps in quanta of that value. Also, while the temperature is gradually declining during the cooling cycle, it will sometimes toggle between two adjacent values before settling on the lower one, e.g.:

Code: Select all

(Cooling cycle)
100.5116
100.5116
100.5116
100.5116
100.4
100.5116
100.5116
100.5116
100.5116
100.4
100.4
100.5116
100.4
100.4
100.4
100.4
100.4
[...]

I also have aberrations during the cooling cycle. I was in the hot tub once when it heated to 102.5, turned off, and (due to us moving around in the hot tub?) appeared to "heat" very briefly while in cooling mode, and my program popped into safe mode. We started getting cold when we figured it out.

Lastly: When the tub goes into cooling mode, one of two (or both) things happen:
  1. The temperature in the water stratifies, so warmer water is at the top and cooler water is at the bottom.
  2. The water in the plumbing (out to the circulation pump, through the heater), which is outside the tub itself, cools more rapidly than the water inside the tub.
In either case, when the temperature reaches the low end of the window and the circulation pump kicks on, the temperature at the DS18b20 *dips* by about 0.5 degrees, and takes roughly 5 minutes to recover to the initial temperature. E.g.:

Code: Select all

101.5 <-- pump kicks on
101.2
101.0 <-- hits bottom, now on the upswing
101.3
101.5 <-- now recovered
101.6 ...

Because of this, I don't make any of the above temperature-based decisions within 5 minutes of the heater kicking on. I wait 5 readings, purge the temperature history, and start from scratch at minute 6.

So, all the background covered, to my solicitation for advice:

What is the best way to "smooth" the stream of outputs from the DS18b20 (which are, again, roughly 1 minute apart) and sensibly figure out what the actual heating/cooling slope looks like?

I've tried some naive approaches like comparing the first and last readings in a 5-reading window (sometimes shows the opposite of what I want), to average the first couple and the last couple, etc. These all have their disadvantages, are are really susceptible to the toggling back and forth of super-sensitive readings.

This strikes me as more of a statistics question, and less of a DS18b20 question. I'm hoping one or two of you are wizzes at this kind of thing. :-)

Thanks in advance!

-Bryan

davef
Posts: 36
Joined: Wed Feb 20, 2013 8:39 pm

Re: Temperature trending with DS18b20

Mon Feb 19, 2018 9:43 am

Don't know about the best way, but would "moving average" help? Due to the complexity of the system maybe you need several sensors, ie one in the circulation system.

You might find some hits on "hot water tank stratification".

morticiaskeeper
Posts: 69
Joined: Mon Aug 27, 2012 6:05 pm

Re: Temperature trending with DS18b20

Mon Feb 19, 2018 1:21 pm

I would be tempted to record all temperatures in a MySQL database. This would give an opportunity to experiment with real time data, using queries such as averaging over differing times.

If you recorded timestamp, temperature, any heater/pump switching, graphing the output would give you a good visual understanding of what is going on.

I am recording room temperatures in my house, with a view to analysing the data before deciding on a smart thermostat. Seven DS18B20 sensors fitted to remote Pi Zero W in each room, all sending data to a central Pi Zero W LAMP server. All analysis is done using PHP web pages and Google charts.

I'm not a web coder, but have found enough examples on the internet to allow me to get what I need.

User avatar
bensimmo
Posts: 3340
Joined: Sun Dec 28, 2014 3:02 pm
Location: East Yorkshire

Re: Temperature trending with DS18b20

Mon Feb 19, 2018 4:50 pm

As much as it may pain you, moving to C from F will give you round numbers as that is what it is all based from.

Also build in an error checking on the DS18 reading (if not already) for a sanity check. They can sometime give false readings and so trip your system.

I would look at logging and keeping the logs so you can visualise it and see later what errors may have cropped up.

Have a look at PID control too, while what you are doing is relatively slow changes, PID (an acronym for the maths used) is pretty much what you may find does the magic for you.

I have to read over what your specs are again.

Consider fixing the DS18 in place and putting some on the input and output pipes. To to see if you can use that data too.

bryandowen
Posts: 6
Joined: Mon Feb 01, 2016 1:14 am

Re: Temperature trending with DS18b20

Sat Feb 24, 2018 6:31 am

@davef: I am doing a moving average (of sorts anyway) - I record temperatures into a FIFO queue with a max length (of 16 readings right now). As soon as a 17th reading is pushed, the 1st one is popped. I then take averages of the first two and the last two readings and compare them to arrive at the rate of temperature change. I've been playing with the queue length -- a longer queue gives me more stable moving average, but is less responsive to change in temperature. This mostly works, but what fails me is when the queue is very short in length (i.e., when I've only built up 4 or 5 readings).

@morticiaskeeper: I am also recording all of these readings (and more) to ThingSpeak once per minute:
- Current temperature (as read by DS18b20)
- Heater state (on/off)
- Calculated rate of change (though I could reconstitute this myself if I wanted)
- Timestamp (automatically recorded by ThingSpeak)

So I do have the data to replay, which has been helpful in troubleshooting why I'm seeing the behavior I am. I'm just powerless to correct it at the moment. :-)

@bensimmo: PID is *fascinating* reading. Thank you! I'd never heard of this before, and I enjoyed learning about it. In this case, I have a single on/off heater control, so really the Proportionality and Integration are non-applicable in my case; and I account for the Derivative factor indirectly, in a really Flinstone way, by applying a 0.5 degree over/under window. (Intentional over/under-shooting because I don't want to flip the heater off and on every 5 seconds to maintain a tight temperature window and burn out my motor and relays.)

BUT... I really appreciate the mathematical rigor involved in PID, and will refactor my algorithm so that it's calculating an error and driving that error to zero (+/- the window factor). This is much cleaner and reads more like a control loop than what I'm doing now!

---
What I'm (still) struggling with the most is the sensor output smoothing issue. I'm thinking the best I might do is to take readings less frequently. The temperature reading may bob up and down during transitions between temperature "quanta", but over less-frequent readings, they're much more likely to move clearly up or down. (In fact, it just now occurs to me that I have this problem only when cooling, since the cooling happens so slowly. When heating, the reading changes appreciably, and at worst I'll see the same reading twice [but not a bobbing up and down].)

Thanks for your thoughts y'all! (And if any math whiz finds a way to compensate for the sketchy sensor output, please share!)

bryandowen
Posts: 6
Joined: Mon Feb 01, 2016 1:14 am

Re: Temperature trending with DS18b20

Sat Feb 24, 2018 6:35 am

Also @bensimmo I'll switch to Celsius and see what happens. My suspicion is that the temperature will still bob back and forth, however. The library I'm using to read temp converts the binary response from the DS18b20 to Celsius, which I'm then converting to Fahrenheit. But the Fahrenheit bobbing up and down *must* be a result of the Celsius bobbing up and down in the first place. (I'm assuming it's not likely an artifact of the C => F conversion process.)

Thanks again!

User avatar
bensimmo
Posts: 3340
Joined: Sun Dec 28, 2014 3:02 pm
Location: East Yorkshire

Re: Temperature trending with DS18b20

Sat Feb 24, 2018 10:57 am

Using C over F was purely for the maths as the sensor itself "reads"* in celsius and hence keeping everything simple without all the extra digits you create in an F. Leave that for the display.

So for your "slop" 0.5C aligns with the actual reading better than 0.5F.
Though what is you device resolving to, many only report in 0.5C steps even at 12bit resolution

Ooh maybe go the next step and use a modulating heater ;-)

It does sound like you're quite enjoying it, maybe pop some link up to the graph and people better at this than me can see some interesting ways.


*It's a digital device and does lot of calculations and measurements in the module itself. It then reports the temperature, that is also calibrated in celsius, which is why your module gives it in celsius, that binary or hex represents the temperature in celsius.

Return to “Automation, sensing and robotics”