Problem with running command line items

Hi,

I’ve read the docs about pipelines, run, readchomp, and the blogs on shelling and pipes, but I can’t figure out how to get these simple commands to work. This is what I would do at a linux command prompt:

read -r line < /dev/ttyACM0
echo $line

Since, Julia doesn’t have native support for serial port stuff, I’m going to the basic command line. This is basically just reading a line of data from the serial port and printing it. I would like to be able to run these command and stuff the result in a variable that I can interrogate. Can anyone help with this?

Thanks

read appears to be a bash-specific function, not an installed program, so julia can’t run it directly. For example:

julia> run(`read`)
ERROR: could not spawn `read`: no such file or directory (ENOENT)
Stacktrace:
 [1] _jl_spawn(::String, ::Array{String,1}, ::Ptr{Void}, ::Base.Process, ::RawFD, ::RawFD, ::RawFD) at ./process.jl:360
 [2] #373 at ./process.jl:512 [inlined]
 [3] setup_stdio(::Base.##373#374{Cmd}, ::Tuple{RawFD,RawFD,RawFD}) at ./process.jl:499
 [4] #spawn#372(::Nullable{Base.ProcessChain}, ::Function, ::Cmd, ::Tuple{RawFD,RawFD,RawFD}) at ./process.jl:511
 [5] run(::Cmd) at ./process.jl:650

But reading a line from a serial port should just be as simple as:

julia> line = readline("/dev/tty/ACM0")

Does that work?

1 Like

Yes, that works. Thanks. Now (again) - I just have to get it working with root permissions. Fun, fun!

Frank

1 Like

One of the problems with just trying to do a readline() on the serial device is timing. That’s why most languages have a set of serial port functions. You have baudrate, etc. that has to be considered.

You could try using this package:

Or this package, which uses PySerial, though there is an open PR to switch the backend to libserialport, though it seems to have stalled a bit.

1 Like

Thanks!! If it works - that will be most helpful!
Frank

This is the error I get:

Pkg.clone(“GitHub - JuliaIO/LibSerialPort.jl: Julia wrapper for the libserialport c library”)
INFO: Cloning LibSerialPort from GitHub - JuliaIO/LibSerialPort.jl: Julia wrapper for the libserialport c library
ERROR: GitError(Code:ERROR, Class:Net, curl error: Couldn’t resolve host ‘github.com
)
Stacktrace:
[1] macro expansion at ./libgit2/error.jl:99 [inlined]
[2] clone(::String, ::SubString{String}, ::Base.LibGit2.CloneOptions) at ./libgit2/repository.jl:276
[3] #clone#100(::String, ::Bool, ::Ptr{Void}, ::Nullable{Base.LibGit2.AbstractCredentials}, ::Function, ::String, ::SubString{String}) at ./libgit2/libgit2.jl:562
[4] clone(::String, ::SubString{String}) at ./pkg/entry.jl:195
[5] (::Base.Pkg.Dir.##4#7{Array{Any,1},Base.Pkg.Entry.#clone,Tuple{String}})() at ./pkg/dir.jl:36
[6] cd(::Base.Pkg.Dir.##4#7{Array{Any,1},Base.Pkg.Entry.#clone,Tuple{String}}, ::String) at ./file.jl:70
[7] #cd#1(::Array{Any,1}, ::Function, ::Function, ::String, ::Vararg{String,N} where N) at ./pkg/dir.jl:36
[8] clone(::String) at ./pkg/pkg.jl:169

I’m running Julia 0.6.0 on
Linux NODE-UDOOX86 4.4.0-53-generic #74-Ubuntu SMP Fri Dec 2 15:59:10 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

Frank

OK. I got past the git part, but now, I get the following error:

julia> Pkg.clone(“https://github.com/andrewadare/LibSerialPort.jl.git”)
INFO: Initializing package repository /home/julia-user/.julia/v0.6
INFO: Cloning METADATA from https://github.com/JuliaLang/METADATA.jl
INFO: Cloning LibSerialPort from https://github.com/andrewadare/LibSerialPort.jl.git
INFO: Computing changes…
INFO: Cloning cache of BinDeps from https://github.com/JuliaLang/BinDeps.jl.git
INFO: Cloning cache of Compat from https://github.com/JuliaLang/Compat.jl.git
INFO: Cloning cache of SHA from https://github.com/staticfloat/SHA.jl.git
INFO: Cloning cache of URIParser from https://github.com/JuliaWeb/URIParser.jl.git
INFO: Installing BinDeps v0.6.0
INFO: Installing Compat v0.31.0
INFO: Installing SHA v0.5.1
INFO: Installing URIParser v0.2.0

julia> Pkg.build(“LibSerialPort”)
INFO: Building LibSerialPort
INFO: Attempting to Create directory /home/julia-user/.julia/v0.6/LibSerialPort/deps/downloads
INFO: Downloading file http://sigrok.org/download/source/libserialport/libserialport-0.1.1.tar.gz
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 178 100 178 0 0 341 0 --:–:-- --:–:-- --:–:-- 341
100 395k 100 395k 0 0 125k 0 0:00:03 0:00:03 --:–:-- 194k
INFO: Done downloading file http://sigrok.org/download/source/libserialport/libserialport-0.1.1.tar.gz
INFO: Attempting to Create directory /home/julia-user/.julia/v0.6/LibSerialPort/deps/src
INFO: Attempting to Create directory /home/julia-user/.julia/v0.6/LibSerialPort/deps
INFO: Directory /home/julia-user/.julia/v0.6/LibSerialPort/deps already created
INFO: Changing Directory to /home/julia-user/.julia/v0.6/LibSerialPort/deps/src/libserialport-0.1.1
INFO: Changing Directory to /home/julia-user/.julia/v0.6/LibSerialPort/deps/src/libserialport-0.1.1
ar: u' modifier ignored since D’ is the default (see `U’)
============================[ ERROR: LibSerialPort ]============================

LoadError: Provider BinDeps.BuildProcess failed to satisfy dependency libserialport
while loading /home/julia-user/.julia/v0.6/LibSerialPort/deps/build.jl, in expression starting on line 27

================================================================================

================================[ BUILD ERRORS ]================================

WARNING: LibSerialPort had build errors.

  • packages with build errors remain installed in /home/julia-user/.julia/v0.6
  • build the package(s) and all dependencies with Pkg.build("LibSerialPort")
  • build a single package by running its deps/build.jl script

Any ideas?

Not sure; FWIW, Pkg.build("LibSerialPort") works for me on Julia 0.6, Ubuntu 16.04.

I deleted the Julia directory, deleted the .Julia directory and did a fresh install of Julia 0.6.0. I still get the same error. Could it be because I’m running a 32-bit version of Julia (which I need)?

Frank

Could be. You can try building libserialport yourself and see if you run into any errors. If it works and it’s in your path Pkg.build will be able to find it. Perhaps also good to make an issue at LibSerialPort.jl that the build script might not work on 32 bits.

Well, making progress. I did:

sudo apt-get install libserialport-dev:i386

Went back into Julia and did:

julia> Pkg.build(“LibSerialPort”)
INFO: Building LibSerialPort

julia> using LibSerialPort

julia> list_ports()
/dev/ttyACM0
ERROR: ccall: could not find function sp_get_port_description in library /usr/lib/i386-linux-gnu/libserialport.so
Stacktrace:
[1] sp_get_port_description(::Ptr{LibSerialPort.SPPort}) at /home/julia-user/.julia/v0.6/LibSerialPort/src/wrap.jl:174
[2] #list_ports#29(::Int32, ::Function) at /home/julia-user/.julia/v0.6/LibSerialPort/src/high-level-api.jl:104
[3] list_ports() at /home/julia-user/.julia/v0.6/LibSerialPort/src/high-level-api.jl:98

julia>

So, at least it got the name of the port. I’ll try some other methods and see if they work.

Frank

Be sure to check if the binaries you got are also version 0.1.1 as expected in the package. Perhaps the package build script should add a validate function to make sure the found libraries can be used.

Success!! That was it. Uninstalled what I had and installed:

libserialport-dev_0.1.1-1_i386.deb

julia> Pkg.build(“LibSerialPort”)
INFO: Building LibSerialPort

julia> readdir(joinpath(Pkg.dir(“LibSerialPort”), “deps/usr/lib”))
6-element Array{String,1}:
“libserialport.a”
“libserialport.la”
“libserialport.so”
“libserialport.so.0”
“libserialport.so.0.1.0”
“pkgconfig”

julia> using LibSerialPort

julia> list_ports()
/dev/ttyS4
Description: ttyS4
Transport type: SP_TRANSPORT_NATIVE
/dev/ttyS5
Description: ttyS5
Transport type: SP_TRANSPORT_NATIVE
/dev/ttyACM0
Description: UDOO X86 - K71212271
Transport type: SP_TRANSPORT_USB

julia>

Thanks for all the help!!

Frank

2 Likes

Great :slight_smile:
I’d still recommend you make a GitHub issue about 32 bit builds, with a link to this discussion. It could save others time when they see the issue. Or perhaps it is easily fixed.

I guess I cheered to soon. Just trying use a bit of code from the test.

julia> port = sp_get_port_by_name(“/dev/ttyACM0”)
Ptr{LibSerialPort.SPPort} @0x0b4ccdf8

julia> sp_open(port, SP_MODE_READ_WRITE)
OS error code 25: Inappropriate ioctl for device
ERROR: From /home/julia-user/.julia/v0.6/LibSerialPort/src/wrap.jl: 111:

libserialport returned SP_ERR_FAIL - Host OS reported a failure.
Stacktrace:
[1] handle_error(::LibSerialPort.SPReturn, ::String) at /home/julia-user/.julia/v0.6/LibSerialPort/src/wrap.jl:106
[2] sp_open(::Ptr{LibSerialPort.SPPort}, ::LibSerialPort.SPMode) at /home/julia-user/.julia/v0.6/LibSerialPort/src/wrap.jl:155

I don’t know if this helps at all. I did a dmesg to show info. on the port I’m using.

[66975.607774] cdc_acm 1-4:1.0: ttyACM0: USB ACM device
[67018.291186] usb 1-4: USB disconnect, device number 45
[67018.565441] usb 1-4: new full-speed USB device number 46 using xhci_hcd
[67018.758199] usb 1-4: New USB device found, idVendor=8087, idProduct=0aba
[67018.758216] usb 1-4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[67018.758227] usb 1-4: Product: UDOO X86
[67018.758236] usb 1-4: Manufacturer: UDOO
[67018.758242] usb 1-4: SerialNumber: K71212271
[67023.185173] usb 1-4: USB disconnect, device number 46
[67023.461549] usb 1-4: new full-speed USB device number 47 using xhci_hcd
[67023.593098] usb 1-4: New USB device found, idVendor=8087, idProduct=0ab6
[67023.593109] usb 1-4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[67023.593116] usb 1-4: Product: UDOO X86
[67023.593122] usb 1-4: Manufacturer: UDOO
[67023.593126] usb 1-4: SerialNumber: K71212271
[67023.595835] cdc_acm 1-4:1.0: ttyACM0: USB ACM device

And, just to add to the fun - I plugged in an arduino Uno to my Udoo x86 board, started up Julia, and did the following:

julia> using LibSerialPort

julia> list_ports()
/dev/ttyS4
Description: ttyS4
Transport type: SP_TRANSPORT_NATIVE
/dev/ttyS5
Description: ttyS5
Transport type: SP_TRANSPORT_NATIVE
/dev/ttyACM0
Description: UDOO X86 - K71212271
Transport type: SP_TRANSPORT_USB
/dev/ttyACM1
Description: ttyACM1 - 64933303732351117121
Transport type: SP_TRANSPORT_USB

julia> port = sp_get_port_by_name(“/dev/ttyACM1”)
Ptr{LibSerialPort.SPPort} @0x09189138

julia> sp_open(port, SP_MODE_READ_WRITE)
OS error code 13: Permission denied
ERROR: From /home/julia-user/.julia/v0.6/LibSerialPort/src/wrap.jl: 111:

libserialport returned SP_ERR_FAIL - Host OS reported a failure.
Stacktrace:
[1] handle_error(::LibSerialPort.SPReturn, ::String) at /home/julia-user/.julia/v0.6/LibSerialPort/src/wrap.jl:106
[2] sp_open(::Ptr{LibSerialPort.SPPort}, ::LibSerialPort.SPMode) at /home/julia-user/.julia/v0.6/LibSerialPort/src/wrap.jl:155

I think I’ll start looking for another solution - maybe on where I don’t need the serial port.

Frank

Do you have write permissions to /dev/ttyACM*?

I did on ttyACM0, but not ttyACM1.

So, I did:

chmod a+rw /dev/ttyACM1

ls -l /dev/ttyACM*
crw-rw-rw- 1 root dialout 166, 0 Aug 30 13:35 /dev/ttyACM0
crw-rw-rw- 1 root dialout 166, 1 Aug 30 13:54 /dev/ttyACM1

Ran Julia:

julia> using LibSerialPort

julia> list_ports()
/dev/ttyS4
Description: ttyS4
Transport type: SP_TRANSPORT_NATIVE
/dev/ttyS5
Description: ttyS5
Transport type: SP_TRANSPORT_NATIVE
/dev/ttyACM0
Description: UDOO X86 - K71212271
Transport type: SP_TRANSPORT_USB
/dev/ttyACM1
Description: ttyACM1 - 64933303732351117121
Transport type: SP_TRANSPORT_USB

julia> port = sp_get_port_by_name(“/dev/ttyACM1”)
Ptr{LibSerialPort.SPPort} @0x0acb0f90

julia> sp_open(port, SP_MODE_READ_WRITE)
OS error code 25: Inappropriate ioctl for device
ERROR: From /home/julia-user/.julia/v0.6/LibSerialPort/src/wrap.jl: 111:

libserialport returned SP_ERR_FAIL - Host OS reported a failure.
Stacktrace:
[1] handle_error(::LibSerialPort.SPReturn, ::String) at /home/julia-user/.julia/v0.6/LibSerialPort/src/wrap.jl:106
[2] sp_open(::Ptr{LibSerialPort.SPPort}, ::LibSerialPort.SPMode) at /home/julia-user/.julia/v0.6/LibSerialPort/src/wrap.jl:155

I’m looking for another approach. I am experimenting with doing remote calls on 3 different development boards that I have on a small local Beowulf cluster: Raspberry Pi, Beaglebone Black, and Udoo x86. I want to demonstrate how you can remotely control sensors attached to different GPIOs [from my desktop running Julia].

I have it working with a digital PIR [motion] sensor on the RPi, and an analog light sensor on the BeagleBone. The interesting thing about the Udoo X86 is that it has an Arduino 101 built directly on the board. It also has GPIOs that I have gotten to work, but I thought it would be cool to connect up to an Arduino script that was running and access it from Julia (remotely) - hence the need for the serial routines. I can just do a readline() and get values, but the timing will never be synced.

I would like to take all of this information that I have been gathering and programming and do a talk at the next Julia Conference. That’s what this all about - lots of experimenting.