EDS File Explained: CANopen and EtherNet/IP Device Files

By | June 19, 2026

An EDS file is a device’s résumé. It is plain text, it ships with the hardware, and your configuration software reads it so it does not have to know anything about your device in advance.

Two industrial worlds use the same three letters for completely different files. CANopen has one EDS format. EtherNet/IP has another. They share an INI-style layout and nothing else — different section names, different fields, different meaning. A CANopen tool handed an EtherNet/IP EDS will simply reject it.

This guide reads both files the way you would actually open them: top to bottom, one section header at a time. Open one of your own vendor files alongside it and follow along.

Reading along with your own file?
Drop it into the online EDS File Viewer and keep it open in a second tab. It detects CANopen or EtherNet/IP automatically and lays out the same sections this guide walks through, so you can match each header to your device as you read.

Where the file comes from

Three places, in order of how much you should trust them:

SourceTrustNote
Vendor download page, matched to the device revisionHighCheck the revision matches the label on the hardware
Installed by the configuration toolMediumOften one file covering a whole product family
Bundled in an old project archiveLowMay predate a firmware change that added objects

The file is not stored in the device. That matters: an EDS describes what the vendor says the device does. The device itself is the authority. When the two disagree, believe the device.

Part 1 — Reading a CANopen EDS

The CANopen EDS format is defined in CiA 306. It is an INI file: square-bracket section headers, key=value lines, semicolon comments.

[FileInfo]

Housekeeping. The one field worth reading is EDSVersion — 4.0 is what you will see on almost everything current.

[FileInfo]
FileName=GenericIO.eds
FileVersion=1
FileRevision=2
EDSVersion=4.0
Description=Generic 16-channel digital I/O node
CreatedBy=Engineering

FileRevision is the revision of the file, not the device. Vendors bump it when they fix a typo in a parameter name. Do not use it to identify hardware.

[DeviceInfo]

This is the identity block, and the first place to look when a device will not come up.

[DeviceInfo]
VendorName=Example Automation
VendorNumber=0x000002F1
ProductName=DIO-16 Node
ProductNumber=0x00000101
RevisionNumber=0x00010002
BaudRate_125=1
BaudRate_250=1
BaudRate_500=1
BaudRate_1000=1
NrOfRXPDO=1
NrOfTXPDO=1
LSS_Supported=1

VendorNumber, ProductNumber, and RevisionNumber should match what the device reports in object 0x1018 over SDO. If they do not, you have the wrong file for that hardware.

RevisionNumber packs two values into 32 bits: the upper 16 are the major revision, the lower 16 are the minor. 0x00010002 is major 1, minor 2.

The BaudRate_xxx lines are flags, not settings. A 1 means the device can run at that bit rate. It says nothing about what the device is currently set to.

LSS_Supported=1 tells you the node ID and bit rate can be set over the bus instead of with DIP switches. Worth knowing before you take the cabinet door off.

[MandatoryObjects], [OptionalObjects], [ManufacturerObjects]

Three index lists. They are a table of contents, not the content itself.

[MandatoryObjects]
SupportedObjects=3
1=0x1000
2=0x1001
3=0x1018

Every CANopen device has those three: device type, error register, and identity. If any is missing from the mandatory list, the file is malformed.

The manufacturer list is the one to read carefully. Anything in it lives in the 0x2000–0x5FFF range, which is vendor territory. That is where the useful device-specific settings hide — filter times, scaling, channel enables — and where two devices from different vendors will never match.

The object sections

Each object gets its own section, named after its index in hex.

[1017]
ParameterName=Producer heartbeat time
ObjectType=0x7
DataType=0x0006
AccessType=rw
DefaultValue=1000
PDOMapping=0

Six fields do the work:

FieldWhat it tells you
ParameterNameDisplay name. Cosmetic, but it is what your tool shows you
ObjectType0x07 VAR, 0x08 ARRAY, 0x09 RECORD — whether the object has sub-indexes
DataTypeNumeric code, see the table below
AccessTypero, wo, rw, const, plus rwr and rww for objects readable or writable only in specific PDO contexts
DefaultValuePower-on value. May be an expression — see the $NODEID section below
PDOMapping1 means this object can be placed in a PDO. 0 means SDO access only

Data type codes come from CiA 301 and are the same in every EDS you will open:

CodeTypeCodeType
0x0001BOOLEAN0x0007UNSIGNED32
0x0002INTEGER80x0008REAL32
0x0003INTEGER160x0009VISIBLE_STRING
0x0004INTEGER320x000AOCTET_STRING
0x0005UNSIGNED80x000FDOMAIN
0x0006UNSIGNED160x0015INTEGER64

