Thinking about PID control

Proportional, Integrative, Differential control.  There is a function in Arduino that implements this and I started thinking about how I would do this and if it would be appropriate.  The function, really an algorithm is all based on error and time.  In this case the error is the difference between the set point and the actual tank temperature.

All three functions Proportional, Integrative and Differential have a factor, Kp, Ki and Kd.  For example let’s calculate each portion of the formula starting with the proportional contribution Kp, if the current temperature of the tank is 100°F and the set point is 140°F the error is 40.  The integrative portion of the formula adds the contribution of the error over time.  This would be the Ki factor multiplied by 40 and added to the previous Ki*error for every time period.  The differential portion is the Kd multiplied by the difference in the tank temperatures or in other words the tank temperature at the beginning of the time period  minus the tank temperature at the end of the time period.  Let’s take some of the data collected by the OpenLog microSD card and take a stab at this in Excel. We’ll assume Kp=6, Ki=.6 and Kd =.2. The time period is one minute.

Raw data imported into Excel with PID data calculated

Raw data imported into Excel with PID data calculated

Now in practical terms how is the the fire being controlled now?  The auger time is being controlled.  Of course practically the fire must not go out so there is a minimum time the auger must run, since in this program the auger is on a fixed time of 5 secs this really means that all of the control comes from varying the time the auger is not running.  But again the fire can’t go out so I figure the max amount of time between the fixed auger feeds of five seconds is forty seconds.  So that is the slowest the fire can go.  How fast can it go?  Well theoretically the feed could run continuously but again we are dealing with a chemical process that cannot simply absorb 100% fuel feed.  In this case the auger motor added a practical aspect by limiting the feed to a duty cycle of 50%, so the maximum time that the feed can be on is half the time.

Since the PID control is based on time periods and the data collection time period is one minute,lets choose a time of 1 minute for argument.  In one minute at max run the feed will be on 30 seconds and off 30 seconds.  In one minute at min run the feed will be on for 5 secs, off for 40 secs, on for 5 secs and then off for the remaining 10 seconds of the minute.  So again we don’t control the on time only the off time and the difference between the max on time (min off time) and min on time (max off time) is 30 secs on, 30 secs off for the max and 10 secs on and 50 secs off for the min.   So the only control between full bore and idle is the difference between 50secs and 30 secs or 20 secs per minute.
This explains some of the challenge,  the other challenge is the inertial effect of the combustion reaction especially if unburned fuel has built up.  So now that the PID output has been calculated I’m having a hard time wrapping my mind around how this would translate to control of the time, I know I could set up a simple proportion between the PID output and the 0-20 scale of  auger off time dwell.  However in this example the PID output  increases as the error decreases.  I guess that’s the beauty of a spreadsheet I will play around with Kp, Ki and Kd to see if I can get this to work a little better.

Software changes to control underdamped Setpoint control

After running for a few days I have been happy with the amount of holes in the bottom of the burner, the ash level when running does not get higher or lower.  However the fuel usage is a little higher than I thought it would be and the program does not hold the set point temperature as well as I would like.  The graph shows the interaction of the excess fuel usage and the set point.  At times the boiler should be idling along with very little fuel feed, the program should be able to determine the fuel usage needed to control the temperature to the set point.

Under damped control

Under damped control

You can see the 140°F horizontal grid line, the set point is currently 140°F. The integral of the area over that line is excessive fuel usage. However that’s not the only issue, the second issue is the amplitude seems to grow larger until approx. 121 minutes.  At that point I shut down and started a new software change.    You can see the slow recovery as I had to relight the fire and then the software starting correcting earlier, so in short more software changes are in order.    The challenge is to build self correcting software since the whole goal of this project is to burn chips and that will require the software to deal with different energy densities.  I’ll make a few more software changes and post another graph soon.

Continuous run, working fine, future improvments

At this point the boiler has been working for a day and based on last years experience I see no reason why I would need to shut down for a week.  Yesterday we brought two tons of pellets into the shop knowing snow and rain mix was in the forecast.  Yesterday was a pleasant 40°F day with full sunshine a great day to move a little fuel.  I believe we are on a two bag a day pace so with luck I won’t have to worry about moving pellets again until nearly February.  We have chairs set up by the boiler and it is a pleasant place to sit and talk in lieu of sitting in front of a woodstove.

