Cooking a Roast

Thread Starter


Joined Jan 18, 2008
Yes, this really has to do with microcontrollers, and I will post code to prove it.

I am working on a digital cooking thermometer, which will primarily be used for roasts and such. Frying is easy to tell by touch. In another thread, I have shown some of my attempts to produce a graphical display. That work is pretty well along. I can scroll both the Y-axis (temperature from 40 to 295°F) and X-axis, which is basically unlimited. Data are put into and retrieved from a circular FIFO buffer and plotted. Code (draft) for that section is attached.

I like line graphs; however, in thinking about the end users (my adult daughters), I think something a little more colorful and graphic would be more useful. My favorite on-line cooking program is this (from MIT):

If you want to test, enter these values:
It is pretty accurate. My TG rib roast was about 10 cm thick (3.5#) and took 1:20 to get to 126°F. I should have taken it out a little sooner, as it (like always) continued to cook on the counter. It was "medium rare" in the middle few inches. What I would like to show is a cross-section with the cooking zones moving inward as the temperature changes. That part should be relatively easy graphics.

What I need help on are the calculations done in the MIT link. Is anyone familiar with them?

As a last resort, I will contact the senior authors, but I don't expect that to be too productive, particularly for adaptation to a small MCU.

The following code snippet is for a PIC16F1829 at 32 MHz. The GLCD is 132x65 and uses an ST7567 controller. It scrolls as described above. I would like to thank member Mike McLaren for the original FIFO routine that was modified to fit this purpose.

PutTemp0                      ;called with new value in temp0
     #define   offsetY   2    ;"1"does not work well, used up to 10 in testing
     #define   offsetX   59   ;use 59...?, 40 used in testing
Validate_Y                    ;must do subtraction as increment may be >1
     movlw     50             ;temp range of graph is 50°
     addwf     offsetF,w      ;offsetF is subtracted from value to make in range
     subwf     temp0,w        ;preserve temp0
     btfss     STATUS,0
     bra       Validate_X     ;check X is (50+offsetF)>temp0 (zero/borrow clear)                       
     movlw     offsetY        ;offset if (50+offsetF)<=temp0(zero set)
     addwf     offsetF,f      ;increase offset by 10, affects all STATUS bits
     bsf       STATUS,0       ;count1 (no change)if this is only adjustment,
;now check X,set C to indicate need for FIFO adjustment - clears with addwf
     incf      count1,f       ;
     movlw     60             ;
     xorwf     count1,w       ;count1 = 60, preserve count1
     btfsc     STATUS,2       ;
     bra       AdjCount
     btfss     STATUS,0
     bra       Continue       ;no adjustment needed
     bra       FIFO_offset
     movlw     offsetX      ;count1=60, reset to offsetX
     movwf     count1         ;
     bra       FIFO_offset    ;count1 = 60, offset X, reset count1 to 0
FIFO_offset                   ;works around the corner
     call      LngDly
     call      ClrGraph
     movf      count1,w
     subwf     bufpull,w
     btfss     STATUS,0
     andlw     bufsize-1      ;turns corner
     movwf     bufpull
     movf      temp0,w        ;PutGraph = movwf tempF, will change but not now
     call      PutFIFO        ;
     DelayCy   (10*msecs)      ;2 ms is very quick
     call      GetFIFO        ;temp0 has been added to FIFO and returns in WREG
     btfsc     STATUS,0       ;keep getting FIFO until buffer empty (STATUS,0 set)
     bra       _FillData      ;FIFO buffer empty, get new value
     call      PutGraph       ;PutGraph still uses tempF, so move temp0 to tempF
     bra       _Continue      ;

     bra       $-1
;This is a stand alone version of M McLaren's FIFO.

#define bufsize 64            ;64 ;bufsize = 2^n = 2,4,8,16,32,64,128                          
#define bufstart 0x2040       ;

     clrf      bufpull
     clrf      bufpush
;     bra       Test

     addlw     low(bufstart)  ;w == bufpull or bufpush                |B?
     movwf     FSR1L          ;                                       |B?
     movlw     high(bufstart) ;                                       |B?
     movwf     FSR1H          ;                                       |B?
     return                   ;                                       |B?                   
;Check buffer MT
     movf      bufpull,W      ;push == pull (buffer empty)?           |B0
     xorwf     bufpush,W      ;  "                                    |B0
     bsf       STATUS,0       ;set "buffer empty flag", if needed     |B0
     btfsc     STATUS,2       ;no, skip & process char, else          |B0
     return                   ;return w/ buffer empty flag set        |B0
;Not necessary to clear buffer MT flag as 'addlw' in loop does that
;Character available:
     movf      bufpull,w
     call      FIFOLoop           ;sets FSRn to bufpull location
     incf      bufpull,W      ;                                       |B0
     andlw     bufsize-1       ;wreg == ++bufpull % bufsize (wrap)    |B0
     movwf     bufpull        ;update bufpull pointer                 |B0
     movf      INDF1,W        ;WREG to be processed                   |B0
     return                   ;                                       |B0
     movf      bufpush,w      ;                                       |B0
     call      FIFOLoop       ;                                       |B0
     movf      temp0,w        ;retieve new value                      |B0
;application specific probably change "put" to temp0 or temp1 comes
;from test generator (below) for simulation
     movwf     INDF1          ;add new value to buffer                |B0
     incf      bufpush,w      ;adjust pointer to new TOS              |B0
     andlw     bufsize-1      ;wreg == ++bufpush % bufsize (wrap)     |B0
     movwf     bufpush        ;update bufpush pointer                 |B0
     return                   ;                                       |B0
Last edited:


Joined Oct 13, 2019
Not sure if it exactly what you are after but Doug Baldwin's discussion of sous vide cooking has some information on heating of food of various shapes using various temperatures. The shape of the food makes a difference - a roundish roast will be different from a slabby steak. It is primarily aimed at low-temperature gradient cooking but does discuss some of the math.

Thread Starter


Joined Jan 18, 2008
My bad. I should have referenced this thread:

I had intended that as the main thread and would like to keep that thread focused on the project. There have been 2 tangents. After I plotted data manually (I show a plot in that thread), I decided that a GLCD with a live plot would be a nice addition. That had nothing to do with cooking per se and everything to do with drawing a line and scrolling it without being able to read the display. It's a 132x65 display, and I was worried about how much RAM would be needed to provide a mirrored buffer. That tangent is in another thread and is working well. I only use half of the display (66x64) and got by with just 64 bytes of RAM. If needed, I can expand that easily to 128 bytes or more.

Then as I looked at the graph, I thought, that will not impress either of my non-scientist daughters and maybe something a little more spiffy like the MIT site (linked in post #1 of this thread) would. So, I started this tread as the second tangent. I have now abandoned that idea for the time being and am simply integrating the code for the MAX31856 with the GLCD code. I hope to get it done in time for my Christmas roast and will post actual results in that original thread.

So, yes, a temperature probe (K-type) is definitely going to be the primary source of data. I almost never use time alone when cooking roasts, but I do like to predict the finish time so other things, like popovers, can be prepared on time.