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