• SDO – Service Data Objects – CanOpen

    The SDO or Service Data Objects provide access to the object dictionaries in each device. They are particularly useful for configuration of devices as the SDO protocol is allowed in pre-operation mode. But it is also possible to get “process” data values by polling via SDO the appropriate object dictionary entry.

    SDO protocol always confirms the read/write operation.

    When performing a SDO Read or Write the Index of the object dictionary entry and the sub index is always specified, the index is 2 bytes and the sub index 1 byte. if the data to be read/written is 32 bits or less then it can be done in an expedited packet thus only one transmit and one confirm receive is necessary.

    SDO uses the following COB-IDs

    COB-ID NMT Function
    0x600+node id SDO Receive
    0x580+node id SDO Transmit

    NB the TX/RX direction are from the point of view of the device. So to query a device on the network you would send a 0x600+nodeid and get back a 0x580+nodeid

    The SDO Packet looks like the following :-

    Can header rtr len Byte 0 Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6 Byte 7
    0x600 + node 0 8 Command Index Sub Index Data

    The Can header consists of the COB ID (Function + Node), the RTR bit and 4 bits representing the packet length (0-8) This makes the header 16 bits. So the total packet is 10 bytes.

    The SDO packet always contains 8 bytes of data (even if they are not all used). Command specifies the nature of the transfer read/write etc. The Index of the object dictionary being queried is the next 2 bytes (Don’t forget its Little Endian on the wire), followed by 1 byte specifying the sub-index. The remaining 4 bytes contain the data of the transfer (or zero if they are not required)

    The command byte bits all have various meanings and the 8 bits of the command can be divided into bits with the following meanings depending on who sent the message. In this context the server is the node initiating the read/write operation and the client is the responding node.

    If there is 4 bytes or less than the transfer can be expedited and all the data sent within the command or response packet. This limits the overall SDO transfer to just two packets. If more than 4 bytes of data is required to be transferred then a segmented transfer is used. Where after the first command or response packet, additional packets are sent and requested/acknowledged until all data is complete. There is also a Block transfer where instead of confirming each segment, the entire block is transferred then only one confirmation is made at the end.

    As the various flags and handshakes are subtly different, details for each is provided.

    Expedited Read Dictionary Object

    Request Server -> Client  (0x600 + Node ID)

    Can Header rtr len Byte 0 B1 B2 B3 B4 B5 B6 B7
    0x600 + node 0 8 Command Index Sub Index 0

     

    Command Code Bits Value Meaning
    7-5 010 CCS – Client Command Specifier
    4-0 00000 Not used

    The overall command for this transfer is

    Command Code Meaning
    0x40 Read Dictionary Object

    Note! at this point you do not actually know it is an expedited transfer you have just requested to read a dictionary object, the server will confirm in the response if it can expedite the transfer. If the total data size is 4 bytes or less, the server will set the appropriate bits in the response and send the data with the response. if you have requested an object that is larger that 4 bytes the reply will have the expedited transfer bit set to 0 and then you must look at the segmented transfer

    Response, Client -> Server (0x580 + Node ID)

    Can Header rtr lrn B0 B1 B2 B3 B4 B5 B6 B7
    0x580 + node 0 8 Command Index Sub Index Data

    The index and Sub index are as you specified and the command byte has the following meaning:-

    Command Code Bits Value Meaning
    7-5 010b SCS – Server Command Specifier
    4 0 (Not Used) Segment toggle bit
    3-2  (n)

    Data size

    n=3 (11b) 1 data bytes sent

    n=2 (10b) 2 data bytes sent

    n=1 (01b) 3 data byte sent

    n=0 (00b) 4 data byte sent

    1 1 expedited transfer
    0 1 data set size is indicated

     

    Command Code Meaning
    0x43 Read Dictionary Object reply, expedited, 4 bytes sent
    0x47 Read Dictionary Object reply, expedited, 3 bytes sent
    0x4B Read Dictionary Object reply, expedited, 2 bytes sent
    0x4F Read Dictionary Object reply, expedited, 1 bytes sent

    Expedited Write Dictionary Object

    Request Server -> Client  (0x600 + Node ID)

    Can Header rtr len B0 B1 B2 B3 B4 B5 B6 B7
    0x600 + node 0 8 Command Index Sub Index Data

     

    Command Code Bits Value Meaning
    7-5 001b SCS – Server Command Specifier
    4 0 (Not Used) Segment toggle bit
    3-2  (n)

    Data size

    n=3 (11b) 1 data bytes sent

    n=2 (10b) 2 data bytes sent

    n=1 (01b) 3 data byte sent

    n=0 (00b) 4 data byte sent

    1 1 expedited transfer
    0 1 data set size is indicated

    The overall command for this transfer is one of :-

    Command Code Meaning
    0x23 Write Dictionary Object reply, expedited, 4 bytes sent
    0x27 Write Dictionary Object reply, expedited, 3 bytes sent
    0x2B Write Dictionary Object reply, expedited, 2 bytes sent
    0x2F Write Dictionary Object reply, expedited, 1 bytes sent

    it is important that the the above data size is correct and the correct command code is used depending on the size of the object dictionary entry you are trying to write to. Can Open will enforce that only a 1 byte write can be performed to a 1 byte entry in the dictionary and the same goes for 1,2,3 and 4 bytes so make sure you use the correct size or an error will be returned

    Response, Client -> Server (0x580 + Node ID)

    The response packet again contains the index and sub index you specified and should look like:-

    Can Header rtr len B0 B1 B2 B3 B4 B5 B6 B7
    0x580 + node 0 8 Command Index Sub Index 00000000

     

    Command Code Bits Value Meaning
    7-5 011 SCS – Server Command Specifier
    4-0 00000 Not used

    Read Dictionary Object (segmented)

    The read starts exactly the same way as documented in Expedited Read Dictionary Object :-

    Request Server -> Client  (0x600 + Node ID)

    Can Header rtr len B0 B1 B2 B3 B4 B5 B6 B7
    0x600 + node 0 8 Command Index Sub Index 00000000

    The difference is in the response

    Response, Client -> Server (0x580 + Node ID)

    Can Header rtr len B0 B1 B2 B3 B4 B5 B6 B7
    0x580 + node 0 8 Command Index Sub Index Len

     

    Command Code Bits Value Meaning
    7-5 010b SCS – Server Command Specifier
    4 0 Not Used
    3-2 00 Not Used
    1 0 expedited transfer
    0 1 data set size is indicated

     

    Instead of any data being returned with the response, the data bytes contain a 32bit length that specifies the total data size that needs to be transferred.

    Then each data “segment” is requested and returned one at a time

    Request Server -> Client  (0x600 + Node ID)

    Can Header rtr len B0 B1 B2 B3 B4 B5 B6 B7
    0x600 + node  0 8 Command Index Sub Index 00000000

     

    Command Code Bits Value Meaning
    7-5 011b CCS – Client Command Specifier
    4 0/1 Toggle bit, must be flipped each request (start with a 0)
    3-2 00 Not Used
    1 0 Not Used
    0 1 Not Used

    Response, Client -> Server (0x580 + Node ID)

    Can Header rtr len B0 B1 B2 B3 B4 B5 B6 B7
    0x580 + node  0 8 Command Data

     

    Command Code Bits Value Meaning
    7-5 000b SCS – Server Command Specifier
    4 0/1 Toggle bit, flipped each request
    3-1 000

    (number of data bytes ([8-n to 7]) that do NOT contain data)

    or zero if segment size not specified

    0 0/1 1 = Last segment

    Write Dictionary Object (segmented)

    If uploading more than 4 bytes to a client a segmented transfer can be used

    Request Server -> Client  (0x600 + Node ID)

    Can Header rtr len B0 B1 B2 B3 B4 B5 B6 B7
    0x600 + node  0 8 Command Index Sub Index Len

    Instead of sending any data bytes, the total length of the data is sent in the Len Field of the first packet

    Command Code Bits Value Meaning
    7-5 001b CCS – Client Command Specifier
    4 0 Not Used
    3-2 00 Not Used
    1 0 expedited transfer
    0 1 data set size is indicated

    The client then responds with the following packet

    Can Header rtr len B0 B1 B2 B3 B4 B5 B6 B7
    0x580 + node  0 8 Command Index Sub Index 00000000

    With command as follows:-

    Command Code Bits Value Meaning
    7-5 011 SCS – Server Command Specifier
    4-0 00000 Not used

    Then the handshake of the data packets(segments) begins

    Can Header rtr len B0 B1 B2 B3 B4 B5 B6 B7
    0x600 + node  0 8 Data

     

    Command Code Bits Value Meaning
    7-5 011 SCS – Server Command Specifier
    4 0/1 toggle (change each packet, start with 0)
    3-0 0000 Not used

    And the client confirms each segment with the following :-

    Can Header rtr len B0 B1 B2 B3 B4 B5 B6 B7
    0x580 + node 8 Command 00000000000000

     

    Command Code Bits Value Meaning
    7-5 001 SCS – Server Command Specifier
    4 0/1 toggle, changes each time
    3-0 0000 Not used

    Error/Abort codes

    When something goes wrong, or it is necessary to abort the command specifier in all cases can be changed to Abort Transfer. There are two abort messages one to the client and one from the client.

    If the server needs to abort the transfer the packet is

    Can Header B0 B1 B2 B3 B4 B5 B6 B7
    0x600 + node 0 8 Command Index Sub index Additional Info Error code Error class

    If the client aborts the transfer the packet is

    Can Header rtr len B0 B1 B2 B3 B4 B5 B6 B7
    0x580 + node 0 8 Command Index Sub index Additional Info Error code Error class

    The command bits are common to both packets for an abort

    Command Code Bits Value Meaning
    7-5 100 SCS/CCS – Abort
    4-0 00000 Not used

    The Fields Add Info, Err code and Err class describe the reason for the abort. some errors need an Additional Code

    Description Error Class Error Code Additional Code
    Toggle bit not alternated 5 Service Error 3 Parameter Inconsistent
    0
    Command specifier not valid 5 Service Error 4 Illegal Parameter
    0
    Object does not exist 6 Access Error 2 Object non-existent
    0
    Attempt to read a write only Object 6 Access Error 1 Object access unsupported
    0
    Attempt to write a read only Object 6 Access Error 1 Object access unsupported
    0
    Index value is reserved for further use (00A0h-0FFFh
    and A000h-FFFFh)
    6 Access Error 4 Invalid address
    0
    Access failed due to hardware 6 Access Error 6 Hardware fault
    0
    Sub-index does not exist 6 Access Error 9 Object attribute inconsistent
    11h
    Object length too high 6 Access Error 7 Type conflict
    12h
    Object length too low 6 Access Error 7 Type conflict
    13h
    Data cannot be transferred / Invalid signature 8 Other Error 0
    20h
    Parameter value out of range 6 Access Error 9 Object attribute inconsistent
    30h
    Sub-parameter value out of range 6 Access Error 9 Object attribute inconsistent
    33h
    Maximum value < Minimum value 6 Access Error 9 Object attribute inconsistent
    36h
    Object cannot be mapped to PDO 6 Access Error 4 Invalid address
    41h
    PDO length exceeded 6 Access Error 4 Invalid address
    42h
    General internal incomptibility 6 Access Error 4 Invalid address
    44h

     

  • CanOpen on a Raspberry PI using CanFestival

    I wanted to hook a Raspberry PI into a CanOpen network and have it as a slave device, mainly for logging purposes. I had previously identified CanFestival  as a potential CanOpen stack to be used for this project as it describes itsself as “CanFestival focuses on providing an ANSI-C platform independent CANOpen® stack that can be built as master or slave nodes on PCs, Real-time IPCs, and Microcontrollers” so that is sounding promising.

    The other potential stack I had considered was CanOpenNode, this stack wins hands down for implementing on a PIC32/24 as it pretty much works out of the box on those platforms. The devil is always in the details and in this case the detail is the driver, or how the stack connects to the actual can hardware. Both stacks have certain “drivers” that allow them to interface to the host, both stacks as C implementations that just seem to work. But the winner was CanFestival supported socket_can.

    Socket_can is an implementation of can using unix sockets, this might not seem like a big deal, but its very efficient. Sockets have built in queuing mechanisms and expose them selves to usespace in a nice friendly way. Through put is not going to be an issue. Other CAN systems use character devices, eg they emulate a serial port and you talk one byte at a time to the character device. This is inefficient and has no queuing, so on busy networks things could go wrong.

    The hardware selected was the PICAN board from SK Pang (UK Supplier). Quick delivery, the board arrived next day and I was excited to start playing with it. I am using a Raspberry PI 2 and there are slight differences between the 1 and 2 when setting up the drivers on the PI (hint PI2 is much improved)

    Can board on raspberry pi 2

    Complete instructions can be found on SK Pang’s blog but the TLDR; version is in raspi-config, advanced -> turn on SPI. then add to /boot/config.txt the following

    dtoverlay=mcp2515-can0-overlay,oscillator=16000000,interrupt=25
    dtoverlay=spi-bcm2835-overlay

    Thats it, a reboot later everything should be good the correct kernel modules will load at boot and the can interface will be ready to go.

    CanFestival

    The purpose of this was CanOpen not just raw can so lets proceed with Festival, we will do this on the raspberry PI as it should be ready to go with code compiling and will save the hassle of a cross compile setup for such a trivial thing.

    Download the source code from http://dev.automforge.net/CanFestival-3/ , you can check out the code as a Mecurial repository, or if you don’t know what that is, just download the latest source from http://dev.automforge.net/CanFestival-3/archive/tip.tar.bz2 which will get the latest code as a tar ball with bz2 compression.

    wget http://dev.automforge.net/CanFestival-3/archive/tip.tar.bz2
    Unpack the code
    tar -xvjf tip.tar.bz2
    Change directory to move into the source tree, Note at the time of writing the tip ID was 8bfe0ac00cdb when you do this it may have changed so just cd into the folder just unpacked which will be named CanFestival-3-?????????????
    cd CanFestival-3-8bfe0ac00cdb
    Now configure and build the code
    ./configure --arch=armv6 --target=unix --can=socket
    make
    sudo make install

    So thats good to go at this point and you should be able to test, an annoying niggle is that the can interface needs to be brought up with the “link” command, i am sure this can be fixed in festival but as it stands out of the box to run the first thing you need to do is :-

    sudo /sbin/ip link set can0 up type can bitrate 500000
    CanOpenShell load#libcanfestival_can_socket.so,can0,500k,1,1

    Where the paramaters for load are library name, can channel, bitrate, nodeID and master(1)/slave(0)

    If CanOpenShell starts correctly you should see

     Node_initialisation
    Note_preOperational

    at this point press enter

    You can then sent NMT commands with the ssta/ssto/srst/scan commands eg ssta#0 start all nodes, and you can read and write SDOs with the rsdo and wsdo commands
    so you can talk to other CanOpen devices and prove you have a working network.

    Creating a node with festival

    So how do you actually use festival to do something real? The best example to start with and the simplest is in examples/SillySlave and is a very basic demo of a CanOpen slave on the network. Of cause sillyslave didn’t compile out of the box with the rest of festival and to get it to work do the following, firsty move to the /examples/sillyslave directory and edit the Makefile( eg use nano Makefile -c) on line 42 go to the very end and remove “-lcanlib”

    Next you also need to edit main.h and change the following defines in the section marked “Please tune the following defines to suit your needs:”

    #define NODE_MASTER 0x1
    #define NODE_SLAVE 0x40
    #define DRIVER_LIBRARY "libcanfestival_can_socket.so"
    #define BAUDRATE 500
    #define BUS 0

    Next you need to build as follows :-
    make mrproper
    make

    This is important as the SillySlave.c file is out of date and old and needs to be regenerated, only the mrproper target will remove it, not just make make all or clean. What it actually does is generate SillySlave.c from an XML representation of the object dictionay and using another tool this can be converted to/from the EDS/electronic data sheet files that is part of the CanOpen standard.

    To run the sample just do :-

    ./SillySlave

    If you have another can node, you can start/stop the node with NMT commands, and it will send a PDO for every SYNC it receives.

    The important thing to take home here is main.c is trivial, its the minimum needed to start up the application, SillySlave.c is machine generated and this is the goodness of the object dictionary and how you configure the main parts of your node.

    Creating an object dictionary with festival

    So the time has come to make the Sillyslave something real, your friend in this process is the objdicteditor tool, which is a python tool

    You need to run this from a GUI, either the PI’s X windows or another system (even windows) with python and python wx installed. Lets assume you are using the PI still. Firstly ensure you have the wx widgets for python
    sudo apt-get install python-wxtools
    Then change to X windows and use a keyboard and mouse to continue
    Open a terminal window and CD to the directory containing the canfestival source, then cd into the objdictgen directory and do the following python objdictedit.py Then if you go to File->Open abd browse to the examples/SillySlave directory and open SillySlave.od you can edit the object dictionary from a nice GUI with ease, any changes you make if you save them back to the od file you can then build this into the slave by following the previous steps to build sillyslave with your new changes.

    Canfestival object dictionary editor

    A few finishing words

    Sillyslave is very basic, the bare minimum and really the defines for the nodeid and the bitrate are wrong and these should be read from the object dictionary directly. If you need to add more advanced functionality CanFestival has callback hooks which can be used, but i leave developing a real application as an exercise for you to do on your own as this is where the business end of what ever you are trying to do actually starts now all the boiler plate is taken care of.

  • NMT Protocol – Network Managment – CanOpen

    Back to CanOpen

    The NMT Protocol is used by the master node to start/stop and reset the slave nodes of the system. Depending on configuration settings (in the object dictionary) nodes may start up in run or pre-operational state. Any nodes in pre-operation state will require being set to run by the master

    The NMT packet is aways sent with a COB-ID of 0x000 this is the highest priority message that can be sent and it has the following format.

    COB-ID rtr len NMT Function Target Node
    0x000 0 2 1 byte 1 byte

    Target Node can be either the specific node to address 0x01-0x7F or 0x00 to address all nodes on the bus

    NMT Function can be one of the following

    Code NMT Function
    0x01 Enter Operational
    0x02 Enter Stop
    0x80 Enter Pre-operational
    0x81 Reset node
    0x82 Reset communication

    Can Open NMT States

     

    After power on the node automatically enters initialization, it then moves to pre-operational and emits a Guard 0x700 Message of type bootup to signal to other nodes that it is present and awake. Depending on the nodes configuration it may then automatically enter Operation state. The Initalisation state is formed from two substates, reset application and reset communications. Reset application resets all the object dictionary entries from the standard profile and the manufacture specific sections. Reset communication resets the object dictionary entries from the communications profile to their power on values.Either of these reset states may be entered directly at any other time .

    In different states various protocols are available to the node, in operational all protocols are available, in Stopped only a limited subset is available, as shown below.

     

    Function Stopped Pre operational operational
    NMT Yes Yes Yes
    EMCY No Yes Yes
    PDO No No Yes
    SDO No Yes Yes
    GUARD Yes Yes Yes
    SYNC NO Yes Yes
    TIMESTAMP NO Yes Yes

     

  • CanOpen

    CanOpen is built on top of the standard CAN protocol and is used extensively in Automation. It is a well defined standard and controlled by the CiA group in the words of the CiA group “CANopen unburdens the developer from dealing with CAN hardware-specific details such as bit timing and acceptance filtering. It provides standardized communication objects (COB) for time-critical processes, configuration as well as network management data.”

    CanOpen splits the network up into individual nodes and each node has multiple functions, the combination of a node ID and a function produce what is known as a COB ID. In theory CanOpen supports up to 127 individual nodes. Everything in CanOpen essentially revolves around the object dictionary, every node has its own object dictionary and this contains all the data that will be transmitted between nodes, it also contains all the configuration and settings parameters of each node. There are a certain number of standard entries that all nodes are expected to have (as defined in the standard) but then there are many optional nodes that are only present if a device implements a certain function, eg a 8 output relay module has a specific entry in dictionary for setting the output states of each channel.

    CanOpen much like Can is a broadcast protocol. A particular node sends a command, the command is received by all nodes. Acceptance filters within the nodes determine if the node cares about a packet or not. Most functions combine a function ID with a node ID to produce the COB ID, the standard functions are discussed next.

    Standard functions

    The standard functions in CanOpen are as follows:-

    ID Description
    0x000 NMT
    0x080 Sync
    0x080 + Node ID Emergency
    0x100 Timestamp
    0x180 + Node ID TX PDO 1
    0x200 + Node ID RX PDO 1
    0x280 + Node ID TX PDO 2
    0x300 + Node ID RX PDO 2
    0x380 + Node ID TX PDO 3
    0x400 + Node ID RX PDO 3
    0x480 + Node ID TX PDO 4
    0x500 + Node ID RX PDO 4
    0x580 + Node ID TX SDO
    0x600 + Node ID RX SDO
    0x700 + Node ID Guard
    0x7E4 LSS TX
    0x7E4 LSS RX

    The various functions listed above are described below in summary. Full details are provided on separate pages.

    NMT

    Network management, This packet is sent only my the master node and is used to start,stop and reset nodes on the network. Nodes have various operation states and in each state they are allowed to do certain operations.

    Sync

    This packet is used in combination with synchronous PDOs, the master sends the sync packet and all the slaves will respond by sending in their PDO data (that is configured as syncronous)

    Emergency

    This packet sends network and node critical events to all other nodes.

    PDO – Process Data Objects

    This protocol is used to rapidly send data from one node to 1 or more others. PDOs are very flexible and transmit particular values from one nodes object dictionary to another. The values they transmit, the update rates and behaviour are fully programmable and are themselves defined in the object dictionary,

    SDO – Service Data Objects

    This protocol allows you to read or write another nodes object dictionary in a polled manner. Two forms exist, a short form for expedited reads or writes where everything required fits within the 8 bytes of the CAN frame, or extended where multiple handshakes are used to transfer all the data.

    Guard

    This protocol is used for various guarding/heartbeat systems to ensure nodes are alive and responding. Wake up messages (when a node first powers up) also are transmitted in this protocol.

    CanOpen Packets

    All CanOpen packets have the same structure,

    COB-ID RTR Data length data
    Length 11 Bits 1 bit 4 bits 0-8 bytes
    Range 0x000-0x7FFF 0,1 0-8 8 Bytes

    As discussed COB ID is function + node id, it has to fit in to the 11 bit can header so values 0x000-0x7FF are allowed, lower COB-IDs have higher priority, so NMT and emergency messages are more important than PDOs and SDOs etc.
    Next 1 bit is RTR, remote transmission request (RTR) this is discouraged from being used in CanOpen
    Next 4 bits are the length, this specifies the length of the rest of the packet, or how many data bytes follow 0-8
    Then up to 8 bytes of data (must agree with length bits)

    CanOpen packets on the wire

    As a quick note, if you are observing can open packets on the wire with a scope for example, what you see is not exactly what is described previously but is more like:-

    Description Length
    Start bit (0) 1
    Can Identifier or COB-ID 11
    Remote Transmission request (RTR) 1
    IDE (0) 1
    Reserved 0 (0) 1
    Data length 4
    Data 0-64
    CRC 15
    CRC Delimiter 1
    ACK slot 1
    ACK Delimiter 1
    End of frame 7

    The Pinky read bytes are the ones describde in this document as those are the ones you have control over at the CanOpen level, the other frames should be considered a lower level and part of CAN.

    But watch out for bit stuffing. Every 5 bits of the same polarity will generate a bit of the other polarity which needs to be factored in the above table when decoding the protocol. If you are using a higher level decoder on a scope, such as Picoscope offers this will handle this for you and just give you the required data which out you worring about the decoding, but handy to know if you ever need to use a scope!