So..what’s next on the list.  1) Software improvements, to be able to adapt to pellets or chips will take a more dynamic software approach.  The software should be able to adapt automatically to varying energy densities.  2) Faster and easier maintenance.  More over center latches to be able to easily take apart the chimney for cleaning and a removable top to the boiler to easily clean the tank tubes.  3) Testing with various materials, chips being at the top of the list.  4) Building a chip dryer.  5) Adding more sensors, I am definitely going to add a fire eye to confirm fire.   I would like to monitor the temperature of the feed motor and the fan motor.   It would be helpful to add a relay for the fan motor so that is controlled by the Arduino.   6) I have tried the self start but it is not in the software yet, that would be a great leap forward especially for March and April when daytime heat is often not required but nighttime heat and hot water are needed.  Automatic starting would be great and would save a lot of fuel.  7) Improving the CNC Plasma cutter, there is still some chatter in the  Y axis and if I can fix that, it would be great and would probably speed the CNC up significantly cutting down on the dross or slag produced when it is cutting.  Cutting down on the slag is a major priority since it is time consuming to grind this off and I am sure part of the development will include trying different burner designs.  8)  Taking a Design of Experiments statistical approach to the burner design to optimize for efficiency.  I gave myself a pretty good list back in September and I have whittled it down to completion so I know it is all possible and fun, I just need to get started.  Tomorrow probably, today I am just going to sit by the fire and enjoy a Sunday.

12/14/12 data, more testing, draft improvements

I  added  gasket rope which I bought at a local hardware store, which is made to replace the gasket material which comes in a wood stove door between the burn plate and the boiler.  This gasket changed the Magnehelic vacuum reading from .1″H2O to .4″H2O.  That I thought would make the flame a bit more vigorous.  I also made the holes in the bottom of the burner larger to allow the ash to fall through.  Lastly I made minor changes by tacking some material across some holes and making more air holes in the ramp plate which the pellets fall down.

Temperature vs. Minutes 12/14/12 data

Temperature vs. Minutes 12/14/12 data

The main differences in this graph and the previous day’s graphs are at approximately minute 273  pellets were added and the sawdust which had been running finally ran out.   As you can see it had enough energy density to overcome the demands of the circulator circuit.  The biggest problem after that came at about 341 when the program allowed the temperature to go past the set point of 140°F  The only explanation I could come up with is the division by different types of declared variables was not allowed and yielded a result of zero.  I was dividing an unsigned long which is an integer by .8 to increase the Auger Off time by 20%.  Since you will not get an integer when you do this the program may not have liked this result.  The Arduino language is a slight variant of C++ .  I have since made all the variables doubles we’ll see if that works.  Today’s burn will be a better test of the burner floors ability to let ash fall through.  Sawdust is very difficult to burn.  It’s also difficult to get the ash to fall through the burner floor.   I think this is because the air cannot get around the sawdust sufficiently to burn it completely and hence it smolders in clumps instead of falling through the grate.    The burner when I pulled it out to inspect it was definitely not clean of ash but did appear better than yesterday.

More Testing, another day, another graph

I rebuilt the burner yesterday added more air holes in selected areas and tried to stop up the misc air leaks to see if that

Tank Temperature vs. Time in minutes

Tank Temperature vs. Time in minutes

would add more power.  I’ll let the graph speak for itself.   Note the issue at 45 or so minutes in where the temperature started to drop.  At this point the sawdust bridged so badly it wasn’t feeding any fuel.  After I poked the sawdust in the hopper, the temperature continued to rise.  I had to continue to poke the pile to get the feed rate to be somewhat normal.  Looks a lot like yesterday’s graph, so I am thinking about adding some additional air through a forced draft fan on the front end of the process.   Once again the burner did do the job but slowly and until approx. 379 minutes or a little more than 6 hours into the test did the temperature rise past the point where the circulator turned on.  I measured the chamber pressure, in this case vacuum and it measured .1″ H2O so additionally I am wondering if I need a larger exhaust fan as well.

Testing with feedback, Step 9 of a DIY record

If last years burner was a vehicle it would have been a freight train, powerful and hard to throttle back.  This new burner is a Jeep, dependable and at at this point slightly underpowered.   The burner design will no doubt need to be tweaked but it was a great first day.  As you can see the burner was having a hard time getting well lit.  Those of you with a wood stove I am sure can relate.    At about 118 minutes in the flames finally took over and the slope looks good.
The saw tooth effect you see up top is the result of the circulator pump turning on and off.  I turned up the thermostat on the shop floor which has radiant tubes so this was a big load and it did not have the power to overcome the load.  Although from the frequency change at the end you can see it was starting to catch up.    But I am going to redesign the burner to direct the air flow a little better.

Chart of Temperature vs. Minutes

Chart of Temperature vs. Minutes

OpenLog partially tested

Well I have to say, I am not particularly impressed with OpenLog’s documentation but I finally got a sketch to work with OpenLog based heavily on the OpenLog command sketch.  I soldered up a  Real time clock kit and am waiting on some male to male jumper wires to breadboard up a thermistor and clock to fully test the OpenLog data logging in a closer to real world trial.  Of course until it is finally mounted in the boiler control box and mounted on the boiler this will only be the next step in testing.

