Using FTDI input pins (DSR DCD CTS)

Go To Last Post
16 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm trying to use FTDI's various "input" pins (DSR, DCD, CTS) to send simple signals from the MCU to the PC. Unfortunately I haven't been able to get this to work, nor found any helpful information online. My current circuit has serial communication working as well as uses the RTS pin to send a signal to my MCU from the PC (which is working).

 

Wiring:

The FTDI is wired up to an RS485 chip (based on the "7.2 USB to RS485 Converter" circuit in the FTDI data sheet).

The DCD pin (pin 10) has a 20k pull-up resistor and connected to a pin on the the MCU. The MCU will drive the line to ground (logic low) as the signal to the PC.

 

Testing:

I've tested this with various serial monitoring tools on my mac (CoolTerm, SerialTerm) as well as a simple python script pySerial:

import serial

def main(argv):
  watchPort(sys.argv[1])

def watchPort(portName):
    ser = serial.Serial(portName)

    while True:
        print("DCD {0}, DSR {1}, CTS {2}".format(ser.cd, ser.dsr, ser.cts))
        time.sleep(0.5)
        
if __name__ == "__main__":
     main()

 

The DCD signal never seems to change. Is this something others have done? Is there a better way to approach this?

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

to send simple signals from the MCU to the PC...

Is there a better way to approach this?

Well, they signals were originally used in the past for hardware based flow control.

I suspect most uC projects don't require their implementation these days.

 

It would seem that the benefit of a serial comm's data link is that the micro can send a message or command to the PC whenever you want to trigger some response, instead of attempting to do so through the hardware flow control signals.

 

The PC is likely to have an input command (or response) parser to interpret the incoming data from the micro, so just add an additional command or two to use instead of the HW signals.

 

JC 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jgillick wrote:

My current circuit has serial communication working as well as uses the RTS pin to send a signal to my MCU from the PC (which is working).

 

The FTDI is wired up to an RS485 chip (based on the "7.2 USB to RS485 Converter" circuit in the FTDI data sheet).

The DCD pin (pin 10) has a 20k pull-up resistor and connected to a pin on the the MCU. The MCU will drive the line to ground (logic low) as the signal to the PC.

 

The DCD signal never seems to change. Is this something others have done? Is there a better way to approach this?

 

The following table is from Wikipedia:

 

The PC acts as DTE and the MCU acts as DCE.

 

What is the full part number of the FTDI chip and how is it configured?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Definitely TX, RTS, DTR are outputs from FTDI chip, others are inputs. CTS is used for hardware flow control, RI, DCD, DSR are used by modem oriented software. For other usage you must use FTDI direct (D2XX) drivers, not VCOM style.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

DocJC wrote:

 

It would seem that the benefit of a serial comm's data link is that the micro can send a message or command to the PC whenever you want to trigger some response, instead of attempting to do so through the hardware flow control signals.

 

 

I would usually agree and use serial communication for this sort of thing. However, I'm setting up a multi-drop RS485 network and planning to use this as a common signal line that can be used to signal "ready", "error" and to prevent communication collisions. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Chuck99 wrote:

 

What is the full part number of the FTDI chip and how is it configured?

 

 

I'm using an FT232R (datasheet) with the factory settings.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I dug out an old FT232R breakout board from Sparkfun and gave it a test.

 

I was able to read DCD, DSR, RI, and CTS just fine.

 

Are you sure that your software is reading/displaying the signals correctly?

 

Below is the schematic for the board I used.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Chuck99 wrote:

I dug out an old FT232R breakout board from Sparkfun and gave it a test.

 

I was able to read DCD, DSR, RI, and CTS just fine.

 

What were you using to read the status of DCD, DSR, RI, and CTS? Would you mind sharing your code? My code returns a status for each of those pins just fine, but their values don't change when I bring them high or low. 

 

For reference, I also tried with the FTDI D2XX driver APIs and the status values reflected the pin values accurately. However, I would much rather use the default serial port drivers than D2XX.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jgillick wrote:

What were you using to read the status of DCD, DSR, RI, and CTS? Would you mind sharing your code?

 

I wrote the test program in PureBasic.

 

If you think it will help, I'll share the source code - but it's FUGLY.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Chuck99 wrote:

I wrote the test program in PureBasic.

 

If you think it will help, I'll share the source code - but it's FUGLY.

 

I don't have a PureBasic compiler, but it might help to see what it's doing. Just to confirm, your program shows the pins change if you toggle them between VCC and GND?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jgillick wrote:

