Version 2 of my homebrew controller


 
The table lookup method is a very popular way of doing it and it saves a lot of CPU cycles if you don't have them to spare.

I used the equation just to try something new.

Here is another example that I've seen someone else using on the arduino with the ET-73 probes:

<pre class="ip-ubbcode-code-pre">

// Lookup table data for a Maverick Industries ET73 probe pulled up to 5 volts with a 22k resistor
const prog_uint16_t table[] PROGMEM = {968, 952, 936, 919, 898, 873, 845, 817, 786, 751, 713, 675, 638, 599, 560,
516, 477, 436, 403, 371, 338, 310, 283, 257, 233, 212, 190, 172, 156, 141,
128, 116, 105};

/**
* Gets the value of the specified table entry
* @param index Table index
* @return table value for the given index
*/
int tableEntry(int index) {
return pgm_read_word(table + index);
}


/**
* Gets the temperature for the given raw A/D value using the provided table
* @param rawValue the raw A/D converter value (0 - 1023)
@ @param tableData pointer to the lookup table data
* @return the corresponding temperature in tenths of degrees F (or -1 or 9999 if out of range)
*/
int convert(int rawValue) {

// Check for a value that is outside the range of the lookup table and
// return the special value (also makes sure the subsequent while loop
// doesn't go off into the weeds)
if (rawValue >= tableEntry(0)) {
return -1;
}
if (rawValue <= tableEntry(TABLE_SIZE - 1)) {
return 9999;
}

// Locate pair of table entries that the raw value lies between
int i = 0;
while (rawValue < tableEntry(i + 1)) {
i++;
}

// Interpolate between the values in the lookup table
// Fractional portion of the value between the two table entries (percent)
int fraction = (100 * (tableEntry(i) - rawValue)) / (tableEntry(i) - tableEntry(i+1));

// Compute and return the temperature value
return (MIN_TEMP * 10) + (SPAN * ((i * 100) + fraction) / 10);

}
</pre>
 
Yea!! I finally got it working!! Both fans are up and running and the probes agree to within 2 degrees.

I'm using the same lookup table for both sides along with the same math so theoretically they should be identical. The error is probably with my fixed resistors. I should have matched them but didn't (wondering if I should go back and do it now). I used 1%ers but maybe that's not close enough.

I'll go into work Saturday (it's supposed to rain) and do a run with one of my Thermotron ovens that is accurate to within 1/2 degree C and tweek my lookup table. The acid test will be Sunday when I actually mount the fans onto the smokers and really cook a brisket in the 22" and maybe some ribs in the 18".

Maybe, just maybe (fingers and toes crossed) I'll be able to sleep the whole night when I'm at comps next weekend. Since I'm a one-man team, sleep is really important.

Russ
 
Alright! Now we're cookin'!

Made a couple of changes to your schematic Bob. First, I added a pretty hefty capacitor (100uF at 25vdc) to the fan outputs. The fans were singing like crazy and I couldn't figure out why until I looked at the output with a scope. Then I remembered that the output is a pulse width modulated output. The cap gets pulse charged via the PWM and 'averages' out the pulses to a DC level and now the fans are super quiet.

I also added a smaller capacitor (10uF) to the A/D input. This serves two purposes. It smoothes out the DC input voltage and makes the A/D readings smoother. It also decouples digital noise I was getting on the A/D input as the impedances were getting very high at lower temperatures.

Ran the controller this morning from 0C to 100C (as high as my oven will go) in 5C steps and it tracked to within 1 degree all the way.

Just for fun I put my two Polders in alongside just to see how close they are. One was dead on, the other was off by about 5 degrees the whole way. Hmm..

Next up is to add the optical encoder so I can adjust the set temp. Going to try out using a hardware interrupt. Should be interesting.

Now to bolt the fan to my WSMs this afternoon and give it a trial run!

Russ
 
This is a very cool post guys. I'm trying to put one of these together and Bob's setup has been instrumental.

