FORUM CTRLX AUTOMATION
ctrlX World Partner Apps for ctrlX AUTOMATION
Dear Community User! We have started the migration process.
This community is now in READ ONLY mode.
Read more: Important
information on the platform change.
05-02-2022 11:39 AM
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)
Solved! Go to Solution.
05-10-2022 02:10 PM - edited 05-10-2022 02:25 PM
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
05-13-2022 02:44 PM
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
05-18-2022 04:52 PM - edited 05-18-2022 05:00 PM
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:
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
05-19-2022 11:42 AM
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:
What would be the next steps to solve the problem?
Best Regards
Chris
05-19-2022 01:42 PM
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).
05-19-2022 04:05 PM
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
05-20-2022 03:19 PM - edited 05-20-2022 03:22 PM
Hi Nick,
we successfully updated our ctrlX to 1.14:
The read via the web ui still works as expected:
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
06-28-2022 12:29 PM - edited 06-28-2022 12:41 PM
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
07-26-2022 08:36 AM
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