Interfacing with a DS1050 5-bit Pulse Width Modulator

copyright, Peter H. Anderson, Baltimore, MD, May, '02


Discussion.

This discussion focuses on the Dallas DS1050 programmable 5-bit pulse width modulator.

The DS1050 uses the Philips Inter IC (I2C) protocol and by strapping the A2, A1 and A0 leads, up to eight DS1050 devices may be accommodated on the same 2-wire bus consisting of SCL (clock) and SDA (data). In addition, such other devices as the PCF8574 IO expander, DS1803 or MCP42010 digital potentiometers, DS1307 RTC and 24LC256 may be accommodated on the same bus.

Typical applications include DC motor speed control with the PWM output driving a section of a ULN2803A, a TIP122 Darlington Power transistor, an IRLZ44 FET or an L293 H bridge controller.

Note that the source and sink capabilities of the PWM output is limited to 2.0 mA which is not a great deal of base current for a TPI41C NPN transistor.

The DS1050 may also be used with a series R, shunt C capacitor to generate a DC voltage. However, my feeling is that a MAX518 Dual D/A conveter is a wiser choice.

The packaging of the DS1050 is an 8-pin SOIC with the leads on 0.05 inch centers which is not readily ammenable for use by all-thumbs hobbyists. However, I have found that I can reliably mount these on Aires SOIC to DIP adaptors and we offer both the SOIC and the SOIC mounted on a DIP adaptor.

The factory assigned device code is 0101. The other three bits are set by strapping the A2, A1 and A0 leads on the device. I note that the MAX518 shares this same factory code. Thus, the command byte consists of;

		0101 A2 A1 A0 R/W
where the R/W bit is a zero for a write command and a logic one for a read. In program DS1050, provison was made to address nay of eight DS1050 devices by passing a number in the range of 0 to 7 corresponding to the A2, A1, A0 strapping. Thus, for a write command, the byte is;
        bx0101_0000 + (Dev * 2) followed by clock pulse for the DS1050 to acknowledge
For a read command;
        bx0101_0000 + (Dev * 2) + bx0000_0001 followed by a clock pulse for the DS1050 to acknowledge.
The address byte (write) is followed by the the command byte;

The PWM duty may be read by sending the address byte (read) and then reading the duty from the DS1050. Note that BX24 does not bring the SDA lead low for one clock cycle to acknowledge the data to signal the DS1050 that the STOP sequence follows. I did find that if the duty is set to full one (32) the setting will not be read as 32, but rather 63.

One aspect of the DS1050 that I found troubling is that when turned on, the output runs at a 50 percent duty cycle. The ramifications are that until the BX24 sends a command to the DS1050, you may well have a motor turning that you just do not want turning. However, a separate output from the BX24 might be used as a Motor On control. This might be anded with the DS1050 PWM output using a section 74HC08. The 74HC08 then drives the FET or similar. I would pull-down each input of the 74HC08 to ground through 1K to guard against the condition where the BX24 is not powered and the input to the 74HC08 would otherwise be floating.

Note that Dallas offers the DS1050 with a number of standard frequencies including 1, 5 and 10 kHz.


Program DS1050_1.Bas


' DS1050_1.Bas
'
' Illustrates an interface with the Dallas DS1050 programmable 5-bit pulse width modulator
' using the Philips IC2 protocol.
'
' Illustrates the use of setting the PWM duty, reading the PWM duty, shutting down the DS1050
' and recalling the device from shutdown.
'
' The program recalls the DS1050 from sleep and increases the duty cycle from 0/32 to 32/32 in
' half second intervals.  The duty cycle is also read and displayed to the terminal.
'
' The DS1050 is then shutdwon for 15 seconds.  The program continually loops.
'
'
' BX24 					DS1050
'
'      Term 15 ------------------------ SDA (term 2) ----------- To other I2C devices
'      Term 14 ------------------------ SCL (term 1) -----------
'
'				                GRD --- A2 (term 6)
'                               GRD --- A1 (term 7)
'                               GRD --- A0 (term 3)
'
'                                       PWM (term 5) --------- To FET driving motor
'                                                              or RC Network
' Compile with SerialPort.Bas.
'
' coyright, Peter H. Anderson, Baltimore, MD, May, '02

