Serial device hell

Mac OS 10.13

My app interfaces with an FTDI USB-UART bridge serial device. The Serial device exists as a project item in a window, because the device is a subclass and I need access to its events.

First problem:
Sometimes the only way to get the device to respond is to unplug it and plug it back in. This works fine as long as I also quit and restart my app. If I unplug and plug back in the device while my app is running, it’s useless, all I get is a repeated LastErrorCode: 6 which effectively puts my app in an endless loop of error code 6 reports.

Second problem:
Trying to solve the first problem, I thought I could close the device using Device.close and then reassign the device from the System.Serial array. This results in a horrifying persistent duplicated serial device on my system bus, and when I restart my app, the device doesn’t show up at all in the System.Serial array. Then when I check System Report > USB, there are now 2 of the device listed, eben though only one is plugged in. If I unplug the device and reopen the report, the device is still listed (only one, not two - the device is no longer plugged in, but the duplicate remains). The only way to get rid of this phantom duplicated device (and get Xojo to see the device again) is to reboot the computer!

Any help out there?

seems a driver problem.
I would try to use another uart bridge, like chg340 or cp2102, with a correct driver install.
and see what happens.

Thanks, but I really don’t think this is a driver problem. The device works fine with other software (software from the chip manufacturer, and also a python script). This is an FTDI chip using the FTDI driver, which are the most reliable in the industry. This is a Xojo problem, which is why I’m asking on the Xojo forum and not FTDI tech support.

yes, may be, but you should try with another chip, as it may be better compatible with xojo …?
if other chips do the same, then it’s almost certainly a xojo problem.
I would also try it with another macos, as the 10.13 is known to break some usb devices compatibility.
I don’t say it will solve the problem, just that you should try these steps to narrow the source of the problem.

Your divice may be drawing too much power, macos will kill the usb port driver stopping your device comms.

Or it may be your code you can use serial.Close and the assign a new instance to it and reconnect.

Note the connection is not instantly, open doesn’t mean connected. Serial.Open + Serial.Lasterror = 0 means your good to go.

2 of my 3 USB-Serial adapters won’t work on my Mac Book Air or my 2018 Mac Mini, but they work fine on my 2013 rMBP and my Mac Pro 5,1. It does appear to be a current draw issue. One of the failing units, when connected to a 5A USB 3 Hub, then works fine on the MBA …

BTW, if you need reliable serial drivers, I can recommend these:

No, as I tried to explain, that does not work. It results in a duplicated device on the USB bus that won’t go away until I reboot the computer. The reason appears to be that .Close doesn’t work on a Serial object dropped into the window, not instantiated only in code. Or maybe .close works, but reopening it doesn’t. I explained that I have the object in the window because it’s a subclass and I need access to its events. What happens when I try to close and reopen it appears to be a Xojo bug, nothing to do with the device or its driver.

Are they FTDI devices, or other chips? Plugging into a hub versus plugging directly into the computer doesn’t change anything here. I’ve encountered USB power-draw issues before and in my experience whenever that happens, other USB devices connected to the machine also stutter (the whole USB bus is affected). That doesn’t happen here, so I don’t think this has to do with power draw.

Thank you, good to know, but that is only for non-FTDI devices, so not applicable in this case.

Aaron, still worth a try if you’re having such serious trouble: Get a Prolific based serial adapter and this driver and see if that solves the issues. If it does, you know for sure it’s a driver issue.

Alternatively, is that something you could share with us (or just me) so we can test this on our hardware?

Another thought to work around your unplug/close issue: Use a child process for your communication, e.g. by making a console app (or, if you don’t have that license, a desktop app and the right flags in the Info.plist to make it a background-only app without an icon in the Dock might work as well), and then running that thru the Shell class. Exchange data over a IPCSocket. Then you can close your connection by simply quitting the child process. That should avoid the closing issues you have now.

Thank you for the offer. You would need a serial device connected to one of these chips (series names): STM32F0, STM32F1, STM32F2, STM32F3, STM32F4, STM32F7, STM32G0, STM32G4, STM32H7, STM32L0, STM32L1, STM32L4, STM32WB. If you have that and want to try, please send me a PM.

I think you’re probably right. I had thought about doing this, but wanted to avoid having yet another interface layer to deal with.

They’re all Prolific chips here.

I did some testing here: I have a Terminal app, made in Xojo, that opens a serial port. Using the Prolific hardware and the “better” serial driver.

Results: When I re-plug it, and then try sending data, I get the Error 6, too. But then I prompt the user to choose a port, and when I then choose that same port, serial works again. So, in my test case, I do not end up with a broken connection after re-opening the serial port.

Also, my driver attaches the USB port address to the tty name, so that, as long as the user re-plugs it into the same physical port, I end up with the same port name - meaning that my software could try re-connecting to the same port without even prompting the user, as long as it can assume that the user keeps using the same port. Also, this means there is no creation of a second serial device like you experienced, while leaving around a “bad” one.

