BASIC STAMP 2 - A 4000 Byte Data Logger Using the DS1621 Thermometer and 24LC32 Serial EEPROM

copyright, Peter H. Anderson and Towanda Malone
Dept of Electrical Enginnering, Morgan State University
March 20, '97

Introduction

This discussion shows how to interface a Dallas Semiconductor DS1621 Thermometer and 24LC32 Serial EEPROM with the Basic Stamp BS2 so as to realize a 4000 byte data acquisition system using only two signal leads. Note that this could easily be extended t o eight DS1621s and eight 24LC32s to provide measurements at eight points and 32,000 bytes of memory storage.

Note that the combined cost of the 1621 and 24LC32 is less than $8.00.

Discussion

This discussion is in rough form. It will be reworked and eventually it will become a part of a new book which discuuses interfacing with serial devices. But, in the interim, you may find it useful.

Program DATA_LOG.BS2 assumes that the DS1621 is set for an A2A1A0 address of 1 and the 24LC32 for an address of 0. Note that in fact, as the two are different devices, they both could have been assigned the same 3-bit address. I used different addresses to illustrate how the variable "device" must be changed depending on which device the Stamp is communicatiing with.

When the Stamp is reset, the program forks based on the setting of input bit 8 to either begin a logging sequence or to dump the previously logged data to the PC. Thus, a data acquisition unit consisting only of the Stamp and the two ICs might be deployed to measure and log temperature. The user would set input 8 to a logic 0 and reset the processor to begin the logging sequence. The logged data might later be uploaded to a PC, by first setting input 8 to a logic one and resetting the Stamp.

The current technique for uploading is crude, consisting only of the use of the Stamp "debug" command. We are working on serial software for the PC which will permit the data to be saved to disk in a format which lends later analysis using spreadsheet. (Note that the various debug writes to the terminal must be removed. I left them in as I found them to be invaluable in appreciating what was going on in communicating with the I2C devices.)

The data logging portion of the program is a combination of routines developed for the DS1621 and 24LC32.

The configuration register in the DS1621 is set to $02. In fact, this need only be done once in the lifetime of the device and could well be done in another program.

The program then takes 4000 measurements at nominally one minute intervals. The DS1621 is commanded to start conversion and then a conversion is read from the 1621. The conversion process is then stopped to conserve power. The data is then written to E EPROM and for good measure, I also read the data back from the EEPROM. This verification is only for debugging and should be removed in the final product.

In addition to improving on the crude technique for uploading the data to the PC, there are a number of other possible areas for improvement.

' DATA_LOG.BS2
'
' Illustrates implementation of a data logger using a single DS1621
' thermometer and a 32 K serial EEPROM on a single two wire pair.
'
'
' BS2                            DS1621             24LC32
'
'   			         A2=A1=A0=1	    A2=A1=A0=0
'
' Pin5 (term 10) --------------- SCL (term 2) ----- SCL (term 6)
' Pin4 (term 9) ---------------- SDA (term 1) ----- SDA (term 5)
'
' Note that 10K pullup resistors to +5VDC are required on both signal
' leads.
'
' Debug and Pause statements were included only to see what is going on.
'
'
' copyright Peter H. Anderson and Towanda L. Malone, MSU, March 18, '97
'

	address var byte	' eeprom address
        device var byte         ' device 0-7

        o_byte var byte         ' byte to send to device
	i_byte var byte		' byte fetched from eeprom
	i_9_bit var word        ' 9 bit reading fetched from 1621
	dta var byte		' data to be programmed in eeprom
	T_C var byte		' Temperature in degrees C

        n var byte              ' index
        b var bit               ' bit
	times var word		' number of measurements

        ack_bit var bit

        SDA_PIN con 4
        SCL_PIN con 5
        SDA_OUT var out4
        SCL_OUT var out5
        SDA_IN  var in4
        SDA_DIR var dir4

        OUT con 1
        IN con 0

        dirs=$f0ff

main

	if IN0=8 then log_data	' if IN8 is zero log data
				' if at logic 1 then dump to PC

dump_data	' read each location in turn and output to terminal

	address = $000
	device=0				' eeprom
	for times = 0 to 3999
	   gosub read_random_data
	   debug dec i_byte
	   debug $0d			' newline character
	   address=address+1
	next
	stop

log_data

	device=1		' DS1621.  A2=0, A1=0, A0=1
	gosub  config_1621	' write to 02 configuration register

	address=$000
	for times = 0 to 3999	' 4000 measurements

	   device = 1
	   gosub start_convert	' write start convert to DS1621
           gosub meas
	   T_C = i_9_bit/2      ' sacrifice some accuracy
	   debug dec T_C
	   gosub stop_convert	' stop conversion to save power

           device=0		' now the eeprom
	   dta = T_C
           gosub write_random_data	' save the temperature
	   gosub read_random_data	' just to check
	   debug dec i_byte
	   sleep 60			' pause for a minute
	   address=address+1		' next address
	next

	stop


