Beer IoT: Estimating beer cooling time

In my last beer IoT post we measured out cooling rate of beer. In this post we try to estimate how long it takes for beer to start freezing. It’s actually simple calculation and we add it to our beer IoT background service before we focus on data reporting and persisting questions.

NB! In this post we are using code from beer IoT posts Measuring temperature with Windows 10 IoT Core and Raspberry Pi and Measuring cooling rate. Here we are making changes to already existing code.

Update. Source code of my TemperatureStation solution is available at Github. The solution contains IoT background service and web application you can use right away. Readings are reported to MSSQL or Azure IoT Hub. Documentation is available at TemperatureStation wiki. Feel free to try out the solution.

In last post we calculated beer cooling rate that is constant through freezing process. We used the following equation with two temperature measurements:

$$k=\frac{ln\left(\frac{T_0-T_a}{T(t)-T_a}\right)}{t}$$

Now let’s sovle this equation for t:

$$t=\frac{ln\left(\frac{T_0-T_a}{T(t)-T_a}\right)}{k}$$

We expect beer surface to start freezing when temperature inside bucket is 1°C. To calculate the estimate we have to do one little dirty trick. We take current beer temperature as initial one (T0) and constant temperature 1°C as T(t). Ambient temperature Ta will stay constant.

Now let’s add this little wisdom to our background application:

public static class Calc
{
    // Other math stuff

    public static double GetCoolingEstimate(double T0, double Ta, double Tt, double k)
    {
        var d1 = T0 - Ta;
        var d2 = Tt - Ta;

        return Math.Log(d1 / d2) / k;
    }
}

We also have to modify temperature reading callback to show estimate. Here we have to consider the special case when cooling rate is not measured yet. In this case our estimate will be -1.

private void TemperatureCallback(object state)
{
    var now = DateTime.Now;
    var temps = _tempClient.Read();

    if (!_kMeasurementDone)
        MeasureCoolingRate(temps);

    var beer = temps.First(m => m.DeviceId == BeerSensorId);
    var ambient = temps.First(m => m.DeviceId == AmbientSensorId);
    var estimate = -1d;

    if (_kMeasurementDone)
        estimate = Calc.GetCoolingEstimate(beer.Value, _ta, 1, _k);

    foreach (var temp in temps)
    {
        Debug.WriteLine(now + " " + temp.DeviceId + ": " + temp.Value);
    }

    Debug.WriteLine(string.Format("Estimate: " + TimeStamp.FromMinutes(estimate)));
}

If we run the code and put sensor to cooling beer we get something like this as output to debug window:

2/3/2016 8:39:06 AM 28-FF-6D-5E-53-15-01-AA: 8
2/3/2016 8:39:06 AM 28-FF-7D-97-01-15-02-AA: 22.3125
Estimate: 16:20:00
The thread 0x404 has exited with code 0 (0x0).
2/3/2016 8:39:11 AM 28-FF-6D-5E-53-15-01-AA: 8
2/3/2016 8:39:11 AM 28-FF-7D-97-01-15-02-AA: 22.25
Estimate: 16:20:00
2/3/2016 8:39:16 AM 28-FF-6D-5E-53-15-01-AA: 8
2/3/2016 8:39:16 AM 28-FF-7D-97-01-15-02-AA: 22.3125
Estimate: 16:20:00

Now we have temperature measuring solution that measures ambient temperature and the temperature of beer.

Wrapping up

After some playing with practical mathematics it was easy to write the code to find cooling rate of beer and estimate how long it takes for beer to start freezing. Now we have simple solution that is able to measure temperatures and make some important calculations. But we have one problem – this data lives only in our background service and we can see it in output window of Visual Studio. Next blog posts in this series focus on how to store measurements.

Gunnar Peipman

Gunnar Peipman is ASP.NET, Azure and SharePoint fan, Estonian Microsoft user group leader, blogger, conference speaker, teacher, and tech maniac. Since 2008 he is Microsoft MVP specialized on ASP.NET.