This is based on a one week assignment given to my Instrumentation Control and Sensors Class (EEGR-419) at Morgan State University during the Fall, 96 semester. Many thanks to them!
This discussion illustrates how you may use a simple thermistor with a 555 to measure temperature using a Stamp BS-1.
Of course, many people have done this. However, this approach uses an 256 byte EEPROM for table lookup and thus this concept may be of aid in measuring quantities other than temperature.
This discussion also illustrates how to convert a quantity to BCD, and then to characters so as to continually send data to a terminal or a PC.
Consider the 555 circuit shown in Figure 1. The high and low times at the output of the 555 are;
t_high = 0.693 * (R1 + R2) * C t_low = 0.693 * R2 * C
Assume that R2 is a thermistor designated R_therm having a nominally 50K resistance at 25 degrees C. Assume C is 0.47 uFd. Thus, t_low at 25 degrees C is;
t_low = 0.693 * 50.0e3 * 1.0e-6 = 34,650 usecs
Thus with the 555 output connected to Pin7 (term 14) of the Stamp, the pulsin command might be used to measure t_low. Knowing C, the value of R_therm may be calculated.
R_therm = t_low / (0.693 * C)Then, one might use the two point model of an NTC thermistor to determine the temperature;
T_kelvin = 1/ (a + b * ln (R_therm)) (See Note below.) T_f = (T_kelvin - 273) * 1.8 + 32
Thus, by measuring the 555 output T_low, the temperature T_f may be calculated by using the above expressions.
Unfortunately, such calculations are not possible using the Stamp.
I used a Panasonic NTC Thermistor, Digikey PNT-122-ND. For this device;
a= 1/4800 b= 1.101584e-3You may order this device from me for $1.00, or you may send me e-mail giving me the resistance of the thermistor at two temperatures and I will reply with the values of "a" and "b" to use in the above equation).
To summarize, an algorithm for determining the temperature would be to use the pulsin command to measure the t_low and then calculate T_f using the above equations. However, such floating point calculations are beyond the capability of the Stamp.
An alternative is a lookup table where the temperatures corresponding to various values of t_low are first calculated and written to EEPROM using a PC. The Stamp may then map the t_low reading to an EEPROM address and then read the corresponding temperat ure at that location .
I used a spreadsheet (Quattro) to generate 256 points. By fooling with the value of C and various ranges of the number of 10 usec clock ticks, I eventually was able to generate values of T_f in the range of 32 to over 100 degrees F.
Please refer to file t_therm.dat
Column A is simply an index ranging from 0 to 255. Column B is the number of 10 usec clock ticks ranging from 820 to 7195 in steps of 25. Columns C, D and E are the resistance R_therm, T_kelvin and T_f calculated from the above equations. Column F is t he temperature in degrees F rounded to an integer.
Thus, if the pulsin command results in 1695 clock ticks, the index or address is 35 and the corresponding temperature is 76 degrees.
If an EEPROM contained the 256 temperatures in Column F, one could take the result of the pulsin command, map this into an address and then fetch the content of that address.
Note that in the table, the number of 10 usec clock ticks are spaced at 25. Thus, mapping clock ticks to an address is a simple matter of;
address = (ticks - 820) /25
"Calculating" the temperature is then a matter of simply fetching the value at that address.
top: pulsin 7, 0, ticks tmp = ticks-820 adr = tmp / 25 gosub read EEPROM we haven't done that yet debug eeprom_value This is T_f goto top
But, wait. Could we get more precision. Of course, we could go to two bytes per temperature, but in this case, we have yet to use a full byte as the largest value is 101.
Returning to the spreadsheet, Column G is the value of temperature T_f multiplied by 2.5 (10/4). If this value is stored in EEPROM (as opposed to Column F);
pulsin 7, 0, ticks tmp = ticks-820 adr = tmp / 25 gosub read EEPROM we haven't done that yet T_f = eeprom_value * 10 * 4 /10 Or just T_f = eeprom_value *4 goto top
Note that this provides three significant figures.
An important point is that this scaling may be done with any quantity. For example, assume you are measuring Zizos which range from 2000 to 3000. Adjusting the higher quantity to 250;
stored_data = (Zizos - 2000) * 250/1000which causes stored_data to be 250 and 0 for a Zizo count of 3000 and 2000, respectively.
Note also, you can save the data in EEPROM in BCD which can save a good amount of precious programming area in the Stamp. My point is, if possible, do the calculations outside the Stamp in generating a lookup table and your Stamp programming then amounts to little more than reading EEPROM.
Programming the EEPROM.
In another discussion, I show how to program a 93C56 using a PC's parallel port. In that discussion, program EEPROM1.C illustrates how to read a file consisting of lines, each line consisting of an address and the data to be stored in that address.
To see this discussion
In this example we were discussing above, the file would consist of columns A and G;
0 252 1 249 2 247 etc
You now have your programmed EEPROM. It is important to note that this was all done without the Stamp. That is, the calculations were made using a spreadsheet and the programming was done using a PC's parallel port.
The following is the connection to the Stamp
Stamp EEPROM Pin0 (term 7) ----------------> CS (term 1) Pin1 (term 8) ----------------> CLK (term 2) Pin2 (term 9) ----------------> DI (term 3) Pin6 (term 13) <--------------- DO (term 4) GRD --- Vss (term 5) +5 ------ Vcc (term 8) GRD ---- ORG (term 6)
Note that the EEPROM DI and DO may share the same pin on the stamp. However, until you have fully debugged your program it is suggested that you use two different pins on the Stamp as shown above.
Note that Pin7 (term 14) on the Stamp is used for the output of the 555.
The pseudo code for reading the Stamp from the EEPROM follows;
CS low, CLK low, DI low CS high Shift out 12 bit code $c00 + address on Pin2 beginning with most sig bit Get 8 bits on Pin 6 (most sig bit first) CS low
Program MEAS_TMP.BAS follows.
' Program MEAS_TMP.BAS ' ' Illustrates technique for measuring temperature by measuring t_low ' of external 555 and mapping this into an address of an external ' EEPROM. The temperature is read from the EEPROM, converted to BCD ' and output serially to an external terminal. ' ' Program continually loops with 5 sec pause. ' ' Pins 0, 1 and 2 are used for control of the external EEPROM and ' correspond to CS, CLK and DI, respectively. DO on the external EEPROM ' is read on Pin6. ' ' Pin7 is used to read the 555 timer. ' ' Pin3 is used as a serial output. ' ' Pin4 and Pin5 are not used. ' ' Peter H. Anderson, MSU, Dec 20, '96 symbol ticks = w0 symbol temp = w0 symbol outdata = w0 symbol t_f = w0 symbol n = b2 symbol adr = b3 symbol data = b4 symbol hunds = b2 symbol tens = b3 symbol units = b4 symbol tenths = b5 symbol cs = pin0 symbol clk = pin1 symbol out_d = pin2 symbol in_d = pin6 dirs = %00001111 pins = %00000000 main: pulsin 7, 0, ticks 'measure the t_low debug ticks tmp = ticks-820 'adr=(ticks-820)/25 adr=temp/25 ' debug adr outdata = $c00+adr 'to read from EEPROM ' debug outdata gosub read_eeprom 'read data from EEPROM gosub calc_temp 'and calculate temperature ' debug t_f gosub display_t_f 'display temperature on external terminal pause 5000 goto main read_eeprom: cs = 0 clk = 0 out_d = 0 cs = 1 for n=0 to 11 ' serially shift out command to EEPROM to read out_d = outdata/%100000000000 pulsout 1, 3 outdata = outdata * 2 next gosub get_data ' now read the EEPROM cs = 0 return get_data: 'fetch the 8-bits from EEPROM, most sig first data = 0 for n = 0 to 7 data = data * 2 pulsout 1, 3 if in_d = 0 then L2 data = data + 1 L2:next return calc_temp: t_f = data * 4 'calculate T_f from data read from EEPROM return display_t_f: gosub convert_bcd 'convert to BCD gosub out_ser 'and output to serial terminal return convert_bcd: hunds = t_f / 1000 + "0" 'note that hunds is ASCII char t_f = t_f // 1000 tens = t_f / 100 + "0" t_f = t_f // 100 units = t_f / 10 + "0" tenths = t_f //10 return out_ser: serout 3, N2400, (hunds, tens, units, ".", tenths, "$0a","$0d") return
All of this assumes the thermistor is precisely 50 Kohms at 25 degrees C, and that the value of the capacitor is precisely 0.47 uFd.
However life is never that way. However, you need not generate a new lookup table.
Assume, you know a temperature is 74.3 degrees. Note that in the spread sheet t_therm.dat, this corresponds to a t_low of 1780 ticks. However, when using your Stamp and thermistor arrangement, you note that the Stamp is reporting 1320 ticks which corresponds to 84.0 degrees.
All that is required is to adjust the number of ticks to report the correct temperature by multiplying by a "fudge", 1320 / 1780 = 0.74157. By fooling with a few ratios you should be able to quickly find something that is close. I didn't fool too long a nd found that 23/31 = 0.74193. Perhaps if I had fooled a bit more, I could have found something closer.
Thus, the revised code;
pulsin 7, 0, ticks 'measure the t_low debug ticks adjusted_ticks = ticks * 29/31 adjusted_ticks = ticks / 5 * 29 / 31 * 5 tmp = adjusted_ticks-820 'adr=(ticks-820)/25 adr=temp/25 debug adr outdata = $c00+adr 'to read from EEPROM
Note that I didn't quite simply multiply by 29 and then divide by 31. Rather, I noted that the largest value of "ticks" is nominally 7000 and to multiply by 29 would exceed the capability of the Stamp (65,535). Thus, I first divided by 5 to avoid this, and finally multiplied by 5. Admittedly, there is some truncation error in doing this, but then again, the resolution in the example which was presented is limited to 25.