Hard experience has taught me many things work on the desk that do not work in the field due often to poor electronic practice, missing diodes, filtering capacitors, missing resistors….

Here is the code which I intend to run when I get the project bread boarded, it compiles but is untested.

RTC, Thermisoter, OpenLog test

One thermistor attached to analog pins 0
The Real time clock SDA pin is attached to analog 4, the RTC SCL pin is attached to analog pin 5

The circuit:
* Thermister  Analog in 0
* RTC SDA, Analog pin 4
* RTC SCL, Analog pin 5
* Arduino digital 0 (rx), OpenLog TX
* Arduino digital 1 (tx), OpenLog Rx
* Arduino digital 2, OpenLog Grn

Created 8/24/12

#include <math.h> // include the library code for thermsiter functions
#include <Wire.h>
#include “RTClib.h”

//section for time keeping
int hour;                //hour
int minute;              //minute

int Roomtemp;            //room temperature

int statLED = 13;        //flashes LED connected to pin 13 for troubleshooting
int resetOpenLog = 2;    //reset on OpenLog

long DataDwell = 60000;    //seperates the data readings by 1 minute
long prevmillis =0;        // previous millis

//define function to calculate the temperature in fahrenheit for Analog pin 0
double ThermisterRoom(int RawADC) {//beginning of function
double Temp;
Temp = log(((10240000/RawADC) – 10000));
Temp = 1 / (0.001129148 + (0.000234125 * Temp) + (0.0000000876741 * Temp * Temp * Temp));
Temp = Temp – 273.15;            // Convert Kelvin to Celcius
Temp = (Temp * 9.0)/ 5.0 + 32.0; // Convert Celcius to Fahrenheit
return Temp;
}//end of function

void TimeSection() {//start time function
DateTime now =;
hour=now.hour(),DEC;       //get the hour from the RTC chip
minute=now.minute(),DEC;   //get the minute from the RTC chip
}// end time function

void OpenLogData(){//start OpenLogData function
int RoomTemp = ThermisterRoom(analogRead(0));  //read from the sensor
Serial.print (hour);
Serial.print (“:”);
Serial.print (minute);
Serial.print (“, “);
Serial.println (RoomTemp);
}// end OpenLog Data section

