FTDI USB<->Serial failure

I’ve got my FTDI USB<->Serial converter working perfectly on Mac now. It does not work on Windows. I was under the impression that the Xojo code (apart from initially finding the right serial port) would be the same for Mac and Windows. Is there any reason the Windows code would need to be different?

It looks like it’s working at first, and then fails …

Hurdle 1: The UART is recognised as a COM serial port, and I can send the command to init the bootloader of my connected device.
Hurdle 2: I can then send one command and the device will respond as long as it’s a simple query and doesn’t involve sending multiple bytes.

The device at Hurdle 2 only responds to single-byte queries. If I try to do something like send an address that takes two bytes, that fails.

After Hurdle 2, communication stops. If I try to send another command, the device does not respond.

To get communication back, I can do this:

  • close, reopen, and then repeat the above process.

Sometimes I do this and the device remains unresponsive, so I have to do it again. Usually the second time it works, sometimes the 3rd time.

My first thought was (based on advice received previously on this forum) this must be a driver problem. So I manually installed the FTDI drivers for Windows. This made absolutely no difference.

As I mentioned, on Mac everything works perfectly. On Mac I can send and receive up to 256 bytes at a time at any baud rate, and I did not have to install any drivers. The USB<->UART chip is an FT232RQ from FTDI. The connected device is an STM32.

Any ideas?

Problem 1. The output buffer doesn’t flush.

I’m using the following code after sending bytes:

me.flush
me.Xmitwait

That code works on Mac, but is not working on Windows.

So I replaced .flush with another method, called FlushOutputBuffer

while me.BytesLeftToSend > 0 me.flush wend

This didn’t change anything.

BUT, when I change it to this:

while me.BytesLeftToSend > 0 MsgBox str( me.BytesLeftToSend ) me.flush wend

Then, in fact it works. I get multiple popup windows after sending a command, between 1 and 5 bytes not yet sent. Only with this msgbox added, sending data works. When I remove the msgbox it stops working.

What’s going on here? Is this a known bug?

The problem seems to be:

  • the two platforms don’t exit methods and return to the main event loop the same
  • serial events interact with the main event loop differently on each platform

This may be only one problem, the first thing, and the second thing follows from that.

I’m a Mac user, and I program on the Mac and port to Windows. That’s not working here. What I got working on Mac is just not going to work on Windows. I obviously have to change the basic structure of my app to make this work. So let me ask this:

In flow-logic, here are the kinds of things I was able to do in a single method on Mac:

' send a serial command
' set a flag, wait in a loop for a serial response to be read which changes that flag
' send the next command
' wait again
' etc.

I’m able to do that on Mac. Apparently that’s a no-go on Windows.

I need to change the way I’m thinking about how this works. Can anyone explain how it has to work in order to function correctly x-plat?

On Windows opening a MsgBox before flushing the buffer appears to accomplish this:

  • it breaks out of the method allowing the serial port to send and receive data in the middle of the method

Is there anything else that would accomplish the same thing without showing a message box?

Apparently serial events can’t happen in the middle of a method on Windows. The events will only happen when the method is exited and control returns to the main event loop. Am I wrong? Because that’s what I’m seeing here. That’s not true on Mac.

Hi Aaron. I’ve been using an FTDI <–> USB device for many years in our main Xojo-built product. It’s based on the FT-232. On OS X we use the serial port driver (kext) that has been customized with our own VID and PID to match the custom VID and PID we were assigned by FTDI. Just as you’ve discovered, this works pretty well.

However, on Windows I gave up on using the serial port approach nearly as soon as I started trying to use in the first place. Instead, I use the .dll driver from FTDI, along with a custom library that uses declares to hook into the .dll functions. This library exposes all the functionality I need from the .dll driver. I’ll be happy to share this library with you if you really want it - but keep reading.

Windows drivers for FTDI are a NIGHTMARE. The single largest demand on our technical support from our customers is helping them resolve FTDI driver problems. Since we have our own VID and PID on the device, we were forced to re-certify the driver package provided by FTDI and put it through Windows certification process so it could be distributed via Windows Update. It still seems to work about as often as it does not. The driver winds up with conflicts with other devices frequently, or does not install from Windows Update properly, or the entries in the registry for it get munged, etc etc etc.

Consequently, about 2 years ago we completed migrating the hardware product in question to a HID-based chip instead of FTDI. We have had exactly zero problems getting these devices to communicate, since HID requires no extra drivers. However, we do rely on the MBS HID libraries to talk to the device from within Xojo, since Xojo has no native HID support. This solution has been rock-solid on both Windows and Mac for us. I realize this is likely not feasible for your project, and not great news - but before you sink too much more time into FTDI, I’d encourage you to explore other options for connecting to your device.

Again, if you’d like a copy of the FTDI .dll driver library I use from within Xojo for Windows builds I’ll be happy to share.

Good luck!

Thank you, Kimball. I’ve sent you a PM.

The problem is in fact that on Windows, serial data is NOT sent or received when those lines of code appear in a method. Serial activity only happens after a method has finished, and control returns to the main event loop.

Here is a solution.

while me.BytesLeftToSend > 0 #if TargetMacOS then me.flush me.Xmitwait #elseif TargetWin32 then Xojo.Core.Timer.CallLater( 1, AddressOf me.flush ) Xojo.Core.Timer.CallLater( 2, AddressOf me.Xmitwait ) App.DoEvents(2) #endif wend

The same strategy has to be used when polling.

#if TargetMacOS then me.Poll #elseif TargetWin32 then Xojo.Core.Timer.CallLater( 1, AddressOf me.Poll ) App.DoEvents(1) #endif

Using this, everything works on Windows exactly the same as it does on Mac.

So, I don’t think this has anything at all to do with the FTDI driver. The problem, to me, appears to be coming from Xojo. I may be wrong. If I’m not, I think the fact that Serial.Poll and Serial.flush commands simply do not execute when they are supposed to on Windows either needs to be fixed, or this needs to be clearly explained in the LR.

P.S. Yes, I know we’re not supposed to use App.DoEvents in anything but a console app. I don’t care. It’s necessary here and it works.

@Aaron Hunt - For what is worth, I’ve used FTDI devices almost exclusively and have never had any issues. To be honest though I haven’t implemented hundred of devices (somewhere in the 40s perhaps). But since the days of RB the serial operation in Windows was done (or appeared to be done) at a higher level allowing some devices to work more seamlessly than other. If I recall you could use some serial terminals and receive everything whereas in Xojo it could be hit and miss (indicating it wasn’t Windows or the drivers but rather the RB/Xojo implementation in Xojo - you can search all the way back to RB forums if you are interested). What seemed to work all the time for me was polling the serial port. grabbing the data, and getting out of the timer (in and out quick). That is the only thing that has never failed me (supporting bauds up to 115k). Another thing that worked good also was doing a similar thing via the DataAvailable event. One thing that never worked reliably was doing a polling loop on a thread.