Closed paholden closed 4 years ago
Yes, I've read both multiple times. I've googled SOEM application examples too. There's all kinds of info on configuring and getting mapping info. I really haven't seen much in the way of actual information on sending/receiving actual object data.
Perhaps SOEM and EtherCAT isn’t for everyone but I’ll give you an example. Check red_test.c, look at digout for a simple sample. Digout, a pointer/variable for/to an outputs slave that is set via .outputs, .outputs that is a pointer to the IOmap. The desired value in the Application IOmap is set via digout and the IOmap is sent via EtherCAT to the slave and the output will get the value.
I picked SOEM due to it being pretty compact in an embedded environment. Thanks for the red_test hint. I am doing this in my code already but nothing is happening with slave. So not quite sure what's going on. Also, I am getting the following error every time I run the slaveinfo example code:
Not all slaves reached safe operational state. Slave 1 ; State=11 ; StatusCode= 11; Invalid requested state change
In my code, I added an error recovery function and it seems to work. But the slave I'm working worth seems to get into this mode every time I run the program while debugging read/write operations.
Here is my write function:
int soem_ecat::soem_write_slave_position(int slave, float position) { float *out_PDO1;
out_PDO1 = (float *)ec_slave[slave].outputs;
// Check for out of range position request
if ((position < SKF_SAFE_LOWER_LIMIT) || (position > SKF_SAFE_UPPER_LIMIT))
return (-1);
*out_PDO1 = position;
ec_send_processdata();
ec_receive_processdata(EC_TIMEOUTRET);
cout << "Slave " << slave << " wrote " << *out_PDO1 << endl;
return(0);
}
As a first step make slaveinfo run properly. Post a wireshark and the console output when running slaveinfo
I just tried to do that & slaveinfo worked this time. Perhaps a timeout issue?
Definitely not timeout. I set the timeout to double what it was & got the same error. But if I run TwinCat3 on my Windows desktop, then run the slaveinfo program from the Linux PC, slaveinfo runs fine and I get all the COE mapping displayed. Setting up Wireshark now.[ slaveinfo.pcapng.gz
I added to my code the recovery function when SAFE_OP test fails and also a write to the output PDO. The output is as follows:
Binding SKF Linear Axis to interface enp0s31f6 EtherCat socket bind on enp0s31f6 succeeded. SkfEtherCatTest Bind succeeded on enp0s31f6 Wait to find Slaves now 1 slaves found and configured. Calculated workcounter 3 Not all slaves reached safe operational state. Slave 1 ; State=11 ; StatusCode= 11; Invalid requested state change Try to recover slave 1 MESSAGE : slave 1 reconfigured SKFTest Found 1 slaves
Slave: 1 Name:AKD Output size: 48bits Input size: 48bits State: 1 Delay: 0[ns] Has DC: 1 DCParentport: Activeports:1.0.0.0 Configured address: 1001 Man: 6a ID: 414b44 Rev: 00000002 SM0 A:1800 L:1024 F: 10026 Type:1 SM1 A:1c00 L:1024 F: 10022 Type:2 SM2 A:1100 L: 6 F: 10024 Type:3 SM3 A:1140 L: 6 F: 10020 Type:4 FMMU0 Ls:00000000 Ll: 6 Lsb:000 Leb:000 Ps:1100 Psb: Ty:02 Act:01 FMMU1 Ls:00000006 Ll: 6 Lsb:000 Leb:000 Ps:1140 Psb: Ty:01 Act:01 FMMUfunc 0:1 1:2 2:3 3:0 MBX length wr: 1024 rd: 1024 MBX protocols : 0e CoE details: 0d FoE details: 01 EoE details: 02 SoE details: 00 Ebus current: 0[mA] only LRD/LWR: PDO mapping according to CoE : Slave 1 wrote 100 Sent position 100 to slave 1 Read position 0 from slave 1 Closing EtherCat connection... ...finished cleanup
Attached is the wireshark log for it. write_test_with_recovery.pcapng.gz
The slave got issues with the way SOEM reset the network, or the slave just got issues it seems. Just to check, you don't have any TwinCAT & SOEM traffic going on in parallel?
To the findings If you filter slaveinfo.pcapng.gz for AL control and AL status ecat.ado == 0x0120 || ecat.ado == 0x0130
Frame No4 , SOEM set slave to INIT + E Frame No6 & No30, "extra" state INIT requests ignored (wkc == 0), slave have probably not ACK the write in No4 making ALCTRL (x120) writable again.
Frame No 100 , AL STATUS report error and Al Status Code 0x11 ("Invalid requested state change") which should not be possible since we request INIT + Err ACK which is always an allowed transition.
Frame No270 , SOEM request PREOP + Err ACK also ignored (wkc == 0) , seems the slave have "hung" in some loop not processing requests.
Frame No360, AL STATUS ERROR/CODE get magically reset
You've to continue the digging yourself.
I originally did have TwinCat3 running just to re-assure myself that the slave can move (it's moving a vertical axis up and down). I actually have to shut down the PC running TwinCat if I use it, I can't just close the TwinCat program. Once I've used TwinCat and then switch over to using SOEM, I get into the funky state where it doesn't respond to the INIT/PREOP/SAFEOP scenario. I'll keep digging & let you know what I find. I did find out that I can get the slave out of its funky mode by using the error-monitoring & recovery function that you've got in the tutorial. I have a funny feeling I'm going to have to use it every time this slave comes up. It gets into weird fault modes occasionally when running continuously.
New question. When I run slaveinfo, I don't get the PDO mapping displayed but the code is getting to "PDO mapping according to CoE :", just nothing follows. So I played around with my version of slaveinfo to call the sii function & then the mapping showed up:
PDO mapping according to SII : SM2 RXPDO 0x1701 Outputs Slave 1 addr b index: sub bitl data_type name [0x0000.0] 0x60C1:0x1 0x20 INTEGER32 1st set-point [0x0004.0] 0x6040:0x0 0x10 UNSIGNED16 Controlword SM3 TXPDO 0x1b01 Inputs Slave 1 addr b index: sub bitl data_type name [0x0006.0] 0x6063:0x0 0x20 INTEGER32 Position actual internal value [0x000a.0] 0x6041:0x0 0x10 UNSIGNED16 Statusword
Does this imply something wrong with the slave config? How do I add other output commands in addition to this? Also, according to the slave documentation, there should be a velocity command at output 0x1702 but I don't see it in the list when I run my slaveinfo. This slave doesn't seem to mesh with SOEM quite right. Or maybe I'm missing something.
If the slave support CoE PDO data, the SII info is used as fallback. I guess your slave don’t reach PREOP ok, from what I’ve seen in logs, and don’t enable SOEM to query the slave for PDOs via CoE.
Try removing the ESI from TwinCAT, make sure no cached data stick, see if that works and you can operate the slave.
I was wondering if maybe some of the TwinCat data was still hanging around even after a cold reboot and causing a problem with slave operation. Thanks for the suggestions.
I don’t think so, but if TwinCAT can operate the slave with online data only, ,eg. no ESI support, so should SOEM.
I stumbled upon another issue posted here which was closed with no resolution about not being able to move from SAFE-OP to OP mode. There was mention of linuxcnc-ethercat working correctly. Have you looked into their solution for this type of problem?
Regarding TwinCAT: You need to put TwinCAT into config mode to let other applications like SOEM use the network interface, otherwise it will be kept blocked by TwinCAT and no frame will reach the slave.
I reloaded TwinCat & set it to config mode, and now no more SAFE-OP problems. Also, the slaveinfo example was able to read the PDO Mapping via COE. Thanks so much for the TwinCat tip!
Well I thought it worked, but that is not the case. I turned off the motor controller, then turned it back on. SlaveInfo example test gets the same error again:
Not all slaves reached safe operational state. Slave 1 State=11 StatusCode= 11 : Invalid requested state change
Given TwinCAT can run the slave, can you check what ”StartUp/InitCmds” TwinCAT use? Its a TAB in the slave window if you select it in the TwinCAT treeview.
Also, what slave is it? Can you post the ESI?
I am working with a Kollmorgen AKD motor controller, P/N AKD-P01206-NBCC-0069. We are configuring it currently in rotary brush, position mode. I found the STARTUP tab for the device. It is attached along with the ESI. I was doing some of the startup operations, but not all (there is very little documented that I could find, most of the information I got is around using their Kollmorgen Workbench or TwinCat3). I'm going to add an init function that does exactly what TwinCat Startup does and see what happens.
The ESI was not included and I couldn’t find the support page for that drive. Do you got a link to the correct Kollmorgen page?
Re: ESI Hopefully you can read the attached ESI this time, I thought I had exported it from TwinCat. As for info about the device, this is all I have for Kollmorgen AKD:
https://www.kollmorgen.com/en-us/developer-network/akd/ AKD EtherCAT Device Description.zip
I followed the Setup Instructions for TwinCat3 with the AKD_2016-02-03 and it worked.
Based on the TwinCat3 STARTUP page for the AKD, I wrote the following function which I call between ec_config(&IOmap) & ec_configdc(): static int akd_dc_setup(uint16 slave) { uint8_t byte_val; uint16_t short_val; uint32_t long_val;
printf ("AKD drive setup\n");
byte_val = 0; // Clear SM PDO 0x1C12 ec_SDOwrite(slave, 0x1C12, 0, FALSE, sizeof(byte_val), &byte_val, EC_TIMEOUTRXM); // Clear SM PDO 0x1C13 ec_SDOwrite(slave, 0x1C13, 0, FALSE, sizeof(byte_val), &byte_val, EC_TIMEOUTRXM); // Clear PDO 0x1A00 entries long_val = 0x656C6300; ec_SDOwrite(slave, 0x1a00, 0, FALSE, sizeof(long_val), &long_val, EC_TIMEOUTRXM); // Add 0x1A00 status word 6041:00 long_val = 0x60410010; ec_SDOwrite(slave, 0x1a00, 0, FALSE, sizeof(long_val), &long_val, EC_TIMEOUTRXM); // Add 0x1A00 entry count long_val = 0x776F6401; ec_SDOwrite(slave, 0x1a00, 0, FALSE, sizeof(long_val), &long_val, EC_TIMEOUTRXM); // Clear 0x1A01 entries long_val = 0x656C6300; ec_SDOwrite(slave, 0x1a01, 0, FALSE, sizeof(long_val), &long_val, EC_TIMEOUTRXM); // Clear 0x1A02 entries long_val = 0x656C6300; ec_SDOwrite(slave, 0x1a02, 0, FALSE, sizeof(long_val), &long_val, EC_TIMEOUTRXM); // Clear 0x1A03 entries long_val = 0x656C6300; ec_SDOwrite(slave, 0x1a03, 0, FALSE, sizeof(long_val), &long_val, EC_TIMEOUTRXM); // Clear 0x1600 entries long_val = 0x656C6300; ec_SDOwrite(slave, 0x1600, 0, FALSE, sizeof(long_val), &long_val, EC_TIMEOUTRXM); // Add 0x1600:01 entries long_val = 0x60400010; ec_SDOwrite(slave, 0x1600, 0, FALSE, sizeof(long_val), &long_val, EC_TIMEOUTRXM); // Add 0x1600:00 entry count long_val = 0x776F6401; ec_SDOwrite(slave, 0x1600, 0, FALSE, sizeof(long_val), &long_val, EC_TIMEOUTRXM); // Clear 0x1601 entries long_val = 0x656C6300; ec_SDOwrite(slave, 0x1601, 0, FALSE, sizeof(long_val), &long_val, EC_TIMEOUTRXM); // Clear 0x1602 entries long_val = 0x656C6300; ec_SDOwrite(slave, 0x1602, 0, FALSE, sizeof(long_val), &long_val, EC_TIMEOUTRXM); // Clear 0x1603 entries long_val = 0x656C6300; ec_SDOwrite(slave, 0x1603, 0, FALSE, sizeof(long_val), &long_val, EC_TIMEOUTRXM); // Set up 0x1C12:01 object index short_val = 0x1701; byte_val = 0x01; ec_SDOwrite(slave, 0x1C12, 0x01, FALSE, sizeof(short_val), &short_val, EC_TIMEOUTRXM); ec_SDOwrite(slave, 0x1C12, 0, FALSE, sizeof(byte_val), &byte_val, EC_TIMEOUTRXM); // Set up 0x1C13:01 short_val = 0x1B01; byte_val = 0x01; ec_SDOwrite(slave, 0x1C13, 0x01, FALSE, sizeof(short_val), &short_val, EC_TIMEOUTRXM); ec_SDOwrite(slave, 0x1C13, 0, FALSE, sizeof(byte_val), &byte_val, EC_TIMEOUTRXM); // Set operation mode byte_val = 0x7; ec_SDOwrite(slave, 0x6060, 0, FALSE, sizeof(byte_val), &byte_val, EC_TIMEOUTRXM); // Set interpolation time period value to 2 seconds byte_val = 0x2; ec_SDOwrite(slave, 0x60C2, 1, FALSE, sizeof(byte_val), &byte_val, EC_TIMEOUTRXM); // Set interpolation time index byte_val = -3; ec_SDOwrite(slave, 0x60C2, 2, FALSE, sizeof(byte_val), &byte_val, EC_TIMEOUTRXM);
/ Explicitly disable sync managers that are activated by EEPROM / ec_slave[slave].SM[4].StartAddr = 0; ec_slave[slave].SM[5].StartAddr = 0;
/ Set a slave name / strncpy (ec_slave[slave].name, "AKDDC", EC_MAXNAME); return 0; }
Then in main initialization function:
... rc = ec_config(FALSE, &IOmap); if (rc <= 0 ) { cout << "No slaves found." << endl; return(-1); }
for (i = 1; i<=ec_slavecount ; i++)
{
// if ((ec_slave[i].eep_id == AKD_DCBRUSH_EEP_ID)
// && (ec_slave[i].eep_man == AKD_DCBRUSH_EEP_MAN))
cout << "Apply Startup commands to Slave " << i << endl;
akd_dc_setup(i);
}
// Locate DC slaves
ec_configdc();
...
Still getting the same error!
Apply Startup commands to Slave 1 AKD drive setup 1 slaves found and configured. Calculated workcounter 3 Not all slaves reached safe operational state. Slave 1 ; State=11 ; StatusCode= 11; Invalid requested state change Try to recover slave 1 SKFSlaveInfoTest Found 1 slaves
At this point, if you were a customer of mine, I’d ask you to send me the drive, would be best to get som hands-on testning. I can’t see any Init->PreOp InitCmds,so why it fails to start and don’t ack read the statechange request is confusing. Maybe you can capture a TwinCAT start? The Linux box you tested on, is it a standalone Linux box? Or a VM?
Ok, I found something, you need to figure out what is right and wrong here.
The slave is rev:2 according to the print you did via slaveinfo.
Man: 6a ID: 414b44 Rev: 00000002 <- REV: 2 SM0 A:1800 L:1024 F: 10026 Type:1 <- SM length: 1024 SM1 A:1c00 L:1024 F: 10022 Type:2 <- SM length: 1024
According to the ESI rev:2 the SM0/1 is 512.
<Sm MinSize="40" MaxSize="512" DefaultSize="512" StartAddress="#x1800" ControlByte="#x26" Enable="1">MBoxOut</Sm>
<Sm MinSize="40" MaxSize="512" DefaultSize="512" StartAddress="#x1C00" ControlByte="#x22" Enable="1">MBoxIn</Sm>
If I add Rev:2 to TwinCAT it set SM0/1 to 512 while SOEM set it to 1024.
You need to fix the data that is wrong, since it works in TwinCAT you should probably take those values and write to the slave from SOEM.
So you think that the ESI file that comes with the Kollmorgen SDK for TwinCat3 is different from the EEPROM values in the drive? Ok, I'll give it a try.
This thread goes way beyond writing an example program that writes data to a slave. Would you like me to rename the topic so others will hit it when looking into problems?
Yes, seem so. As a paying customer you should be able to get the answers needed from their tech support. Basically, you would see the same issues in TwinCAT if you remove the ESI file you placed in the ../EtherCAT/
”Missmatching Kollmorgen AKD EEPROM data”, if my assumption proves to be right.
If your assumption is correct, which I'm sure it is as just about every other rock has been turned on this problem, then I will definitely report this back to their forum. I posted my problem on their forum 3 days ago and got absolutely no response. I'm most grateful to you for your assistance!
I removed the TwinCat ESI file from c:\TwinCat\Config\IO\EtherCat and got the same basic errors I'm seeing with SOEM. I put it back & then tried to use the TwinCat EEPROM updater and got a Write error. So now I'd like to use your eepromtool but all I have is an XML file. The eepromtool wanta a bin or Intel Hex file. Do you have a reliable tool that you use to convert from XML to either type?
Sorry, but we have no such tool. Did the EEPROM get overwritten? It it was a com error you might wanna try again, if there was a syntax error, it might be possible to temp fix the ESI.
Or just ask Kollmorgen for a correct EEPROM or the original that you can modify. I’d try to hex edit the SMs first with the assumed correct length.
No, the EEPROM did not get overwritten. It failed at address 0x0. No indication of what kind of error TwinCat got and I retried several times. I visited Kollmorgen's site and saw that they suggest updating the latest rev of ESI with "your EtherCat Master". I also updated the open issue I have on their site with your findings that I verified this morning. There has been no response from them at all on this issue, 5 days later!
So I tried to change SMlength and got the following error:
Time: 9861.900 SDO slave:1 index:1a00.00 error:06070010 Data type does not match, length of service parameter does not match
So there's something else I missed apparently.
If you know what you do and can interpret the errors that might pop-up. As a workaround re-use the code in firm_update.c used to re-program the SM0/1 for BOOTSTRAP, don’t use the EEPROM values as in the example but the fixed/ESI values and don’t go to BOOT of course.
Do it after config init and request PREOP+ERR ack state your self, then call config map. Since we’ve seen wierd result from requesting statechange 0x120 PREOP returning wkc == 0, you might do it more times until you get wkc == 1.
I do know exactly what I did & put it in a function so I can make changes as I go. Will try your next suggestion & see what happens. I am also contacting the distributor that send me the drive to see if he can get it re-programmed for me with correct ESI.
Subindex 0 is byte size, not long.
Thanks, I think I knew that but will check all my code to make sure it's correct. One question: can I brick the box doing this & how do I recover if I do?
Oh boy, it's not happy! I added the bit from firm_update & got the following back now:
Time: 18383.302 SDO slave:1 index:1a00.00 error:06070010 Data type does not match, length of service parameter does not match
Time: 18383.303 SDO slave:1 index:1a00.00 error:06070010 Data type does not match, length of service parameter does not match
Time: 18383.305 SDO slave:1 index:1a00.00 error:06070010 Data type does not match, length of service parameter does not match
Time: 18383.308 SDO slave:1 index:1a01.00 error:06070010 Data type does not match, length of service parameter does not match
Time: 18383.310 SDO slave:1 index:1a02.00 error:06070010 Data type does not match, length of service parameter does not match
Time: 18383.313 SDO slave:1 index:1a03.00 error:06070010 Data type does not match, length of service parameter does not match
Time: 18383.315 SDO slave:1 index:1600.00 error:06070010 Data type does not match, length of service parameter does not match
Time: 18383.317 SDO slave:1 index:1600.00 error:06070010 Data type does not match, length of service parameter does not match
Time: 18383.318 SDO slave:1 index:1600.00 error:06070010 Data type does not match, length of service parameter does not match
Time: 18383.320 SDO slave:1 index:1601.00 error:06070010 Data type does not match, length of service parameter does not match
Time: 18383.322 SDO slave:1 index:1602.00 error:06070010 Data type does not match, length of service parameter does not match
Time: 18383.324 SDO slave:1 index:1603.00 error:06070010 Data type does not match, length of service parameter does not match
Time: 18383.346 PACKET slave:1 index:60c2.02 error:1
1 slaves found and configured. Calculated workcounter 1 Not all slaves reached safe operational state. Slave 1 ; State= 0 ; StatusCode= 0; No error Try to recover slave 1 SKFSlaveInfoTest Found 1 slaves
Slave: 1 Name:AKDDC Output size: 0bits Input size: 48bits State: 0 Delay: 0[ns] Has DC: 1 DCParentport: Activeports:1.0.0.0 Configured address: 1001 Man: 6a ID: 414b44 Rev: 00000002 SM0 A:1800 L:1024 F: 10026 Type:1 SM1 A:1c00 L:1024 F: 10022 Type:2 SM2 A:1100 L: 0 F: 24 Type:3 SM3 A:1140 L: 6 F: 10020 Type:4 FMMU0 Ls:00000000 Ll: 6 Lsb:000 Leb:000 Ps:1140 Psb: Ty:01 Act:01 FMMUfunc 0:1 1:2 2:3 3:0 MBX length wr: 1024 rd: 1024 MBX protocols : 0e CoE details: 0d FoE details: 01 EoE details: 02 SoE details: 00 Ebus current: 0[mA] only LRD/LWR: PDO mapping according to SII :
It never comes back once it gets to the SII mapping function. So I tried the COE mapping path & got:
Binding SKF Linear Axis to interface enp0s31f6 EtherCat socket bind on enp0s31f6 succeeded. Slave count = 0 SkfEtherCatTest Bind succeeded on enp0s31f6 Wait to find Slaves now Apply Startup commands to Slave 1 AKD drive setup Time: 18574.726 SDO slave:1 index:1a00.00 error:06070010 Data type does not match, length of service parameter does not match
Time: 18574.727 SDO slave:1 index:1a00.00 error:06070010 Data type does not match, length of service parameter does not match
Time: 18574.729 SDO slave:1 index:1a00.00 error:06070010 Data type does not match, length of service parameter does not match
Time: 18574.730 SDO slave:1 index:1a01.00 error:06070010 Data type does not match, length of service parameter does not match
Time: 18574.732 SDO slave:1 index:1a02.00 error:06070010 Data type does not match, length of service parameter does not match
Time: 18574.734 SDO slave:1 index:1a03.00 error:06070010 Data type does not match, length of service parameter does not match
Time: 18574.736 SDO slave:1 index:1600.00 error:06070010 Data type does not match, length of service parameter does not match
Time: 18574.737 SDO slave:1 index:1600.00 error:06070010 Data type does not match, length of service parameter does not match
Time: 18574.739 SDO slave:1 index:1600.00 error:06070010 Data type does not match, length of service parameter does not match
Time: 18574.740 SDO slave:1 index:1601.00 error:06070010 Data type does not match, length of service parameter does not match
Time: 18574.742 SDO slave:1 index:1602.00 error:06070010 Data type does not match, length of service parameter does not match
Time: 18574.745 SDO slave:1 index:1603.00 error:06070010 Data type does not match, length of service parameter does not match
1 slaves found and configured. Calculated workcounter 3 Not all slaves reached safe operational state. Slave 1 ; State= 0 ; StatusCode= 0; No error Try to recover slave 1 SKFSlaveInfoTest Found 1 slaves
Slave: 1 Name:AKDDC Output size: 48bits Input size: 48bits State: 0 Delay: 0[ns] Has DC: 1 DCParentport: Activeports:0.0.0.0 Configured address: 1001 Man: 6a ID: 414b44 Rev: 00000002 SM0 A:1800 L:1024 F: 10026 Type:1 SM1 A:1c00 L:1024 F: 10022 Type:2 SM2 A:1100 L: 6 F: 10024 Type:3 SM3 A:1140 L: 6 F: 10020 Type:4 FMMU0 Ls:00000000 Ll: 6 Lsb:000 Leb:000 Ps:1100 Psb: Ty:02 Act:01 FMMU1 Ls:00000006 Ll: 6 Lsb:000 Leb:000 Ps:1140 Psb: Ty:01 Act:01 FMMUfunc 0:1 1:2 2:3 3:0 MBX length wr: 1024 rd: 1024 MBX protocols : 0e CoE details: 0d FoE details: 01 EoE details: 02 SoE details: 00 Ebus current: 0[mA] only LRD/LWR: PDO mapping according to CoE : OPERATIONAL state not set, exiting Closing EtherCat connection... ...finished cleanup
Good news! I got something to work. Now I'm getting the following, but note that PDO mapping is now not correct:
Binding SKF Linear Axis to interface enp0s31f6 EtherCat socket bind on enp0s31f6 succeeded. Slave count = 0 SkfEtherCatTest Bind succeeded on enp0s31f6 Wait to find Slaves now Try to fix SM0/SM1 data length bug. Request pre-op state for slave 1 Slave 1 state to PRE_OP; wkc = 2. Read-EEPROM SM0: hi-word = 400, lo-word = 1800 Read-EEPROM SM1: hi-word = 400, lo-word = 1c00 SM0 A:1800 L: 512 F:00010026 SM1 A:1c00 L: 512 F:00010022 Request safe-op state for slave 2 Slave 2 state to SAFE_OP, wkc = 0. Apply Startup commands to Slave 1 AKD drive setup 1 slaves found and configured. Calculated workcounter 3 SKFSlaveInfoTest Found 1 slaves
Slave: 1 Name:AKDDC Output size: 48bits Input size: 48bits State: 4 Delay: 0[ns] Has DC: 1 DCParentport: Activeports:1.0.0.0 Configured address: 1001 Man: 6a ID: 414b44 Rev: 00000002 SM0 A:1800 L: 512 F: 10026 Type:1 SM1 A:1c00 L: 512 F: 10022 Type:2 SM2 A:1100 L: 6 F: 10024 Type:3 SM3 A:1140 L: 6 F: 10020 Type:4 FMMU0 Ls:00000000 Ll: 6 Lsb:000 Leb:000 Ps:1100 Psb: Ty:02 Act:01 FMMU1 Ls:00000006 Ll: 6 Lsb:000 Leb:000 Ps:1140 Psb: Ty:01 Act:01 FMMUfunc 0:1 1:2 2:3 3:0 MBX length wr: 512 rd: 512 MBX protocols : 0e CoE details: 0d FoE details: 01 EoE details: 02 SoE details: 00 Ebus current: 0[mA] only LRD/LWR: PDO mapping according to SII : SM2 RXPDO 0x1701 Slave 1 addr b index: sub bitl data_type name SM3 TXPDO 0x1b01 Slave 1 addr b index: sub bitl data_type name Closing EtherCat connection... ...finished cleanup
I forgot to wait for PRE-OP state. I ran slaveinfo example program & the SM datalen is still 1024 for both SM0 & SM1.
Post a wireshark and lets have a look.
Note from previous post You should write PDOs with number of entries in subindex 0, the actual PDO entry in subindex 1-n.
Pseudo Write 0x1a00:00 1 Bytesize Write 0x1a00:01 xxxxyyzz uint32
Waiting for PRE-OP worked, but then when I ran the example program slaveinfo I see that the EEPROM datalen is back to 1024. How can this be?
sudo ./slaveinfo enp0s31f6 -map SOEM (Simple Open EtherCAT Master) Slaveinfo Starting slaveinfo ec_init on enp0s31f6 succeeded. 1 slaves found and configured. Calculated workcounter 3 Not all slaves reached safe operational state. Slave 1 State=11 StatusCode= 11 : Invalid requested state change
Slave:1 Name:AKD Output size: 48bits Input size: 48bits State: 17 Delay: 0[ns] Has DC: 1 DCParentport:0 Activeports:1.0.0.0 Configured address: 1001 Man: 0000006a ID: 00414b44 Rev: 00000002 SM0 A:1800 L:1024 F:00010026 Type:1 SM1 A:1c00 L:1024 F:00010022 Type:2 SM2 A:1100 L: 6 F:00010024 Type:3 SM3 A:1140 L: 6 F:00010020 Type:4 FMMU0 Ls:00000000 Ll: 6 Lsb:0 Leb:7 Ps:1100 Psb:0 Ty:02 Act:01 FMMU1 Ls:00000006 Ll: 6 Lsb:0 Leb:7 Ps:1140 Psb:0 Ty:01 Act:01 FMMUfunc 0:1 1:2 2:3 3:0 MBX length wr: 1024 rd: 1024 MBX protocols : 0e CoE details: 0d FoE details: 01 EoE details: 02 SoE details: 00 Ebus current: 0[mA] only LRD/LWR:0 PDO mapping according to CoE : End slaveinfo, close socket End program
Results from my program that updates firmware SM0/SM1:
sudo ./ecinfotest Binding SKF Linear Axis to interface enp0s31f6 EtherCat socket bind on enp0s31f6 succeeded. Slave count = 0 SkfEtherCatTest Bind succeeded on enp0s31f6 Wait to find Slaves now Try to fix SM0/SM1 data length bug in EEPROM. Request pre-op state for slave 1 Slave 1 state to PRE_OP; wkc = 1. Read-EEPROM SM0: hi-word = 1024, lo-word = 1800 Read-EEPROM SM1: hi-word = 1024, lo-word = 1c00 SM0 A:1800 L: 512 F:00010026 SM1 A:1c00 L: 512 F:00010022 Request safe-op state for slave 2 Slave 2 state to SAFE_OP, wkc = 0. Apply Startup commands to Slave 1 AKD drive setup 1 slaves found and configured. Calculated workcounter 3 Not all slaves reached safe operational state. Slave 1 ; State=11 ; StatusCode= 11; Invalid requested state change Try to recover slave 1 SKFSlaveInfoTest Found 1 slaves
Slave: 1 Name:AKDDC Output size: 48bits Input size: 48bits State: 17 Delay: 0[ns] Has DC: 1 DCParentport: Activeports:1.0.0.0 Configured address: 1001 Man: 6a ID: 414b44 Rev: 00000002 SM0 A:1800 L: 512 F: 10026 Type:1 SM1 A:1c00 L: 512 F: 10022 Type:2 SM2 A:1100 L: 6 F: 10024 Type:3 SM3 A:1140 L: 6 F: 10020 Type:4 FMMU0 Ls:00000000 Ll: 6 Lsb:000 Leb:000 Ps:1100 Psb: Ty:02 Act:01 FMMU1 Ls:00000006 Ll: 6 Lsb:000 Leb:000 Ps:1140 Psb: Ty:01 Act:01 FMMUfunc 0:1 1:2 2:3 3:0 MBX length wr: 512 rd: 512 MBX protocols : 0e CoE details: 0d FoE details: 01 EoE details: 02 SoE details: 00 Ebus current: 0[mA] only LRD/LWR: PDO mapping according to SII : SM2 RXPDO 0x1701 Outputs Slave 1 addr b index: sub bitl data_type name [0x0000.0] 0x60C1:0x1 0x20 INTEGER32 1st set-point [0x0004.0] 0x6040:0x0 0x10 UNSIGNED16 Controlword SM3 TXPDO 0x1b01 Inputs Slave 1 addr b index: sub bitl data_type name [0x0006.0] 0x6063:0x0 0x20 INTEGER32 Position actual internal value [0x000a.0] 0x6041:0x0 0x10 UNSIGNED16 Statusword OPERATIONAL state not set, exiting Closing EtherCat connection... ...finished cleanup
It don’t write it permanent, until you fix the EEPROM you need to override the EEPROM values every time as you did above.
Finally, it looks like things are working a bit better. I got the following from my program that applies the SM0/1 datalen of 512:
sudo ./ecinfotest Binding SKF Linear Axis to interface enp0s31f6 EtherCat socket bind on enp0s31f6 succeeded. Slave count = 0 SkfEtherCatTest Bind succeeded on enp0s31f6 Wait to find Slaves now 1 slaves found. Try to fix SM0/SM1 data length bug in EEPROM. Slave 1 state to PRE_OP; wkc = 2. Read-EEPROM SM0: hi-word = 1024, lo-word = 1800 Read-EEPROM SM1: hi-word = 1024, lo-word = 1c00 SM0 A:1800 L: 512 F:00010026 SM1 A:1c00 L: 512 F:00010022 Request safe-op state for slave 1 Slave 1 state to SAFE_OP, wkc = 2. Apply Startup commands to Slave 1 AKD drive setup 1 slaves found and configured. Calculated workcounter 3 SKFSlaveInfoTest Found 1 slaves
Slave: 1 Name:AKDDC Output size: 48bits Input size: 48bits State: 4 Delay: 0[ns] Has DC: 1 DCParentport: Activeports:1.0.0.0 Configured address: 1001 Man: 6a ID: 414b44 Rev: 00000002 SM0 A:1800 L: 512 F: 10026 Type:1 SM1 A:1c00 L: 512 F: 10022 Type:2 SM2 A:1100 L: 6 F: 10024 Type:3 SM3 A:1140 L: 6 F: 10020 Type:4 FMMU0 Ls:00000000 Ll: 6 Lsb:000 Leb:000 Ps:1100 Psb: Ty:02 Act:01 FMMU1 Ls:00000006 Ll: 6 Lsb:000 Leb:000 Ps:1140 Psb: Ty:01 Act:01 FMMUfunc 0:1 1:2 2:3 3:0 MBX length wr: 512 rd: 512 MBX protocols : 0e CoE details: 0d FoE details: 01 EoE details: 02 SoE details: 00 Ebus current: 0[mA] only LRD/LWR: PDO mapping according to SII : SM2 RXPDO 0x1701 Outputs Slave 1 addr b index: sub bitl data_type name [0x0000.0] 0x60C1:0x1 0x20 INTEGER32 1st set-point [0x0004.0] 0x6040:0x0 0x10 UNSIGNED16 Controlword SM3 TXPDO 0x1b01 Inputs Slave 1 addr b index: sub bitl data_type name [0x0006.0] 0x6063:0x0 0x20 INTEGER32 Position actual internal value [0x000a.0] 0x6041:0x0 0x10 UNSIGNED16 Statusword Closing EtherCat connection... ...finished cleanup
Then I run your example program slaveinfo & get all the correct mappings including the ones I added in my program, but it's getting an invalid config:
./slaveinfo enp0s31f6 -map SOEM (Simple Open EtherCAT Master) Slaveinfo Starting slaveinfo ec_init on enp0s31f6 succeeded. 1 slaves found and configured. Calculated workcounter 3 Not all slaves reached safe operational state. Slave 1 State=12 StatusCode= 1d : Invalid output configuration
Slave:1 Name:AKD Output size: 136bits Input size: 136bits State: 18 Delay: 0[ns] Has DC: 1 DCParentport:0 Activeports:1.0.0.0 Configured address: 1001 Man: 0000006a ID: 00414b44 Rev: 00000002 SM0 A:1800 L:1024 F:00010026 Type:1 SM1 A:1c00 L:1024 F:00010022 Type:2 SM2 A:1100 L: 17 F:00010024 Type:3 SM3 A:1140 L: 17 F:00010020 Type:4 FMMU0 Ls:00000000 Ll: 17 Lsb:0 Leb:7 Ps:1100 Psb:0 Ty:02 Act:01 FMMU1 Ls:00000011 Ll: 17 Lsb:0 Leb:7 Ps:1140 Psb:0 Ty:01 Act:01 FMMUfunc 0:1 1:2 2:3 3:0 MBX length wr: 1024 rd: 1024 MBX protocols : 0e CoE details: 0d FoE details: 01 EoE details: 02 SoE details: 00 Ebus current: 0[mA] only LRD/LWR:0 PDO mapping according to CoE : SM2 outputs addr b index: sub bitl data_type name [0x0000.0] 0x6040:0x00 0x10 [0x0002.0] 0x6040:0x00 0x10 [0x0004.0] 0x6060:0x00 0x08 [0x0005.0] 0x6040:0x00 0x10 [0x0007.0] 0x607A:0x00 0x20 [0x000B.0] 0x6040:0x00 0x10 [0x000D.0] 0x60FF:0x00 0x20 SM3 inputs addr b index: sub bitl data_type name [0x0011.0] 0x6041:0x00 0x10 [0x0013.0] 0x6041:0x00 0x10 [0x0015.0] 0x6061:0x00 0x08 [0x0016.0] 0x6041:0x00 0x10 [0x0018.0] 0x6064:0x00 0x20 [0x001C.0] 0x6041:0x00 0x10 [0x001E.0] 0x606C:0x00 0x20 End slaveinfo, close socket End program
Now to fix my output configuration & then try to make the motor controller do motion commands! Thanks for your patience and help!
Here is the code I wrote that now works, should anyone else run into this issue or something similar:
Wait function: void soem_ecat:: soem_wait_for_state(int slave, int wait_time, uint32_t ecat_state) { int chk;
ec_slave[slave].state = ecat_state + EC_STATE_ERROR;
ec_writestate(slave);
chk = wait_time;
do
{
ec_send_processdata();
ec_receive_processdata(EC_TIMEOUTRET);
ec_statecheck(slave, ecat_state, 50000);
}
while (chk-- && (ec_slave[slave].state != ecat_state));
}
FW update function: void soem_ecat:: soem_do_akd_fw_update() { uint32 data; int slave; int wkc; int chk;
printf("Try to fix SM0/SM1 data length bug in EEPROM.\n");
for (slave = 1 ; slave <= ec_slavecount ; slave++)
{
/* wait for slaves to reach PRE_OP state */
soem_wait_for_state(slave, 200, EC_STATE_PRE_OP);
wkc = ec_statecheck(slave, EC_STATE_PRE_OP, EC_TIMEOUTSTATE * 4);
printf("Slave %d state to PRE_OP; wkc = %d.\n", slave, wkc);
/* read BOOT mailbox data, master -> slave */
data = ec_readeeprom(slave, ECT_SII_BOOTRXMBX, EC_TIMEOUTEEP);
printf("Read-EEPROM SM0: hi-word = %d, lo-word = %x\n", HI_WORD(data), LO_WORD(data));
ec_slave[slave].SM[0].StartAddr = AKD_SM0_STARTADDR;
ec_slave[slave].SM[0].SMlength = AKD_REV2_SMLEN;
/* store boot write mailbox address */
ec_slave[slave].mbx_wo = (uint16)AKD_SM0_STARTADDR;
/* store boot write mailbox size */
ec_slave[slave].mbx_l = (uint16)AKD_REV2_SMLEN;
/* read BOOT mailbox data, slave -> master */
data = ec_readeeprom(slave, ECT_SII_BOOTTXMBX, EC_TIMEOUTEEP);
printf("Read-EEPROM SM1: hi-word = %d, lo-word = %x\n", HI_WORD(data), LO_WORD(data));
ec_slave[slave].SM[1].StartAddr = (uint16)AKD_SM1_STARTADDR;
ec_slave[slave].SM[1].SMlength = (uint16)AKD_REV2_SMLEN;
/* store boot read mailbox address */
ec_slave[slave].mbx_ro = (uint16)AKD_SM1_STARTADDR;
/* store boot read mailbox size */
ec_slave[slave].mbx_rl = (uint16)AKD_REV2_SMLEN;
printf(" SM0 A:%4.4x L:%4d F:%8.8x\n",
ec_slave[slave].SM[0].StartAddr,
ec_slave[slave].SM[0].SMlength,
(int)ec_slave[slave].SM[0].SMflags);
printf(" SM1 A:%4.4x L:%4d F:%8.8x\n",
ec_slave[slave].SM[1].StartAddr,
ec_slave[slave].SM[1].SMlength,
(int)ec_slave[slave].SM[1].SMflags);
/* program SM0 mailbox in for slave */
ec_FPWR (ec_slave[slave].configadr, ECT_REG_SM0, sizeof(ec_smt), &ec_slave[slave].SM[0], EC_TIMEOUTRET);
/* program SM1 mailbox out for slave */
ec_FPWR (ec_slave[slave].configadr, ECT_REG_SM1, sizeof(ec_smt), &ec_slave[slave].SM[1], EC_TIMEOUTRET);
// Wait for safe-op
printf("Request safe-op state for slave %d\n", slave);
soem_wait_for_state(slave, 200, EC_STATE_SAFE_OP);
/* wait for slave to reach PRE_OP state */
wkc = ec_statecheck(slave, EC_STATE_SAFE_OP, EC_TIMEOUTSTATE * 4);
printf("Slave %d state to SAFE_OP, wkc = %d.\n", slave, wkc);
}
}
Init function that calls the fw_update: /**
@param IFNAME */ int soem_ecat::soem_find_slaves(void) { int rc; int i, j; uint32_t mapping;
rc = ec_config_init(FALSE); if (rc <= 0 ) { cout << "No slaves found." << endl; return(-1); } cout << ec_slavecount << " slaves found." << endl; soem_do_akd_fw_update(); ec_config_map(&IOmap);
// Locate DC slaves ec_configdc();
while(EcatError) cout << ec_elist2string() << endl; cout << ec_slavecount << " slaves found and configured." << endl; expectedWKC = (ec_group[0].outputsWKC 2) + ec_group[0].inputsWKC; cout << "Calculated workcounter " << expectedWKC << endl; / wait for all slaves to reach SAFE_OP state */ soem_wait_for_state(0, 200, EC_STATE_SAFE_OP);
ec_statecheck(0, EC_STATE_SAFE_OP, EC_TIMEOUTSTATE * 4); ... }
False alarm on things working better. The wait loop function was always setting ec_slave[slave].state to pre-op:
ec_slave[slave].state = EC_STATE_PRE_OP + EC_STATE_ERROR;
When I fixed this, I still end up at status 11:
Binding SKF Linear Axis to interface enp0s31f6 EtherCat socket bind on enp0s31f6 succeeded. Slave count = 0 SkfEtherCatTest Bind succeeded on enp0s31f6 Wait to find Slaves now 1 slaves found. Fix SM0/SM1 data length bug in EEPROM. Slave 1 state to PRE_OP; wkc = 1. Read-EEPROM SM0: hi-word = 1024, lo-word = 1800 Read-EEPROM SM1: hi-word = 1024, lo-word = 1c00 SM0 A:1800 L: 512 F:00010026 SM1 A:1c00 L: 512 F:00010022 Request safe-op state for slave 1 Slave 1 state to SAFE_OP, wkc = 1. Apply Startup commands to Slave 1 1 slaves found and configured. Calculated workcounter 3 Not all slaves reached safe operational state. Slave 1 ; State=11 ; StatusCode= 11; Invalid requested state change Try to recover slave 1 MESSAGE : slave 1 reconfigured
soem_do_akd_fw_update() needs some changes
Try to check the wireshark , 0x120 and 0x130 for state transition to be correct.
In general, Your code might need some general fixes and clearing but shouldn’t stop you from getting it to work.
Thank you for the review and suggestions. I will try it out tomorrow and capture it on wireshark. Question about mapping my own PDOs. Should this be done at the same time I make the SMO/1 fix (i.e. INIT state) or once I get to PRE-OP?
Wireshark log attached, I am just going through the SM0/1 fixup and then get the slave info & display:
Binding SKF Linear Axis to interface enp0s31f6 EtherCat socket bind on enp0s31f6 succeeded. Slave count = 0 SkfEtherCatTest Bind succeeded on enp0s31f6 Wait to find Slaves now 1 slaves found. Fix SM0/SM1 data length bug in EEPROM. Slave 1 state to INIT; wkc = 2 SM0 A:1800 L:0512 F:00010026 SM1 A:1c00 L:0512 F:00010022 Request pre-op state for slave 1 Slave 1 state to PRE_OP, wkc = 2. Apply Startup commands to Slave 1 1 slaves found and configured. Calculated workcounter 3 Not all slaves reached safe operational state. Slave 1 ; State=02 ; StatusCode=0000; No error Try to recover slave 1 SKFSlaveInfoTest Found 1 slaves
Slave: 1 Name:AKD Output size: 48bits Input size: 48bits State: 2 Delay: 0[ns] Has DC: 1 DCParentport: Activeports:1.0.0.0 Configured address: 1001 Man: 6a ID: 414b44 Rev: 00000002 SM0 A:1800 L: 512 F: 10026 Type:1 SM1 A:1c00 L: 512 F: 10022 Type:2 SM2 A:1100 L: 6 F: 10024 Type:3 SM3 A:1140 L: 6 F: 10020 Type:4 FMMU0 Ls:00000000 Ll: 6 Lsb:000 Leb:000 Ps:1100 Psb: Ty:02 Act:01 FMMU1 Ls:00000006 Ll: 6 Lsb:000 Leb:000 Ps:1140 Psb: Ty:01 Act:01 FMMUfunc 0:1 1:2 2:3 3:0 MBX length wr: 512 rd: 512 MBX protocols : 0e CoE details: 0d FoE details: 01 EoE details: 02 SoE details: 00 Ebus current: 0[mA] only LRD/LWR: CoE Object Description found, 0 entries. PDO mapping according to CoE : Closing EtherCat connection... ...finished cleanup
I'm not sure it is helpful to run slaveinfo example at this point, since we already know there is a problem with EEPROM data. One note of interest, every time I run my program (which is just doing the workaround, then getting slaveinfo), the slave faults with the following messages: "FieldBus sync frames lost" and "Fieldbus cyclic setpoints missing".
According to the wireshark you now can get to PREOP. In PREOP the mailboxes are started, hence first in PREOP can you program the PDOs Then call config_map (calls STATE SAFEOP ) Then check for SAFEOP Then go to OP
Try to go back to basics, use the current examples, simply add the SM0/1 fix and go to PREOP. You now should have all the pieces of the puzzle to complete this task on your own. To understand how to work this example is the best way to learn EtherCAT.
One small success! I'll try the examples out with the SM0/1 added & see what happens. When I program the PDOs, I only need to add the ones that are not in the SII map I'm already reading, correct? TwinCat has a big startup for this drive but it doesn't translate very well to what really needs to be done on the SOEM side. Also, once I get all this going would I then use the eeprom example to read in all the EEPROM, apply SM0/1, then write EEPROM back? TwinCat zeroed the AKD config when I tried to write the ESI, so I think it's going to have to be done this way via SOEM.
Ok, back to the drawing board. I turned off the TwinCat PC and rebooted the AKD. Then I ran slaveinfo test with my fix. I am back to the same error again but pretty sure when I add back PDO mapping it will be ok.
Have you studied the documentation? https://openethercatsociety.github.io/doc/soem/
Tutorial https://openethercatsociety.github.io/doc/soem/tutorial_8txt.html