Interfacing the BASIC STAMP 2 with the DS1803 Dual Potentiometer

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

Introduction

The DS1803 is an addressable dual digital potentiometer. Standard resistance values of 10K, 50K and 100K are available;

   DS1803-010	10K
   DS1803-050	50K
   DS1803-100 	100K

A data sheet is available at Dallas Semiconductor. We sell the DS1803-010 in a 14-pin DIP.

The interface with the master, in this case the Basic Stamp 2, uses the Philips Inter IC 2-wire portocol (I2C). The device code is 0101. Up to eight such devices may be controlled on the same two wires. The device address on the 2-wire bus is determine d by the wiring of terminal A2, A1 and A0. Thus, the command byte is 0101 A2 A1 A0 * where * is 0 for writes and 1 for reads.

Each potentiometer may be independently varied from 0 to full range in 256 steps. Note that the end to end resistor tolerance is +/- 20 percent.

In addition to being able to set the value of the potentiometers, the values of the settings of both potentiometers may also be read.

In Program DS1803_1.BS2, potentiometer 0 is set to $55 and pot 1 to $80. Thus, on pot 0, the resistance between terminals L0 (low 0) and W0 (wiper 0) will be $55/$100 of the full resistance. That between the wiper (W0) and the high side (H0) will be 1- ($55/$100) of the full value.

The settings of both pots is then read from the 1803.

' DS1803_1.BS2
'
' Illustrates how to control DS1803 Addressable Dual Potentiometer
'
' BS2					DS1803
'
' Pin5 (term 10) ------------------- SCL (term 8) ----- To Other 
' Pin4 (term 9) -------------------- SDA (term 9) ----- I2C Devices
' 
' Note that the slave address is determined by A2 (term 4), A1 (term 5)
' and A0 (term 6) on the 1803.  The above SCL and SDA leads may be multipled
' to eight devices, each strapped for a unique A2 A1 A0 setting.
'
' Pot 0 is set to a value of $55 and Pot 1 to $80.  The settings of the 
' two pots is then read from the 1803.
'
' Debug and Pause statements were included only to see what is going on.
'
' copyright Peter H. Anderson and H. Paul Roach, MSU, March 20, '97
'

	device var byte		' device 0-7
	setting var byte	' potentiometer setting
	pot var bit		' either potentiometer 0 or 1

	o_byte var byte		' byte to send to device
	i_byte var byte		' byte from device
	i_byte_0 var byte	' byte fetched from pot 0
	i_byte_1 var byte	' byte fetched from pot 1

	n var byte		' index
	b var bit		' bit 
	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
        
        device=0
	pot = 0
	setting=$55		' pot setting in range of $00 to $ff
        gosub write_eeprom_pot	'write setting to specified potentiometer 

	pot=1
	setting=$80
	gosub write_eeprom_pot	

	gosub read_eeprom_pots	'read from both pots
	debug hex i_byte_0, i_byte_1

	stop

write_eeprom_pot	'writes specified setting to specified potentiometer

	gosub start

	o_byte=$50 | (device << 1)	' 0 1 0 1 a2 a1 a0 0
	gosub out_byte
	gosub nack
	o_byte= $a9 + pot		' 1010 1001 for pot 0
					' 1010 1010 for pot 1
        gosub out_byte
	gosub nack
	
	o_byte= setting			' potentiometer setting
	gosub out_byte
	gosub nack

	gosub sstop
	return

read_eeprom_pots	' reads data from both potentiometers
			' returns in variables i_byte_0 and i_byte_1

	gosub start
	o_byte=$50 | (device << 1) | $01 ' 0 1 0 1 a2 a1 a0 1
	gosub out_byte
	gosub nack
	
	gosub get_byte
	gosub send_ack
	i_byte_0 = i_byte

	gosub get_byte
	gosub send_ack
	i_byte_1 = i_byte	

	gosub sstop
	return

out_byte
	
        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_byte
    	SDA_DIR=IN	'input

   	i_byte=0
        for n=0 to 7
           pause 200
           high SCL_PIN
           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

send_ack		' send a 0 to acknowledge receipt of the byte
	SDA_DIR=OUT
 	high SCL_PIN
	low SCL_PIN
        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