Calculate cook time based on meat probe temperature?

I agree, Meater probes are crazy expensive, but I wanted an option that didn’t involve wires so I didn’t find any other solutions. I never intended to make it work with HA, but the downside of these gadgets (at least the original meater) is range. Their website claims that they’re good for 30 feet. I have a kettle grill and most of the time when I’d put the lid on, signal would be lost (probes report to your phone via BLE thorugh an app). So that made me quite furious, I contacted them and they suggested me to buy an accessory to amplify the signal (around $50 pfff), so I went to google looking for a DIY option. I was surprised to find out there were some attempts at making it work and I tried a couple of them and found that hanging a Raspberry Pi Zero in a small box in direct line of sight of the grill would get me a perfect signal (I guess the Raspberry Pi Zero has a better antenna than my phone… or phones in general?).

So that ended up better than I anticipated :slight_smile:.

And I obviously take no offence, I know I payed a lot, but I wanted my setup to be as wireless as possible.

1 Like

BTW, yesterday’s test was a success, estimated time was incredibly stable and did not jump around as it did when I was running tests earlier by heating a pot with water (test setup was a little sketchy hehe) and the result was spot on.

Any ideas of what I could do with the other value I get which is the “ambient” temperature (ie. grill temperature)?

I’m not sure how big an effect the ambient temperature affects the end result. However, if we go back to the Heat diffusion equation (my first post), then conceptually the ambient temperature would affect how fast the meat heats-up. Of course this makes more sense if the grill is open and there is snow outside. However, if the cover is closed, then the outside temp effect is likely to be very small.

I use mine just as a smoker setpoint indication to know whether my 'low and slow" temperature is at the desired temp.

It probably wouldn’t be as useful when grilling when you are using direct high heat tho.

I have a bunch of automations set up around my smoker…

it announces the smoker temp over my Alexa devices every 15 minutes during the cook and it announces every time the smoker temp deviates from the setpoint by more than 10 degrees.

I also have an announcement at the 2 hour mark (and then every 30 minutes thereafter) to remind me to check the water pan level.

And then I have announcements to tell me the food is getting close to being done (within 20 degrees and then within 10 degrees of the “done” setpoint) and again when the food actually reaches the “done” setpoint.

I also plot both the food temp and smoker temp on a mini-graph card.

And now, thanks to your inspiration, I have a calculated time the food will be done! :laughing: Thanks!

But I still haven’t had a chance to actually try mine out in the real world yet… :disappointed: Hopefully soon tho.

1 Like

This is really getting fancy now … and you’re giving me nice ideas. I wonder, if one grills chicken/steak/shrimp at the same time … one can have Alexa dictate the time in/out and time to flip the meat as well.

1 Like

As long as you have enough probes, I only have 2 so I’m probably more limited than you guys.

Here’s something I did which is not so much a calculation, but a handy addition:

I set up an input_select with an assortment of meats and their corresponding usda safe to consume temperatures. That way I can set up my cook selecting for instance “Beef” and when I select the option in the input_select combo box that sets my target temperature to the corresponding value. I can also fine tune this number with a slider, but I rarely do that since we like our meat medium-rare.

So that way you only have to look up the temperatures once and set them up for poultry, fish, beef, lamb, etc.

You get the idea, the action that sets the temperature looks like this:

      - service: input_number.set_value
        data:
          entity_id: input_number.meater_target_temp
          value: >
            {% set cook = states('input_select.meater_cook') | lower %}
            {% if 'pork' in cook %}
              62
            {% elif 'chicken' in cook %}
              65
            {% elif 'salmon' in cook %}
              52
            {% elif 'lamb' in cook %}
              60
            {% else %}
              57
            {% endif %}

2 Likes

yeah, me too. one for the smoker temp (“ambient” as you called it) and one food probe.

My smoker temp probe is permanently connected into my smoker and then plugs into the controller when in use. and depending on what I’m cooking I may or may not use the food probe which I can unplug from the controller when not in use, too.

Other than power (from a battery pack or 5v wall wart) it’s wireless from there and connects directly to my wifi so I don’t need to worry about the range limitations of bluetooth.

I like it. Besides, isn’t that the point of all of this in the first place? :slightly_smiling_face:

The ironic thing is that it takes way more brain power upfront to figure out how to get it all setup in the first place. So, in a way, you get the best of both worlds - expending all of that brain power learning all of this and figuring out how to implement it to keep the intellect sharp and then sitting back and letting the machine do the rest resulting in doing what humans like to do best, nothing! :laughing:

1 Like

