LibSerialPort.jl – access serial ports
LibSerialPort
— ModuleThe LibSerialPort
module provides access to serial ports (UARTs or USB/Bluetooth devices that emulate their operating-system interface) using the portable C library libserialport.
It defines the SerialPort
type, which is returned by LibSerialPort.open
. This is a subtype of Base.IO
and can therefore be used like a file handle, using many of the same read
, write
, print
, etc. methods defined for Base.IO
.
Example
using LibSerialPort
list_ports()
ports = get_port_list()
sp = LibSerialPort.open("/dev/ttyUSB0", 115200)
set_flow_control(sp)
sp_flush(sp, SP_BUF_BOTH)
write(sp, "hello\n")
println(readline(sp))
close(sp)
Enumerating serial ports
LibSerialPort.list_ports
— Functionlist_ports([nports_guess::Integer])`
Print a list of currently visible ports, along with some basic info.
nports_guess
provides the number of ports guessed. Its default is 64
.
LibSerialPort.get_port_list
— Functionget_port_list([nports_guess::Integer])
Return a vector of currently visible ports.
nports_guess
provides the number of ports guessed. Its default is 64
.
LibSerialPort.print_port_metadata
— Functionprint_port_metadata(sp::SerialPort; show_config::Bool = true)
Print info found for this port. Note: port should be open to obtain a valid FD/handle before accessing fields.
show_config
is true
by default and prints out the current port settings.
Opening and configuring ports
Base.open
— Methodopen(portname::AbstractString, baudrate::Integer;
mode::SPMode, ndatabits::Integer,
parity::SPParity, nstopbits::Integer)
Construct, configure and open a SerialPort
object.
portname
is the name of the serial port to open. Typical port names available depend on the operating system. Some valid names are listed byget_port_list()
, but there are can be others and aliases:- Linux:
"/dev/ttyS0"
,"/dev/ttyUSB0"
,"/dev/serial/by-id/..."
- Linux:
- macOS:
"/dev/cu.usbserial-0001"
,"/dev/cu.Bluetooth-Incoming-Port"
- macOS:
- Windows:
"COM1"
,"COM2"
,"COM3"
- Windows:
baudrate
is the data signalling rate, or the reciprocal duration of one data bit, in bits/s. The set of values supported depends on the UART hardware, but typically includes e.g. 9600, 19200 and 115200.mode
selects in which direction of transmission access is requested and can take the values:SP_MODE_READ
,SP_MODE_WRITE
, andSP_MODE_READ_WRITE
(default).
The parameters ndatabits
, parity
and nstopbits
have the same meaning as in set_frame
and default to the common “8N1” frame format (8 data bits, no parity, one stop bit).
To set the flow-control method, use set_flow_control
.
LibSerialPort.SerialPort
— MethodSerialPort(portname::AbstractString)
Constructs and returns a SerialPort
object.
Base.open
— Methodopen(sp::SerialPort; mode::SPMode = SP_MODE_READ_WRITE)
Open the serial port sp
.
mode
selects in which direction of transmission access is requested and can take the values: SP_MODE_READ
, SP_MODE_WRITE
, and SP_MODE_READ_WRITE
(default).
Base.close
— Methodclose(sp::SerialPort)
Close the serial port sp
.
LibSerialPort.set_speed
— Functionset_speed(sp::SerialPort, baudrate::Integer)
Set the data signalling rate, or the reciprocal duration of one data bit, in bits/s. The set of values supported depends on the UART hardware, but typically includes e.g. 9600, 19200 and 115200.
Raise an ErrorException
if bps
is not a value supported by the driver or hardware.
LibSerialPort.set_frame
— Functionset_frame(sp::SerialPort;
ndatabits::Integer = 8,
parity::SPParity = SP_PARITY_NONE,
nstopbits::Integer = 1)
Configure the data framing parameters. Defaults to the very common “8N1” scheme, which consists of a start bit followed by eight data bits, no parity bit, one stop bit.
for more details.
ndatabits
is the number of data bits, which is8
in the common "8N1" schemeparity
controls the presence and value of a party bit and can take the valuesSP_PARITY_NONE
(default),SP_PARITY_ODD
,SP_PARITY_EVEN
,SP_PARITY_MARK
andSP_PARITY_SPACE
nstopbits
sets the number of stop bits, typically1
(default) or2
LibSerialPort.set_flow_control
— Functionset_flow_control(sp::SerialPort;
rts::SPrts = SP_RTS_OFF,
cts::SPcts = SP_CTS_IGNORE,
dtr::SPdtr = SP_DTR_OFF,
dst::SPdsr = SP_DSR_IGNORE,
xonxoff::SPXonXoff = SP_XONXOFF_DISABLED)`
Configure the flow-control lines and method. Many systems don't support all options. If an unsupported option is requested, the library will return SPERRSUPP.
rts
controls the output line Ready To Send (RTS) and can take the valuesSP_RTS_OFF
(default),SP_RTS_ON
andSP_RTS_FLOW_CONTROL
.cts
controls the input line Clear To Send (CTS) and can take the valuesSP_CTS_IGNORE
(default) andSP_CTS_FLOW_CONTROL
dtr
controls the output line Data Terminal Ready (DTR) and can take the valuesSP_DTR_OFF
(default),SP_DTR_ON
, andSP_DTR_FLOW_CONTROL
dsr
controls the input line Data Set Ready (DSR) and can take the valuesSP_DSR_IGNORE
(default) andSP_DSR_FLOW_CONTROL
xonxoff
controls whether software flow control via the control bytes XOFF (pause transmission, 0x13, Ctrl-S) and XON (resume transmission, 0x11, Ctrl-Q) is active, and in which direction; it can take the values:SP_XONXOFF_DISABLED
(default),SP_XONXOFF_IN
,SP_XONXOFF_OUT
, andSP_XONXOFF_INOUT
Base.isopen
— Methodisopen(sp::SerialPort) -> Bool
Determine whether a SerialPort
object is open.
Base.eof
— Methodeof(sp::SerialPort) -> Bool
Return the “end-of-file” state (true
or false
). Since serial ports do not have any standard mechanism for signalling the end of a transmitted file, this is just a dummy function that returns whatever Boolean value eof
was previously set with seteof(sp, eof)
. Returns false
by default.
LibSerialPort.seteof
— Functionseteof(sp::SerialPort, state::Bool)
Set the return value of eof(sp)
to state
.
LibSerialPort.get_port_settings
— Functionget_port_settings(sp::SerialPort)
Return port settings for sp
as a dictionary.
LibSerialPort.print_port_settings
— Functionprint_port_settings(sp::SerialPort)
Print port settings for sp
.
LibSerialPort.set_read_timeout
— Functionset_read_timeout(sp::SerialPort, seconds::Real)
Set a read timeout limit of t
> 0 seconds for the total (cumulative) time that subsequently called blocking read functions can wait before a Timeout
exception is thrown.
Example
sp=LibSerialPort.open("/dev/ttyUSB0", 115200)
# wait until either two lines have been received
# or 10 seconds have elapsed
set_read_timeout(sp, 10)
try
line1 = readuntil(sp, '
')
line2 = readuntil(sp, '
')
catch e
if isa(e, LibSerialPort.Timeout)
println("Too late!")
else
rethrow()
end
end
clear_read_timeout(sp)
See also: clear_read_timeout
, set_write_timeout
LibSerialPort.set_write_timeout
— Functionset_write_timeout(sp::SerialPort, seconds::Real)
Set a write timeout limit of t
> 0 seconds for the total (cumulative) time that subsequently called blocking read functions can wait before a Timeout
exception is thrown.
Example
sp=LibSerialPort.open("/dev/ttyUSB0", 300)
# wait until either 4000 periods have been
# passed on to the serial-port driver or
# 10 seconds have elapsed
set_write_timeout(sp, 10)
try
for i=1:50 ; write(sp, '.' ^ 80); end
catch e
if isa(e, LibSerialPort.Timeout)
println("This took too long!")
else
rethrow()
end
end
clear_write_timeout(sp)
See also: clear_write_timeout
, set_read_timeout
LibSerialPort.clear_read_timeout
— Functionclear_read_timeout(sp::SerialPort)
Cancel any previous read timeout, such that blocking read operations will now wait without any time limit.
LibSerialPort.clear_write_timeout
— Functionclear_write_timeout(sp::SerialPort)
Cancel any previous write timeout, such that blocking write operations will block without any time limit.
LibSerialPort.Lib.sp_flush
— Functionsp_flush(port::Port, buffers::SPBuffer)
sp_flush(port::SerialPort, buffers::SPBuffer)
Discard data in the selected serial-port buffer(s).
Supported values for buffers
: SP_BUF_INPUT
, SP_BUF_OUTPUT
, SP_BUF_BOTH
Returns SP_OK
upon success or raises an ErrorException
otherwise.
Not to be confused with Base.flush
, which writes out buffered data rather than discarding it: the underlying libserialport
C library unfortunately uses the verb “flush” differently from its normal meaning for Base.IO
(sp_drain
provides the latter in this library).
LibSerialPort.Lib.sp_drain
— Functionsp_drain(port::Port)
sp_drain(SerialPort::Port)
Wait for buffered data to be transmitted.
LibSerialPort.Lib.sp_output_waiting
— FunctionReturns the number of bytes in the output buffer.
Read and write methods from Base
Many of the read/write methods defined in Base
that operate on an object of type IO
can also be used with objects of type SerialPort
. Therefore we repeat the documentation of some of these here. (Note that some of the following docstings also refer to other methods that are not applicable to SerialPort
.)
Base.read
— Methodread(io::IO, T)
Read a single value of type T
from io
, in canonical binary representation.
Note that Julia does not convert the endianness for you. Use ntoh
or ltoh
for this purpose.
read(io::IO, String)
Read the entirety of io
, as a String
.
Examples
julia> io = IOBuffer("JuliaLang is a GitHub organization");
julia> read(io, Char)
'J': ASCII/Unicode U+004A (category Lu: Letter, uppercase)
julia> io = IOBuffer("JuliaLang is a GitHub organization");
julia> read(io, String)
"JuliaLang is a GitHub organization"
Base.read!
— Functionread!(stream::IO, array::AbstractArray)
read!(filename::AbstractString, array::AbstractArray)
Read binary data from an I/O stream or file, filling in array
.
Base.readbytes!
— Functionreadbytes!(stream::IO, b::AbstractVector{UInt8}, nb=length(b))
Read at most nb
bytes from stream
into b
, returning the number of bytes read. The size of b
will be increased if needed (i.e. if nb
is greater than length(b)
and enough bytes could be read), but it will never be decreased.
readbytes!(stream::IOStream, b::AbstractVector{UInt8}, nb=length(b); all::Bool=true)
Read at most nb
bytes from stream
into b
, returning the number of bytes read. The size of b
will be increased if needed (i.e. if nb
is greater than length(b)
and enough bytes could be read), but it will never be decreased.
If all
is true
(the default), this function will block repeatedly trying to read all requested bytes, until an error or end-of-file occurs. If all
is false
, at most one read
call is performed, and the amount of data returned is device-dependent. Note that not all stream types support the all
option.
Base.readavailable
— Functionreadavailable(stream)
Read all available data on the stream, blocking the task only if no data is available. The result is a Vector{UInt8}
.
Base.readline
— Functionreadline(io::IO=stdin; keep::Bool=false)
readline(filename::AbstractString; keep::Bool=false)
Read a single line of text from the given I/O stream or file (defaults to stdin
). When reading from a file, the text is assumed to be encoded in UTF-8. Lines in the input end with '\n'
or "\r\n"
or the end of an input stream. When keep
is false (as it is by default), these trailing newline characters are removed from the line before it is returned. When keep
is true, they are returned as part of the line.
Examples
julia> open("my_file.txt", "w") do io
write(io, "JuliaLang is a GitHub organization.\nIt has many members.\n");
end
57
julia> readline("my_file.txt")
"JuliaLang is a GitHub organization."
julia> readline("my_file.txt", keep=true)
"JuliaLang is a GitHub organization.\n"
julia> rm("my_file.txt")
Base.readlines
— Functionreadlines(io::IO=stdin; keep::Bool=false)
readlines(filename::AbstractString; keep::Bool=false)
Read all lines of an I/O stream or a file as a vector of strings. Behavior is equivalent to saving the result of reading readline
repeatedly with the same arguments and saving the resulting lines as a vector of strings.
Examples
julia> open("my_file.txt", "w") do io
write(io, "JuliaLang is a GitHub organization.\nIt has many members.\n");
end
57
julia> readlines("my_file.txt")
2-element Array{String,1}:
"JuliaLang is a GitHub organization."
"It has many members."
julia> readlines("my_file.txt", keep=true)
2-element Array{String,1}:
"JuliaLang is a GitHub organization.\n"
"It has many members.\n"
julia> rm("my_file.txt")
Base.eachline
— Functioneachline(io::IO=stdin; keep::Bool=false)
eachline(filename::AbstractString; keep::Bool=false)
Create an iterable EachLine
object that will yield each line from an I/O stream or a file. Iteration calls readline
on the stream argument repeatedly with keep
passed through, determining whether trailing end-of-line characters are retained. When called with a file name, the file is opened once at the beginning of iteration and closed at the end. If iteration is interrupted, the file will be closed when the EachLine
object is garbage collected.
Examples
julia> open("my_file.txt", "w") do io
write(io, "JuliaLang is a GitHub organization.\n It has many members.\n");
end;
julia> for line in eachline("my_file.txt")
print(line)
end
JuliaLang is a GitHub organization. It has many members.
julia> rm("my_file.txt");
Base.write
— Functionwrite(io::IO, x)
write(filename::AbstractString, x)
Write the canonical binary representation of a value to the given I/O stream or file. Return the number of bytes written into the stream. See also print
to write a text representation (with an encoding that may depend upon io
).
The endianness of the written value depends on the endianness of the host system. Convert to/from a fixed endianness when writing/reading (e.g. using htol
and ltoh
) to get results that are consistent across platforms.
You can write multiple values with the same write
call. i.e. the following are equivalent:
write(io, x, y...)
write(io, x) + write(io, y...)
Examples
Consistent serialization:
julia> fname = tempname(); # random temporary filename
julia> open(fname,"w") do f
# Make sure we write 64bit integer in little-endian byte order
write(f,htol(Int64(42)))
end
8
julia> open(fname,"r") do f
# Convert back to host byte order and host integer type
Int(ltoh(read(f,Int64)))
end
42
Merging write calls:
julia> io = IOBuffer();
julia> write(io, "JuliaLang is a GitHub organization.", " It has many members.")
56
julia> String(take!(io))
"JuliaLang is a GitHub organization. It has many members."
julia> write(io, "Sometimes those members") + write(io, " write documentation.")
44
julia> String(take!(io))
"Sometimes those members write documentation."
User-defined plain-data types without write
methods can be written when wrapped in a Ref
:
julia> struct MyStruct; x::Float64; end
julia> io = IOBuffer()
IOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=0, maxsize=Inf, ptr=1, mark=-1)
julia> write(io, Ref(MyStruct(42.0)))
8
julia> seekstart(io); read!(io, Ref(MyStruct(NaN)))
Base.RefValue{MyStruct}(MyStruct(42.0))
Base.print
— Methodprint([io::IO], xs...)
Write to io
(or to the default output stream stdout
if io
is not given) a canonical (un-decorated) text representation. The representation used by print
includes minimal formatting and tries to avoid Julia-specific details.
print
falls back to calling show
, so most types should just define show
. Define print
if your type has a separate "plain" representation. For example, show
displays strings with quotes, and print
displays strings without quotes.
string
returns the output of print
as a string.
Examples
julia> print("Hello World!")
Hello World!
julia> io = IOBuffer();
julia> print(io, "Hello", ' ', :World!)
julia> String(take!(io))
"Hello World!"
Additional read methods
Base.read
— Methodread(sp::SerialPort)
Return all incoming bytes currently available in the UART as a Vector{UInt8}.
Julia's Base module defines read(s::IO, nb::Integer = typemax(Int))
. This method overrides the default value nb
to bytesavailable(sp)
, which is useful for this context.
LibSerialPort.nonblocking_read
— Methodnonblocking_read(sp::SerialPort)
Read everything from the specified serial ports sp
input buffer, one byte at a time, until it is empty. Returns a String
.
Base.bytesavailable
— Methodbytesavailable(sp::SerialPort)
Return the number of bytes waiting in the input buffer.
Other references
The following are listed here only because they are referenced above:
Base.ntoh
— Functionntoh(x)
Convert the endianness of a value from Network byte order (big-endian) to that used by the Host.
Base.hton
— Functionhton(x)
Convert the endianness of a value from that used by the Host to Network byte order (big-endian).
Base.ltoh
— Functionltoh(x)
Convert the endianness of a value from Little-endian to that used by the Host.
Base.htol
— Functionhtol(x)
Convert the endianness of a value from that used by the Host to Little-endian.
Base.stdout
— Constantstdout
Global variable referring to the standard out stream.
Base.string
— Methodstring(xs...)
Create a string from any values, except nothing
, using the print
function.
string
should usually not be defined directly. Instead, define a method print(io::IO, x::MyType)
. If string(x)
for a certain type needs to be highly efficient, then it may make sense to add a method to string
and define print(io::IO, x::MyType) = print(io, string(x))
to ensure the functions are consistent.
Examples
julia> string("a", 1, true)
"a1true"