Arduino Wood Stove Controller

A thermostat and controller for a wood stove

Similar projects worth following
I was originally looking for an over-temperature alarm for a wood stove but couldn't find a nice one. This is where the project started and it slowly morphed into a full blown temperature controller.

This project consists of an Arduino Mega with a thermocouple sensor to measure the stove and room temperatures. Using these inputs, a PID control loop calculates the proper servo setting to control the air baffle of my wood stove .

I have used this controller for many seasons now and very surprised at the reduced wood burn at night. Before using this temperature controller, the stove would be empty in the morning. Now there are plenty of coals left to get the fire started again.

For my stove, I found the preferred temperature settings are 500 deg for the stove running temperature and 73 deg for the room.

*** make sure that the controller is plugged into a UPS in case of a power failure.


Related Project:
Raspberry Pi Wood Stove Data

Current program features:

-run a wood stove at a user defined temperature by controlling the stove air damper with a servo
-will shut the stove down to a slow burn when the room temperature reaches a user defined setting
-incorporates an over temperature alarm preset at 100 deg over the defined stove run temperature set point
-has a mute button to mute the over temp alarm
-has a reminder (5 beeps) to close the flu damper and ash drawer at 200 deg and 400 deg during the initial start of the fire
-will completely shut the air damper when the stove temperature is within 10 deg of the room temperature
-can log all data to the serial, utilized for "Raspberry Pi Wood Stove Data Logger"
-the servo throw setup is configurable through a set up process built into the program which is accessed by pressing the stove up and stove down buttons simultaneously.

Arduino Mega pin usage:

Powered from 9v wall power supply

buttonMutePin = 2;
buttonStoveTempSetPointUp = 6;
buttonStoveTempSetPointDown = 18;
buttonRoomTempSetPointUp = 16;
buttonRoomTempSetPointDown = 17;
thermoCLK = 3;
thermoCS = 4;
thermoDO = 5;
lcd1 = 7;
lcd2 = 8;
lcd3 = 9;
lcd4 = 10;
lcd5 = 11;
lcd6 = 12;
buzzerPin = 15;

servoPin = 14;
Power = VIN;

Screen Display:

First line: stove temp / servo position / room temp
Second line: stove set temp / stove temp change / room set temp

  • 1 × Arduino Mega
  • 1 × Thermocouple Type-K Glass Braid Insulated (K)
  • 1 × Thermocouple Amplifier MAX31855 breakout board (MAX6675 upgrade) (v2.0)
  • 1 × Power HD 1501MG Metal Gear Servo 60g/ 17kg-cm
  • 1 × Clear Enclosure for pcDuino/Arduino with spacer