To me is more like the sense of accomplishment of extending some functionality or doing something myself that a product didn’t offer in the first place.

Ever since I discovered HA I’ve been perfecting my doing-elaborate-things-to-automate-mundane-tasks because let’s face it, you can only play so much with lights (I think it’s the first thing most of us do) before it gets boring, at least that’s what happened to me.

2 Likes

You could add Percent complete as a calculation also, so when you are asked how done is the steak, you can say about 60% done.
Accumulated Cook time / (Accumulated Cook time + Time Left)

1 Like

Hi, just come accross this and love the topic.

Did a final product come out of it in the end?

Sorry to resurrect an old thread but I just got this working today making updates to things that have changed (like needing to change variable.xyz to sensor.xyz and requiring float(default=0)). Anyone have some fancy math for maintaining a somewhat accurate time estimate when the rate gets close to 0 or even negative during the 'stall"?

I don’t know what you are using now but this should keep the estimated food done setting the same amount of time into the future:

  - alias: SM Set Time Smoker Food Done
    trigger:
      - platform: time_pattern
        minutes: "/5"
    condition:
      - condition: state
        entity_id: input_boolean.smoker_sensor_active
        state: 'on'
    action:
      - service: input_datetime.set_datetime
        entity_id: input_datetime.smoker_food_done
        data:
          timestamp: >
            {% if states('sensor.smoker_food_temp_rate') | float > 0.0 %}
              {{ (((states('input_number.smoker_food_setpoint') | float(0) - states('sensor.smoker_food_temperature') | float(0)) / states('sensor.smoker_food_temp_rate') | float(0)) * 60) + as_timestamp(now()) }}
            {% else %}
              {{ as_timestamp(states('input_datetime.smoker_food_done')) + 300 }} 
            {% endif %}

it should estimate the food done time based on:

  1. the rate of change
  2. the food temp setpoint
  3. the food temp actual

if the rate is 0 or less then it will just add 5 minutes to the curent estimated food done time. So if the estimate was an hour from now then every 5 minutes if the rate is not above 0 the the estimated time will still be an hour from now (and now will also be 5 minutes into the future by then).

I’m in the process of testing this now, but I had Meta AI look at the code that I put together pieced from the forum posts here and asked if it had any suggestions to improve it. I was blown away as it worked first try just copy and pasting. It recommended using a heat transfer calculation, all it required was a second probe for the ambient temperature as well as an input for the thickest part of the meat. I’ve got ribs on the smoker this very moment. Note that in the calculations I’m using imperial measurements so adjust accordingly.

# Input for the estimated time food will be done
input_datetime:
  food_done:
    name: Estimated Time Food Will Be Done
    has_date: true
    has_time: true

# Input for the target temperature of the food
input_number:
  food_temp_done:
    name: Food Done Temp
    initial: 195
    min: 0
    max: 200
    step: 1

# Input for the thickness of the food (in inches)
input_number:
  food_thickness:
    name: Food Thickness (in)
    initial: 2
    min: 0.5
    max: 5
    step: 0.1

# Template sensor to calculate the food temperature rate. Don't -32  * 5/9 if measuring in C or *2.54 if measuring in CM
sensor:
  - platform: template
    sensors:
      food_temp_rate:
        friendly_name: Food Temp Rate
        value_template: >
          {% set temp_meat = (states('sensor.probe_1') | float - 32) * 5/9 %}
          {% set temp_amb = (states('sensor.probe_2') | float - 32) * 5/9 %}
# Convert food thickness from inches to centimeters
          {% set thickness = states('input_number.food_thickness') | float * 2.54 %}
# Calculate thermal mass (adjust for metric system: use thickness in cm and thermal_mass = 0.75 * thickness * (temp_meat - temp_amb)). 0.75 was used as an average number for most meat types.
          {% set thermal_mass = 0.75 * thickness * (temp_meat - temp_amb) %}
          {{ (temp_meat - temp_amb) / thermal_mass }}
        unit_of_measurement: "degrees/min"

# Automation to update the estimated time food will be done
automation:
  - alias: Set Time Food Done
    trigger:
      - platform: time_pattern
        minutes: "/2"
    action:
      - service: input_datetime.set_datetime
        entity_id: input_datetime.food_done
        data:
          timestamp: >
            {% set temp_rate = states('sensor.food_temp_rate') | float %}
            {% set temp_done = states('input_number.ibbq_target_probe_1') | float %}
            {% set int_temp = states('sensor.probe_1') | float(default=0) %}
            {% set calc = (((temp_done - int_temp) / temp_rate) * 60) + as_timestamp(now()) %}
            {{ calc }}

