FORUM CTRLX AUTOMATION
ctrlX World Partner Apps for ctrlX AUTOMATION
11-27-2023 12:02 PM - edited 11-27-2023 12:48 PM
Hello,
I am currently facing an issue while trying to control a Festo VTEM device via EtherCAT using the C++ SDK provided by Bosch Rexroth. Below is the code snippet I am using
#include <stdio.h>
#include <map>
#include <iostream>
#include <chrono>
#include <thread>
#include <csignal>
#include "comm/datalayer/datalayer.h"
#include "comm/datalayer/datalayer_system.h"
#include "comm/datalayer/memory_map_generated.h"
static bool g_endProcess = false;
static void signalHandler(int signal)
{
std::cout << "signal: " << signal << std::endl;
g_endProcess = true;
}
int main(void)
{
comm::datalayer::DlResult result;
comm::datalayer::Variant data;
comm::datalayer::Variant dataIn;
comm::datalayer::DatalayerSystem datalayer;
datalayer.start(false);
std::signal(SIGINT, signalHandler);
// First we have to open the realtimememory, reading the whole outputs.
uint8_t* outData;
std::cout << "Opening some realtime memory" << std::endl;
std::shared_ptr<comm::datalayer::IMemoryUser> output;
result = datalayer.factory()->openMemory(output, "fieldbuses/ethercat/master/instances/VTEM/realtime_data/output");
if (comm::datalayer::STATUS_FAILED(result))
{
std::cout << "Open the memory failed with: " << result.toString() << std::endl;
}
// We can read the Inputs to get a Start trigger for example
uint8_t* inData;
std::cout << "Opening some realtime memory" << std::endl;
std::shared_ptr<comm::datalayer::IMemoryUser> input;
result = datalayer.factory()->openMemory(input, "fieldbuses/ethercat/master/instances/VTEM/realtime_data/input");
if (comm::datalayer::STATUS_FAILED(result))
{
std::cout << "Open the memory failed with: " << result.toString() << std::endl;
}
do
{
std::cout << "Try to get MemoryMap" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
result = output->getMemoryMap(data);
std::cout << "Getting MemoryMap with: " << result.toString() << std::endl;
} while (comm::datalayer::STATUS_FAILED(result) && !g_endProcess);
return 0;
}
I can successfully open the memory input and output; however, when I attempt to read, get a map, or begin access, I encounter errors such as DL_RT_NOTOPEN or DL_RT_NOVALIDDATA (I will provide more details on this soon).
I have not initialized the Data Layer client as shown in the sample code provided in the SDK(https://github.com/boschrexroth/ctrlx-automation-sdk/tree/main/samples-cpp/datalayer.ecat.io). My reasons for not doing so are as follows:
I would appreciate any guidance or suggestions on resolving these issues and whether initializing the client is necessary for my specific setup.
Thank you for your assistance, and please let me know if you require any further information to help diagnose the problem.
Solved! Go to Solution.
11-27-2023 10:59 PM - edited 11-29-2023 12:04 AM
Hi @prachandabhanu ,
I do believe you will need to create a client in order to utilize the memory maps. As your code is written, the application doesn't inherently know that it should open memory on the local device. Creating the client will tell the application to create an ipc connection if no other address is provided.
With regard to the AppArmor error, what does your snapcraft.yaml look like? Take a look at the datalayer.ecat.io example and make sure you have the same plugs.
EDIT: @ipa-vsp --- You actually should not need a client, my mistake. Using the shared memory requires IPC and therefore the application must run on the same device as the datalayer broker. Are you running the application locally on the CORE?
11-28-2023 12:10 PM - edited 11-28-2023 12:12 PM
Hi @Sgilk,
Thank you for your previous assistance. I've resolved the AppArmor error and realized that I hadn't correctly initialized the snapcraft.yaml file with all the necessary plugins.
Here's an example of my current initialization:
comm::datalayer::IClient* client = getClient(datalayer);
if (client == nullptr)
{
std::cout << "ERROR Client connected" << std::endl;
datalayer.stop();
return 1;
}
result = client->readSync("fieldbuses/ethercat/master/instances/VTEM/realtime_data/output/map", &data);
std::cout << "Read returned: " << result.toString() << std::endl;
result = client->readSync("fieldbuses/ethercat/master/instances/VTEM/realtime_data/input/map", &dataIn);
std::cout << "Read returned: " << result.toString() << std::endl;
std::signal(SIGINT, signalHandler);
// First we have to open the realtimememory, reading the whole outputs.
uint8_t* outData;
std::cout << "Opening some realtime memory" << std::endl;
std::shared_ptr<comm::datalayer::IMemoryUser> output;
result = datalayer.factory()->openMemory(output, "fieldbuses/ethercat/master/instances/VTEM/realtime_data/output");
std::cout << "Open the memory with: " << result.toString() << std::endl;
if (comm::datalayer::STATUS_FAILED(result))
{
std::cout << "Open the memory failed with: " << result.toString() << std::endl;
}
// We can read the Inputs to get a Start trigger for example
uint8_t* inData;
std::cout << "Opening some realtime memory" << std::endl;
std::shared_ptr<comm::datalayer::IMemoryUser> input;
result = datalayer.factory()->openMemory(input, "fieldbuses/ethercat/master/instances/VTEM/realtime_data/input");
std::cout << "Open the memory with: " << result.toString() << std::endl;
if (comm::datalayer::STATUS_FAILED(result) && !g_endProcess)
{
std::cout << "Open the memory failed with: " << result.toString() << std::endl;
}
This setup successfully opens the memory with the result DL_OK. However, I encounter an issue with the following section of the code
do
{
std::cout << "Try to get MemoryMap" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
result = output->getMemoryMap(data);
std::cout << "Getting MemoryMap with: " << result.toString() << std::endl;
} while (comm::datalayer::STATUS_FAILED(result));
In this part, I receive the error DL_RT_INVALIDMEMORYMAP when attempting to get the MemoryMap. Interestingly, if I comment out this section, I can print the memory map values without any issues. For example, I can find and print details like Name of Output and Bitoffset.
Name of Output we found: CPX_FB37/VTEM_8_Valves_48DI_DO_/Outputs.Valve_1_Output_5
Bitoffset: 168
However, when I try to begin access, I face another issue indicated by the result DL_RT_NOTOPEN.
Could you help me identify any potential mistakes that might still exist in my implementation?
Best regards,
Vishnuprasad Prachandabhanu
11-29-2023 08:10 AM
Hi Vishnuprasad Prachandabhanu,
The problem might be, that your fieldbus is not running when you are trying to access the RT-data. After you installed your snap you have to switch back into operating mode, so your fieldbus (EtherCAT) gets switched into "Running".
Please have a look into this Post. This blog-poster had a similar problem. (Note: but you don't have to deactivate the watchdog since you don't run in sync with the scheduler)
Best regards,
Nick