0

I have a proprietary device that is connected to my computer with a USB cable.

I have been unable to successfully read (or write, or both?) when running the code on my Xubuntu installation.

Note: The same logic works pretty much flawlessly on both Windows (tested on 7, 8 and 10) and Mac (tested on Yosemite and Mojave).

Here is the code I'm trying to run (hardcoded some values for simplicity):

ser = serial.Serial('/dev/ttyACM0', 500000, timeout = 0.03, write_timeout = 0.015)
ser.write(bytes([248, 40, 0]))
ser.flush()
reply = ser.read(40)

Current behaviour

The device is running some code that responds to the packets that it receives. In this initial packet, my Python code is requesting a full copy of the device's state, which it receives in a whopping 40 bytes array.

On Linux, the following is returned instead of the requested 40 bytes: [248, 13, 10, 40, 13, 10, 0, 13, 10]

What I find interesting is that it returns the exact same bytes that I tried writing, with 13 and 10 in between them.

Expected behaviour On both Mac and Windows, something like this is returned (contents are not that important):

[71, 89, 65, 32, 1, 4, 50, 0, 27, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 238, 1, 255, 255, 136, 1, 255, 255, 255, 255]

The expected behaviour is the same as the behaviour on Mac and Windows.

Extra info

  • Running on Python 3.5.

  • I'm using the exact same USB device and cable.

  • I've tried all ports on the computer.

  • The code is exactly the same on all operating systems, with only the port name being different due to the nature of said OSs.

  • The serial port is confirmed to be device I need (I print the name) and is confirmed to be open (I print out the serial object).

  • I've played around with timeouts and baudrates, but to no avail.

  • I've tried exchanging the read with a if(ser.in_waiting): reply = ser.read() but nothing really changes.

  • I have verified that the device is on port /dev/ttyACM0.

  • I have added permissions to that port after encountering a OSError: [Errno 13] Permission denied: '/dev/ttyACM0' error.

  • Permissions were added by using both sudo chmod 666 /dev/ttyACM0 and sudo usermod -aG dialout $USER after reading some solutions on here.

  • I have experimented with time.sleep().

  • [EDIT] Tried out the suggestions given by @michael-o. No luck.

  • Some other SO questions I've researched and tried, in no particular order:

Any info/ideas will be greatly appreciated!

[EDIT2] The problem has become even weirder. Here's what I tried today:

  • First, I programmed an Arduino on a Windows machine to constantly print a number and to blink the LED if it receives anything. Then I tested on the Linux machine and everything worked great.

  • Then, we programmed our hardware to do the same - constantly print a number and blink the LED if it receives anything.

  • Even though the logic is the same, it still fails to read or write anything to it. I even tried using GtkTerm to just inspect what is being communicated between the device and the computer. Nothing.

  • However! Sending "X" to the device triggers a small custom-made terminal that has some built-in commands, like "S" for stress testing and such.

  • The important command here is "E", which exits the terminal. If this is done (in GtkTerm), the device suddenly starts printing that number mentioned earlier. The intuition here was that on Linux (or at least in GtkTerm), "X" is sent to the device for whatever reason. So we tried exiting that custom terminal.

  • This unfortunately didn't in Python. It still continues receiving the same packet as described before.

  • So... we are stuck. But it seems like it is a firmware issue bundled with some weird quirks of the operating system. Will update if we ever figure it out.

Ivan
  • 1
  • 2

2 Answers2

0

Try to do it after rebooting the computer if you didn't it after adding a user into the group dialout.

Try to send additional information related to your device when connecting, such as XON/XOFF, parity, stopbits etc.

Add # coding: utf-8 at the beginning of your script.

Michael O.
  • 4,173
  • 2
  • 8
  • 29
  • Hi Michael, thanks for the suggestions. I tried all of them. 1. Restarting was done many many times, but I tried again anyways. No luck. 2. `# coding: utf-8` didn't work. I also tried `# -*- coding: -*-` from https://docs.python.org/3.4/howto/unicode.html#the-string-type. 3. It took me awhile to try all options for `XON/XOFF`, `parity` and `stopbits` but they all result in the same reply from the device. – Ivan Mar 08 '19 at 15:44
  • @Ivan Try not to flush after writing, but adding a delay; also try `ser.read_all()` instead of `ser.read(40)` – Michael O. Mar 08 '19 at 16:11
  • None of these worked. I did some further testing (including writing/reading to an Arduino to validate that it's the device that's the problem). You can check out my edit if you're curious. – Ivan Mar 11 '19 at 15:31
0

Resolution:

The OS sends "X" to the device 5-6 seconds after the initial connection.

This happens regardless of what applications are started. It does so in the background.

Our firmware was programmed such that "X" starts debug mode, which we use for testing the status of the hardware. It has to be exited before anything of value can be sent/received.

I am unsure as to why the system sends this character, or whether it happens only on that single installation, but it is a barebones computer with almost no additional software installed other than VS Code and Git.

[FINAL UPDATE]

The same issue was observed on other systems that were running Linux, more specifically, a Fedora instance.

Ivan
  • 1
  • 2