config_1621				'configure DS1621

        gosub start
	o_byte = $90 | (device<<1)    ' 1001 a2 a1 a0 0
	gosub out_byte
	gosub nack
	o_byte = $ac		' config as CPU control, continuous
	gosub out_byte
	gosub nack
	o_byte = $02
	gosub out_byte
	gosub nack
	high SCL_PIN
	gosub sstop
	return

start_convert			' begin temperature conversion

        gosub start
	o_byte = $90 | (device<<1)
	gosub out_byte
	gosub nack
	o_byte = $ee
	gosub out_byte
	gosub nack
	high SCL_PIN
	gosub sstop
	return

meas 	' sends read temperature command
	' value fetched from DS1621 return in i_9_bit

        gosub start
	o_byte = $90 | (device<<1)	' note this is a write
	gosub out_byte
	gosub nack
	o_byte = $aa		' command to read temperature
	gosub out_byte
	gosub nack
	gosub start          	' note there is no stop

        o_byte = $90 | (device<<1) | $01	' now a read
	gosub out_byte
	gosub nack
	gosub get_9_bits
	high SCL_PIN
        gosub sstop
	return

stop_convert	' send command $22 to stop the continuous conversion

        gosub start
        o_byte = $90 | (device<<1)
        gosub out_byte
        gosub nack
	o_byte = $22
	gosub out_byte
	gosub nack
	high SCL_PIN
	return

write_random_data	'writes specified data to specified address
agn

	gosub start

	o_byte=$a0 | (device << 1)		' 1 0 1 0 a2 a1 a0 0
	gosub out_byte
	gosub nack
	o_byte= address >> 8		' high byte of address
        gosub out_byte
	gosub nack
	o_byte= address & $ff		' low byte of address
	gosub out_byte
	gosub nack
	o_byte=dta
	gosub out_byte
	gosub nack

	gosub sstop

	gosub ack			' ack polling
	if ack_bit=1 then agn
	return

read_random_data	' reads data from specified address
			' returns in variable in_byte

	gosub start
	o_byte=$a0 | (device << 1)	' 1 0 1 0 a2 a1 a0 0
	gosub out_byte
	gosub nack
	o_byte= address >> 8		' high byte of address
	gosub out_byte
	gosub nack
	o_byte= address & $ff		' low byte of address
	gosub out_byte
	gosub nack

	gosub start
	o_byte=$a0 | (device << 1) | $01' 1010 a2 a1 a0 1
	gosub out_byte
	gosub nack

	gosub get_byte
	gosub nack

	gosub sstop
	return

out_byte	' shift out o_byte beginning with most sig bit

        low SDA_PIN

        for n=0 to 7
           b= (o_byte >> 7) & 1
           if (b=1) then out_one
           SDA_DIR=OUT
           debug "0"
_clk
           high SCL_PIN
           pause 100
           low SCL_PIN
           pause 100
           o_byte=o_byte << 1
        next

        SDA_DIR=IN
        return

out_one
        SDA_DIR=IN
        debug "I"
        goto _clk

get_9_bits	' read 9 bits from DS1621, most sig bit first

        SDA_DIR=IN      'input

        i_9_bit=0
        for n=0 to 8
           pause 200
	   high SCL_PIN	' clock high, then read SDA, then clock low
           pause 200
	   i_9_bit=(i_9_bit << 1) | SDA_IN
           debug dec SDA_IN
           low SCL_PIN
        next

        SDA_DIR=OUT     'output
        return


get_byte	' read 8 bits from 24LC32, most sig bit first

        SDA_DIR=IN      'input

	i_byte=0
	for n=0 to 7
           pause 200
	   high SCL_PIN	' clock high, then read SDA, then clock low
           pause 200
	   i_byte=(i_byte << 1) | SDA_IN
           debug dec SDA_IN
           low SCL_PIN
        next

        SDA_DIR=OUT     'output
        return

nack
        SDA_DIR=IN      ' input just in case
        ack_bit=1
        high SCL_PIN

	   ack_bit=SDA_IN
        debug "A"
        debug dec ack_bit
        debug $0d
        low SCL_PIN
        SDA_DIR=OUT     ' output
        return

ack

        debug "POLL"
        gosub start
        o_byte=$a0 | (device << 1)
        gosub out_byte
        gosub nack
        return

start
        high SDA_PIN
        high SCL_PIN
        debug "START"
        debug $0d
        low SDA_PIN     'bring SDA low while clock is high
        low SCL_PIN
        return

sstop
        low SDA_PIN
        high SCL_PIN
        pause 10
        high SDA_PIN    'bring SDA high while clock is high
        debug "STOP"
        debug $0d
        return