JuliaIO / LibSerialPort.jl

Julia wrapper for the libserialport c library
MIT License
64 stars 21 forks source link

libserialport returned SP_ERR_FAIL #98

Open mithgil opened 3 weeks ago

mithgil commented 3 weeks ago

I am trying to plot serial port real-time data (pico and ads1115) with the following julia script:

using Plots, DataStructures, LibSerialPort
using Plots:px

# plotting setting
plot_font = "Arial";

default(fontfamily=plot_font,
        linewidth=3, framestyle=:grid,# ":box" ":semi" ":origin" ":zerolines" ":grid" ":none"
        grid=true,
        titlefontsize=24,
        guidefontsize=30, # means labelfontsize
        tickfontsize=28,
        legendfontsize=18,
        legend=:outertopright,
        fg_legend = :false);

function print_serial_data(port_name, baudrate, buffer_size)

    # Create a circular buffer to store data
    data_buffer = CircularBuffer{Float64}(buffer_size)
    time_data = CircularBuffer{Float64}(buffer_size)

    start_time = time();

    # Open the serial port, Real-time plotting loop
    while true
        LibSerialPort.open(port_name, baudrate) do sp
            # Read a line of data from the serial port
            line = readline(sp)

            if line in ["", ".", "-"]
                volt_data = 0.0;
            else
                volt_data = parse(Float64, line)
            end

            # Calculate elapsed time in seconds
            elapsed_time = time() - start_time  

            # Append data to the buffers
            push!(data_buffer, volt_data)
            push!(time_data, elapsed_time)

            # Update the plot
            volt_vec = convert(Vector{Float64}, data_buffer);
            time_vec = convert(Vector{Float64}, time_data);

            p = plot(time_vec, volt_vec)

            plot!(title = "",
            size=(950,500),
            left_margin = 40px,
            right_margin = 70px,
            bottom_margin = 70px,
            xlabel="Time (s)",
            ylabel="Voltage (V)",
            tickfontsize=18,
            guidefontsize=22,
            legend = :none,
            framestyle = :box,
            dpi = 500,
            )

            display(p)

            sleep(0.004) # unit second
        end
    end
end

print_serial_data("/dev/ttyACM0", 115200, 200)

My device is "/dev/ttyACM0", and it works well with only line printing (no plotting). But when I add a plotting function inside the LibSerialPort.open(port_name, baudrate) do sp. I encounter the issue:

OS error code 16: Device or resource busy ERROR: LoadError: libserialport returned SP_ERR_FAIL - Host OS reported a failure. Stacktrace: [1] error(s::String) @ Base ./error.jl:35 [2] check(ret::LibSerialPort.Lib.SPReturn) @ LibSerialPort.Lib ~/.julia/packages/LibSerialPort/i1kHh/src/wrap.jl:299 [3] sp_open(port::Ptr{LibSerialPort.Lib.SPPort}, mode::SPMode) @ LibSerialPort.Lib ~/.julia/packages/LibSerialPort/i1kHh/src/wrap.jl:341 [4] open(portname::String, baudrate::Int64; mode::SPMode, ndatabits::Int64, parity::SPParity, nstopbits::Int64) @ LibSerialPort ~/.julia/packages/LibSerialPort/i1kHh/src/LibSerialPort.jl:474 [5] open(portname::String, baudrate::Int64) @ LibSerialPort ~/.julia/packages/LibSerialPort/i1kHh/src/LibSerialPort.jl:467 [6] open(::var"#1#2"{Float64, CircularBuffer{Float64}, CircularBuffer{Float64}}, ::String, ::Vararg{Any}; kwargs::@Kwargs{}) @ Base ./io.jl:394 [7] open @ ./io.jl:393 [inlined] [8] print_serial_data(port_name::String, baudrate::Int64, buffer_size::Int64) @ Main ~/pico/pico-ads1115/getads/serial_plot/julia/libserial-plot.jl:30 [9] top-level scope @ ~/pico/pico-ads1115/getads/serial_plot/julia/libserial-plot.jl:75 in expression starting at /home/tim/pico/pico-ads1115/getads/serial_plot/julia/libserial-plot.jl:75

I am using Ubuntu 22LTS. How to fix the problem? Thanks in advance.

mgkuhn commented 3 weeks ago

OS error code 16: Device or resource busy

Make sure you always close the /dev/ttyACM0 device before opening it again. You may have ended up trying to open it several times. Or there is some other process that has that device file open. Try the lsof command to find out which process has a device file open. Terminating a process closes all files and devices that it had open, so restarting either Julia, your login session, or your entire computer may also fix this situation.