Precision Cooker: A Temperature Controlled Cooker Using Atmega

The Precision Cooker

Precise time and temperature control are critical when cooking. Slight deviations in either temperature or cooking time can ruin delicate ingredients. Despite this fact, most modern day stovetops provide no data regarding their current temperatures and do not have built in timers. The stovetops that do provide these functionalities are often expensive and require specialized cookware. As our final project for ECE 4760 at Cornell University, we decided to build a programmable temperature and time controlled cooker that would use traditional thermal conduction to cook food regardless of the cooking vessel’s material. The cooker can be used for a variety of purposes ranging from simply boiling the perfect 6-minute soft-boiled egg to sous-vide cooking a piece of delicate white fish. Quickset options can be programmed into the cooker allowing for easy preset operation.

The Precision Cooker
The Precision Cooker
Delicious Results
Delicious Results

High Level Design


Our aim for this project was to make temperature controlled cooking accessible to those without culinary training and/or professional kitchen appliances. Our project focuses on immersion cooking methods such as poaching, simmering, boiling, or sous vide cooking. We decided to focus on these cooking methods as they require very little technique but rather precise temperature control and cooking time. Recipes often call for specific temperatures and timings, but as most modern-day stovetops provide no temperature or timing feedback, it is difficult to know when these requirements have been met. By being able to set precise timings and temperatures, users simply have to place the food in the cooker when prompted and let the cooker handle the rest in order to create a perfectly cooked dish.

Rationale and Motivation Behind our Project

Cooking foods at controlled temperatures is a very difficult thing to achieve for extended periods of time. Using traditional gas stovetops, it is almost impossible to maintain a specific temperature for a set amount of time. However, by controlling the heat source electronically using a feedback loop, we can continuously measure the temperature and adjust it as necessary. Our project is designed to maintain any temperature between 45 and 100 degrees Celsius for extended periods of time with minimal deviation in temperature.

Background Math

For background math, we will be discussing our PID controller and our voltage-temperature sensor calibration and equation derivation. For our temperature control feedback loop, we utilized a proportional-integral-derivative (PID) controller. The PID controller measures the deviation between the desired result and the current measurement and outputs a value that is calibrated to reach the desired value with minimal overshoot or undershoot. Our PID controller is sourced from the AVR221 application. The PID controller is composed of three terms: the proportional term, integral term, and derivative term. These three terms are summed together to calculate the output of the PID controller. The PID equation is defined as:


  • Kp : Proportional term
  • Ki : Integral term
  • Kd : Derivative term
  • e : Error term
  • t : Time of measurement
  • τ : Integration variable ( 0 -> t)

For our final PID values, we selected P = .07, I = .04, and D = .05. All of these values are low as our system changes very slowly and adjustments to the system take a long time to take effect due to the high specific heat of our immersion liquid (water). For our voltage-temperature sensor calibration, we utilized the LM35 temperature sensor to measure the temperature of the immersion liquid. The LM35’s datasheet provided us with the below voltage-temperature curve.

Stock LM35 voltage temperature curve
Figure 1: Stock LM35 voltage temperature curve

After some experimentation, we discovered that the given curve did not fit our measured results. To properly calibrate our temperature readings we swept across numerous temperatures and measured the voltage output of the LM35 using the microcontroller’s built in ADC. We then plotted these values and performed linear regression to find a line of best fit that we used as our voltage-temperature equation

Measured Temperature ADC Voltage Curve
Figure 2: Measured Temperature-ADC Voltage Curve

Logical Structure

Our project is composed of three discrete modes of operation: input, heating, and cooking. These stages are further split into smaller states for implementation purposes. These smaller states can be seen in the software finite state machine shown in Figure 10.

During input mode, the heating element remains off and the system waits for user input. During this mode, the temperature desired and the cooking time should be set using either the three analog knobs or the UART computer interface. Once the temperature and cooking time are set, the system waits for the mode switch to be moved from off to on. Once the switch is moved to the on state, the system stores the desired temperature and cooking time and transitions into heating mode.