LowLimit and HighLimit show up on writable objects. Your tool uses them to reject a bad value before it goes on the bus. They are advisory — the device enforces its own limits and will send an SDO abort regardless.

Sub-index sections

An ARRAY or RECORD splits across several sections. The naming is the parent index, then sub, then the sub-index in hex.

[1018]
ParameterName=Identity object
ObjectType=0x9
SubNumber=5

[1018sub0]
ParameterName=Highest sub-index supported
DataType=0x0005
AccessType=ro
DefaultValue=4

[1018sub1]
ParameterName=Vendor-ID
DataType=0x0007
AccessType=ro
DefaultValue=0x000002F1

Sub-index 0 is always the count. On a RECORD it holds the highest sub-index supported; on an ARRAY it holds the number of entries. Read it before you read anything else in that object.

SubNumber in the parent section says how many sub-index sections follow — including sub 0. A mismatch between SubNumber and the sections actually present is a broken file, and some tools will refuse to load it.

CompactSubObj

An array of 64 identical channels would mean 65 sections. Compact storage collapses them:

[6000]
ParameterName=Read input 8-bit
ObjectType=0x8
DataType=0x0005
AccessType=ro
CompactSubObj=64

Sub-indexes 1 through 64 are implied. They all share the data type and access type of the parent. If you are diffing two EDS files and one looks half the size, check whether it uses compact storage.

The index ranges

Where an object sits tells you who defined it. This is the single most useful thing to know when reading a dictionary you have never seen before.

RangeAreaWho owns it
0x0000–0x0FFFData typesCiA
0x1000–0x1FFFCommunication profileCiA 301 — identical on every device
0x2000–0x5FFFManufacturer-specificThe vendor. No portability
0x6000–0x9FFFDevice profileCiA device profile, e.g. 401 for I/O, 402 for drives
0xA000–0xBFFFInterface profileCiA
0xC000–0xFFFFReserved—

An object in 0x6000 does the same thing on every CiA 401 I/O module ever made. An object in 0x2000 does whatever that vendor decided. Plan your engineering accordingly.

PDO communication and mapping objects

Four blocks in the communication area, and they are the reason most people open an EDS at all.

RangeWhat it is
0x1400–0x15FFRPDO communication parameters
0x1600–0x17FFRPDO mapping parameters
0x1800–0x19FFTPDO communication parameters
0x1A00–0x1BFFTPDO mapping parameters

The offset is the PDO number. RPDO1 is 0x1400 and 0x1600. RPDO2 is 0x1401 and 0x1601. Same pattern for transmit.

The communication object holds the identifier and the timing:

[1800sub1]
ParameterName=COB-ID used by TPDO
DefaultValue=$NODEID+0x180

[1800sub2]
ParameterName=Transmission type
DefaultValue=254

[1800sub3]
ParameterName=Inhibit time
DefaultValue=100

[1800sub5]
ParameterName=Event timer
DefaultValue=500

Transmission type is a single byte that changes the entire behavior of the PDO:

ValueBehavior
0Synchronous, acyclic — transmitted after SYNC, only if the data changed
1–240Synchronous, cyclic — transmitted every nth SYNC
252Synchronous, RTR only
253Asynchronous, RTR only
254Asynchronous, manufacturer-specific event
255Asynchronous, device-profile event

Inhibit time is in units of 100 µs. A value of 100 is 10 ms — the minimum gap between two transmissions of that PDO. Event timer is in milliseconds and forces a transmission even when nothing changes.

The mapping object says what goes in the eight data bytes:

[1A00sub0]
ParameterName=Number of mapped objects
DefaultValue=2

[1A00sub1]
DefaultValue=0x60000108

[1A00sub2]
DefaultValue=0x60000208

Each mapping entry is one 32-bit word, split three ways:

0x60000108
  6000  → index of the mapped object
    01  → sub-index
      08 → length in bits

So that PDO carries object 0x6000 sub 1 in the first byte and 0x6000 sub 2 in the second. Add the lengths of all entries — if the total goes past 64 bits, the device will reject the mapping with an SDO abort. That is a five-minute check in the file versus an hour on the bus.

$NODEID expressions

COB-IDs in an EDS are almost never hardcoded. The same file has to work for node 1 and node 100, so identifiers are written as arithmetic:

DefaultValue=$NODEID+0x200

On node 5 that is 0x205. On node 12 it is 0x20C. The offsets are the CANopen predefined connection set:

