Engee documentation

CAN software control

This page contains all the available CAN software control functions in Engee.

To work with the CAN software control functions in Engee. install the hardware support package as specified in article. After installation, run:

using Main.EngeeDeviceManager.Devices.CAN

Next, you need to create a CAN object.:

CAN.Can()
CAN.bus_status(device, channel::String)->Int64

Bus condition:

  • 0 — there are no mistakes;

  • A non-zero value is an error.

Arguments

  • device::Main.EngeeDeviceManager.Devices.CAN.CanType: the CAN device object.

  • channel::String: channel ID (for example, "can0", "virtual_0").

CAN.close(device)

Closing the CAN object and releasing resources.

Arguments

  • device::Main.EngeeDeviceManager.Devices.CAN.CanType: the CAN device object.

CAN.create_bus(device, interface::String, channel::String, kbits::Float64, auto_reset::Bool, is_fd::Bool=false, data_kbits::Float64=0.0, timing=nothing)

Creates and activates the CAN bus with the specified settings.

Arguments

  • device::Main.EngeeDeviceManager.Devices.CAN.CanType: the CAN device object.

  • interface::String: Interface type ("socketcan", "pcan", "marathon", "virtual").

  • channel::String: channel ID (for example, "can0", "virtual_0").

  • kbits::Float64: transmission rate in kbit/s.

  • auto_reset::Bool: automatic restart in case of errors;

  • is_fd::Bool: whether to use CAN FD (optional, default false);

  • data_kbits::Float64: speed for CAN FD (optional, default 0.0);

  • timing::Union{Nothing, CanFdTiming, CanTiming}: additional timing parameters (optional, default Nothing).

CAN.destroy_bus(device, channel::String)

Stops and removes the CAN bus.

Arguments

  • device::Main.EngeeDeviceManager.Devices.CAN.CanType: the CAN device object.

  • channel::String: channel ID (for example, "can0", "virtual_0").

CAN.get_tx_rx_errors(device, channel::String)->Vector{Int64}

Returns a vector of the number of errors during reception and transmission [tx_errors, rx_errors].

Arguments

  • device::Main.EngeeDeviceManager.Devices.CAN.CanType: the CAN device object.

  • channel::String: channel ID (for example, "can0", "virtual_0").

CAN.recv(device, channel::String, timeout::Float64, async_rpc::Bool=false)->Union{Nothing, CanMessage}

Receiving a single message with a timeout in seconds. Returns Nothing if there are no messages.

Arguments

  • device::Main.EngeeDeviceManager.Devices.CAN.CanType: the CAN device object.

  • channel::String: channel ID (for example, "can0", "virtual_0").

  • timeout::Float64: timeout in seconds.

  • async_rpc::Bool: optional, by default false. If true, reception is performed asynchronously.

CAN.reset(device, channel::String)

Restarting the interface (restoring after Bus-off).

Arguments

  • device::Main.EngeeDeviceManager.Devices.CAN.CanType: the CAN device object.

  • channel::String: channel ID (for example, "can0", "virtual_0").

CAN.send(device, channel::String, message::CanMessage, async_rpc::Bool=false)

Sending a CAN message.

Arguments

  • device::Main.EngeeDeviceManager.Devices.CAN.CanType: the CAN device object.

  • channel::String: channel ID (for example, "can0", "virtual_0").

  • message::CanMessage: a CAN message being sent.

  • async_rpc::Bool: optional, by default false. If true, sending is performed asynchronously, the call is non-blocking.

CAN.set_bus_settings(device, interface::String, channel::String, kbits::Float64, auto_reset::Bool, is_fd::Bool=false, data_kbits::Float64=0.0, timing=nothing)

Configures the CAN interface before creating the bus.

Arguments

  • device::Main.EngeeDeviceManager.Devices.CAN.CanType: the CAN device object.

  • interface::String: Interface type ("socketcan", "pcan", "marathon", "virtual").

  • channel::String: channel ID (for example, "can0", "virtual_0").

  • kbits::Float64: transmission rate in kbit/s.

  • auto_reset::Bool: automatic restart in case of errors;

  • is_fd::Bool: whether to use CAN FD (optional, default false);

  • data_kbits::Float64: speed for CAN FD (optional, default 0.0);

  • timing::Union{Nothing, CanFdTiming, CanTiming}: additional timing parameters (optional, default Nothing).

CAN.set_filters(device, channel::String, filter_id::Int64, mask::Int64)

Hardware acceptance filter by arbitration ID. Filter (0, 0) accepts all messages.

Arguments

  • device::Main.EngeeDeviceManager.Devices.CAN.CanType: the CAN device object.

  • channel::String: channel ID (for example, "can0", "virtual_0").

  • filter_id::Int64: ID of the filter.

  • mask::Int64: a mask specifying which bits of the arbitration ID should match.

CAN.start_stream(device, channel::String, sample_time::Float64=0.01)->Tuple{String, String}

Start streaming reception with a preset step. Returns queue names for AMQPStream.

Arguments

  • device::Main.EngeeDeviceManager.Devices.CAN.CanType: the CAN device object.

  • channel::String: channel ID (for example, "can0", "virtual_0").

  • sample_time::Float64: step to start reception (optional, default 0.01)

Structure of the CAN message

Base.@kwdef struct CanMessage
    timestamp::Float64          # метка времени
    arbitration_id::Int64       # ID сообщения (11 или 29 бит)
    is_extended_id::UInt8       # 1 — 29-битный ID
    is_remote_frame::UInt8      # 1 — RTR
    is_error_frame::UInt8       # 1 — кадр ошибки
    is_fd::UInt8                # 1 — CAN FD
    bitrate_switch::UInt8       # 1 — переключение скорости
    error_state_indicator::UInt8
    dlc::Int64                  # длина данных (0–8 Classic, 0–64 FD)
    data::Union{Vector{UInt8}, Int64}
end

Examples

Interface virtual

can = CAN.Can()

CAN.set_bus_settings(can, "virtual", "virtual_0", 500.0, true)
CAN.set_bus_settings(can, "virtual", "virtual_1", 500.0, true)
CAN.create_bus(can, "virtual", "virtual_0", 500.0, true)
CAN.create_bus(can, "virtual", "virtual_1", 500.0, true)
CAN.set_filters(can, "virtual_0", 0, 0)

data_field = rand(UInt8, 8)
message = CanMessage(
    timestamp = rand(Float64),
    arbitration_id = rand(UInt32),
    is_extended_id = 0,
    is_remote_frame = 0,
    is_error_frame = 0,
    is_fd = 0,
    bitrate_switch = 0,
    error_state_indicator = 0,
    dlc = length(data_field),
    data = data_field,
)

CAN.send(can, "virtual_0", message, true)
msg = CAN.recv(can, "virtual_1", 0.0)
println("Отправлено: $data_field")
println("Получено:   $(msg.data)")

CAN.destroy_bus(can, "virtual_0")
CAN.close(can)

CAN FD

CAN.set_bus_settings(can, "socketcan", "can0", 500.0, true, true, 2000.0)
CAN.create_bus(can, "socketcan", "can0", 500.0, true, true, 2000.0)

fd_message = CanMessage(
    timestamp = time(), arbitration_id = 0x123,
    is_extended_id = 0, is_remote_frame = 0, is_error_frame = 0,
    is_fd = 1, bitrate_switch = 1, error_state_indicator = 0,
    dlc = 64, data = rand(UInt8, 64),
)
CAN.send(can, "can0", fd_message)