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