490 lines
17 KiB
Markdown
490 lines
17 KiB
Markdown
e3-ecmc_plugin_socketcan
|
|
======
|
|
ESS Site-specific EPICS module : ecmcPlugin_socketcan
|
|
|
|
# SocketCAN
|
|
|
|
This module adds some CAN support to ecmc based on SocketCAN:
|
|
https://en.wikipedia.org/wiki/SocketCAN
|
|
|
|
## Hardware
|
|
|
|
This module have been tested with Kvaser Leaf Light v2 usb can interface.
|
|
More info about how to setup this hardware can be found here:
|
|
|
|
[Kvaser Leaf V2 setup](kvaser/readme.md)
|
|
|
|
# Install ecmc plugin module
|
|
|
|
## Dependencies
|
|
This module have dependencies to:
|
|
|
|
1. ecmc
|
|
|
|
3. asyn
|
|
|
|
## Configuration
|
|
Ensure that these two files are correct:
|
|
|
|
1. configure/CONFIG_MODULE:
|
|
```
|
|
EPICS_MODULE_TAG:=master
|
|
E3_MODULE_VERSION:=master
|
|
ECMC_DEP_VERSION:=6.3.2
|
|
ASYN_DEP_VERSION:=4.41.0
|
|
```
|
|
|
|
2. configure/RELEASE:
|
|
```
|
|
EPICS_BASE:=${HOME}/epics/base-7.0.4
|
|
E3_REQUIRE_VERSION:=3.4.0
|
|
```
|
|
|
|
## Install
|
|
|
|
The module is installed like any other e3 module by "make install":
|
|
```
|
|
make install
|
|
```
|
|
Now the module should be ready for use.
|
|
|
|
## Load plugin into ecmc
|
|
Like all ecmc plugins the plugin must be loaded into ecmc with the "loadPlugin.cmd" command.
|
|
The loading is needed so that ecmc can link to the callbacks, plc functions and plc constants in the plugin.
|
|
|
|
The "loadPlugin.cmd" command basically takes three arguments:
|
|
|
|
1. PLUGIN_ID: This is just an index of the different plugins loaded into ecmc. So the first loaded plugin should have index 0.
|
|
|
|
2. FILE: Path to the "libecmc_plugin_socketcan.so" file.
|
|
|
|
3. CONFIG: Plugin configuration string. See below for details
|
|
|
|
### Configurations string "CONFIG"
|
|
|
|
The configuration string contains startup configs for the plugin. Currentlly the below configurations can be specified in the CONFIG string:
|
|
```
|
|
DBG_PRINT=<1/0> : Enables/disables printouts from plugin, default = disabled (=0).
|
|
IF=<if name> : Sets can interface (example: can0, vcan0..).
|
|
CONNECT=<1/0> : Auto connect to if at startup, default = autoconnect (=1).
|
|
```
|
|
Also see "Plugin" chapter below for more information about the plugin.
|
|
|
|
### Example
|
|
Example of loading the plugin connecting to the "can0" interface:
|
|
```
|
|
## Load plugin:
|
|
epicsEnvSet(ECMC_PLUGIN_FILNAME,"${HOME}/epics/base-7.0.4/require/${E3_REQUIRE_VERSION}/siteMods/ecmc_plugin_socketcan/master/lib/${EPICS_HOST_ARCH=linux-x86_64}/libecmc_plugin_socketcan.so")
|
|
epicsEnvSet(ECMC_PLUGIN_CONFIG,"IF=can0;DBG_PRINT=0;")
|
|
${SCRIPTEXEC} ${ecmccfg_DIR}loadPlugin.cmd, "PLUGIN_ID=0,FILE=${ECMC_PLUGIN_FILNAME},CONFIG='${ECMC_PLUGIN_CONFIG}', REPORT=1"
|
|
epicsEnvUnset(ECMC_PLUGIN_FILNAME)
|
|
epicsEnvUnset(ECMC_PLUGIN_CONFIG)
|
|
```
|
|
|
|
A complete example can be found in the pmu905 repo where a R&S amplifier is interfaced using this module:
|
|
https://github.com/anderssandstrom/ecmc_pmu905_can
|
|
|
|
|
|
### Access to templates
|
|
|
|
In order to access the templates in the plugin a "require" is needed in the startup script:
|
|
|
|
```
|
|
require ecmc_plugin_socketcan master
|
|
|
|
```
|
|
|
|
# CANOpen
|
|
|
|
This module implements a few of the CANOpen functionalities (but it is far from a full CANOpen Implementation).
|
|
|
|
The current implemented features are:
|
|
|
|
* Simple master:
|
|
|
|
* LSS (basic)
|
|
|
|
* NMT (Heartbeat, dev state)
|
|
|
|
* Sync
|
|
|
|
* Simple generic (slave) device
|
|
|
|
* SDO segmented r/w
|
|
|
|
* PDO r/w
|
|
|
|
These functionalities are configured through iocsh cmds:
|
|
|
|
* ecmcCANOpenAddMaster
|
|
|
|
* ecmcCANOpenAddDevice
|
|
|
|
* ecmcCANOpenAddSDO
|
|
|
|
* ecmcCANOpenAddPDO
|
|
|
|
## ecmcCANOpenAddMaster
|
|
|
|
Issueing "ecmcCANOpenAddMaster -h" in the iocsh you will get the following help printout:
|
|
```
|
|
ecmcCANOpenAddMaster -h
|
|
Use ecmcCANOpenAddMaster(<name>, <node id>,....)
|
|
<name> : Name of master device.
|
|
<node id> : CANOpen node id of master.
|
|
<LSS sample time ms> : Sample time for LSS.
|
|
<Sync sample time ms> : Sample time for SYNC.
|
|
<Heartbeat sample time ms> : Sample time for Heartbeat.
|
|
```
|
|
|
|
Example to add a master with LSS, sync, heartbeat sample time of 1s:
|
|
```
|
|
ecmcCANOpenAddMaster("ecmcCANOpenMaster",0,1000,1000,1000)
|
|
|
|
# Load status records for device
|
|
dbLoadRecords(ecmcPluginSocketCAN_Dev.template, "P=${ECMC_PREFIX},PORT=${ECMC_ASYN_PORT},ADDR=0,TIMEOUT=1,CH_ID=00,DEV_ID=0")
|
|
```
|
|
|
|
Note:: You can only have one master in each ioc (one call to "ecmcCANOpenAddMaster").
|
|
|
|
## ecmcCANOpenAddDevice
|
|
|
|
Issueing "ecmcCANOpenAddDevice -h" in the iocsh you will get the following help printout:
|
|
```
|
|
ecmcCANOpenAddDevice -h
|
|
Use ecmcCANOpenAddDevice(<name>, <node id>)
|
|
<name> : Name of device.
|
|
<node id> : CANOpen node id of device.
|
|
<NMT Heartbeat timeout ms> : Timeout for NMT Heartbeat.\n")
|
|
|
|
```
|
|
Example to add a device with node id 3 and a NMT heartbeat timeout of 3s:
|
|
```
|
|
ecmcCANOpenAddDevice("testDevice",3,3000)
|
|
|
|
# Load status records for device
|
|
dbLoadRecords(ecmcPluginSocketCAN_Dev.template, "P=${ECMC_PREFIX},PORT=${ECMC_ASYN_PORT},ADDR=0,TIMEOUT=1,CH_ID=03,DEV_ID=3")
|
|
```
|
|
|
|
Note:: You can only use the below commands (ecmcCANOpenAddSDO and ecmcCANOpenAddODO) to nodes of an existing device or master.
|
|
|
|
## ecmcCANOpenAddSDO
|
|
|
|
Issueing "ecmcCANOpenAddSDO -h" in the iocsh you will get the following help printout:
|
|
```
|
|
ecmcCANOpenAddSDO -h
|
|
ecmcCANOpenAddSDO( in the iocsh<name>, <node id>,.....)
|
|
<name> : Name of master device.
|
|
<node id> : CANOpen node id of device/master.
|
|
<cob id tx> : CANOpen cob id of Tx of slave SDO.
|
|
<cob id rx> : CANOpen cob id of Rx of slave SDO.
|
|
<dir> : Direction 1=write and 2=read.
|
|
<ODIndex> : OD index of SDO.
|
|
<ODSubIndex> : OD sub index of SDO.
|
|
<ODSize> : OS Siz
|
|
<readSampleTimeMs>: Sample time for read in ms (write is always on demand).
|
|
```
|
|
|
|
A few examples:
|
|
```
|
|
# Example read SDO from device, will be cyclically read at an intervall of 7000ms:
|
|
ecmcCANOpenAddSDO("analogValues",3,0x583,0x603,2,0x2640,0x0,56,7000)
|
|
|
|
# Load record for SDO data
|
|
dbLoadRecords(ecmcPluginSocketCAN_SDO_input.template, "P=${ECMC_PREFIX},PORT=${ECMC_ASYN_PORT},ADDR=0,TIMEOUT=1,T_SMP_MS=${ECMC_SAMPLE_RATE_MS},TSE=${ECMC_TSE},NELM=${NELM=1},CH_ID=03,DEV_ID=3,suffix=AI03-Array,source=basicConfig,DTYP=asynInt8ArrayIn,FTVL=CHAR,NELM=7")
|
|
|
|
# Load record for SDO error
|
|
dbLoadRecords(ecmcPluginSocketCAN_SDO_error.template, "P=${ECMC_PREFIX},PORT=${ECMC_ASYN_PORT},ADDR=0,TIMEOUT=1,T_SMP_MS=${ECMC_SAMPLE_RATE_MS},TSE=${ECMC_TSE},CH_ID=03,DEV_ID=3,suffix=SDO01-AnalogValuesErr,source=analogValues")
|
|
|
|
# Example write SDO to device, will be written on demand (when write data from epics):
|
|
ecmcCANOpenAddSDO("basicConfig",3,0x583,0x603,1,0x2690,0x1,7,0)
|
|
|
|
# Load record for SDO data
|
|
dbLoadRecords(ecmcPluginSocketCAN_SDO_output.template, "P=${ECMC_PREFIX},PORT=${ECMC_ASYN_PORT},ADDR=0,TIMEOUT=1,T_SMP_MS=${ECMC_SAMPLE_RATE_MS},TSE=${ECMC_TSE},NELM=${NELM=1},CH_ID=03,DEV_ID=3,suffix=BasicConfig,source=basicConfig,DTYP=asynInt8ArrayOut,FTVL=CHAR,NELM=7")
|
|
|
|
# Load record for SDO error
|
|
dbLoadRecords(ecmcPluginSocketCAN_SDO_error.template, "P=${ECMC_PREFIX},PORT=${ECMC_ASYN_PORT},ADDR=0,TIMEOUT=1,T_SMP_MS=${ECMC_SAMPLE_RATE_MS},TSE=${ECMC_TSE},CH_ID=03,DEV_ID=3,suffix=SDO02-BasicConfigErr,source=basicConfig")
|
|
|
|
```
|
|
## ecmcCANOpenAddPDO
|
|
|
|
Issueing "ecmcCANOpenAddPDO -h" in the iocsh you will get the following help printout:
|
|
```
|
|
ecmcCANOpenAddPDO -h
|
|
Use "ecmcCANOpenAddPDO(<name>, <node id>
|
|
<name> : Name of master device.
|
|
<node id> : CANOpen node id of device/master.
|
|
<cob id> : CANOpen cob id of PDO.
|
|
<dir> : Direction 1=write and 2=read.
|
|
<ODSize> : Size of PDO (max 8 bytes).
|
|
<readTimeoutMs> : Readtimeout in ms.
|
|
<writeCycleMs> : Cycle time for write (if <= 0 then only write on change).
|
|
|
|
```
|
|
An example:
|
|
|
|
```
|
|
# Read PDO, if not recived pdo within 10s the PDO object will go into error state:
|
|
ecmcCANOpenAddPDO("status",3,0x183,2,8,10000,0)
|
|
|
|
# Load record for PDO data
|
|
dbLoadRecords(ecmcPluginSocketCAN_PDO_input.template, "P=${ECMC_PREFIX},PORT=${ECMC_ASYN_PORT},ADDR=0,TIMEOUT=1,T_SMP_MS=${ECMC_SAMPLE_RATE_MS},TSE=${ECMC_TSE},NELM=${NELM=1},CH_ID=03,DEV_ID=3,suffix=PDO01-Array,source=status,NELM=8")
|
|
|
|
# Load record for PDO error
|
|
dbLoadRecords(ecmcPluginSocketCAN_PDO_error.template, "P=${ECMC_PREFIX},PORT=${ECMC_ASYN_PORT},ADDR=0,TIMEOUT=1,T_SMP_MS=${ECMC_SAMPLE_RATE_MS},TSE=${ECMC_TSE},CH_ID=03,DEV_ID=3,suffix=PDO01-StatusErr,source=status")
|
|
|
|
```
|
|
|
|
# PVs
|
|
|
|
## Communication
|
|
|
|
The status of the CAN communication can be supervised by loading the "ecmcPluginSocketCAN_Com.template":
|
|
|
|
```
|
|
dbLoadRecords(ecmcPluginSocketCAN_Com.template, "P=${ECMC_PREFIX},PORT=${ECMC_ASYN_PORT},ADDR=0,TIMEOUT=1")
|
|
|
|
# Will load:
|
|
IOC_TEST:CAN-Stat-ComErr
|
|
IOC_TEST:CAN-Stat-Connected
|
|
```
|
|
The Connected Pv show if the plugin is connected to socketcan and the hardware.
|
|
The ComErr Pv shows error codes for reads and writes to socketcan socket.
|
|
|
|
## Device (also Master)
|
|
|
|
### ecmcPluginSocketCAN_Dev.template
|
|
|
|
The ecmcPluginSocketCAN_Dev.template loads a NMT PV:
|
|
```
|
|
IOC_TEST:CAN03-Stat-NMT
|
|
```
|
|
The PV tells wich state the device is in and can have the following values:
|
|
* NMT_NOT_VALID : State not valid. Something is wrong.
|
|
|
|
* NMT_BOOT_UP : Device is booting
|
|
|
|
* NMT_STOPPED : Device is stopped
|
|
|
|
* NMT_OP : Device is operational (this is the normal state when running the ioc).
|
|
|
|
* NMT_PREOP : Device is in pre operational state
|
|
|
|
|
|
## PDO
|
|
|
|
## ecmcPluginSocketCAN_PDO_input.template
|
|
|
|
The ecmcPluginSocketCAN_PDO_intput.template in used for input PDOS (data read from a device device to EPICS).
|
|
The template only contains one PV that holds the data:
|
|
|
|
Example:
|
|
```
|
|
dbLoadRecords(ecmcPluginSocketCAN_PDO_input.template, "P=${ECMC_PREFIX},PORT=${ECMC_ASYN_PORT},ADDR=0,TIMEOUT=1,T_SMP_MS=${ECMC_SAMPLE_RATE_MS},TSE=${ECMC_TSE},CH_ID=03,DEV_ID=3,suffix=PDO01-Status_,source=status,NELM=8")
|
|
|
|
# Loads this PV:
|
|
IOC_TEST:CAN03-PDO01-Status_
|
|
```
|
|
The data PV is an waveform of type uchar and length NELM.
|
|
|
|
## ecmcPluginSocketCAN_PDO_output.template
|
|
|
|
The ecmcPluginSocketCAN_PDO_output.template in used for output PDOS (data written from EPICS to device).
|
|
The template only contains one PV that holds the data:
|
|
|
|
Example:
|
|
```
|
|
dbLoadRecords(ecmcPluginSocketCAN_PDO_output.template, "P=${ECMC_PREFIX},PORT=${ECMC_ASYN_PORT},ADDR=0,TIMEOUT=1,T_SMP_MS=${ECMC_SAMPLE_RATE_MS},TSE=${ECMC_TSE},CH_ID=00,DEV_ID=0,suffix=PDO01-Reset_, source=reset,NELM=8")
|
|
|
|
# Loads this PV:
|
|
IOC_TEST:CAN03-PDO01-Reset_
|
|
```
|
|
The data PV is an waveform of type uchar and length NELM.
|
|
|
|
|
|
## ecmcPluginSocketCAN_PDO_error.template
|
|
|
|
The ecmcPluginSocketCAN_PDO_error.template in used to read the PDO error code.
|
|
|
|
Example:
|
|
```
|
|
dbLoadRecords(ecmcPluginSocketCAN_PDO_error.template, "P=${ECMC_PREFIX},PORT=${ECMC_ASYN_PORT},ADDR=0,TIMEOUT=1,T_SMP_MS=${ECMC_SAMPLE_RATE_MS},TSE=${ECMC_TSE},CH_ID=00,DEV_ID=0,suffix=PDO01-ResetErr,source=reset")
|
|
|
|
# Loads this PV:
|
|
IOC_TEST:CAN03-PDO01-ResetErr
|
|
```
|
|
|
|
An error could for example be that the PDO data have not been recived within the correct time frame (readTimeoutMs).
|
|
The PDO is in error state if the error code is not 0.
|
|
|
|
## SDO
|
|
|
|
## ecmcPluginSocketCAN_SDO_input.template
|
|
|
|
The ecmcPluginSocketCAN_SDO_intput.template in used for input SDOS (data read from a device device to EPICS).
|
|
The template only contains one PV that holds the data:
|
|
|
|
Example:
|
|
```
|
|
dbLoadRecords(ecmcPluginSocketCAN_SDO_input.template, "P=${ECMC_PREFIX},PORT=${ECMC_ASYN_PORT},ADDR=0,TIMEOUT=1,T_SMP_MS=${ECMC_SAMPLE_RATE_MS},TSE=${ECMC_TSE},CH_ID=03,DEV_ID=3,suffix=SDO01-AnalogValues_, source=analogValues,DTYP=asynInt16ArrayIn,FTVL=SHORT,NELM=28")
|
|
|
|
# Loads this PV:
|
|
IOC_TEST:CAN03-SDO01-AnalogValues_
|
|
```
|
|
The data PV is an waveform of type uchar and length NELM.
|
|
|
|
## ecmcPluginSocketCAN_SDO_output.template
|
|
|
|
The ecmcPluginSocketCAN_SDO_output.template in used for output SDOS (data written from EPICS to device).
|
|
The template only contains one PV that holds the data:
|
|
|
|
Example:
|
|
```
|
|
dbLoadRecords(ecmcPluginSocketCAN_SDO_output.template,"P=${ECMC_PREFIX},PORT=${ECMC_ASYN_PORT},ADDR=0,TIMEOUT=1,T_SMP_MS=${ECMC_SAMPLE_RATE_MS},TSE=${ECMC_TSE},CH_ID=03,DEV_ID=3,suffix=SDO02-BasicConfig_, source=basicConfig,DTYP=asynInt8ArrayOut,FTVL=UCHAR,NELM=7")
|
|
|
|
# Loads this PV:
|
|
IOC_TEST:CAN03-SDO02-BasicConfig_
|
|
```
|
|
The data PV is an waveform of type uchar and length NELM.
|
|
|
|
## ecmcPluginSocketCAN_SDO_error.template
|
|
|
|
The ecmcPluginSocketCAN_PSO_error.template in used to read the SDO error code.
|
|
|
|
Example:
|
|
```
|
|
dbLoadRecords(ecmcPluginSocketCAN_SDO_error.template, "P=${ECMC_PREFIX},PORT=${ECMC_ASYN_PORT},ADDR=0,TIMEOUT=1,T_SMP_MS=${ECMC_SAMPLE_RATE_MS},TSE=${ECMC_TSE},CH_ID=03,DEV_ID=3,suffix=SDO02-BasicConfigErr,source=basicConfig")
|
|
|
|
# Loads this PV:
|
|
IOC_TEST:CAN03-SDO02-BasicConfigErr
|
|
```
|
|
|
|
An error could for example be that the SDO data have not been recived within the correct time frame or slave is not reposning like it should.
|
|
The SDO is in error state if the error code is not 0.
|
|
|
|
# Plugin
|
|
|
|
Plugin report printout:
|
|
```
|
|
Plugin info:
|
|
Index = 0
|
|
Name = ecmcPlugin_socketcan
|
|
Description = SocketCAN plugin for use with ecmc.
|
|
Option description =
|
|
DBG_PRINT=<1/0> : Enables/disables printouts from plugin, default = disabled (=0).
|
|
IF=<if name> : Sets can interface (example: can0, vcan0..).
|
|
CONNECT=<1/0> : Auto connect to if at startup, default = autoconnect (=1).
|
|
|
|
Filename = /home/dev/epics/base-7.0.4/require/3.4.0/siteMods/ecmc_plugin_socketcan/master/lib/linux-x86_64/libecmc_plugin_socketcan.so
|
|
Config string = IF=vcan0;DBG_PRINT=1;
|
|
Version = 2
|
|
Interface version = 65536 (ecmc = 65536)
|
|
max plc funcs = 64
|
|
max plc func args = 10
|
|
max plc consts = 64
|
|
Construct func = @0x7fb36b81d310
|
|
Enter realtime func = @0x7fb36b81d220
|
|
Exit realtime func = @0x7fb36b81d230
|
|
Realtime func = @0x7fb36b81d270
|
|
Destruct func = @0x7fb36b81d240
|
|
dlhandle = @0xa45a50
|
|
Plc functions:
|
|
funcs[00]:
|
|
Name = "can_connect();"
|
|
Desc = double can_connect() : Connect to can interface (from config str).
|
|
Arg count = 0
|
|
func = @0x7fb36b81d280
|
|
funcs[01]:
|
|
Name = "can_connected();"
|
|
Desc = double can_connected() : Connected to can interface.
|
|
Arg count = 0
|
|
func = @0x7fb36b81d2a0
|
|
funcs[02]:
|
|
Name = "can_add_write(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);"
|
|
Desc = double can_add_write(canId,len,data0..data7) : Add write frame to can interface output buffer.
|
|
Arg count = 10
|
|
func = @0x7fb36b81d2e0
|
|
funcs[03]:
|
|
Name = "can_last_writes_error();"
|
|
Desc = double can_last_writes_error() : get error from last writes.
|
|
Arg count = 0
|
|
func = @0x7fb36b81d2c0
|
|
Plc constants:
|
|
```
|
|
# ecmcByteToArray Asub record
|
|
This module implements an asub record that can merge bytes into an array (waveform)
|
|
|
|
Usage:
|
|
1. Link bytes to inputs A..S.
|
|
|
|
2. Link array to VALA.
|
|
|
|
3. Set size of output in NOVA. This also defines how many inputs will be used.
|
|
|
|
Note: Max 18 bytes (input A..S) will be merged into the array.
|
|
|
|
|
|
EPICS database example of 7 bytes merged intio an array:
|
|
```
|
|
record(aSub, "$(P)CAN${CH_ID}-BasicConfigPackArray_") {
|
|
field(INAM, "ecmcByteToArrayInit")
|
|
field(SNAM, "ecmcByteToArray")
|
|
field(FTA, "UCHAR")
|
|
field(NOA, "1")
|
|
field(INPA, "$(P)CAN${CH_ID}-BasicConfigB0_.VAL") # Byte 0
|
|
field(FTB, "UCHAR")
|
|
field(NOB, "1")
|
|
field(INPB, "$(P)CAN${CH_ID}-VrefPwrCmdCalcB1_.VAL") # Byte 1
|
|
field(FTC, "UCHAR")
|
|
field(NOC, "1")
|
|
field(INPC, "$(P)CAN${CH_ID}-VrefPwrCmdCalcB2_.VAL") # Byte 2
|
|
field(FTD, "UCHAR")
|
|
field(NOD, "1")
|
|
field(INPD, "$(P)CAN${CH_ID}-VdcCtrlCmdCalcB3_.VAL") # Byte 3
|
|
field(FTE, "UCHAR")
|
|
field(NOE, "1")
|
|
field(INPE, "$(P)CAN${CH_ID}-VdcCtrlCmdCalcB4_.VAL") # Byte 4
|
|
field(FTF, "UCHAR")
|
|
field(NOF, "1")
|
|
field(INPF, "0") # Byte 5
|
|
field(FTG, "UCHAR")
|
|
field(NOG, "1")
|
|
field(INPG, "0") # Byte 6
|
|
field(FTVA, "UCHAR")
|
|
field(OUTA, "$(P)CAN${CH_ID}-SDO02-BasicConfig")
|
|
field(NOVA, "7") # 7 bytes (0..6 corresponds to input A..G)
|
|
field(FLNK, "$(P)CAN${CH_ID}-SDO02-BasicConfig.PROC") # Send the data
|
|
}
|
|
```
|
|
|
|
# Testing
|
|
You can use a virtual can, vcan network for testing:
|
|
|
|
## Prerequirements
|
|
|
|
Install can utils:
|
|
```
|
|
$ git clone https://github.com/linux-can/can-utils
|
|
$ cd can-utils
|
|
$ make
|
|
$ make install
|
|
```
|
|
|
|
## vcan setup
|
|
Start virt can 0 (vcan0) and candump:
|
|
```
|
|
$ sudo modprobe vcan
|
|
$ sudo ip link add dev vcan0 type vcan
|
|
$ sudo ip link set up vcan0
|
|
$ candump vcan0
|
|
```
|
|
candump will start to printout the raw can meassages on vcan0 network.
|
|
|
|
# Other intressting things
|
|
|
|
In future it could be an option to use one of these repos for the CANOpen support:
|
|
1. https://github.com/CANopenNode/CANopenNode
|
|
2. https://github.com/CANopenNode/CANopenSocket
|
|
3. https://github.com/marel-keytech/openCANopen
|
|
|