A problem that I have had is figuring out how to calibrate a thermistor from a vendor that doesn't have a datasheet readily available. I am figuring out how to get some reference datapoints by using a separate calibrated probe at specific temperatures and then read the resistance on another probe (production probe for pit).

I found a pretty cool sketch on another site that I'm going to use to return the resistance. I haven't done this yet, but will give it a shot soon. I'll post my results.

I just figured I'd post the sketch here as it seems applicable:

/*
Measuring temperature with Arduino

Alan Wendt, PhD

A thermistor is a resistor whose resistance decreases
as the temperature increases. With some care, you can
use Arduino to read accurate temperatures. My project
is a decent evaporative cooler controller. In Arizona, you
can usually run the fan motor on high or low, and you can
also turn the water on and off. If you measure the temperature
in the house, outside in the shade, and the air right after the
evaporative pads, you can calculate the relative humidity,
and also program the unit to shut down the pump if the outside
air is already cool enough.

To measure the current resistance of the thermistor,
wire a thermistor and a 10K resistor up in serial.
Connect the open end of the thermistor to +5V, and the
open end of the resistor to ground. Now, there's a 5V drop
across the pair, and the drop across the thermistor is
proportional to its resistance as a fraction of the
sum of both resistances. For example, if the voltage at the
junction of resistor and thermistor is 4, that means that the
thermistor dropped 1 volt, and the fixed resistor dropped 4, so the
thermistor's current resistance is 1/4th of the fixed.

Once you have the resistance, the temperature of the thermistor is approximated with the formula:

T = 1 / (A + B log(R) + C log(R) ^ 3)

where A, B, and C are experimentally-determined constants.
(The Steinhart-Hart approximation). You need to collect
4-5 few data points, preferably with a big temperature spread.

I put the board into a refrigerator along with a little
Radio Shack remote thermometer sensor, and snaked out
the USB cable and the remote sensor cable. Once the program's
downloaded, enter the "serial monitor" in the Arduino
SDK to see the output.

Google "steinhart hart moshier" for further discussion of calibration, and for software to calculate the constants.

*/

int firstSensor = 5; // first analog sensor

void setup()
{
// start serial port at 9600 bps:
Serial.begin(9600);
}

void loop()
{
// read the analog input
float a5 = analogRead(5);
Serial.print("analogread = ");
Serial.print(a5);
Serial.print("\n");

// calculate voltage
float voltage = a5 / 1024 * 5.0;
Serial.print("voltage = ");
Serial.print(voltage);
Serial.print("\n");

// calculate resistance
float resistance = (10000 * voltage) / (5.0 - voltage);
Serial.print("resistance = ");
Serial.print(resistance);
Serial.print("\n");

// calcuate temperature. Use these values for A, B, and C till you
// get everything working, and then do some measurements to calibrate
// your thermistor in circuit.
float logcubed = log(resistance);
logcubed = logcubed * logcubed * logcubed;
float kelvin = 1.0 / (-7.5e-4 + 6.23e-4 * log(resistance) - 1.73e-6 * (logcubed));

// Convert to Fahrenheit
float f = (kelvin - 273.15) * 9.0/5.0 + 32.0;
Serial.print("temp = ");
Serial.print(f);
Serial.print("\n");

// delay 1s to let the ADC recover:
delay(1000);
}
 
Alright... I had to try it tonight. I ran the code with only one minor change--setting the delay to 5000. The results are interesting. I am using a cooper-atkins 9335A food probe. It was sitting on the table and the room temp was about 71 degrees. Right after I started the sketch, I picked up the probe and put it in my hand, clenched to try and bring up the temperature. The results are strange in two ways:

1.) The temp is reading very low, obviously not in upper 60's or lower 70's.

2.) The temperature actually drops when I put it in my hand. Either I'm dead and didn't realize it or my setup is jacked somehow.

I also tried this on some cheaper Polder probes and the results were about the same.

I'll keep investigating, but haven't had any breakthroughs on google yet.

Here is the output:

