![]() |
The Virtual Weber Bulletin Board
Automatic Temperature Control Systems
Version 2 of my homebrew controller|
Go
![]() |
New
![]() |
Find
![]() |
Notify
![]() |
Tools
![]() |
Reply
![]() |
|
|
TVWBB Fan |
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:
// 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);
}
|
|||
|
|
TVWBB Super Fan |
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 Team 'Second Star BBQ', FBA & KCBS CBJ 18" WSM, 22" WSM, 22 OTG, 18 OTG, SJS, Vermont Castings Gasser |
|||
|
|
TVWBB Super Fan |
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 Team 'Second Star BBQ', FBA & KCBS CBJ 18" WSM, 22" WSM, 22 OTG, 18 OTG, SJS, Vermont Castings Gasser |
|||
|
|
New Member |
Bob Hruska,
Please email Jerry Bass at Jerry.Bass@lsi.com. |
|||
|
|
New Member |
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); } |
|||
|
|
New Member |
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 |
|||
|
|
TVWBB Member |
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 |
|||
|
|
TVWBB Fan |
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. |
|||
|
|
TVWBB Member |
Thanks for the great post guys and sharing your hard work.
Fred Snyder Relax and have a home brew while your smoking your Que. |
|||
|
|
TVWBB Member |
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.
|
|||
|
|
TVWBB Member |
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 Relax and have a home brew while your smoking your Que. |
|||
|
|
TVWBB Member |
here's the link to a lot of different sizes at digi-key
http://search.digikey.com/scri...574&k=ribbon%20cable good luck Relax and have a home brew while your smoking your Que. |
|||
|
|
TVWBB Member |
Thanks Fred
|
|||
|
|
TVWBB Fan |
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. |
|||
|
|
TVWBB Member |
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. |
|||
|
|
New Member |
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. |
|||
|
|
New Member |
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 |
|||
|
|
New Member |
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[i][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 |
|||
|
|
TVWBB Pro |
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? |
|||
|
|
TVWBB Member |
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 Relax and have a home brew while your smoking your Que. |
|||
|
| Powered by Social Strata | Page 1 2 3 4 5 ... 25 |
|
The Virtual Weber Bulletin Board
Automatic Temperature Control Systems
Version 2 of my homebrew controller