LibSerialPort problem on MacBook Pro

I’m writing bytes to a serial port using LibSerialPort.jl. My code works on a Linux machine but not on a MacBook Pro. There are no errors, but the desired effect (a connected Arduino Nano Every lights up an LED on an LED strip) doesn’t happen when using a Mac. I should mention that the Arduino is connected to the Mac via a USB hub (powerless by design) that is connected to the Mac through the Mac’s USB-C port…

Any idea what’s going on?

It would be better if you share with us some samples of data sent and received in both platform as hex. It may be the endianness of data sent changes between platforms.

Have you had success with something like the arduino serial monitor?

The data sent (I don’t read any data from the microcontroller) is 5 bytes at a time (e.g. UInt8[0, 255, 0, 1, 3]). The first three are the RGB values of the LEDs, the next 2 denote the first and last indices of the LEDs that need to be turned on. So, UInt8[0, 255, 0, 1, 3] would mean turn on LEDs 1, 2, and 3 to green.
The code (including the Arduino code) that does all of that is hosted here: https://github.com/yakir12/SimpContDQ.jl

But even the following MWE doesn’t work on the Mac:

using LibSerialPort
port = "<the path to the port connected to the Arduino>"
baudrate = 115200
sp = open(port, baudrate)
write(sp, UInt8[0, 255, 0, 1, 3])

while it works perfectly on Linux.

Elsewhere, yes, but do you mean I could have the Arduino IDE’s serial monitor open, and then use LibSerialPort.jl to send data to the Arduino all at the same time…?

? No. I mean have you been able to communicate with the device using, for example, the arduino serial monitor on macOS.

Ruling out julia packages being the problem is the first step I recommend with hardware interaction.

Ah! I see, great idea. I’ll try that now. Thank you.

OK, I had a hard time finding an easy way to send an array of bytes to a serial port (on either system). The serial monitor on the Arduino IDE sends text, not raw bytes. So I resorted to using Python for this purpose.

The following Python script works on both Linux and Mac OS:

import serial
import time
ser = serial.Serial('/dev/ttyACM1', 115200) # on mac the port was '/dev/cu.usbmodem143201'
time.sleep(1)
values = bytearray([0, 255, 0, 1, 3])
ser.write(values)

I honestly don’t know what exactly happened, it must be some human error on my part, sorry for the noise.

But for what it’s worth, I wrote the following MWE, using PythonCall.jl (awesome package), to try and help me (and you) find the glitch, but in the process of doing so it suddenly worked™… So all is well that ends well:

using PythonCall

port = Sys.islinux() ? "/dev/ttyACM1" : Sys.isapple() ? "/dev/cu.usbmodem143201" : error("not supported")
baudrate = 115200

serial = pyimport("serial")
ser = serial.Serial(port, baudrate)
sleep(1)
values = UInt8[0, 255, 0, 1, 3]
ser.write(values) # works on both Linux and Apple
ser.close()

using LibSerialPort
sp = open(port, baudrate)
sleep(1)
values = UInt8[255, 0, 0, 4, 7] # different
write(sp, values) # worked only on Linux but not Apple, but now works on both :)
close(sp)

with

$ cat CondaPkg.toml 
[deps]
pyserial = ""

Thanks for the helpful suggestions!

You don’t call set_flow_control(sp) to get the default of no hardware flow-control, and therefore might have used hardware flow control enabled without actually having connected the relevant wires (in case that was the state the OS had that port in). That’s why the example in the documentation calls that function.

It’s possible that the Python library switches off hardware flow control by default, and then your Julia code benefited from this.

Note that on Unix/macOS/Linux, the serial-port and other tty driver settings (baud rate, flow control, raw/cooked mode, etc.) persist across open/close sessions. Without that, you couldn’t use the stty program to configure a port.

1 Like