During heating mode, the cooker’s heating element heats up the cooking vessel to the desired temperature. During heating mode it is possible to switch between the LED display showing current temperature and desired temperature by toggling the display mode switch. The microcontroller controls the cooker by reading the temperature probe submerged in the cooking liquid and switching the relay inside the power box. When the relay is switched on, the cooker’s heating element is connected to the main power line and current flows through the heating element. This current flow causes the heating element to heat up. Through thermal conduction, both the cooking vessel and the cooking liquid begin to heat up as well. Once the desired temperature has been reached in the cooking liquid, the relay is turned off and a buzzer sounds. This buzzer signals the user that food should be placed into the cooker as the desired temperature has been reached. The cooker then transitions into cooking mode.

In cooking mode, the cooker begins to count down the desired cooking time recorded during input mode. During this mode, the cooking vessel will maintain the desired temperature by turning on and off the relay according to the readings from the immersed temperature probe. The cooker counts down until the timer reaches 0 and then a buzzer goes off to signal the user that the food has finished cooking. The buzzer continues to sound until the mode switch is set to input mode. At this point the cooker moves back into input mode to wait for further instructions. If the desired cooking time is left at 0, the system will beep immediately.

Hardware and Software Tradeoffs

In our hardware design, we decided to increase the hardware complexity by adding analog potentiometers for setting the temperature and time and building our own LED display screen. While we could have used an LCD display to display temperature and cooking time information, we decided to build our own LED display as it allowed us to print to a larger font. Despite the LED display being very difficult to build and program, it provides a larger and brighter display compared to the LCD display. We decided to implement analog potentiometers for setting the temperature and cooking time so that the system could be used independently of the UART computer interface. While our cooker can be programmed using the serial UART connection to a PC, it can also operate independently using only the analog potentiometers.

In our software design, we decided to use the Tiny Real Time (TRT) kernel written by Dan Henriksson and Anton Cervin as it allowed us to easily schedule tasks at set intervals and synchronize variables across multiple tasks. While using the TRT kernel decreased the amount of flexibility we had in writing our software, it ultimately made scheduling software tasks a lot easier.

Relevant existing patents, copyrights, and trademarks

There are no existing patents, copyrights or trademarks that our project infringes on. While numerous patents exist regarding temperature controlled cookers (e.g Patent EP2661944 A2 & Patent WO2012092683 A3), they utilize inductive heating surfaces which we do not use. The patent closest to our design that we found was Patent CA2722383 A1 which describes a temperature controlled heating element. However, this patent still does not apply to our project as it describes controlling the heating element’s temperature using electrical sensors within the heating coil while our system measures the temperature of the food’s immersion liquid. We utilize the Tiny Real Time (TRT) kernel and its supplemental UART libraries, both of which are filed under the “Beer-Ware License” by Joerg Wunsch. We also utilize the generic PID Controller code created by Atmel for the AVR221 application.


Our overall hardware design is composed of numerous subsystems. The various subsystems can be seen in the figure below.

Hardware subsystem block diagram.
Figure 3: Hardware subsystem block diagram.

The following subsystems compose our overall system:

  • Atmel Atmega 1284P Microcontroller
  • Analog Inputs
  • Buzzer Sound Subsystem
  • LED Display
  • Temperature Sensor
  • Power Supply and Heating Element


Our microcontroller, an Atmel Atmega 1284P, is the logic controller of our system. Our microcontroller is mounted on a custom PCB produced by Professor Bruce Land of Cornell University. In addition to the microcontroller, the PCB includes an external oscillator, voltage regulators, and a FTDI serial module. The majority of the microcontroller’s functionality will be covered under the software design section. The microcontroller performs the following functions:

  • Controls the power supply relay to turn on and off the heating element.
  • Reads the temperature probe and calculates the current temperature.
  • Reads the analog inputs to correctly set the desired temperature and cooking time.
  • Turns on and off the piezoelectric buzzer.
  • Sends messages to display on the LED display.