ServiceBaseNode 5
EMCY0x080 + node0x085
TPDO10x180 + node0x185
RPDO10x200 + node0x205
TPDO20x280 + node0x285
RPDO20x300 + node0x305
SDO server → client0x580 + node0x585
SDO client → server0x600 + node0x605
Heartbeat0x700 + node0x705

The COB-ID value also carries flags in its top bits. Bit 31 set means the PDO is disabled — which is why a COB-ID that looks like 0xC0000205 on an analyzer is not a valid identifier at all, it is a switched-off PDO. Bit 30 means RTR is not allowed. Bit 29 selects the 29-bit extended frame format.

[DummyUsage] and [Comments]

[DummyUsage] lists which dummy data types the device accepts as PDO padding. It matters when you need to align a value to a byte boundary in a mapping.

[Comments] is free text, numbered by line. Vendors sometimes put real information in there — supported firmware versions, known limitations. Worth a read.

Part 2 — Reading an EtherNet/IP EDS

The ODVA EDS format looks similar at a glance and parses completely differently. Entries end with a semicolon, not a newline, so a single entry can span twenty lines. Comments start with $ and run to end of line. Strings are double-quoted and can contain commas.

That means you cannot read this format line by line. You read it entry by entry.

[File]

Header block. DescText and Revision are the ones people check.

[File]
        DescText = "Example EtherNet/IP Adapter";
        CreateDate = 03-11-2024;
        Revision = 1.1;
        HomeURL = "http://www.example.com";

[Device]

The identity block, and the source of the electronic key.

[Device]
        VendCode = 1298;
        VendName = "Example Automation";
        ProdType = 12;
        ProdTypeStr = "Communications Adapter";
        ProdCode = 257;
        MajRev = 1;
        MinRev = 2;
        ProdName = "EIP-ADPT-16";
        Catalog = "EIP-ADPT-16";

When a scanner opens a connection it can check four of these against what the device reports: vendor code, device type, product code, and revision. That check is the electronic key. Set it to exact match in your scanner and swap in a device with a different minor revision, and the connection fails before any data moves. The error is a connection failure, not a network failure — the cable is fine, the key does not match.

ProdType is a CIP device type code. A few of the common ones:

CodeDevice typeCodeDevice type
0x00Generic device0x0EProgrammable logic controller
0x02AC drive0x10Position controller
0x07General purpose discrete I/O0x16Motor starter
0x0CCommunications adapter0x22Encoder

Vendor codes are assigned by ODVA. The file carries the name in VendName, so you rarely need the number for anything except the key.

[Device Classification]

One line per supported network.

[Device Classification]
        Class1 = EtherNetIP;

A device that also speaks DeviceNet or ControlNet will list those too. Some multiprotocol devices ship one EDS per network instead.

[Params]

Every configurable parameter, one entry each. The fields are positional, comma-separated, and mostly unlabeled — which is why this section is unreadable without either a tool or a lot of counting.

Param1 =
        0,                          $ reserved
        6, "20 04 24 64 30 03",     $ link path size, link path
        0x0000,                     $ descriptor
        0xC7,                       $ data type
        2,                          $ data size in bytes
        "Input Assembly Size",      $ name
        "bytes",                    $ units
        "Number of input bytes produced", $ help
        1, 496, 8,                  $ min, max, default
        ,,,,                        $ scaling
        ,,,,                        $ links
        0;                          $ decimal places

The data type is a CIP type code, not a CANopen one:

CodeTypeCodeType
0xC1BOOL0xC7UINT
0xC2SINT0xC8UDINT
0xC3INT0xCAREAL
0xC4DINT0xD0STRING
0xC6USINT0xDASHORT_STRING

The descriptor word carries flags — whether the parameter is read only, whether it supports scaling, whether it has enumerated strings. If it does have enumerated strings, they appear as a separate EnumN entry with the same number:

Enum2 = 0, "Disabled",
        1, "Enabled";

The link path is a CIP path in hex: class, instance, attribute. 20 04 24 64 30 03 reads as class 0x04 (assembly), instance 0x64 (100), attribute 0x03. That is how the parameter maps onto something the device actually exposes.

[Assembly]

The section that decides what your input and output tags contain.

Assem100 =
        "Input Assembly",
        "20 04 24 64 30 03",
        8,
        0x0000,
        ,
        ,
        8, Param1,
        8, Param2;

Name, path, size in bytes, descriptor, two reserved fields, then pairs: bit size and the parameter it references. An empty reference means padding.

Two things to check here. First, the member bit sizes should add up to the declared byte size — if they do not, there is undocumented padding. Second, the instance number in the section name (Assem100 is instance 100) is what you type into the scanner’s connection configuration. Pick the wrong instance and you get data, just not the data you wanted. That failure mode looks like corrupted values rather than a broken connection, which is why it costs so much time.