analogread = 950.00
voltage = 4.64
resistance = 128378.38
temp = 18.72
analogread = 949.00
voltage = 4.63
resistance = 126533.34
temp = 18.55
analogread = 930.00
voltage = 4.54
resistance = 98936.17
temp = 16.11
analogread = 916.00
voltage = 4.47
resistance = 84814.82
temp = 15.06
analogread = 909.00
voltage = 4.44
resistance = 79043.48
temp = 14.70
analogread = 904.00
voltage = 4.41
resistance = 75333.34
temp = 14.49
analogread = 902.00
voltage = 4.40
resistance = 73934.43
temp = 14.42
analogread = 900.00
voltage = 4.39
resistance = 72580.65
temp = 14.35
analogread = 898.00
voltage = 4.38
resistance = 71269.85
temp = 14.29
analogread = 898.00
voltage = 4.38
resistance = 71269.85
temp = 14.29

Alan
 
Dose any one have Front and back picture of their proto-shield circuit. I don't know how to read electrical schematics that well , and I am having problems. I have traced a lot of it with the picture of the built circuit and a picture of the unpopulated board. I can not clearly see what is going on around the power transistor diode area. May be pictures showing the externals connected such as the screen and the power and probe and blower wire connections. Dose any one ave a complete pars list listing all of the connecting jacks etc. Any Help would be greatly appreciated.

PS I emailed the designer and did not get a
reply yet.

SRoy
 
Alan-

It may be that you have the voltage divider backwards? (or your math to compute it) If you run switch 5V and ground, the circuit will be backwards to what you expect. When I first started the project I ran 5V through the thermistor then to the 22K resistor and then to ground. This worked (after reversing the math to figure the ratio) but it also made for wonky readings when you touched the metal probe. Make sure the probe goes to ground.
 
Dose any one know where to get the white ribbon type connection wire from that was used in version 2. Thanks for replying to my email Bob Hruska.
 
S Roy,

You should be able to get it at digi-key and maybe at a radio shack store, depending on how well your local one is set up. You might also google ribbon cable. It can come up to 40 wires in a ribbon or more, but you can easily peel off the number you need. If you don't find it in the next few days, leave another post and I will find a link for you and post it.

Fred
 
Originally posted by S ROY:
Dose any one know where to get the white ribbon type connection wire from that was used in version 2. Thanks for replying to my email Bob Hruska.

That ribbon cable is from an IDE cable that I had lying around. Strip off the number of connectors you need and you're good to go. One IDE cable will do a lot of projects.
 
Here are some pictures of my build of Bob's design. BTW Bob was awesome helped me with a bunch of, frankly, stupid questions I had. To pay him back I'll try to answer what I can on this topic (so he doesn't have to bear the load himself).

I guess I should point out I altered Bob's plans a bit. I added 5 temperature probes (actually 6, but one isn't working), basically I used all the analog pins on the Arduino to read temperature. I altered his sketch accordingly (I can upload that if people want it), plus I altered his sketch to produce JSON output over the web, which opens up a ton of possibilities for using a web app to control and log.

