Xyntos | Logo

Overview  |  Quick Start  |  Samples  |  Architecture  |  CoSlave  |  CoMaster  |  Listeners  |  Object Dictionary  |  Configuration  |  Eds2Od


Object dictionary

The object dictionary (OD) is your device’s data — every parameter and process value, addressed by index/sub-index. In CANoopEn the OD is a class — deriving from CoObjectDictionary (Source/ObjectDictionary/CoObjectDictionary.hpp) — whose members are typed entry objects. No tables, no macros. You can write this class by hand, but you don’t have to: the Eds2Od generator creates it from your EDS file.

class MyDeviceOd : public CANoopEn::CoObjectDictionary
{
public:
    MyDeviceOd(CANoopEn::ICoObjectDictionaryListener& listener) :
        CoObjectDictionary(listener),
        _entryDeviceType(0x1000, 0x00, 0x00000000, CANoopEn::CoOdAccessType::ReadOnly),
        _entryHeartbeatTime(0x1017, 0x00, 1000,    CANoopEn::CoOdAccessType::ReadWrite),
        _entryDigitalInputs(0x6000, 0x01, 0,       CANoopEn::CoOdAccessType::ReadOnly),
        _tpdoMapping1(1)
    {
        AddEntry(_entryDeviceType);
        AddEntry(_entryHeartbeatTime);
        AddEntry(_entryDigitalInputs);

        AddTpdoMappingParameter(_tpdoMapping1);
        _tpdoMapping1.AddMappingParameterEntry(_entryTpdoMappingEntry1);
    }

private:
    CANoopEn::CoOdEntryUnsigned32 _entryDeviceType;
    CANoopEn::CoOdEntryUnsigned16 _entryHeartbeatTime;
    CANoopEn::CoOdEntryUnsigned8  _entryDigitalInputs;
    CANoopEn::CoOdPdoMappingParameter _tpdoMapping1;
    // ...
};

Entries are owned by your class — the dictionary stores references only, and nothing is allocated dynamically. Capacity limits come from CoSettings (MaxNumberOfOdEntries, mapping parameter counts).

The stack itself reads and writes the OD for you: an SDO request from a master, a received RPDO, the heartbeat producer reading 1017h — all go through these entries. Communication-profile entries the protocols rely on (1000h, 1001h, 1017h, 1018h, 1200h, 140xh/160xh/180xh/1A0xh, …) must exist in your OD; the samples show a complete minimal set.

Generating the dictionary from an EDS file (Eds2Od)

Eds2Od, the code generator that ships with CANoopEn (canoopentools), generates the OD class from a standard CANopen EDS file. The EDS is your single source of truth: maintain it with any EDS editor — for example the free graphical CANeds from Vector — and regenerate after every change:

Eds2Od MyDevice.eds MyDeviceOd.cpp MyDeviceOd.hpp
  • On the first run — when the .cpp/.hpp files don’t exist yet — complete default files are generated (a class named after the header file). Adapt them freely: on every later run only the code between the *** BEGIN/END GENERATED CODE (Eds2Od) *** markers is replaced, and everything outside the markers is preserved — custom members, methods and constructor code stay untouched, so generated and hand-written code live side by side in the same class.
  • $NODEID+... default values become expressions of the constructor’s uint16_t nodeId parameter (e.g. nodeId + 0x600), so COB-ID objects are initialized with the device’s actual node id.
  • The generated header carries a NumberOfOdEntries constant plus a static_assert against CoSettings::MaxNumberOfOdEntries — a dictionary that outgrows the configured capacity is a compile error, not a runtime surprise.
  • The generated dictionary is exactly as type-safe as a hand-written one: entries are typed member objects (CoOdEntryUnsigned16, …) and every access goes through the typed GetValue/SetValue overloads below — no void*, no casts.

All test and sample dictionaries in the CANoopEn repositories are generated this way. The Eds2Od page describes the tool in detail and links the ready-to-run downloads for Windows and Linux.

Entry types

One class per CANopen data type, all constructed as (index, subIndex, initialValue, accessType):

CoOdEntryBoolean, CoOdEntryUnsigned8/16/24/32/40/48/56/64, CoOdEntryInteger8/16/24/32/40/48/56/64, CoOdEntryReal32/64, CoOdEntryVisibleString, CoOdEntryOctetString, CoOdEntryUnicodeString, CoOdEntryDomain, CoOdEntryTimeOfDay, CoOdEntryTimeDifference.

Access types (CoOdAccessType): Const, ReadOnly (ro), WriteOnly (wo), ReadWrite (rw), ReadWriteProcessInput (rwr), ReadWriteProcessOutput (rww).

Registration

Method Description
void AddEntry(ICoOdEntry& entry) Adds an entry. The entry must stay alive as long as the dictionary (member object).
bool AddRpdoMappingParameter(CoOdPdoMappingParameter&) Registers a receive-PDO mapping (false when MaxNumberOfRpdoMappingParameters is reached).
bool AddTpdoMappingParameter(CoOdPdoMappingParameter&) Registers a transmit-PDO mapping.

Reading and writing values

GetValue/SetValue overloads exist for every plain type (bool, uint8_tuint64_t, int8_tint64_t, float, double), for strings (GetValue(index, subIndex, char* value, size_t bufferSize) / SetValue(index, subIndex, const char* value)) and for domains (address + size). All return true on success (false: entry missing or access not permitted).

// application publishes a process value:
_objectDictionary.SetValue(0x6000, 0x01, inputs);
WritePdoAsync(1);                                  // transmit TPDO 1

// application reads what an RPDO / SDO write delivered:
uint8_t outputs;
_objectDictionary.GetValue(0x6200, 0x01, outputs);

Every value change — no matter whether caused by the stack or your own SetValue — is reported to the ICoObjectDictionaryListener passed to the constructor (details). NotifyValueChanged(nodeId, index, subIndex) triggers the same notification manually. Access is internally serialized with CoSemaphore, so application tasks and the stack may access the dictionary concurrently.

For direct entry access (e.g. to check metadata), GetEntry(index, subIndex) returns the ICoOdEntry* (nullptr if absent) with GetIndex, GetSubIndex, GetAccessType, GetDataType, GetDataSize, and typed GetValue/SetValue.

PDO mapping

CoOdPdoMappingParameter(pdoNumber) describes which entries a PDO carries. Add the OD entries that hold the CANopen mapping values (e.g. 0x1A00sub1 = 0x60000108 — object 6000h sub 01h, 8 bit) with AddMappingParameterEntry, and register the parameter with AddRpdoMappingParameter/AddTpdoMappingParameter. A PDO carries at most 8 bytes (MaxNumberOfPdoMappingParameterEntries mapped objects).

For MPDOs, the constructor takes the addressing mode: CoOdPdoMappingParameter(pdoNumber, CoOdMpdoAddressingMode::...) (source or destination addressing; see the CoMaster MPDO methods).

Master: object dictionaries of remote nodes

A master creates one OD class per remote device type — the local image of that device’s dictionary — and hands it to a CoNode. ReadSdo/ReadObjectDictionary fill the image from the device; WriteSdo/WriteObjectDictionary push image values to the device (details). The image class is built exactly like the local OD above.

XYNTOS_Logo_mit_claim_weiss