Closed balazs1123 closed 3 years ago
There is one issue in your slave configuration. You start with SDO download of object 0x1600. But according to the standard you should first write object 0x1c12 and 0x1c13. Could you add that to your startup routine?
The effect from your restart is that now 0x1c12 is configured from the attempt before. So this would explain the behaviour.
Thank you for your really quick response. However, I'd like to ask some further questions.
...
retval += ec_SDOwrite(
slave,
0x1600,
0x00,
TRUE,
sizeof(map_1600_),
&map_1600_,
EC_TIMEOUTRXM);
retval += ec_SDOwrite( slave, 0x1a00, 0x00, TRUE, sizeof(map1a00), &map1a00, EC_TIMEOUTRXM);
retval += ec_SDOwrite( slave, 0x1c12, SUBINDEX, TRUE, sizeof(map1c12), &map1c12, EC_TIMEOUTRXM);
retval += ec_SDOwrite( slave, 0x1c13, 0x00, TRUE, sizeof(map1c13), &map1c13, EC_TIMEOUTRXM); ...
Example for the arrays to be mapped:
uint16_t map1600[9]{ 0x0004, 0x0010, 0x2010, 0x0010, 0x2014, 0x0020, 0x2021, 0x0020, 0x201a };
uint16_t map1c12[2]{0x0001, 0x1600};
So should I change it for the following?
retval += ec_SDOwrite( slave, 0x1c12, SUBINDEX, TRUE, sizeof(map1c12), &map1c12, EC_TIMEOUTRXM);
retval += ec_SDOwrite( slave, 0x1c13, 0x00, TRUE, sizeof(map1c13), &map1c13, EC_TIMEOUTRXM);
retval += ec_SDOwrite( slave, 0x1600, 0x00, TRUE, sizeof(map1600), &map1600, EC_TIMEOUTRXM);
retval += ec_SDOwrite( slave, 0x1a00, 0x00, TRUE, sizeof(map1a00), &map1a00, EC_TIMEOUTRXM);
As mentioned before I tried this version, but I've got the same issue (even if I tried to do it in a "sandwich". So map 1c12,1c13, then 1600,1a00, then 1c12,1c13 again).
3. Before my question I read through the forum, if someone had the same issue, but without luck. However, I found the following answer to another problem:
"And the order is also important, first the mapping object (0x1a01) then the SM assign (0x1c13)."
in https://github.com/OpenEtherCATsociety/SOEM/issues/419
According to this answer I did it correctly in my original version, or did I misunderstand something here?
Ehh, reading back my comment it was perhaps not too clear.
The order for mapping:
In most slaves it does not matter what order you use because they only check assignment and mapping at pre-OP -> safe-OP transition. But there are implementations that are a bit too strict.
Thank you for your quick response, especially on Friday evening. I appreciate your support.
I tried your last proposal, so "clear assign, map, assign". Unfortunately, the cold-start configuration produces the same behaviour. Without knowing the exact ESC type, and its datasheet, it's "tapping in the dark", at least for me. Anyway, please see my latest pdo mapping code:
uint8_t reset = 0x00;
retval += ec_SDOwrite(
slave,
0x1c12,
0x00,
FALSE,
sizeof(reset),
&reset,
EC_TIMEOUTRXM);
retval += ec_SDOwrite(
slave,
0x1c13,
0x00,
FALSE,
sizeof(reset),
&reset,
EC_TIMEOUTRXM);
// CA from this point
retval += ec_SDOwrite(
slave,
0x1600,
0x00,
TRUE,
sizeof(map_1600_),
&map_1600_,
EC_TIMEOUTRXM);
retval += ec_SDOwrite(
slave,
0x1a00,
0x00,
TRUE,
sizeof(map_1a00_),
&map_1a00_,
EC_TIMEOUTRXM);
retval += ec_SDOwrite(
slave,
0x1c12,
0x00,
TRUE,
sizeof(map_1c12_),
&map_1c12_,
EC_TIMEOUTRXM);
retval += ec_SDOwrite(
slave,
0x1c13,
0x00,
TRUE,
sizeof(map_1c13_),
&map_1c13_,
EC_TIMEOUTRXM);
Mapping arrays remained the same as mentioned above.
Please see the wireshark files below.
In above mapping code could you insert following after each SDOwrite()?
ec_readstate();
for(i = 1; i<=ec_slavecount ; i++)
{
if(ec_slave[i].state != EC_STATE_SAFE_OP)
{
printf("Slave %d State=%2x StatusCode=%4x : %s\n",
i, ec_slave[i].state, ec_slave[i].ALstatuscode, ec_ALstatuscode2string(ec_slave[i].ALstatuscode));
}
}
Of course it is best to make a function of this. This has two effects, first to see if there can be an error during the mapping process and not after all is done, and second to have some delay between mapping configuration steps. It is possible SOEM is a bit too fast for the slave and it first needs to do some internal bookkeeping before a transition to safe-OP is possible. The ESM (EtherCAT state machine) protocol should handle this, but you never know.
An other thing to try is to insert a delay of 1sec before doing the slave mapping.
What is also strange is that slave 1 and slave 2 output different AL status codes. Code 0x0052 is even not defined in the EtherCAT standard. Statuscode 0x0024 "Invalid input mapping" indicates that the mapping list is incorrect and not that the SM is programmed the wrong way.
As a last resort, could you wireshark a TwinCat sequence at cold boot? Perhaps there is some tiny detail we are overlooking.
When looking at: https://doc.ingeniamc.com/summit/manuals/summit-reference-manual/tricks-and-tips/ethercat-pdo-mapping
I noticed that the order of mapping inputs and outputs are reversed from what you are doing. Perhaps nothing, perhaps important. So first the inputs and then the outputs.
Thank you for the tips, I appreciate it. I'll try them one by one and see, if any of them helps, then let you know about the results.
Servo Drive 1 State= 2 StatusCode= 0 : No error
Servo Drive 2 State= 2 StatusCode= 0 : No error
Servo Drive 1 State= 2 StatusCode= 0 : No error
Servo Drive 2 State= 2 StatusCode= 0 : No error
Servo Drive 1 State= 2 StatusCode= 0 : No error
Servo Drive 2 State= 2 StatusCode= 0 : No error
Servo Drive 1 State= 2 StatusCode= 0 : No error
Servo Drive 2 State= 2 StatusCode= 0 : No error
Servo Drive 1 State= 2 StatusCode= 0 : No error
Servo Drive 2 State= 2 StatusCode= 0 : No error
Servo Drive 1 State= 2 StatusCode= 0 : No error
Servo Drive 2 State= 2 StatusCode= 0 : No error
Servo Drive 1 State= 2 StatusCode= 0 : No error
Servo Drive 2 State= 2 StatusCode= 0 : No error
Servo Drive 1 State= 2 StatusCode= 0 : No error
Servo Drive 2 State= 2 StatusCode= 0 : No error
Servo Drive 1 State= 2 StatusCode= 0 : No error
Servo Drive 2 State= 2 StatusCode= 0 : No error
Servo Drive 1 State= 2 StatusCode= 0 : No error
Servo Drive 2 State= 2 StatusCode= 0 : No error
Servo Drive 1 State= 12 StatusCode= 24 : Invalid input mapping Servo Drive 2 State= 12 StatusCode= 52 : Unknow
3. I captured the network traffic of TwinCAT. The difference, at least in the mapping, that I saw, it mapped all the input and output registers (so 0x1a01, 0x1a02, 0x1601, 0x1602), but assigned only one-one(0x1600 and 0x1a00) to SM2/SM3. Could it be relevant, or am I mistaken here? (PDO mapping in the TwinCAT file from line 1117 to line 1345 - I'll give it a try probably tomorrow)
Please see the attached wireshark files of the executions in point 2 and 3, below:
[Wireshark_3.zip](https://github.com/OpenEtherCATsociety/SOEM/files/6802157/Wireshark_3.zip)
I also noticed a small difference. The SDOwrite of 0x1c12 and 0x1c13 in TwinCAT is in "expedited" form instead of "normal". This should not matter but we never know for sure. I do have to change the SOEM source a bit to mimic TwinCAT. Have a bit of patience.
Thank you, I appreciate your help on this.
I tried to do the PDO mapping for 0x1a01, 0x1a02, 0x1601 and 0x1602 as well, but it produced the same behaviour at cold-start, unfortunately.
Servo Drive 1 State= 12 StatusCode= 24 : Invalid input mapping
Servo Drive 2 State= 12 StatusCode= 52 : Unknown
I made some changes to allow CA to use expedited when objects <= 4 bytes are send via SDOwrite(). Please pull from branch coe_ca I hope this helps.
Thank you again for your support. I cloned the branch, and I rebuilt my repo, but unfortunately, it did not solve the problem. I have the same behaviour at cold-start:
Servo Drive 1 State= 12 StatusCode= 24 : Invalid input mapping
Servo Drive 2 State= 12 StatusCode= 52 : Unknown
Please see the captured files as well: wireshark_4.zip
I'll also contact Ingenia, maybe they had this behaviour before.
Did you ever test with only one slave? Or reverse the slave order? I find it strange that the StatusCode is different for the two slaves.
Contacting the vendor is a good idea. They can debug this 100x faster than you and me. Do provide them with a good way to reproduce the issue. Send them the exact software you use for testing.
Please, see my answers below:
Did you ever test with only one slave? Not yet, I'll give it a try tomorrow, with a modified simpletest. Or reverse the slave order? I tried now, and I had the same error messages:
Servo Drive 1 State= 12 StatusCode= 24 : Invalid input mapping
Servo Drive 2 State= 12 StatusCode= 52 : Unknown
Ofc, the physical position is reversed now. So Servo Drive 1
is always the last slave on the network (from Master point of view).
Hello,
I contacted the vendor and I`m still waiting for their answer. However in the meantime I noticed something in the library, which might be relevant: If I did the power cycle while the program was running, the ecatcheck function (same as in redtest.c) could map successfully the slaves and bring them back to operational state (10/10 test-cases). Please see the attached wireshark files, where I captured the failed cold-start (with the intial configuration) and the cold-start by ecatcheck funtion with already configured and running master stack.
On the otherhand I had to add the following lines to the ethercatconfig.c after #L1599:
if (context->slavelist[slave].PO2SOconfigx) /* only if registered */
{
context->slavelist[slave].PO2SOconfigx(context, slave);
}
I use the ecx_ functions in my wrapper code and I noticed that ` ecx_reconfig_slave(ecx_contextt context, uint16 slave, int timeout)does not call the
PO2SOconfigx(context, slave)` function pointer.
(Before the added code above the ecatcheck function could not bring them back to OP_STATE, only after this modification.)
Could this be relevant for you as well?
After my comment above, I tried to call ecx_configdc(&context) after the slaves reached SAFEOP and not after the ecx_config_overlap_map_group function call. However this order can only be seen in red_test.c example. Not in simple test or ec_master.c. Apperently this modification solved the cold-start configuration issue, decribed above. Could you please give some explanation on the reason behind this? (As stated before I`m not an expert in ECAT.)
The code below should have been in the configuration section.
if (context->slavelist[slave].PO2SOconfigx) /* only if registered */
{
context->slavelist[slave].PO2SOconfigx(context, slave);
}
This is clearly a bug. Thanks for catching this!
ecx_configdc() does a lot of things. But most of them are invisible for the slaves. So I am really head scratching why this would make the slave behave. There are only two possible effects:
The more important function of ecx_configdc() is to measure the latency between each slave. It uses the unsynchronized local slave clocks and the timestamps of a packet entering and leaving each port of the slave. It solves a set of linear equations to figure out the time each packet travels between the slave ports. It then corrects the local slave clock to a course EtherCAT absolute time. The measured delay between a packet reaching the reference slave and the current slave is then programmed in the delay register. This delay value is needed to later synchronize all slaves to the reference slave clock.
After the slave clock set-up the slaves can be synchronized to each other. This is done automatically by the PDO transfer function. It attaches a clock read-multiple-write instruction to the PDO transfer. This reads the current clock value from the reference slave (the first slave in the chain that has DC clock function), and then writes it to the following slave clocks. The slave that gets the clock write will not actually write the clock value to its own local clock but use the value to compare it with its local clock. Taking into account the propagation delay between the reference slave and the current slave. A PLL will then skew the local clock until it is phase synchronous with the reference clock.
So when the master orders slaves to fire a clock event (SYNC0) then all slaves fire at the same absolute time (or at least within +/-20ns or so). No matter how much propagation delay there is between slaves. This is a mayor capability of EtherCAT.
Hello, Thank you very much for your detailed answer and your support. I do appreciate it. I think we can close this issue. Regarding the bug (described above) should I create a seperate issue for it?
You are welcome. No need for a separate issue, I will make a patch for the PO2SOconfigx hook.
Hello,
I'd like to ask your help on a PDO mapping issue of Ingenia EVE-XCR servo-drives (since I'm not an expert of EtherCAT). When I do a power cycle (so having a cold-start) on the drives and then run my SOEM wrapper program, I get the following error almost everytime (rarely, approx. 1 out of 10, I have a successful configuration):
Servo Drive 1 State= 12 StatusCode= 24 : Invalid input mapping
Servo Drive 2 State= 12 StatusCode= 52 : Unknown
However, if I restart the my program, while the drives are still powered, then everything works fine. Or if I run TwinCAT this issue never happens, but that's irrelevant for me, since we use will not use TwinCAT as a Master stack. I tried to do the PDO mapping with and without Complete Access, it did not change anything.
Slave info after cold-start with failed PDO mapping:
Slave info after the restarted program, with successful PDO mapping:
However, I did not find any difference except for the error message at the beginning and the state of slave 1.
I captured the network traffic during the failed PDO mapping on cold start and afterwards when I restarted my program with a successful PDO mapping. Please see the .pcapng files below.
wireshark.zip
Please let me know, if you need further details and thank you for your help in advance.