However, this Terminal app I used for testing with made with an older Xojo version (RS 2012r2.1, actually). Update Tested it in Xojo 2019r1.1 as well - same result. So, should work for you, too. I guess it IS a problem with the FTDI driver’s interaction with Xojo’s code. Or it’s a bug in your own code.

BTW, instead of using System Report to check for the devs, simply do this in Terminal: ls -1 /dev/tty.*

Did you install a driver manually ? If so your probably out of luck as macOS doesn’t like that.
I recomment to NOT install drivers manually (been there done that). Use the default drivers and it should work with ANY uart device (serial). Anyway if you have installed a driver from the internet, you’r better off removing it so mac is restored to the XOJO and other Supported way of doing things.

Or make sure your device NEVER draws more than 500mA (as USB specs allow, perhaps USB-C is more forgiving?)
I’ve had previously installed FT-x… drivers but they screwed my mac, i had to Reinstall the original and never looked back.
it all worked (eventually) on the system supplied drivers.

Read some here:

If someone told ya you needed drivers on a MacOS, my eyes fly open, as i’ve never had to actually use that. We’ve worked with 10’s of different FTID/non-ftid chips all working normally.

-If you do want to install the drivers anyway, do make a backup of the original, and remove if from that folder leaving only the “newly installed driver” in the drivers folder, that way the system won’t be able to start duplicate usb drivers.

Okay, then it sounds like I’m simply missing something in my code which resolves Error 6. How do you do it? What happens in your code when a user chooses a port?

The weirdest thing about the duplicate port is that it has exactly the same name. I think this is why it confuses Xojo and as long as the duplicate exists then neither it nor the actual port can be seen.

My hunch is that it’s probably both …

Thanks, yes in my case it’s rather ls -1 /dev/cu.*

Aaron, here’s the gist of my serial code:

The Error event handler:

self.remainingInput = "" if not self.isChoosingPort then self.isChoosingPort = true beep MsgBox "Error: "+Str(me.LastErrorCode) me.Close call self.choosePort() end if

In choosePort:

self.isChoosingPort = true do Serial1.SerialPort = SerPortChooser.Enter (self) if Serial1.SerialPort = nil then self.isChoosingPort = false return false end if not Serial1.Open then MsgBox "Opening port failed. Try again" else exit end loop self.isChoosingPort = false return true

The SerPortChooser is a modal dialog.

So, basically, when I get an error, I set a property to make sure I do not repeatedly handle the error until I’ve re-opened the port. Then I wait until I can reopen the port.

Also, to make sure my app regularly reads from the port, I do not rely solely on the DataAvailable event but also a recurring Timer with Period=50 that reads from the serial port (I have a “pollData” function that I call from both events and that also reads all available data into self.remainingInput first, and then have a loop that processes and removes data packets from that property, as was already explained in a separate question you asked yesterday. In my case, I wait until I find a CR in the buffer, and then extract that from the buffer, leaving the remaining, i.e. partial, data in the buffer).

Yes, I installed the FTDI driver because FTDI recommended this. They said the Apple driver won’t work.

[quote]Read some here:[/quote]

Thank you for that. Since that seems to be an exact description of the problem I am seeing, I should apologise to Jean-Yves Pochez, who said above:

Jean-Yves, you were right all along. My apologies. I am now eating my hat, which I believe is gluten-free but is of questionable nutritional value.

The good news is that after removing the FTDI driver, the duplicate port problem goes away …

However, there is bad news. A new problem. It appears that the buffer size of the Apple driver is smaller than that of the FTDI driver (which I guess is probably the reason FTDI says it’s better to install their driver). So I am going to have to refactor my code to work with smaller chunks of data. This will take me some time (as I didn’t make the chunk size a property, I should have) but it should not be too difficult to get that working. I’ll report back.

Sometimes the road to take is an experience another had.

There is no buffering issue, it will be exactly as it should be.
You get data that has been send by the device buffering over to your mac. Your mac manages a buffer event based, xojo has a mainloop hidden somewhere that polls or requests data and sets it for you. It may be an in-between-event so you are not guaranteed to get the entire buffer per ReadAll or per DataAvailable event.

You should do that checking yourself depending on your protocol.

Well no, it isn’t as it should be. Maybe there is no buffering issue for you. There is here for me. As I said, it doesn’t work the same, and what’s different is that only 32 bytes at a time can reliably be transferred. So there certainly appears to be a buffering issue here. I am doing what’s necessary in Xojo to get all the bytes when trying to transfer more than 32. The bytes are sometimes there and sometimes not, but they are never as many as requested when the number requested is greater than 32. So I’m not saying it’s a 32-byte buffer, just it’s a buffer that is only reliable for up to 32 bytes at a time. Why that is I don’t know. One of the responses on the superuser forum reported that installing an earlier version of the FTDI driver fixed the problem for him, so I may try that.