The estimate was almost perfect, off only by a few minutes! I bet it would be even better with a more consistent heat source than my Big Green Egg as the ambient temp fluctuated during the whole cook ranging from 220 to 260 since I wasn’t babysitting the vents.

I was surprised that no one thought of this. This is why a linear extrapolation of the temperature rise will always be wrong.

Different meats, even different cuts of meats will stall differently. What happens is that the meat at around 150°F to 170°F starts to sweat. Moisture in the meat evaporates. This cools the meat just as sweat cools your body.

Having said that- consider measuring the humidity in the smoker. When the moisture in the meat is mostly evaporated, the humidity in the smoker should start to drop.

Finding a humidity sensor in a hobbyist price range that would operate at smoker temperatures, like 220°F or more will be the problem. The DHT22 operating temperature only goes up to 220°F.

Yep! Great idea. That’s why I went with my code as it’s not taking a temperature sample over a set amount of time. For sure it’s not taking into consideration the evaporation. The code I posted worked well for ribs but I’ll still have to test with other cuts. Maybe there’s a high temp humidity sensor out there that we could factor into the equation to get the exact second the meat is ready? Lol I’m just happy I can give a roundabout time dinner will be ready with my current setup. I piped this concept into Meta AI and got a response considering a cooling factor and it suggested to adjust the rate around 150F. Here’s the response:

sensor:
  - platform: template
    sensors:
      food_temp_rate:
        friendly_name: Food Temp Rate
        value_template: >
          {% set temp_meat = (states('sensor.probe_1') | float - 32) * 5/9 %}
          {% set temp_amb = (states('sensor.probe_2') | float - 32) * 5/9 %}
          {% set thickness = states('input_number.food_thickness') | float * 2.54 %}
          {% set thermal_mass = 0.75 * thickness * (temp_meat - temp_amb) %}
          {% set cooling_factor = 0.5 if (temp_meat > 150 and temp_meat < 170) else 1 %}
          {{ (temp_meat - temp_amb) / (thermal_mass * cooling_factor) }}
        unit_of_measurement: "degrees/min"

I’m not sure why you need to calculate the thermal mass and then feed that back into the final answer.

{% set thermal_mass = 0.75 * thickness * (temp_meat - temp_amb) %}
{{ (temp_meat - temp_amb) / thermal_mass }}

is simply equal to:

{{ 1/ (0.75 * thickness) }}

since:

(temp_meat - temp_amb) / thermal_mass = (temp_meat - temp_amb) / (0.75 * thickness * ((temp_meat - temp_amb))

and the (temp_meat - temp_amb) on the top and bottom cancels out.

I’m also confused about the units of that equation. It seems to me that they will be “1/cm” not “degrees/min”

Here is the units in the equation broken down:

(degrees - degrees)/0.75 * cm * (degrees - degrees)

And where does the .75 value actually come from? And then later where does the .5 cooling correction factor come from? What exactly are those numbers based on? I poked around online and couldn’t find that heat transfer equation anywhere.

The “.75 * thickness” number may work for a thin piece of meat where the thickness allows for the internal temperature to change rather quickly but I’m not sure if it would work the same with a pork butt that’s 4 inches thick.

And it doesn’t take into account the shape of the meat. A meatball will have a different heat transfer than a hamburger patty since in the patty almost all of the heat is coming in from the top & bottom sides (so more quickly) vs a ball where the heat from in every direction equally. That is called surface to mass ratio.

That and I’m sure the number would be different if the meat was more dry vs more moist (no injection of marinade vs injection) since the specific heat capacity of the extra internal liquid will change how much heat needs to be absorbed by the mass to change by 1 degree vs a drier piece of meat that will by definition have less moisture and more solids per unit volume so the mass will heat up faster. What is the ratio of specific heat capacity in muscle fiber vs water?

There are so many variables (including instrumentation measurement errors and variability) to take into account that I’m not sure that any one formula will give exact results for all situations.

Which I why I used real world measurements in my approximation formula. You are updating yours every 2 minutes but I update mine every 5 minutes.

Lastly I’m not sure that it would work exactly as posted by copy/paste since in the code block above you have two “input_number:” domain keys. If you copy it as is then the second one would override the first and not create the first input number (food_temp_done)

that should be changed to:

# Input for the target temperature of the food
input_number:
  food_temp_done:
    name: Food Done Temp
    initial: 195
    min: 0
    max: 200
    step: 1

# Input for the thickness of the food (in inches)
  food_thickness:
    name: Food Thickness (in)
    initial: 2
    min: 0.5
    max: 5
    step: 0.1