diff --git a/README.md b/README.md index b09dec0..832d014 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,208 @@ e3-ecmc_plugin_socketcan ====== ESS Site-specific EPICS module : ecmcPlugin_socketcan + +# ScoketCAN + +This module adds some CAN support to ecmc based on SocketCAN: +https://en.wikipedia.org/wiki/SocketCAN + + +# CANOpen + +This module implements a few of the CANOpen functionalities (but it is far from a full CANOpen Implementation). + +The currect implemented features are: + +* SDO segmented r/w + +* PDO r/w + +* Simple master: + + * Simple LSS + + * Heartbeat + + * Sync + +* Simple generic (slave) device + +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 of master device. + : CANOpen node id of master. + : Sample time for LSS. + : Sample time for SYNC. + : Sample time for Heartbeat. +``` + +Example to add a master with LSS, sync, heartbeat sample time of 1s: +``` +ecmcCANOpenAddMaster("ecmcCANOpenMaster",0,1000,1000,1000) +``` + +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 of device. + : CANOpen node id of device. + +``` +Example to add a device with node id 3: +``` +ecmcCANOpenAddDevice("testDevice",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 of master device. + : CANOpen node id of device/master. + : CANOpen cob id of Tx of slave SDO. + : CANOpen cob id of Rx of slave SDO. + : Direction 1=write and 2=read. + : OD index of SDO. + : OD sub index of SDO. + : OS Siz + : 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) +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") + +# 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) +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") + +``` +## ecmcCANOpenAddPDO + +Issueing "ecmcCANOpenAddPDO -h" in the iocsh you will get the following help printout: +``` + ecmcCANOpenAddPDO -h + Use "ecmcCANOpenAddPDO(, + : Name of master device. + : CANOpen node id of device/master. + : CANOpen cob id of PDO. + : Direction 1=write and 2=read. + : Size of PDO (max 8 bytes). + : Readtimeout in ms. + : 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) +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") +``` + +# 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= : 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: +``` + +# 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 +``` + +## vccn 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