Microcontroller PCB schematic
Figure 4: Microcontroller PCB schematic

Buzzer Sound System

Our piezoelectric buzzer, a CET12A35, is connected to a TI 296-6501-1-ND 555 timer that is wired to oscillate at 1 KHz. The output of the 555 timer is connected to the gate of an nMOS transistor that has its drain connected to VCC and its source connected to the drain of another nMOS transistor. The gate of the second nMOS transistor is connected to the microcontroller and the source is connected to the first terminal of the piezoelectric buzzer. The second terminal of the piezoelectric buzzer is connected to ground. The 555 timer switches the first nMOS transistor at a 1KHz frequency and allows the source to have full VCC-GND voltage swing. This signal is then gated by the signal from the microcontroller. If the microcontroller sets the buzzer control signal high, the second nMOS transistor will turn on and the piezoelectric buzzer will convert the square signal produced by the 555 timer to audible sound.

Buzzer sound system hardware schematic.
Figure 5: Buzzer sound system hardware schematic.

Heating Element and Power Supply

Our heating element and power supply subsystem is composed of a power box and a resistive heating element. The power box controls the current and voltage received by the heating element. The power box consists of a 2 way gang box with a duplex electrical outlet, a single pole electrical switch, and a high current relay module. For there to be an electrical connection between the electrical outlets built into the gang box and the main power lines, both the relay and the single pole electrical switch must be turned on. The electrical switch is the first line of protection that the user must physically switch on. Once the electrical switch is switched on, the relay controls the connection between the electrical outlets and the mains. The relay is controlled by three wires: VCC, GND, and EN. The VCC and GND pins are connected to the USB VCC and GND pins of the microcontroller. We initially connected VCC to the VCC port on the microcontroller, but we found that the large current spike of the relay during switching would lower the voltage of the VCC rail and result in improper operation of other devices connected to the microcontroller’s VCC rail, such as the temperature sensor. The relay is an active low device and will remain off unless its EN signal is pulled low by the microcontroller. By default, the microcontroller sets the EN signal to high. If the EN signal is set to floating, the relay will still not turn on. With both the relay and single pole switch turned on, a connection is made between the heating element and the main power rail. With this connection enabled, the heating element begin heating up. This generated heat is transferred to the cooking vessel by thermal conduction which in turn is transferred to the immersion liquid.

Our heating element and chassis was sourced from an old Panasonic rice cooker. We stripped the rice cooker of all parts and kept only the metallic shell and the 400W resistive heating element. We had initially planned to replace the 400W heating element with a more powerful 1000W heating element sourced from a hot water heater, but due to thermal conduction issues we settled with the 400W heating element for our final design.

 Power box and heating element hardware schematic.
Figure 6: Power box and heating element hardware schematic.

Temperature Sensor and Analog Inputs

Our temperature sensor is a LM35 solid state temperature sensor. It is connected to the microcontroller by three pins: VCC, GND, and OUT. The VCC and GND pins are connected to the VCC and GND pins of the microcontroller. The OUT signal is connected to port A0 and is read by the internal ADC of the microcontroller. Since the OUT signal changes according to the temperature that the LM35 detects, the ADC is continuously polled every 4 seconds.

Three potentiometers and two slide switches provide user input to our cooker. The potentiometers are read using the ADC on PORTA and converted to digital values which are interpreted on software. Two types of potentiometers are used. 500 Ohm potentiometers are used for the minutes and seconds knobs. While these provide relatively coarse grained control, the wipers on these potentiometers are very smooth and give good user feedback. A 10K pot is used for precise control of temperature because fine grained temperature control is critical for our application and provides more resolution in the data coming in. If we were to use a 500 Ohm here as well, the user would have to be much more careful to distinguish temperatures 1 degree off. This 10k pot also has more wiper turning resistance which makes reaching these exact temperatures easier.

Analog potentiometers and switches hardware schematic.
Figure 7: Analog potentiometers and switches hardware schematic.

LED Display

