The Dallas DS2450 is a Quad A/D with a Dallas 1-W Interface.
However, any of the A/D channels might alternately be used as an open collector output. Thus, one might locate a remote DS2540 in a green house and use two A/D channels to measure temperature (perhaps an NTC thermistor) and relative humidity using a Honeywell HIH-3605 (3610) sensor and the other two channels as outputs to control a fan and an alarm.
Suppliers either do not have the DS2450 in stock or insist on a minimum of 88 pieces. In addition, the device is in a surface mount SOIC package, not the easiest thing for hobbyists to work with. If it appears there is sufficient interest, I will stock the DS2450 mounted on an SOIC to DIP converter at $12.00. Drop me an e-mail if you are interested.
In the following routines, I have only scratched the surface in illustrating the capabilities of this device.
Areas for additional work include;
Program DS2450_1.Bas.
' DS2450_1.Bas
'
' Illustrates an interface with a DS2450 Quad A/D.
'
' Configures for VDD = 5V operation by writing &H40 to memory location &H001c.
'
' Configures all four channels for 12 bit, 5.12 full scale by writing to
' locations &H0008 and 0009 for Channel A, &H000a and 000b for channel B, etc.
'
' Continually loops, setting mask to 1111 (all channels) with a preset of 0.
' Reads from locations &H0000 and 0001 for Channel A, &H0002 and 0003 for Channel B,
' etc.
'
' Displays the A/D value for each channel and the voltage on Channel D.
'
' Note that the 16-bit CRC is not implemented.
'
' Compile with SerialPort.Bas.
'
' +5
' |
' 4.7K
' |
' BX24 (term 13) ------------------------ DS2450 (term 3)
'
' copyright, Peter H Anderson, Baltimore, MD, Dec, '01
const W1_PIN as Byte = 13
Sub Main()
Dim Dummy as Byte, HighByte as Byte, LowByte as Byte
Dim CRCRead as Integer, ADVal as Integer
Dim Volts as Single
Call OpenSerialPort(1, 19200)
Call PutPin(W1_PIN, 2)
Sleep(0.25)
Call Init_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &Hcc)
Call OutByte_1W(W1_PIN, &H55)
Call OutByte_1W(W1_PIN, &H1c) ' write to 001c
Call OutByte_1W(W1_PIN, &H00)
Call OutByte_1W(W1_PIN, &H40) ' VCC operation
CRCRead = FetchCRCBytes(W1_PIN)
Dummy = InByte_1W(W1_PIN) ' read back data
Init_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &Hcc)
Call OutByte_1W(W1_PIN, &H55) ' write to locations beginning at 00 08
Call OutByte_1W(W1_PIN, &H08)
Call OutByte_1W(W1_PIN, &H00)
Call OutByte_1W(W1_PIN, &H0b) ' set up Channel A for 12 bit
CRCRead = FetchCRCBytes(W1_PIN)
Dummy = InByte_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &H01) ' 5.12 VDC range
CRCRead = FetchCRCBytes(W1_PIN)
Dummy = InByte_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &H0b) ' set up Channel B for 12 bit
CRCRead = FetchCRCBytes(W1_PIN)
Dummy = InByte_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &H01) ' 5.12 VDC range
CRCRead = FetchCRCBytes(W1_PIN)
Dummy = InByte_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &H0b) ' set up Channel C for 12 bit
CRCRead = FetchCRCBytes(W1_PIN)
Dummy = InByte_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &H01) ' 5.12 VDC range
CRCRead = FetchCRCBytes(W1_PIN)
Dummy = InByte_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &H0b) ' set up Channel D for 12 bit
CRCRead = FetchCRCBytes(W1_PIN)
Dummy = InByte_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &H01) ' 5.12 VDC range
CRCRead = FetchCRCBytes(W1_PIN)
Dummy = InByte_1W(W1_PIN)
Do
Call Init_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &Hcc)
Call OutByte_1W(W1_PIN, &H3c) ' convert
Call OutByte_1W(W1_PIN, &H0f) ' All channels
Call OutByte_1W(W1_PIN, &H01) ' preset to all zeros
CRCRead = FetchCRCBytes(W1_PIN)
Do
Dummy = InByte_1W(W1_PIN)
Loop Until (Dummy = &Hff)
Call Sleep(0.001)
Call Init_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &Hcc)
Call OutByte_1W(W1_PIN, &Haa) ' read memory
Call OutByte_1W(W1_PIN, &H00) ' Channel A
Call OutByte_1W(W1_PIN, &H00) ' locations 0000 and 0001
LowByte = InByte_1W(W1_PIN)
HighByte = InByte_1W(W1_PIN)
ADVal = CInt(HighByte)
ADVal = ADVal * 16 + CInt(LowByte\16)
Debug.Print "Channel A "; CStr(ADVal)
LowByte = InByte_1W(W1_PIN)
HighByte = InByte_1W(W1_PIN)
ADVal = CInt(HighByte)
ADVal = ADVal * 16 + CInt(LowByte\16)
Debug.Print "Channel B "; CStr(ADVal)
LowByte = InByte_1W(W1_PIN)
HighByte = InByte_1W(W1_PIN)
ADVal = CInt(HighByte)
ADVal = ADVal * 16 + CInt(LowByte\16)
Debug.Print "Channel C "; CStr(ADVal)
LowByte = InByte_1W(W1_PIN)
HighByte = InByte_1W(W1_PIN)
ADVal = CInt(HighByte)
ADVal = ADVal * 16 + CInt(LowByte\16)
Debug.Print "Channel D "; CStr(ADVal)
Volts = CSng(ADVal) / 4096.0 * 5.12
PutS(Volts)
Call NewLine()
Call NewLine()
Sleep(1.0)
Loop
End Sub
Function FetchCRCBytes(ByVal Pin as Byte) as Integer
Dim X as Byte, Y as Byte
Dim CRC as Integer
X = InByte_1W(Pin)
Y = InByte_1W(Pin)
CRC = CInt(Y)
CRC = CRC * 256 + CInt(X)
FetchCRCBytes = CRC
End Function
Sub Init_1W(ByVal Pin as Byte) ' bring Pin low for 500 usecs and then back
' high
Dim N as Integer
Call PutPin(Pin, 2) ' be sure DQ is an input
Call PutPin(Pin, 0)
For N = 1 to 3 ' adjust for 500 usec delay
Next
Call PutPin(Pin, 2)
For N = 1 to 3
Next
End Sub
Function InByte_1W(ByVal Pin as Byte) as Byte
Dim N as Integer, IByte as Byte, B as Byte
For N =1 to 8
B = Get1Wire(Pin)
If (B=1) then
IByte = (IByte\2) OR bx10000000
Else
IByte = IByte\2
End If
Next
InByte_1W = IByte
End Function
Sub OutByte_1W(ByVal Pin as Byte, ByVal OByte as Byte)
Dim N as Integer, B as Byte
For N = 1 to 8
B = OByte AND bx00000001
If (B=1) Then
Call Put1Wire(Pin, 1)
Else
Call Put1Wire(Pin, 0)
End If
OByte = OByte \ 2
Next
End Sub
Sub StrongPullUp_1W(ByVal Pin as Byte)
' Provide a hard logic one for 0.75 secs
Call PutPin(Pin, 1)
Call Sleep(0.75)
Call PutPin(Pin, 2)
End Sub
Program DS2450_2.Bas
' DS2450_2.Bas
'
' Illustrates an interface with a DS2450 Quad A/D. Two channels are used for
' A/D and the other two are used as outputs
'
' Configures for VDD = 5V operation by writing &H40 to memory location &H001c.
'
' Configures channels A and B for 12 bit, 5.12 full scale by writing to
' locations &H0008 and 0009 for Channel A, &H000a and 000b for channel B.
'
' Configures Channels C and D as output logic zeros.
'
' Continually loops, setting mask to 0011 (channels A and B) with a preset of 0.
' Reads from locations &H0000 and 0001 for Channel A, &H0002 and 0003 for Channel B,
'
' If the voltage on Channel A is greater 3.5 Volts, Output C is brought to a logic one.
' If less than 2.5 VDC, Output C is brought to a zero. The same is true for measurement
' channel B and output D.
'
' Displays the A/D value for each channel and the voltage on Channel D.
'
' Note that the 16-bit CRC is not implemented.
'
' Compile with SerialPort.Bas.
'
' +5
' |
' 4.7K
' |
' BX24 (term 13) ------------------------ DS2450 (term 3)
'
' copyright, Peter H Anderson, Baltimore, MD, Dec, '01
const W1_PIN as Byte = 13
Sub Main()
Dim Dummy as Byte, HighByte as Byte, LowByte as Byte
Dim CRCRead as Integer, ADVal as Integer
Dim ChAVoltage as Single, ChBVoltage as Single
Call OpenSerialPort(1, 19200)
Call PutPin(W1_PIN, 2)
Sleep(0.25)
Call Init_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &Hcc)
Call OutByte_1W(W1_PIN, &H55)
Call OutByte_1W(W1_PIN, &H1c) ' write to 001c
Call OutByte_1W(W1_PIN, &H00)
Call OutByte_1W(W1_PIN, &H40) ' VCC operation
CRCRead = FetchCRCBytes(W1_PIN)
Dummy = InByte_1W(W1_PIN) ' read back data
Init_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &Hcc)
Call OutByte_1W(W1_PIN, &H55) ' write to locations beginning at 00 08
Call OutByte_1W(W1_PIN, &H08)
Call OutByte_1W(W1_PIN, &H00)
Call OutByte_1W(W1_PIN, &H0b) ' set up Channel A for 12 bit
CRCRead = FetchCRCBytes(W1_PIN)
Dummy = InByte_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &H01) ' 5.12 VDC range
CRCRead = FetchCRCBytes(W1_PIN)
Dummy = InByte_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &H0b) ' set up Channel B for 12 bit
CRCRead = FetchCRCBytes(W1_PIN)
Dummy = InByte_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &H01) ' 5.12 VDC range
CRCRead = FetchCRCBytes(W1_PIN)
Dummy = InByte_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &H80) ' set up Channel C for output 0
CRCRead = FetchCRCBytes(W1_PIN)
Dummy = InByte_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &H00) ' this is don't care
CRCRead = FetchCRCBytes(W1_PIN)
Dummy = InByte_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &H80) ' set up Channel D for output logic one (open)
CRCRead = FetchCRCBytes(W1_PIN)
Dummy = InByte_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &H00) ' this is don't care
CRCRead = FetchCRCBytes(W1_PIN)
Dummy = InByte_1W(W1_PIN)
Do
Call Init_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &Hcc)
Call OutByte_1W(W1_PIN, &H3c) ' convert
Call OutByte_1W(W1_PIN, &H03) ' channels A, B
Call OutByte_1W(W1_PIN, &H01) ' preset to all zeros
CRCRead = FetchCRCBytes(W1_PIN)
Do
Dummy = InByte_1W(W1_PIN)
Loop Until (Dummy = &Hff)
Call Sleep(0.001)
Call Init_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &Hcc)
Call OutByte_1W(W1_PIN, &Haa) ' read memory
Call OutByte_1W(W1_PIN, &H00) ' Channel A
Call OutByte_1W(W1_PIN, &H00) ' locations 0000 and 0001
LowByte = InByte_1W(W1_PIN)
HighByte = InByte_1W(W1_PIN)
ADVal = CInt(HighByte)
ADVal = ADVal * 16 + CInt(LowByte\16)
ChAVoltage = CSng(ADVal) / 4096.0 * 5.12
Debug.Print "Channel A = "; CStr(CInt(1000.0 * ChAVoltage)); "mV"
LowByte = InByte_1W(W1_PIN)
HighByte = InByte_1W(W1_PIN)
ADVal = CInt(HighByte)
ADVal = ADVal * 16 + CInt(LowByte\16)
ChBVoltage = CSng(ADVal) / 4096.0 * 5.12
Debug.Print "Channel B = "; CStr(CInt(1000.0 * ChBVoltage)); "mV"
If (ChAVoltage > 3.5) Then
Init_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &Hcc)
Call OutByte_1W(W1_PIN, &H55) ' write to location 00 0c
Call OutByte_1W(W1_PIN, &H0c)
Call OutByte_1W(W1_PIN, &H00)
Call OutByte_1W(W1_PIN, &Hc0) ' bring Ch C ouput to high
CRCRead = FetchCRCBytes(W1_PIN)
Dummy = InByte_1W(W1_PIN)
ElseIf (ChAVoltage < 2.5) Then
Init_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &Hcc)
Call OutByte_1W(W1_PIN, &H55) ' write to location 00 0c
Call OutByte_1W(W1_PIN, &H0c)
Call OutByte_1W(W1_PIN, &H00)
Call OutByte_1W(W1_PIN, &H80) ' bring Ch C ouput to 0
CRCRead = FetchCRCBytes(W1_PIN)
Dummy = InByte_1W(W1_PIN)
End If
If (ChBVoltage > 3.5) Then
Init_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &Hcc)
Call OutByte_1W(W1_PIN, &H55) ' write to location 00 0e
Call OutByte_1W(W1_PIN, &H0e)
Call OutByte_1W(W1_PIN, &H00)
Call OutByte_1W(W1_PIN, &Hc0) ' bring Ch D ouput to high
CRCRead = FetchCRCBytes(W1_PIN)
Dummy = InByte_1W(W1_PIN)
ElseIf (ChBVoltage < 2.5) Then
Init_1W(W1_PIN)
Call OutByte_1W(W1_PIN, &Hcc)
Call OutByte_1W(W1_PIN, &H55) ' write to location 00 0e
Call OutByte_1W(W1_PIN, &H0e)
Call OutByte_1W(W1_PIN, &H00)
Call OutByte_1W(W1_PIN, &H80) ' bring Ch D ouput to 0
CRCRead = FetchCRCBytes(W1_PIN)
Dummy = InByte_1W(W1_PIN)
End If
Call NewLine()
Call NewLine()
Sleep(1.0)
Loop
End Sub
Function FetchCRCBytes(ByVal Pin as Byte) as Integer
Dim X as Byte, Y as Byte
Dim CRC as Integer
X = InByte_1W(Pin)
Y = InByte_1W(Pin)
CRC = CInt(Y)
CRC = CRC * 256 + CInt(X)
FetchCRCBytes = CRC
End Function
Sub Init_1W(ByVal Pin as Byte) ' bring Pin low for 500 usecs and then back
' high
Dim N as Integer
Call PutPin(Pin, 2) ' be sure DQ is an input
Call PutPin(Pin, 0)
For N = 1 to 3 ' adjust for 500 usec delay
Next
Call PutPin(Pin, 2)
For N = 1 to 3
Next
End Sub
Function InByte_1W(ByVal Pin as Byte) as Byte
Dim N as Integer, IByte as Byte, B as Byte
For N =1 to 8
B = Get1Wire(Pin)
If (B=1) then
IByte = (IByte\2) OR bx10000000
Else
IByte = IByte\2
End If
Next
InByte_1W = IByte
End Function
Sub OutByte_1W(ByVal Pin as Byte, ByVal OByte as Byte)
Dim N as Integer, B as Byte
For N = 1 to 8
B = OByte AND bx00000001
If (B=1) Then
Call Put1Wire(Pin, 1)
Else
Call Put1Wire(Pin, 0)
End If
OByte = OByte \ 2
Next
End Sub
Sub StrongPullUp_1W(ByVal Pin as Byte)
' Provide a hard logic one for 0.75 secs
Call PutPin(Pin, 1)
Call Sleep(0.75)
Call PutPin(Pin, 2)
End Sub