void setup()
{//Begin Setup section
pinMode(statLED, OUTPUT);        //set pin to output
pinMode(resetOpenLog, OUTPUT);   //set pin to output

Serial.begin(9600); // initiate serial communication
//Reset OpenLog
digitalWrite(resetOpenLog, LOW);
digitalWrite(resetOpenLog, HIGH);
//Wait for OpenLog to respond with ‘<‘ to indicate it is alive and recording to a file
while(1) {
if( == ‘<‘) break;
//Send three control z to enter OpenLog command mode
//Works with Arduino v1.0
//Wait for OpenLog to respond with ‘>’ to indicate we are in command mode
while(1) {
if( == ‘>’) break;
//send the open file
Serial.print(“Templog.txt\r”); //\r in string + regular print works with older v2.5 Openlogs

//Wait for OpenLog to return to waiting for a command
while(1) {
if( == ‘>’) break;
// send the command to append the file
Serial.print(“append Templog.txt\r”);

//Wait for OpenLog to indicate file is open and ready for writing
while(1) {
if( == ‘<‘) break;

//start process of setting clock time
RTC.adjust(DateTime(__DATE__, __TIME__));

} //End setup section

void loop()
{//Begin Loop section
if (millis()-prevmillis> DataDwell)
{//start if sections
TimeSection();           //displays the time
OpenLogData();           //saves the time and solar temp to the SD card
}// end if section

}//End loop section



OpenLog Firmware updated and tested

OpenLog is a data logger from SparkFun electronics that is touted as being easy to use and a reliable writer to a microSd card.  I haven’t found that to be true, I think it is a pain in the a** but maybe that’s the experience more than the actual product.  I ordered the data logger in January and got busy and didn’t have the time to use it so I set it aside.

Really the only reason I ordered it was because I could not get GoBetwino, a Freeware Arduino Data logging software program to work.   The GoBetwino program uses a USB connection to a computer connected to the Arduino to log to a file on the PC.  A great concept that I tested and worked fine on the desktop machine.  However on the laptop that I was using to make changes to the Arduino controlling the boiler  in the shop it didn’t work.  It seemed easier to come up with a standalone solution rather than troubleshoot the USB connections, the power managment issues with the Laptop etc.  So I bought the data logger.

As I wrote in an earlier post since the time of my purchase of the OpenLog board it was recommended to update the firmware, this required updating the board with a FTDI board that accepts the USB connection from the PC to update the firmware, after 2-3 hours of frustration this task is finally completed.  The main problem being Windows XP didn’t seem to recognize the FTDI board and assign it a com port but finally was able to find the correct driver and download the firmware.

I ran the test sketch, pulled the micro SD card and reviewed the data.  The board  did log the data correctly so the next step is to write a function that writes temperature data to a file with a time stamp.  Since I have an Arduino on my desk with a real time clock chip that measures the outside temperature  as well as the temperature of a solar hot water storage tank this would seem like a perfect application to test.   After testing the function in that application it will be easy to modify the function for the monitoring of the boiler function.  I prefer to write the code in functions and call the functions from the main body of the loop.  This makes the code modular and easy to reuse.  I comment very carefully and probably over comment, but I personally prefer to make the code painfully simple to understand on the assumption I may not look at the code again for a few years.  I am hoping you will comment as well since your comments will no doubt improve the code.

I will post the function when I complete it.  Thanks for reading.

Magnehelic Data

I ordered a Magnehelic gauge from Dwyer Instruments  that measures plus or minus 2″ of water column.   This allows you to take pressure or vacuum readings within a limited range around atmospheric pressure.  Observe the nipple in the picture below.   To test the burn chamber I took my plasma

torch and cut a hole in the upper section of the burn chamber where I didn’t think a ash or flame would be an issue and welded a nipple airtight into the chamber.  As you can see I added a coupler, 3/4″-3/8″ reducer and a 1/4″ barbed nipple.   With the upper exhaust fan running alone, the burn chamber tested at barely .1″ H2O vacuum.  With the draft fan running the burn chamber vacuum fell to .05″ H2O vacuum.   No wonder there is occasionally a puff of smoke back through the system.

After that initial test in an uncleaned condition the system was taken apart and the second pipe was blocked.  After reassembly the testing was done again and the burn chamber vacuum rose.  This indicates that the venturi effect we thought we were inducing was not working.  By changing fans and cleaning the soot out, we were able to induce a vacuum of .85 in the burn chamber.  At this vacuum the smoke observed was non existent, but the exhaust pipe was significantly hotter than in the previous configuration indicating more waste heat.   So tuning the vacuum and monitoring the vacuum makes sense and may be an integral way to test the cleanliness of the pipes as well as the required O2 of the burn process.  To that end I am going to order a pressure gauge on a chip and see if I can get a reading to be monitored by the Arduino control system.    After burning in the .85″ vacuum configuration it became apparent that smoldering in the auger pipe was taking place and the system was shut down safely to allow more work to be done.  At this point it appears that .05″ H2o is insufficient and .7-.85″ is too much so a damper or variable fan drive is required to allow burn chamber vacuum adjustment.

Software cuts pellets by third, saving $112/month

Minor changes in the software that force the boiler to maintain a tighter range from the set point has cut the fuel consumption from 3 (40 pound) bags of pellets to 2 daily.    These software improvements and a extension to the pellet hopper mean the boiler will now run 24 hours without needing  additional fuel.    The hopper extension adds at least another 40 lb bag of pellets capacity bringing the total capacity to approx. 2 1/2-3 bags.  I haven’t measured only estimated.

The boiler  set point is currently set at 135°F which seems to work just fine for the temperatures we have been having and the software is consistently running within4 degrees of set point.  This range may seem excessive but seems to run just fine.  The program is becoming more modular in that there is only one number to change,  the set point.  The set point currently  is a variable declared in the setup section of the program but eventually the set point will be self adjusted by the program based on the outside temperature.  Economy and efficiency by software optimization is the goal for this next week.

We have had a very mild winter in my opinion.  The Heating Degree Day total for the month of Dec 2011 was 1091 as measured by the local weather station.  The normal is 1209 HDD a difference of 118 HDD, not as much as I would have thought.  The total for the month of January 2012 so far is 1140 with four days to go, with a normal of 1419.  We’ll see how the month ends but if it continues as the average day it will be short approx the same number of HDD as  last month,December.   My interest in HDD is to see if there is a correlation to HDD and fuel consumption.  There should be and if there is than the fuel economy is starting to improve.  As I told a friend of mine, at this point the boiler is like a truck I used to own, 10 mpg  going uphill loaded, 10 mpg empty going downhill….so seeing fuel consumption changing to track the weather will be the first step to seeing some optimization.

Software work on fuel economy and the  extrapolation of costs for the upcoming remainder of the season is of great interest.    The next step in fuel economy may be better insulation  of the boiler and piping and will not be as simple as software improvements.  But if I can get a correlation between the outside temperature and fuel consumption that is measurable then the software will be nearly optimized and further improvements will have to come from physical changes.  This week sees a 40 pound bag and $4.00 improvement per day, $28/week, $112 per month.  Next week’s goal:  another $60/month.  I am hoping for a total seasonal heating cost of $500 or less using $200/ton pellets.  I will consider that a huge victory for heating a 2300 sq ft house with 3 garage doors.