The LED display is made of a pair of E3005 common anode 8 by 8 LED matrices for a total screen width of 16 columns by 8 rows. The display is row scanned with a separate 8 stage 74HC164N SIPO shift register addressing each display. The microcontroller scans each row of the combined display and turns on each row of the 16 column display for the shift register to drive. Before each row is turned on, values are clocked into the shift registers at 1 MHz before we pull a row low and drive the display with the shift register. Rows are scanned at 50 KHz. Figure 5 illustrates the connections from the LED displays to the microcontroller’s PORTD.

 Wiring schematic for LED Display
Figure 8: Wiring schematic for LED Display. Click to Enlarge


Software Design

We devised a common interface so that each software subsystem could be worked on independently but still be integrated easily with minimal modifications. As a result, a lot of code is encapsulated into structs. Our software design is composed of the following subsystems:

  • State Control FSM
  • Writing to the LED Display
  • Temperature Measurement and PID Adjustment
  • Input Reading

Each system is implemented in a separate file and tied together with header files and common interface methods. Below is a high level description of each subsystem and main function listing.

State Control Finite State Machine (fsm.h)

 State Control Finite State Machine (FSM).
Figure 9: State Control Finite State Machine (FSM). Click to Enlarge

Our cooker is controlled by the FSM described above. The FSM takes into account user input and the current state of the cooker. The following composes our FSM implementation.


Sets up the LED display for a different display mode depending on the current state of the FSM. The LED can display the temperature, time, cooking status or display a neutral smile.


Stores input values such as desired temperature or desired cooking time into operational variables. This includes turning on/off the buzzer when the cooker has reached the desired temperature and cooking time, saving the desired temperature or saving the cooking time.


The control table that implements the state transitions for our Moore machine. Data from all the available input methods impact which state transition to take. The control table can be found in our source code.

Writing to the LED Display (screen.c, screen.h)

Writing to a 16 by 8 LED matrix was non-trivial considering how few pins we had available on our microcontroller. This was accomplished by shifting bits serially to a SIPO shift register which would drive the LED display through row scanning.

write_to_buffer(int * left_valueR, int * left_valueL, int * right_valueR, int * right_valueL)

Stores screen data in a temporary buffer in preparation for writing to the screen. This buffer is a complete copy of what is displayed on the LED display.


Writes the values stored in the buffer by serially sending bits to the shift registers that control the shift registers. When writing to the shift registers, our data clocks shifts at 1 MHz. To save power, when we are not shifting, the shift register clock is turned off. The LED screens are row scanned at around 50 KHz.

write_temp_to_buffer(int temp_celsius);
write_min_to_buffer(int min);
write_time_to_buffer(int total_seconds);

These functions are a sampling of the various display modes that our LED display supports. Each function extends write_to_buffer by including functionality to convert human readable values into the bit arrays that populate the screen.

Input Reading and Debouncing (analog_input.c, analog_input.h, input_db.h)

These files contain the ANALOG INPUT struct and associated utilities to read and update the struct. ANALOG INPUT centralizes the reading and updating of all the potentiometers we use as dials in the user interface. Centralizing the analog input was a key factor in making our code modular and streamlining our development process. Prototyping was done with the UART serial input but our final design included all 3 analog dials. Centralizing the inputs made integration easier and cut development time because the subsystems could be tested independently and integrated as long as a common interface was followed. This common interface is embodied in struct members and methods. Analog input is read in from the ADC and linearly scaled from the 0-1023 range that the potentiometers provide to human readable ranges such as 0-99 for minutes, 0-59 for seconds, or 0-100 degrees Celsius for temperature.

analog_input_init(struct ANALOG_INPUT * t)
analog_input_update(struct ANALOG_INPUT * t)

Functions that create and update analog input values through the ADC.

pot_to_temp(int value)
pot_to_minutes(int value)
pot_to_seconds(int value)

The utility functions that convert potentiometer values into human readable values. Each function performs a simple linear scaling from the potentiometer’s input range to the desired output range.