const SCL as byte=14
const SDA as byte=15

Sub Main()

   Dim Duty as Byte, DutyRead as Byte

   Call Sleep(1.0)			' to avoid download problems

   Call OpenSerialPort(1, 19200)	' if using functions in SerialPort.Bas
   Debug.Print "..............."	' to see that something is happening

   Do

      Call DS1050Recall(0)			' be sure it is not in shut down
      Call DS1050SetPWMDuty(0, bx0000_0000)	' set duty to 0

      For Duty = 0 to 32			' Note that 32 is full on
         Call DS1050SetPWMDuty(0, Duty)
         DutyRead = DS1050ReadPWMDuty(0)	' read back PWM duty and display
         Debug.Print CStr(Duty); "  "; CStr(DutyRead)
         Call Sleep(0.5)
      Next

      Call DS1050Shutdown(0)
      Call Sleep(15.0)
   Loop

End Sub

Sub DS1050SetPWMDuty(ByVal Dev as Byte, ByVal Duty as Byte)	' 0 - 31.  32 for full on

   Call I2CStart()
   Call I2COutByte(bx0101_0000 OR (Dev * 2))
   Call I2COutByte(Duty)
   Call I2CStop()

End Sub


Sub DS1050ShutDown(ByVal Dev as Byte)

   Call I2CStart()
   Call I2COutByte(bx0101_0000 OR (Dev * 2))
   Call I2COutByte(bx1100_0000)
   Call I2CStop()
End Sub

Sub DS1050Recall(ByVal Dev as Byte)

   Call I2CStart()
   Call I2COutByte(bx0101_0000 OR (Dev * 2))
   Call I2COutByte(bx1000_0000)
   Call I2CStop()

End Sub

Function DS1050ReadPWMDuty(ByVal Dev as Byte) as Byte
   Dim PWMSetting as Byte
   Call I2CStart()
   Call I2COutByte(bx0101_0000 OR (Dev * 2) OR bx0000_0001)

   PWMSetting = I2CInByte(0)	' no ack prior to stop
   Call I2CStop()
   DS1050ReadPWMDuty = PWMSetting
End Function


Sub I2CStart()
   Call PutPin(SCL,0)
   Call PutPin(SDA,2)
   Call PutPin(SCL,2)
   Call PutPin(SDA,0)
   Call PutPin(SCL,0)
End Sub


Sub I2CStop()
   Call PutPin(SCL, 0)
   Call PutPin(SDA, 0)
   Call PutPin(SCL,2)
   Call PutPin(SDA,2)
End Sub


Sub I2COutByte(ByVal X as Byte)

   Dim N as Integer

   For N=1 to 8

     If((x AND &H80) <> 0) Then
       Call PutPin(SDA,2)
'      Call PutByte(Asc("1"))   ' used for debugging
     Else
       Call PutPin(SDA,0)
'      Call PutByte(Asc("0"))	' used for debugging
    End If

    Call PutPin(SCL,2)
    Call PutPin(SCL,0)
    x=x*2

   Next

'  Call NewLine()		' used for debugging

   Call PutPin(SDA,2)
   Call PutPin(SCL,2)
   Call PutPin(SCL,0)
   Call PutPin(SDA,2)

End Sub


Function I2CInByte(ByVal Ack as Byte) as Byte

   Dim N as Integer
   Dim X as Byte

   FOR N=1 to 8

    Call PutPin(SCL,2)
    If(GetPin(SDA)=1) Then
      X = X * 2 +1
    Else
      X = X * 2
    End If
    Call PutPin(SCL, 0)
   NEXT

   If (Ack <> 0) Then
      Call PutPin(SDA, 0)
   Else
      Call PutPin(SDA,2)

   End If

   Call PutPin(SCL,2)
   Call PutPin(SCL,0)
   Call PutPin(SDA,0)
   I2CInByte = X

End Function