[Connection Manager]

Each entry describes one connection the device supports: trigger and transport bits, connection parameters, RPI limits, sizes, format codes, a name, and a path.

Connection1 =
        0x04010002,
        0x44640405,
        ,,,
        ,,,
        ,,
        ,,
        "Exclusive Owner",
        "Bidirectional class 1 connection",
        "20 04 24 05 2C 96 2C 64";

The names tell you most of what you need. “Exclusive Owner” is a bidirectional class 1 connection that only one scanner can hold. “Input Only” and “Listen Only” are the read-paths other scanners use for the same device. The path at the end names the configuration, output, and input assembly instances the connection uses — which cross-checks against the [Assembly] section.

Vendors leave optional fields blank, so the commas run together. Count them carefully or let a parser do it.

[Port]

The physical or logical ports and their CIP paths. Short, and rarely the problem.

[Capacity]

Connection and packet-rate limits — how many class 1 connections the device supports, and the total packets per second it can handle. If you are fanning out a lot of I/O connections to one adapter, this is the section that tells you when you have asked for too much.

EDS or DCF?

A DCF is a device configuration file. Same format as a CANopen EDS, same sections, but with actual configured values written in for one specific node — plus a [DeviceComissioning] section carrying the node ID and bit rate.

An EDS says what the device can do. A DCF says what one particular device is set to do. If you are handed a DCF, someone has already made configuration decisions and written them down. Read it before you overwrite them.

What goes wrong

SymptomLikely cause in the file
Device will not appear in the tool’s catalogWrong format — a GSD, GSDML, or IODD given to a tool expecting an EDS
Device appears but rejects the downloadEDS revision does not match device firmware; objects listed that the device does not have
CANopen connection fails on key checkVendorNumber, ProductNumber, or RevisionNumber does not match object 0x1018
EtherNet/IP connection fails immediatelyElectronic key mismatch on vendor, device type, product code, or revision
PDO mapping rejected with SDO abortMapped entries total more than 64 bits
PDO configured but nothing on the wireBit 31 set in the COB-ID — the PDO is disabled
Data arrives but the values are wrongWrong assembly instance selected, or a run/idle header the scanner is not expecting
Tool refuses to load the fileSubNumber does not match the sub-index sections present

Quick reference: section names

CANopen (CiA 306)EtherNet/IP (ODVA)Holds
[FileInfo][File]File housekeeping
[DeviceInfo][Device]Vendor, product, revision
—[Device Classification]Supported networks
[MandatoryObjects] etc.—Index lists
[1000], [1018sub1][Params]The configurable content
[1600], [1A00][Assembly]What goes in the cyclic data
[1400], [1800][Connection Manager]Connection identity and timing
—[Port], [Capacity]Ports and limits
[Comments]—Free text

Frequently asked questions

Can I edit an EDS file by hand? You can — it is text. Whether you should is another matter. Object counts, SubNumber fields, and sub-index-0 values all have to stay consistent with the content, and most vendor tools will refuse a file they did not write. If you need a device to behave differently, change the device, not the description of it.

Why does one EDS cover several part numbers? Vendors ship one file per product family to cut support load. The unused objects stay in the file. This is why an EDS can show objects your device returns an abort on — the file is describing a sibling.

Do I need the EDS to talk to the device? No. The EDS is for the engineering tool, not the protocol. A CANopen master can read any object by index over SDO with no file at all, and a CIP scanner can open a connection given the right instance numbers. The file saves you from having to know those numbers.

What is the difference between an EDS and a GSD or GSDML? Same job, different network. GSD is PROFIBUS, GSDML is PROFINET, IODD is IO-Link, EDS is CANopen and the CIP family. None of them are interchangeable.

The EDS says an object is read/write but the device rejects the write. Believe the device. AccessType in the file is documentation. The device enforces access in firmware, and some objects are only writable in specific NMT states — pre-operational, typically. Check the state before you check the file.

How do I know which assembly instance to use? The [Assembly] section names them, and the connection path in [Connection Manager] shows which instances each connection type uses. Exclusive Owner connections normally use both an input and an output instance; Input Only uses the input instance with a heartbeat instance for the output.

Author: Zakaria El Intissar

I've spent 13 years in power system automation, electrical protection, and SCADA communication, as an automation and industrial computing engineer. ScadaProtocols.com is where I turn what I've learned on site into plain guides and working tools — so other engineers can decode, analyze, and troubleshoot industrial communication protocols without the guesswork.