I don't have a PureBasic compiler, but it might help to see what it's doing.

Just to confirm, your program shows the pins change if you toggle them between VCC and GND?

 

You can download a free demo version of PureBasic (Link) that might be able to compile/run my test program.

 

Yes, my program shows the state of the DCD, DSR, RI, and CTS pins.

  (DCD pin was grounded.  The other 3 pins were left floating.)

 

 

 

     PureBasic Program to test FT232R

Global comID.l                 ;Communication Handle
Global ComPort.s               ;Communications Port

 

;Windows
Enumeration
  #Window_0
EndEnumeration

;Menu
Enumeration
  #Menu_Return
EndEnumeration

 

;Gadgets
Enumeration
  #ListPortsLbl
  #ListPorts
  #Button_OpenPort
  #Button_ClosePort
 
  #DCDLbl
  #DSRLbl
  #RILbl
  #CTSLbl

  #DCD
  #DSR
  #RI
  #CTS
  #Button_DTR
  #Button_RTS
EndEnumeration

Procedure SetPortList()
  If CountGadgetItems(#ListPorts)
    SetGadgetState(#ListPorts,0)
    DisableGadget (#Button_OpenPort, 0)  ;Enable Open Button
  EndIf
EndProcedure

Procedure Init()
  Protected PortNr,Port.s
 
  ClearGadgetItems(#ListPorts)
  For PortNr = 1 To 256
    Port = "COM" + Str(PortNr)
    comID = OpenSerialPort(#PB_Any,Port,9600,#PB_SerialPort_NoParity,8,1,#PB_SerialPort_NoHandshake,0,0)
    If comID
      AddGadgetItem(#ListPorts,-1,Port)
      CloseSerialPort(comID)
    EndIf
  Next
  comID = 0
 
  DisableGadget (#Button_OpenPort, 1) ; Disabled
  DisableGadget (#Button_ClosePort, 1) ; Disabled
  SetPortList()
EndProcedure

 

Procedure Open_Window_0()
  If OpenWindow(#Window_0, 0, 0, 700, 200, "Test FT232R", #PB_Window_TitleBar | #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
    
    TextGadget(#ListPortsLbl, 100, 10, 120, 15, "Select Serial Port", #PB_Text_Center)
    ComboBoxGadget(#ListPorts, 100, 25, 120, 25)
    ButtonGadget(#Button_OpenPort, 250, 25, 120, 25, "Open Serial Port")
    ButtonGadget(#Button_ClosePort, 400, 25, 120, 25, "Close Serial Port")
    
    ;TextGadget(#UTCLbl, 17, 63, 140, 17, "------------- UTC -----------", #PB_Text_Center)
    
    TextGadget(#DCDLbl, 10, 78, 75, 17, "DCD", #PB_Text_Center)
    TextGadget(#DSRLbl, 100, 78, 55, 17, "DSR", #PB_Text_Center)
    TextGadget(#RILbl, 190, 78, 50, 17, "RI", #PB_Text_Center)
    TextGadget(#CTSLbl, 270, 78, 50, 17, "CTS", #PB_Text_Center)
    
    TextGadget(#DCD, 35, 95, 25, 20, "-", #PB_Text_Border | #PB_Text_Center)
    TextGadget(#DSR, 115, 95, 25, 20, "-", #PB_Text_Border | #PB_Text_Center)
    TextGadget(#RI, 202, 95, 25, 20, "-", #PB_Text_Border | #PB_Text_Center )
    TextGadget(#CTS, 282, 95, 25, 20, "-", #PB_Text_Border | #PB_Text_Center )
    
    ButtonGadget(#Button_DTR, 350, 90, 70, 25, "DTR", #PB_Button_Toggle)
    ButtonGadget(#Button_RTS, 450, 90, 70, 25, "RTS", #PB_Button_Toggle)
    
    AddKeyboardShortcut(#Window_0, #PB_Shortcut_Return, #Menu_Return)
  EndIf
EndProcedure

 

 

; Start of main part

Define Event, Buffer.b, GadgetID

Open_Window_0()

Init()

Repeat
  Event = WaitWindowEvent(100)
  Select Event
    Case 0 ; no event
      If comID And IsSerialPort(comID)   ; a serial port is open
        ; Check for incoming characters from serial port
        While (AvailableSerialPortInput(comID) > 0)
          If ReadSerialPortData(comID, @Buffer, 1) ; Read Byte            
              Buffer = 0 ; throw away incoming data              
          EndIf    
        Wend
        
        ; Check Serial Port siganls
        If GetSerialPortStatus(comID, #PB_SerialPort_DCD)
          SetGadgetText(#DCD, "1")
        Else
          SetGadgetText(#DCD, "0")
        EndIf   
        
        If GetSerialPortStatus(comID, #PB_SerialPort_DSR)
          SetGadgetText(#DSR, "1")
        Else
          SetGadgetText(#DSR, "0")
        EndIf   

        If GetSerialPortStatus(comID, #PB_SerialPort_RI )
          SetGadgetText(#RI, "1")
        Else
          SetGadgetText(#RI, "0")
        EndIf   
        
        If GetSerialPortStatus(comID, #PB_SerialPort_CTS )
          SetGadgetText(#CTS, "1")
        Else
          SetGadgetText(#CTS, "0")
        EndIf   
        
      EndIf
      

    Case #PB_Event_Gadget
      ;Debug "#PB_Event_Gadget"
      GadgetID = EventGadget()
      Select GadgetID
      
        Case #Button_OpenPort ; Open Com Port
          If comID And IsSerialPort(comID)        ;If serial port is in use, close it
            CloseSerialPort(comID)
          EndIf
          
          ComPort = GetGadgetText(#ListPorts)
          comID = OpenSerialPort(#PB_Any,ComPort,9600,#PB_SerialPort_NoParity,8,1,#PB_SerialPort_NoHandshake,1000,1000)
          If comID = 0
            Debug "OpenSerialPort() failed"
          Else              
              DisableGadget (#Button_OpenPort, 1)   ; Disabled
              DisableGadget (#ListPorts, 1)         ; Disabled
            DisableGadget (#Button_ClosePort, 0)  ; Enabled
          EndIf
          
        Case #Button_ClosePort  ; Close Serial Port
          If comID And IsSerialPort(comID)
            CloseSerialPort(comID)
            comID = 0
              DisableGadget (#Button_OpenPort, 0)   ; Enabled
              DisableGadget (#ListPorts, 0)         ; Enabled
            DisableGadget (#Button_ClosePort, 1)  ; Disabled
          EndIf
          
        Case #Button_DTR ;
            If GetGadgetState(#Button_DTR)
              SetSerialPortStatus(comID, #PB_SerialPort_DTR, 1)
            Else   
              SetSerialPortStatus(comID, #PB_SerialPort_DTR, 0)
            EndIf
            
        Case #Button_RTS ;
          ;Debug "Button_RTS"  
          If GetGadgetState(#Button_RTS)
              ;Debug "#Button_RTS Pressed"
              SetSerialPortStatus(comID, #PB_SerialPort_RTS, 1)
            Else  
              ;Debug "#Button_RTS Released"
              SetSerialPortStatus(comID, #PB_SerialPort_RTS, 0)
            EndIf

     EndSelect
  EndSelect

Until Event = #PB_Event_CloseWindow

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Chuck99 wrote:

You can download a free demo version of PureBasic (Link) that might be able to compile/run my test program.

 

Yes, my program shows the state of the DCD, DSR, RI, and CTS pins.

 

I finally got around to trying your program and it works! Which kinda blows my mind and now I need to figure out how to get this to work outside of PureBasic. Thanks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jgillick wrote:

Chuck99 wrote:

You can download a free demo version of PureBasic (Link) that might be able to compile/run my test program.

 

Yes, my program shows the state of the DCD, DSR, RI, and CTS pins.

 

I finally got around to trying your program and it works! Which kinda blows my mind and now I need to figure out how to get this to work outside of PureBasic. Thanks.

 

Looks like the problem was OS X (my main computer). It turns out the default FTDI drivers do not support accessing the control signals. (http://stackoverflow.com/a/29919...) Downloading the official drivers from FTDI fixed it and I can now get the signals through my Python script too. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm glad you got it working.

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@ Chuck, thanks for the Pure Basic link.

 

Currently I write my PC software with VB, but Pure Basic looks like an interesting option.

 

JC

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

DocJC wrote:

@ Chuck, thanks for the Pure Basic link.

 

Currently I write my PC software with VB, but Pure Basic looks like an interesting option.

 

I chose PureBasic because it generates code that is dependent only on the operating system.

No mfc or .net required.  This allowed me to share an  .exe with others and not worry if it would

work on their machine.

 

An added bonus is that PureBasic has compilers that support Windows, Linux, and OSX.

You get all three for the price of one, with lifetime updates.

 

Note:  This was not intended as a sales pitch ... it just reads that way.