seconds_changed(struct ANALOG_INPUT * t)
minutes_changed(struct ANALOG_INPUT * t)
temperature_changed(struct ANALOG_INPUT * t)

Functions that use hysteresis to detect when the potentiometers change value. This is necessary because there is a jitter in ADC readings which gives a lot of false positives when moving the dials. These functions take care of identifying true changes in the potentiometer values.

Temperature Measurement and PID Adjustment (main.c, pid.c, pid.h)

Much like the ANALOG INPUT struct is used in reading analog input values, the PID DATA struct is used to read and adjust the PID controller. Again, this allowed us to work concurrently and integrate our parts at a later time. Centralizing PID into its own struct allowed us to separate the control logic from the pertinent details of the PID algorithm.

pid_Init(double p, double i, double d, struct PID_DATA *p)
double pid_Controller(int target, int current_value, struct PID_DATA *p)

Instantiate the PID control algorithm in a self-contained struct. The main file gets control values from the PID struct to decide whether or not to enable the relay.

adjustTemp(void* args)

TRT Task dedicated to making fine adjustments to the temperature by turning on and off the relay.


Execution Speed

The speed of our program execution varies from task to task. Our slowest task, the temperature measurement reading, has a deadline of 4 seconds. This time was chosen as the specific heat of water is high and our immersion liquid is able to absorb a significant amount of heat before rising in temperature. By only polling the temperature sensor every 4 seconds, we reduce the amount of relay switching. Since the relay we chose for our project is a physical relay, it produces a loud switching noise when turning on or off. In the case where the current temperature is oscillating around the desired temperature, if the temperature sensor would be read and adjusted quickly, the relay could switch on and off at a very high rate and become a nuisance.

While our slowest task may have a deadline of 4 seconds, we also have numerous tasks that are never set to sleep and are continuously running. These include the serial communication task which prints to and reads from the UART and the LED display update task. As the image on the LED display is generated by quickly cycling through the columns of LEDs, our LED display task runs very quickly to produce a recognizable image. Based on our code, we cycle through a column of LEDs on the LED display every 24 milliseconds.

A satisfied customer
A satisfied customer.


Our cooker is surprisingly accurate in the temperature that it is able to maintain. For starters, our calibration function for converting the raw ADC input to degrees Celsius is accurate within 2 degrees when the temperature probe is immersed in water above 45 degrees Celsius. Since all of the cooking will be done at temperatures above 45 degrees Celsius, we calibrated our temperature probe to be especially accurate between 45 and 100 degrees Celsius.

In addition to our calibration function being accurate, our temperature feedback loop is also quite effective. Because our temperature readings are very accurate due to the aforementioned calibration function, we are able to turn off our heat source as soon as the temperature of the immersion liquid reaches our desired temperature. In addition, due to the carry over cooking effect that is present due to the large heating element, we actually shut off our heating element once the temperature of the immersion liquid reaches 95% of our desired temperature. From that point, we let the carry over effect continue to heat up the immersion liquid. By doing this, we prevent thermal overshoot, which is particularly difficult to deal with as our cooking vessel retains heat very well.


Since our project utilized main power lines as a power source, we were extremely aware of safety considerations. The power box that we built to supply power to our heating element contains both a relay and a discrete physical switch to prevent accidental turn on. For the first layer of protection, a discrete physical switch disconnects the output of the power box from the input mains. Only when the switch is turned on, does the second layer of protection become applicable. For our second layer of protection, we utilize an active low relay. By default, whether during microcontroller startup or if the control wire is left floating, the relay disconnects the main lines coming from the output of the switch to the output of the power box. Only when the control signal of the relay is actively pulled low does the relay turn on and allow a connection between the main power line and the output. During startup the microcontroller sets the control signal of the relay to high, thereby initializing the relay to be disconnected. By implementing both the physical switch and the relay as intermediaries between the output of the power box and the main power lines, we prevent as much accidental turn on as possible.


