Temperature Measurement Using an EEPROM Lookup Table

copyright, Peter H. Anderson, Morgan State University
Baltimore. MD 21239, Dec, 96

Introduction.

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-3
You 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.

Table Lookup.

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.

For example;

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/1000
which 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 Click Here.

In this example we were discussing above, the file would consist of columns A and G;

     0    252
     1    249
     2    247

     etc

The Stamp.

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

MEAS_TMP.BAS.

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

Calibration.

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.