photo%20[1%29.jpg
photo%20[2%29.jpg
photo.jpg
 
Bob, Thanks for the response on the possible backwards voltage divider. I ended up putting this project down for a while, but before I did I finally managed to get it to work with the table lookup method.

If anyone needs the numbers for a cooper atkins or a polder, these are them. Both probes seem to be made by the same manufacturer in China.

short temptable[NUMTEMPS][2] = { // Cooper Atkins / Polder Resistance Table
{-40,336450},
{-39,324270},
{-38,312580},
{-37,301350},
{-36,290560},
{-35,280200},
{-34,270250},
{-33,260680},
{-32,251490},
{-31,242660},
{-30,234170},
{-29,226010},
{-28,218160},
{-27,210610},
{-26,203350},
{-25,196370},
{-24,189650},
{-23,183180},
{-22,176960},
{-21,170980},
{-20,165210},
{-19,159660},
{-18,154320},
{-17,149170},
{-16,144210},
{-15,139440},
{-14,134840},
{-13,130410},
{-12,126140},
{-11,122030},
{-10,118060},
{-9,114240},
{-8,110550},
{-7,107000},
{-6,103570},
{-5,100260},
{-4,97072},
{-3,93996},
{-2,91027},
{-1,88163},
{0,85399},
{1,82731},
{2,80156},
{3,77670},
{4,75269},
{5,72951},
{6,70712},
{7,68550},
{8,66461},
{9,64443},
{10,62403},
{11,60609},
{12,58788},
{13,57028},
{14,55326},
{15,53681},
{16,52091},
{17,50553},
{18,49065},
{19,47627},
{20,46235},
{21,44889},
{22,43586},
{23,42326},
{24,41106},
{25,39926},
{26,38783},
{27,37677},
{28,36606},
{29,35569},
{30,34565},
{31,33592},
{32,32650},
{33,31738},
{34,30854},
{35,29999},
{36,29169},
{37,28366},
{38,27587},
{39,26832},
{40,26100},
{41,25391},
{42,24703},
{43,24037},
{44,23390},
{45,22763},
{46,22155},
{47,21565},
{48,20993},
{49,20438},
{50,19899},
{51,19376},
{52,18869},
{53,18377},
{54,17899},
{55,17435},
{56,16985},
{57,16548},
{58,16123},
{59,15711},
{60,15311},
{61,14922},
{62,14544},
{63,14177},
{64,13820},
{65,13474},
{66,13137},
{67,12810},
{68,12492},
{69,12183},
{70,11883},
{71,11591},
{72,11307},
{73,11031},
{74,10762},
{75,10501},
{76,10247},
{77,10000},
{78,9759.70},
{79,9526},
{80,9298.60},
{81,9077.30},
{82,8862},
{83,8652.40},
{84,8448.50},
{85,8250},
{86,8056.80},
{87,7868.70},
{88,7685.60},
{89,7507.30},
{90,7333.70},
{91,7164.60},
{92,7000},
{93,6839.70},
{94,6683.50},
{95,6531.40},
{96,6383.20},
{97,6238.80},
{98,6098.20},
{99,5961.10},
{100,5827.60},
{101,5697.40},
{102,5570.60},
{103,5446.90},
{104,5326.40},
{105,5208.90},
{106,5094.30},
{107,4982.70},
{108,4873.80},
{109,4767.60},
{110,4664},
{111,4563},
{112,4464.50},
{113,4368.40},
{114,4274.70},
{115,4183.20},
{116,4094},
{117,4007},
{118,3922.10},
{119,3839.20},
{120,3758.30},
{121,3679.40},
{122,3602.30},
{123,3527.10},
{124,3453.70},
{125,3382},
{126,3312},
{127,3243.70},
{128,3177},
{129,3111.80},
{130,3048.20},
{131,2986.10},
{132,2925.40},
{133,2866.20},
{134,2808.30},
{135,2751.70},
{136,2696.40},
{137,2642.50},
{138,2589.70},
{139,2538.20},
{140,2487.80},
{141,2438.60},
{142,2390.50},
{143,2343.50},
{144,2297.50},
{145,2252.60},
{146,2208.70},
{147,2165.70},
{148,2123.80},
{149,2082.70},
{150,2042.60},
{151,2003.30},
{152,1964.90},
{153,1927.40},
{154,1890.70},
{155,1854.70},
{156,1819.60},
{157,1785.20},
{158,1751.60},
{159,1718.60},
{160,1686.40},
{161,1654.80},
{162,1623.90},
{163,1593.70},
{164,1561.20},
{165,1535.30},
{166,1507},
{167,1479.30},
{168,1452.20},
{169,1425.70},
{170,1399.80},
{171,1374.40},
{172,1349.50},
{173,1325.20},
{174,1301.40},
{175,1278},
{176,1255.20},
{177,1232.80},
{178,1210.90},
{179,1189.50},
{180,1168.50},
{181,1147.90},
{182,1127.70},
{183,1108},
{184,1088.70},
{185,1069.70},
{186,1051.10},
{187,1033},
{188,1015.10},
{189,997.66},
{190,980.54},
{191,963.77},
{192,947.33},
{193,931.22},
{194,915.43},
{195,899.95},
{196,884.78},
{197,869.91},
{198,885.33},
{199,841.04},
{200,827.03},
{201,813.3},
{202,799.83},
{203,786.63},
{204,773.68},
{205,760.99},
{206,748.54},
{207,736.33},
{208,724.36},
{209,712.61},
{210,701.09},
{211,689.79},
{212,678.71},
{213,667.8},
{214,657.8},
{215,646.59},
{216,636.28},
{217,626.17},
{218,616.25},
{219,606.51},
{220,596.96},
{221,587.58},
{222,578.38},
{223,569.34},
{224,560.48},
{225,551.77},
{226,543.23},
{227,534.84},
{228,526.64},
{229,518.53},
{230,510.59},
{231,502.79},
{232,495.14},
{233,487.62},
{234,480.24},
{235,472.98},
{236,465.86},
{237,458.86},
{238,451.99},
{239,445.24},
{240,438.61},
{241,432.09},
{242,425.69},
{243,419.4},
{244,413.22},
{245,407.15},
{246,401.19},
{247,395.32},
{248,389.56},
{249,383.9},
{250,378.33},
{251,372.85},
{252,367.48},
{253,362.19},
{254,356.99},
{255,351.88},
{256,346.86},
{257,341.92},
{258,337.06},
{259,332.29},
{260,327.6},
{261,322.98},
{262,318.44},
{263,313.98},
{264,309.59},
{265,305.27},
{266,301.03},
{267,296.86},
{268,292.75},
{269,288.72},
{270,284.74},
{271,280.83},
{272,276.99},
{273,273.21},
{274,269.48},
{275,265.82},
{276,262.21},
{277,258.67},
{278,255.18},
{279,251.74},
{280,248.36},
{281,245.03},
{282,241.76},
{283,238.53},
{284,235.36},
{285,232.24},
{286,229.17},
{287,226.15},
{288,223.18},
{289,220.25},
{290,217.37},
{291,214.53},
{292,211.74},
{293,208.99},
{294,206.28},
{295,203.62},
{296,201},
{297,198.41},
{298,195.87},
{299,193.37},
{300,190.9},
{301,188.47}
};

I'm picking up the project again so hopefully I can finish this out.

Thanks guys for contributing.
 
Now I remember why I put it down for a while... Trying to figure out Bob's logic with the DoControlAlgorithm and update_time functions. Holy @#*#, I'm going to have to find an old calculus book!

AD
 
Can anyone help me with the following code snippet?

int thermister_temp(int aval) {

int Z;
char line[40];

float voltage_aval = aval / 1024 * 5.0;
float resistance_aval = (1000 * voltage_aval) / (5.0 - voltage_aval);

sprintf(line, "Pit=%3d aval=%3d vaval=%.4f raval=%.4f", pit_temp, aval, voltage_aval, resistance_aval);
Serial.println(line);

for (int i=NUMTEMPS; i>0; i--)
{
// if (temptable[1] >= resistance_aval)
// {
// Z = temptable[i+1][0];
// break;
// }
}
return (Z);
}

My serial output shows the following:

Pit= 0 aval=956 vaval=? raval=?
Pit= 0 aval=954 vaval=? raval=?
Pit= 0 aval=956 vaval=? raval=?
Pit= 0 aval=954 vaval=? raval=?


I have tried everything, but I can't figure this out. If I change the floating point to an integer and set it to some value, it prints fine. When I move to floating point it goes berzerk. Maybe I've just been looking at this thing for too long tonight.

Thanks
 
Maybe it is a limitation of the sprintf in the library you are using.

Try using just %f and see if it works any better.

Does the cross compiler support floating point at all?
 
Hi J,

Are you using the keep alive portion of Bob's code? Do you have a program running on your pc that sends a reply? Is it just working off a ping since all but the first buffer is discarded?
Thanks,
Fred
 

 

Back
Top