View all 9 components

  • Source Code

    rockfishon12/11/2014 at 18:08 0 comments

  • Code

    rockfishon12/11/2014 at 17:48 0 comments

    // stove ver 110

    #include <Adafruit_MAX31855.h>

    #include <LiquidCrystal.h>

    #include <Servo.h>

    #include <PID_v1.h>

    // define integers

    int x = 0;

    int setBeepBuzzer= 1;

    int muteBuzzer = LOW;

    int overTemp = LOW;

    int stoveMode = HIGH;

    int stoveShutdown = LOW;

    double stoveRunTemp = 500;

    int overtempSetPoint = 600;

    int servoPos = 15;

    int roomTempSetPoint = 72;

    int minStoveDamperSetting = 45;

    int stoveShutdownSetting = 31;

    double fdiff = 0;

    double insideTemp = 70;

    double f = 0;

    int fInt = f;

    int cfg = 0;

    double Output;

    double fnew;

    const int pulseWidthMin = 500;

    const int pulseWidthMax = 2100;

    int stoveRunTempInt = stoveRunTemp;

    // define pin constants

    const int buttonMutePin = 2;

    const int thermoCLK = 3;

    const int thermoCS = 4;

    const int thermoDO = 5;

    const int buttonStoveTempSetPointUp = 6;

    const int buttonStoveTempSetPointDown = 18;

    const int lcd1 = 7;

    const int lcd2 = 8;

    const int lcd3 = 9;

    const int lcd4 = 10;

    const int lcd5 = 11;

    const int lcd6 = 12;

    const int buzzerPin = 15;

    const int servoPin = 14;

    const int buttonRoomTempSetPointUp = 16;

    const int buttonRoomTempSetPointDown = 17;

    Servo myservo;

    Adafruit_MAX31855 thermocouple(thermoCLK, thermoCS, thermoDO);

    LiquidCrystal lcd(lcd1, lcd2, lcd3, lcd4, lcd5, lcd6);

    PID myPID(&f, &Output, &stoveRunTemp, 4, .2, 1, DIRECT);

    void setup() {

    myservo.attach(servoPin, pulseWidthMin, pulseWidthMax);

    pinMode(buzzerPin, OUTPUT);

    pinMode(buttonRoomTempSetPointUp, INPUT);

    pinMode(buttonRoomTempSetPointDown, INPUT);

    pinMode(buttonMutePin, INPUT);

    pinMode(buttonStoveTempSetPointUp, INPUT);

    pinMode(buttonStoveTempSetPointDown, INPUT);


    lcd.begin(16, 2);


    myPID.SetOutputLimits(minStoveDamperSetting, 180);


    // 1234567890123456

    lcd.print("Stove Control 8");

    lcd.setCursor(0, 1);

    // 1234567890123456

    lcd.print("by ROCKFISHON");

    // wait for MAX chip to stabilize



    void loop() {

    // read thermocouple and subtract internal heat from lcd and interface board

    insideTemp = (thermocouple.readInternal() * 9 / 5 + 29);

    fnew = thermocouple.readFarenheit();

    while (isnan(fnew)) {

    fnew = thermocouple.readFarenheit();

    lcd.print("T/C Problem");


    fdiff = fnew - f;

    f = fnew;

    fInt = f;

    // Compute PID



    // Damper control section

    // servoPos = 0 then damper is closed

    // servoPos = 180 then damper is fully opened

    if (!stoveShutdown && f <= insideTemp + 10) { // close the damper if the fire is out

    stoveShutdown = HIGH;


    if (stoveShutdown && f >= insideTemp +20) { // open the damper when the fire is started

    stoveShutdown = LOW;


    if (insideTemp <= roomTempSetPoint-.25) {

    stoveMode = HIGH;


    if (insideTemp >= roomTempSetPoint+.25 || overTemp == HIGH) {

    stoveMode = LOW;


    if (stoveShutdown) {


    servoPos = stoveShutdownSetting;


    else {

    if (stoveMode) {


    servoPos = Output;





    servoPos = minStoveDamperSetting;



    // input loop for 5 seconds

    for (int y = 0; y < 50; y++) {

    // read mute button

    if (muteBuzzer == LOW) {

    muteBuzzer = digitalRead(buttonMutePin);


    // buzzer overtemp alarm section

    if (muteBuzzer) {

    if (f < overtempSetPoint) { //resets the mute buzzer variable if the stove temp goes below the set temp

    muteBuzzer = LOW;

    overTemp = LOW;


    digitalWrite(buzzerPin, LOW);




    if (f > overtempSetPoint) {

    digitalWrite(buzzerPin, HIGH);

    overTemp = HIGH;




    digitalWrite(buzzerPin, LOW);

    overTemp = LOW;



    // beep buzzer to remind to close damper

    if (setBeepBuzzer == 0 && fInt <=175) {

    setBeepBuzzer = 1;


    if (setBeepBuzzer ==1 && fInt >=200) {

    for (int x = 0; x < 5; x++) {

    digitalWrite(buzzerPin, HIGH);

    delay (100);

    digitalWrite(buzzerPin, LOW);

    delay (500);


    setBeepBuzzer = 2;


    // beep buzzer to remind to close drawer

    if (setBeepBuzzer == 2 && fInt >=400) {

    for (int x = 0; x < 5; x++)...

    Read more »

View all 2 project logs

Enjoy this project?



sphrogahn wrote 08/10/2023 at 15:45 point

I want to put this electric Honda program object into my webpage, You can see it here because you did such a superb job of it.

  Are you sure? yes | no

wseo wrote 06/13/2018 at 14:01 point

Hi, is it possible to get a circuit drawing?

  Are you sure? yes | no

bullethead67 wrote 10/22/2017 at 18:54 point

This will be my first Arduino build. Can I use an UNO with a LCD+Button keypad shield? Could i just change the pin constants? I was looking at the pin numbers are they all digital?

  Are you sure? yes | no

rockfishon wrote 02/04/2018 at 02:00 point

You can, but your program will be very much different than mine.  I do not know how many digital pins the UNO has, but you would need some for the buzzer and thermocouple.

  Are you sure? yes | no

Dan wrote 10/10/2016 at 13:23 point

I consider myself a newbie with arduino, i find your project quite interesting and i trying to use it.
I modified it to use max6675  instead of Adafruit_MAX31855
first thing i m confused is how you read the room temperature. As far
as can understand both stove and room temperature are read with the same
thermocouple. In my mind i m thinking i would need tu use two separate
Could you elaborate on this ?


  Are you sure? yes | no

rockfishon wrote 10/10/2016 at 23:32 point

I believe that thermocouples need to have a compensation temperature source, but I am not an expert.  This package that I used allows one to use this temperature reading as well as the probe temp.  In your case you would need a separate temperature sensor for the room.  You might want to use one that will give a better resolution than a thermocouple, maybe with an integrated humidity sensor?

  Are you sure? yes | no

Dan wrote 10/11/2016 at 12:42 point

Thank you guys, i will try to add another sensor and modify the code. I will let you know how it goes

  Are you sure? yes | no

K.C. Lee wrote 10/11/2016 at 00:09 point

Unlike the MAX31855, there is no way of reading off the cold junction temperature from the MAX6675.  You might have to read off the temperature from your microcontroller - readable from ADC MUX.  It would require some calibration.

I don't use any of these chips, so can't help beyond this.

  Are you sure? yes | no

JanoHak wrote 08/17/2016 at 16:47 point

I have similar project a bit more complex because water radiators regulation but it is great idea to measure temperature inside boiler. I am using boiler water temperature which have big delay. I have hot gases fan to regulate boiler and termostatic input air regulation from boiler producer. I am not shure now how to use new temperature as second parameter because I need water temperature as primary one.

  Are you sure? yes | no

Nick Cook wrote 02/12/2016 at 17:36 point

Here is a link to oshpark for ordering a board that will fit on a arduino mega. if you are interested in a board let me know through private message and i can submit an order as the minimum is 3 boards.

  Are you sure? yes | no

rockfishon wrote 08/17/2016 at 12:32 point

Not sure how this will help me.

  Are you sure? yes | no

veneziaj wrote 09/23/2015 at 12:06 point

HI Rock, My wood boiler setup is coming along nicely thanks to your project.. I am finding some volatility in the servo you used and am wondering what power supply you used for the arduino mega/servo.. I am using the mega and the same servo..  Did you power the servo with the VIN or provide power seperately?

  Are you sure? yes | no

rockfishon wrote 09/23/2015 at 12:41 point

I seem to have left that detail out of my write up.

I use a 9v power adapter to power the Arduino.  I then connect the servo power to the VIN pin on the board.  I found that the servo would draw more power than a 5v adapter could provide and reset the Arduino.

  Are you sure? yes | no

veneziaj wrote 09/23/2015 at 12:47 point

perfect, makes sense.. The 9v battery worked well for very short periods of testing, so an adapter it is! Thanks! 

  Are you sure? yes | no

rockfishon wrote 08/20/2015 at 00:16 point

The servo wires go directly to power, ground and also uses pin 14 in my code.  Servo's do not need a controller.

  Are you sure? yes | no

veneziaj wrote 08/26/2015 at 21:06 point

thanks, I've only used stepper motors and I had to get a shield for those.. 

  Are you sure? yes | no

veneziaj wrote 08/18/2015 at 18:07 point

Did you use a motorshield for the servo?

Any chance you have the wiring diagrams you used? great project! very slick solution.. I have a wood boiler which I am planning to control the draft door.

  Are you sure? yes | no

mikes7350 wrote 12/10/2014 at 23:10 point
I love this project and am currently looking to build a similar model for my hot air wood furnace. Can you repost the source code? The link does not seem to work.

  Are you sure? yes | no

rockfishon wrote 12/11/2014 at 18:20 point
I placed an updated link as well as the code in the project log. Good luck with your build.

  Are you sure? yes | no

cueballjw wrote 10/28/2014 at 12:31 point
Do you have any more details on the Thermocouple? How did you mount it to the stove?

  Are you sure? yes | no

rockfishon wrote 11/29/2014 at 16:54 point
I have a magnetic wood stove thermometer that I hold the thermocouple to the stove. Any magnet would work.

  Are you sure? yes | no

h_2_o wrote 08/11/2014 at 01:26 point
a quick question did you ever measure the extended burn times or wood usage?


  Are you sure? yes | no

rockfishon wrote 11/29/2014 at 16:52 point

  Are you sure? yes | no

Sara Oclet wrote 06/26/2014 at 20:06 point
Hey rock!!! Nice stove controller!!!

  Are you sure? yes | no

Eric Evenchick wrote 04/15/2014 at 15:19 point
Hey, just a tip on sharing source code. Hackaday Projects isn't the best for this, so I usually recommend if you want a quick way to share code. You can link to your Gist from here, and it will provide syntax highlighting and formatting for you.

Nice build though. I'm surprised that you can get sufficient control just by moving the damper, but if so it's a nice simple solution!

  Are you sure? yes | no

schmirrwurst wrote 04/11/2014 at 20:50 point
Hi rock,

Very nice project, I try something similar with a oil stove, but I couldn't find any way to control easily the AC 220V blower, is your blower DC ? How much pressure do you need ?

  Are you sure? yes | no

rockfishon wrote 04/11/2014 at 21:31 point
I do not have a blower on my stove. It is convection only.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates