Dear Community User! We are updating our platform to a new system.
Read more: Important information on the platform change.

cancel
Showing results for 
Search instead for 
Did you mean: 
SOLVED

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

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

c-u
New Poster

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)

9 REPLIES 9

nickH
Community Moderator
Community Moderator

Hello Chris, 

sorry for the late reply. Unfortunately I did not find the time to build a test setup and investigate your issue. 

On the first look, the handling of your FlatBuffer looks good. I'm not sure about the requestData but I would need to try this out by myself. Additionally you could try to use the flatbuffers method ForceDefaults to use default values. 

 

...
builder.ForceDefaults(true);

builder.Finish(requestSDO);
_result = _data.shareFlatbuffers(builder);
std::cout<<"_data.shareFlatbuffers(builder) "<< _result.toString()<<std::endl;

_result =_client->readSync("fieldbuses/ethercat/master/instances/ethercatmaster/device_access/coe/sdo", &_data);
std::cout<<"_client->readSync(...) "<< _result.toString()<<std::endl;  
...

 

Further I would recommend to try it with a synchronous read first, to eliminate sources for error. 

I am sorry but at this point there is not more documentation on the interface.

 

Best regards,

Nick

 

Hi Nick,

thanks for the reply, we tried to do the read the SDO synchronously with following minimal example, but we still get a DL_TYPE_MISMATCH as result. 

#include "comm/datalayer/datalayer.h"
#include "comm/datalayer/datalayer_system.h"
#include "comm/ethercat/master/fbs/sdo_generated.h"
// ... further includes

int main(int ac, char *av[])
{
  comm::datalayer::DlResult result;
  comm::datalayer::DatalayerSystem datalayer;
  datalayer.start(false);
  // connect to client
  // * in process communication (runs as bundle of rexroth-automation) use factory()->createClient()
  // * inter process communication (runs on same target) use factory()->createClient(DL_IPC_AUTO)
  // * on other device use  factory()->createClient("tcp://<ip>:2069")
  comm::datalayer::IClient *client = datalayer.factory()->createClient(DL_IPC_AUTO);

  if (client->isConnected())
  {
    std::cout << "Client connected" << std::endl;
  }
  else
  {
    std::cout << "Client not connected" << std::endl;
  }

  comm::datalayer::Variant data;
  do
  {
    uint16_t address = 1003;
    uint16_t objectIndex = 0x6041;
    uint8_t objectSubIndex = 0;
    flatbuffers::FlatBufferBuilder flatBufferBuilder;

    auto sdoRequest = comm::ethercat::master::fbs::CreateSDORequest(flatBufferBuilder,
                                                                    comm::ethercat::master::fbs::Addresstype::Addresstype_fixedphysical,
                                                                    address,
                                                                    objectIndex,
                                                                    objectSubIndex,
                                                                    comm::ethercat::master::fbs::SDOFlags::SDOFlags_noFlags);
    auto sdo = comm::ethercat::master::fbs::CreateSDO(flatBufferBuilder, sdoRequest);
    flatBufferBuilder.ForceDefaults(true);
    flatBufferBuilder.Finish(sdo);

    std::cout << "------------------StartCycle--------------------------" << std::endl;
    result = data.shareFlatbuffers(flatBufferBuilder);
    std::cout << "data.shareFlatbuffers(builder) " << result.toString() << std::endl;
    result = client->readSync("fieldbuses/ethercat/master/instances/ethercatmaster/device_access/coe/sdo", &data);
    std::cout << "client->readSync(...) " << result.toString() << std::endl;
    std::cout << "------------------StopCycle---------------------------" << std::endl;

    std::this_thread::sleep_for(std::chrono::seconds(1));
  } while (!endProcess);
}

 

We would appreciate any information that could help us to resolve this issue.

Best regards 
Chris

nickH
Community Moderator
Community Moderator

Hello Chris, 

I found some time to do some testing and successfully read out a EtherCAT CoE SDO parameter. 

Here is the access from the Web UI of the Data Layer:

fbea6852-4510-4a81-a505-985bfccd9809.png

Here you can see the FlatBuffer Schema of an SDO: 

 

include "addresstype.fbs";



namespace comm.ethercat.master.fbs;



enum SDOFlags: uint32 (bit_flags)
{
noFlags = 0,
completeAccess = 1,
}



table SDORequest
{
addressType: Addresstype;
address: uint16;
objectIndex: uint16;
subIndex: uint8;
flags: SDOFlags;
data: [uint8];
maxLength: uint32;
}



table SDOResponse
{
data: [uint8];
}



table SDO
{
request: SDORequest;
response: SDOResponse;
}



root_type SDO;

 

Here I read the same SDO Parameter in C++ and printed out the response to the console:

 

 //_result is DlResult
//_data is Variant
//_client is IClient
 

  flatbuffers::FlatBufferBuilder builder;

  //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
                                                                  );
  builder.ForceDefaults(true);
  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.ForceDefaults(true);
  builder.Finish(responseSDO);

  //Build SDO
  auto sdo = comm::ethercat::master::fbs::CreateSDO(builder, requestSDO, responseSDO);
  builder.ForceDefaults(true);
  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(...) "<< _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;
      }

      }
  }

 

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

 

 

Sorry for the late reply. I hope this (not optimized) code snippet can help you out. 

 

Best regards,

Nick 

Hi Nick, 

thanks for your reply, we used your code snippet (with no changes besides the Ethercat-Address, ObjectIndex and SubIndex), but we still get following result:

Client connected
_data.shareFlatbuffers(builder) DL_OK
_client->readSync(...) DL_TYPE_MISMATCH

 

Since we used exactly the same code, we assume we might have some inconsistencies/problems with our versions.

Our used versions are:

  • SDK: SDK-V-0112
  • EthercatMasterApp: 1.12.0
  • ctrlX Release: RM21.11 (release from November 2021)

What would be the next steps to solve the problem? 

Best Regards
Chris

 

nickH
Community Moderator
Community Moderator

Hello Chris,

To read it form the web ui works with your settings (Ethercat-Address, ObjectIndex and SubIndex,...), right?

I used the SDK V1.14, and all apps on my ctrlX CORE are V1.14. You could also try to do it with this version. 

 

Hint for updating your ctrlX CORE:
If your System is V1.12 you can perform an app-update on your ctrlX CORE. Please follow the steps in the Releas Notes (chapter 2.3.2) in the collaboration room (path: ctrlX_CORE_APPS_Releases/V1.14/ctrlX CORE SystemImage). You can download all necessary apps also from the collaboration room (path: ctrlX_CORE_APPS_Releases/V1.14/ctrlX APPs/DC APP Paket). 

Hi Nick

yes the read via the web ui works and returns the expected values.

We will update to 1.14, run the snippet again and let you know about the results.

 

Best regards
Chris

c-u
New Poster

Hi Nick,

we successfully updated our ctrlX to 1.14:

versions.png

The read via the web ui still works as expected:

request.png

 

But with the same code snippet as above (built with the SDK v1.14) the read still returns a DL_TYPE_MISMATCH.

Can you double check that the versions of our installed apps are compatible? 

The only difference (we can see) between your and our setup are the different Ethercat devices and maybe a slightly different build environment. 
What would be the next steps to find a solution?

Best regards
Chris

nickH
Community Moderator
Community Moderator

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

Hi Nick,

thank you very much. We tried your code in the sample and there its working. 

We will update you when we integrated the solution into our realtime bundle and tested it properly.

 

Best regards,
Chris

 

Icon--AD-black-48x48Icon--address-consumer-data-black-48x48Icon--appointment-black-48x48Icon--back-left-black-48x48Icon--calendar-black-48x48Icon--center-alignedIcon--Checkbox-checkIcon--clock-black-48x48Icon--close-black-48x48Icon--compare-black-48x48Icon--confirmation-black-48x48Icon--dealer-details-black-48x48Icon--delete-black-48x48Icon--delivery-black-48x48Icon--down-black-48x48Icon--download-black-48x48Ic-OverlayAlertIcon--externallink-black-48x48Icon-Filledforward-right_adjustedIcon--grid-view-black-48x48IC_gd_Check-Circle170821_Icons_Community170823_Bosch_Icons170823_Bosch_Icons170821_Icons_CommunityIC-logout170821_Icons_Community170825_Bosch_Icons170821_Icons_CommunityIC-shopping-cart2170821_Icons_CommunityIC-upIC_UserIcon--imageIcon--info-i-black-48x48Icon--left-alignedIcon--Less-minimize-black-48x48Icon-FilledIcon--List-Check-grennIcon--List-Check-blackIcon--List-Cross-blackIcon--list-view-mobile-black-48x48Icon--list-view-black-48x48Icon--More-Maximize-black-48x48Icon--my-product-black-48x48Icon--newsletter-black-48x48Icon--payment-black-48x48Icon--print-black-48x48Icon--promotion-black-48x48Icon--registration-black-48x48Icon--Reset-black-48x48Icon--right-alignedshare-circle1Icon--share-black-48x48Icon--shopping-bag-black-48x48Icon-shopping-cartIcon--start-play-black-48x48Icon--store-locator-black-48x48Ic-OverlayAlertIcon--summary-black-48x48tumblrIcon-FilledvineIc-OverlayAlertwhishlist