Our project does not interfere with other people’s designs. Since our system is a closed system, for the most part we do not need to take into account other people’s designs.


Our project is usable to both the technically adept and the technically challenged. For those that are technically challenged, we provide three clearly labeled analog dials that adjust the temperature, the minute timer, and the second timer. For the technically adept, we provide a UART computer interface to digitally program the desired temperature and time to cook. In addition, for those that are technically adept, we provide the source code to allow users to program in quickset cooking options for commonly cooked foods, such as eggs or noodles. While our final project may look complicated, the majority of user inputs are clearly labeled to allow all users a good experience in cooking their food.


Results vs Expectations

We were pleasantly surprised that the results of our project exceeded our expectations. Our initial design was to produce a simple temperature controlled cooker that would only be usable through the UART interface and would utilize a stock LCD screen for temperature and time remaining statistics. However, we managed to include additional hardware dials and switches to allow for programming of the device without a UART connection to a PC. In addition, we implemented a larger and brighter LED display that would display the temperature or time remaining depending on the switch settings. We feel that both of these inclusions makes our project more appealing to a variety of users and allows for operation in environments without a PC or technically skilled personnel. In hindsight, there are a few changes that we would make regarding our design. For starters, we would have been more discerning in selecting a high powered heating element for our cooker. Our initial intention was to build a deep fat fryer that could achieve temperatures of up to 180 degrees Celsius, but due to a poorly selected heating element, we were forced to utilize the lower powered heating element that originally came with our rice cooker. In addition, we would have also been more discerning in the shift register that we selected to power our LED display. Due to poor shift register selection, we had to perform some high speed signal shifting on our microprocessor to correctly render images on the LED display. To further iterate on this project, we anticipate including an automatic lift to place food into the cooker when the desired temperature has been reached and to remove the food once cooking has completed. This would improve our timing accuracy as the time required to place food into and remove food from the cooker would be constant across multiple uses and foods.

Applicable Standards

As our temperature controlled cooker is derived from a rice cooker, it adheres to the standards set by the Electric Rice Cooker Criteria Standard Subcommittee, which is a subdivision of the Energy Efficiency Standards Subcommittee of the Advisory Committee on Energy and Natural Resources. The specifications can be found here:

Intellectual Property Considerations

To build our project we relied on both the hardware and software designs of others. For part selection, we based our temperature sensor and relay selection on the Sous-vide cooker project by Harrison Wong and David Diner. In our software, we employ heavy usage of the TRT kernel and its UART library which are licensable under the Beer-ware license by Joerg Wunsch. We also utilize the AVR221 Discrete PID Controller provided by Atmel. For this project we did not attempt to reverse-engineer a design. Rather we took a commonly known design (temperature controlled induction cooktops) and applied the idea to standard conduction cooktops. We did not request sample parts for our project and therefore we were not required to sign a non-disclosure act. As the system design that we employed is relatively well known, it is highly unlikely that we would be able to patent or publish our design.

Ethical Considerations

Our product design and design process adheres to the IEEE Code of Ethics. Throughout the design of our project, we heavily considered safety when making design choices. We were adamant in ensuring that our power box would have multiple layers of electrical protection to prevent unwanted turn on of our heating element. We also insulated all high voltage electrical components with electrical tape to prevent any risk of a short circuit. In addition, we clearly labeled all plugs and have clear documentation regarding all high voltage wiring. Outside of successfully completing this project, we do not foresee any conflicts of interest, patent considerations or other intellectual property considerations.

To the best of our ability we have documented our project and given credit to others where credit is due. We welcome any discussion to the contrary in the hopes that all disputes can be resolved and that the correct people receive due credit. In addition to maintaining the IEEE Code of Ethics, we also factored in the Chef’s Code of Ethics set by the American Culinary Federation ( All results outputted by our project is done in good faith that our procedures and design choices are correct. We make no attempt to misrepresent our data.

Read more: Precision Cooker: A Temperature Controlled Cooker

Leave a Comment

Your email address will not be published. Required fields are marked *