Error while reading Ethercat CoE SDO via Datalayer (C++)

Hi everyone,

we need to read (and write) acyclical CoE objects to configure some motion controllers.

In this example we try to read the object with index 0x6041 of type U16

First we tried a request via the GUI and received the expected response. The request looks like this:

{
    "request": {
        "addressType": "fixedphysical",
        "address": 1003,
        "objectIndex": 24641,
        "subIndex": 0,
        "flags": "noFlags",
        "data": [],
        "maxLength": 2
    }
}

 

But when we try to do the apparently same request in our C++ application we always get a "DL_TYPE_MISMATCH". We build the flatbuffer as follows:

 

#include "comm/ethercat/master/fbs/sdo_generated.h"

// ...

flatbuffers::FlatBufferBuilder flatBufferBuilder = flatbuffers::FlatBufferBuilder();
std::vector<uint8_t> data;
data.resize(2);
auto requestData = flatBufferBuilder.CreateVector<uint8_t>(data);
auto sdoRequest = comm::ethercat::master::fbs::CreateSDORequest(flatBufferBuilder,
                                                                comm::ethercat::master::fbs::Addresstype::Addresstype_fixedphysical,
                                                                1003,    // ethercat slave address
                                                                24641,   // object index 0x6041
                                                                0,       // sub index 0
                                                                comm::ethercat::master::fbs::SDOFlags::SDOFlags_noFlags,
                                                                requestData,
                                                                2);
auto sdo = comm::ethercat::master::fbs::CreateSDO(flatBufferBuilder, sdoRequest);
flatBufferBuilder.Finish(sdo);
comm::datalayer::Variant payload;
auto variantResult = payload.copyFlatbuffers(flatBufferBuilder);

// ...

 

and do an asynchronous read:

 

 // DataLayerClient_ is an initialized comm::datalayer::IClient
auto result = DataLayerClient_->readAsync("fieldbuses/ethercat/master/instances/ethercatmaster/device_access/coe/sdo",
                                          payload,
                                          [](comm::datalayer::DlResult result, const comm::datalayer::Variant *data)
                                          {
                                              if (comm::datalayer::STATUS_FAILED(result))  // here we get the DL_TYPE_MISMATCH
                                              {
                                                  TRACE_MSG("Datalayer Read failed: %s", result.toString());
                                              }
                                              else
                                              {
                                                  // ...
                                              }
                                          });

 

 

We already tried several variations of the flatbuffer (e.g. different sized data, omitting the data, ..) but always get a DL_TYPE_MISMATCH.

What might be the reason for this Error? How can we fix it?

Is there any additional documentation of the Datalayer Interface of the EthercatMasterApp? All our information is based on the read-/write-type descriptions in the Datalayer itself.

 

Best Regards,
Chris

 


(The ctrlX is running on RM21.11 with SDK 1.12.0)

Best reply by nickH

Hello Community, 

after some further testing we were able to find a functioning example-code which uses this interface in the ctrlX Data Layer, to read out EtherCAT CoE SDO parameters from C++. 

Some changes to the code from my earlier post above where necessary:

 

/* global defined stuff (see: sample-cpp/datalayer.client)
    comm::datalayer::DlResult _result;
    comm::datalayer::Variant _data;
    comm::datalayer::IClient *_client = datalayerSystem.factory()->createClient(connectionString);
*/

//actual communication with the DL interface: "fieldbuses/ethercat/master/instances/ethercatmaster/device_access/coe/sdo"

flatbuffers::FlatBufferBuilder builder;
builder.ForceDefaults(true);
//build SDORequest
auto requestSDO = comm::ethercat::master::fbs::CreateSDORequest(builder,                                                          
                                                             comm::ethercat::master::fbs::Addresstype::Addresstype_fixedphysical,
                                                                  1001,
                                                                  12403,
                                                                  1,
                                                                  comm::ethercat::master::fbs::SDOFlags::SDOFlags_noFlags,
                                                                  0,
                                                                  65535
                                                                  );
   
builder.Finish(requestSDO);

//Build SDOResponse
std::vector<uint8_t> data;
data.resize(2);
auto responseData = builder.CreateVector<uint8_t>(data);
auto responseSDO = comm::ethercat::master::fbs::CreateSDOResponse(builder, responseData);
builder.Finish(responseSDO);

//Build SDO
auto sdo = comm::ethercat::master::fbs::CreateSDO(builder, requestSDO, responseSDO);
builder.Finish(sdo);

//share Flatbuffer to Variant
_result = _data.shareFlatbuffers(builder);
std::cout<<"_data.shareFlatbuffers(builder) "<< _result.toString()<<std::endl;

//use a data layer client to do the actual reading
_result =_client->readSync("fieldbuses/ethercat/master/instances/ethercatmaster/device_access/coe/sdo", &_data);
std::cout<<"_client->readSync(.../coe/sdo) "<< _result.toString()<<std::endl;
  
if(_result == comm::datalayer::DlResult::DL_OK){
   _result = _data.verifyFlatbuffers(comm::ethercat::master::fbs::VerifySDOBuffer);
   std::cout<<"verifyFlatbuffers: "<<_result.toString()<<std::endl;
   if (_result == comm::datalayer::DlResult::DL_OK){
      auto buffer = _data.getData();
      auto sdoValue = comm::ethercat::master::fbs::GetSDO(buffer);

      auto sdoValueResponse = sdoValue->response();
      auto sdoValueResponseData = sdoValueResponse->data();

      auto length = sdoValueResponseData->Length();
      for(uint32_t i = 0; i<length; i++){
        std::cout<<"Response Data Byte" << i <<": "<<int(sdoValueResponseData->Get(i))<<std::endl;
      }
  }
}

 

 

Like before I tested it with a IndraDrive connected to my ctrlX CORE via EtherCAT CoE. The output in the console is:

 

_data.shareFlatbuffers(builder) DL_OK
_client->readSync(...) DL_OK
verifyFlatbuffers: DL_OK
Response Data Byte0: 1
Response Data Byte1: 96

 

 

Please let me know if this sample code can help you with your solution. 

Sorry for any inconvenience caused. We are working on improving the interfaces and the description of the interfaces.

Best regards, 
Nick

View original
9 replies