EtherCAT.NET icon indicating copy to clipboard operation
EtherCAT.NET copied to clipboard

Help Needed

Open klchin66 opened this issue 3 years ago • 93 comments

Hi,

Under "soem_wrapper.c"

int CALLCONV ScanDevices(ecx_contextt* context, char* interfaceName, ec_slave_info_t** slaveInfoSet, int* slaveCount)

    // request PREOP state for all slaves
    int counter = 5;

    do
    {
        ecx_statecheck(context, 0, EC_STATE_PRE_OP, EC_TIMEOUTSTATE);
    } while (counter-- && (context->slavelist[0].state != (EC_STATE_PRE_OP | EC_STATE_ACK)));

    if (context->slavelist[0].state != (EC_STATE_PRE_OP | EC_STATE_ACK))
        return -0x0104;

Should the Slave module required reply with EC_STATE_ACK?

But the "EC_STATE_ACK" was refer "Error or ACK error".

Or the code should be

    {
        ecx_statecheck(context, 0, EC_STATE_PRE_OP, EC_TIMEOUTSTATE);
    } while (counter-- && (context->slavelist[0].state != (EC_STATE_PRE_OP)));

    if (context->slavelist[0].state != (EC_STATE_PRE_OP))
        return -0x0104;

Regards, KL Chin

klchin66 avatar Jun 15 '21 09:06 klchin66

Hi, a few month ago we had the same discussion. Please see my conclusion here: https://github.com/Apollo3zehn/EtherCAT.NET/issues/57#issuecomment-784869641

Do you encounter problems with that code?

Apollo3zehn avatar Jun 15 '21 09:06 Apollo3zehn

The salve module did not reply EC_STATE_ACK. Tested with 1 or 2 salve, problem were same, the code never work for me. I did increase the counter, also not work. My both salve using LAN9252 and AX58100 chip with stm32F407 (from China).

klchin66 avatar Jun 15 '21 15:06 klchin66

Can you debug into that code and see what the actual value of context->slavelist[0].state is? Or did you do that already? Does changing the code to the version you suggested work for your slaves?

Apollo3zehn avatar Jun 16 '21 13:06 Apollo3zehn

a) '0' before entering to the loop b) '2' immediate after ecx_statecheck -> ecx_BRD -> ecx_srconfirm was return '2'

My modified code works for my slave. Not sure why so many DC drifted.

image

klchin66 avatar Jun 16 '21 16:06 klchin66

Thanks for your investigations. Unfortunately I have no slaves available to reproduce the behavior. I would like to keep this issue open and wait for others to report similar problems. Only then I can see if this behavior is specific to your slaves or a general behavior. With Beckhoff slaves I have to take the EC_STATE_ACK flag into account.

Many DC drifts may occur often when not operating on a real time system.

Apollo3zehn avatar Jun 18 '21 09:06 Apollo3zehn

Will it better to by code below, so it cover both condition

        counter--;
      } while ( (0 < counter) && (EC_STATE_NONE == (context->slavelist[0].state) & (EC_STATE_PRE_OP | EC_STATE_ACK)) );
    if ( EC_STATE_NONE == (context->slavelist[0].state & (EC_STATE_PRE_OP | EC_STATE_PRE_OP)) )
      return ( -0x0104 );

From the sample salve code (SOES), I don't see it reply together with EC_STATE_ACK.

klchin66 avatar Jun 18 '21 16:06 klchin66

From the WireShark, I got these result

image

image

image

Look likely it did receive STATE_ACK on the ecx_FPWRw( context->port,configadr,ECT_REG_ALCTL,htoes(EC_STATE_PRE_OP | EC_STATE_ACK),EC_TIMEOUTRET3 );

But not during ecx_statecheck( context,0,EC_STATE_PRE_OP,EC_TIMEOUTSTATE );

Anything wrong?

klchin66 avatar Jun 22 '21 15:06 klchin66

I am not sure, I will have to check this behavior against the EtherCAT specs. I am sorry, but unfortunately I have not much time right now to investigate this deeper. I will keep this issue open and come back when I have more time available.

Apollo3zehn avatar Jul 06 '21 15:07 Apollo3zehn

I believe I'm having a similar issue.

I'm using a HBM TIM EC EtherCAT module and with version EtherCAT.NET version 1.0.0-alpha.9.final. I get the error "ScanDevices failed (0x0104): One or more terminals did not reach PreOp-state.

Changing the check to ignore the ACK state allows it to work: if (context->slavelist[0].state != (EC_STATE_PRE_OP)) return -0x0104;

jacckk avatar Sep 09 '21 08:09 jacckk

he funtion ( var rootSlave = EcUtilities.ScanDevices(context, interfaceName, referenceRootSlave);)but An error occurred "System.Exception:“ScanDevices failed (0x0104): One or more terminals did not reach PreOp-state."ignore the ACK state allows it to work,but can't find slaves ,How to solve the issues

xutingjie168 avatar Sep 16 '21 12:09 xutingjie168

I changed two modules to resolve my problem. "EC_STATE_ACK" was acknowledge by the salve during ecx_config_init, but not ScanDevices.

a) ethercatconfig.c
-> int ecx_config_init( ecx_contextt *context, uint8 usetable )

        //  some slaves need eeprom available to PDI in init->preop transition
        ecx_eeprom2pdi( context,slave );
        //  User may override automatic state change
        if ( 0 == context->manualstatechange )
          {
            //  request pre_op for slave - set preop status
            if ( 0 != ecx_FPWRw(context->port,configadr,ECT_REG_ALCTL,htoes(EC_STATE_PRE_OP | EC_STATE_ACK),EC_TIMEOUTRET3) )
              irack++;
            EC_PRINT( "Slave %d receive STATE_ACK - %d.\n",slave,irack );
          }
        else
          {
            irack++;
          }
      }
  }
return ( (irack << 16) | wkc );

}

b) soem_wrapper.cs -> ScanDevices( ecx_contextt *context, char *interfaceName, ec_slave_info_t **slaveInfoSet, int *slaveCount )

    irack = ecx_config_init( context,false );
    wkc   = (irack & 0xFFFF);
    if ( 0 > wkc )
      {
        return ( -0x0103 );
      }
    irack         = (irack >> 16) & 0xFFFF;
    *slaveInfoSet = (ec_slave_info_t *)calloc( (size_t)(*context->slavecount + 1),sizeof(ec_slave_info_t) );
    *slaveCount   = *context->slavecount;
    counter = 5;
    do
      {
        counter--;
        ecx_statecheck( context,0,EC_STATE_PRE_OP,EC_TIMEOUTSTATE );
      //  } while ( (0 < counter) && ((EC_STATE_PRE_OP | EC_STATE_ACK) != context->slavelist[0].state) );
      } while ( (0 < counter) && (EC_STATE_NONE == (context->slavelist[0].state & (EC_STATE_PRE_OP | EC_STATE_ACK))) );
    if ( irack != *slaveCount )
      {
        //  if ( context->slavelist[0].state != (EC_STATE_PRE_OP | EC_STATE_ACK) )
        if ( EC_STATE_NONE == (context->slavelist[0].state & (EC_STATE_PRE_OP | EC_STATE_ACK)) )
          return ( -0x0104 );
      }

klchin66 avatar Sep 16 '21 17:09 klchin66

I am also getting "One or more terminals did not reach PreOp-state" error with HNC servo using SamleMaster. My technician thinks the servo on has to be sent, in order to reach preop state.

ga5tan avatar May 05 '23 07:05 ga5tan

I did what @jacckk suggested (commenting error 104 out) if (context->slavelist[0].state != (EC_STATE_PRE_OP)) return -0x0104; and got little further. Now I got this error:

Could not find ESI information of manufacturer '0x88' for slave with product code '0x88710000' and revision '0x1'

any ideas what to do next would be appreciated.

ga5tan avatar May 05 '23 10:05 ga5tan

@ga5tan

You need provide the ESI file for your device to EtherCAT.NET. You get this from the manufacturer. Then provide the path to your ESI folder as shown here: https://github.com/Apollo3zehn/EtherCAT.NET/blob/master/sample/SampleMaster/Program.cs#L48

Apollo3zehn avatar May 05 '23 11:05 Apollo3zehn

Thanx @Apollo3zehn I was able to get some XML files, do you think that could be it? I will try it when machine is back on.

ga5tan avatar May 05 '23 13:05 ga5tan

Yes, ESI files are XML files, so it could work.

Apollo3zehn avatar May 05 '23 15:05 Apollo3zehn

with XMLs in place I got little further. Now it breaks here: EcUtilities.CreateDynamicData(settings.EsiDirectoryPath, slave);

with message

System.FormatException: Input string was not in a correct format.

Coudl it be the XML is no good?

full stack:

System.FormatException: Input string was not in a correct format.
   at System.Number.ThrowOverflowOrFormatException(ParsingStatus status, TypeCode type)
   at System.Convert.ToByte(String value)
   at EtherCAT.NET.EcUtilities.<>c__DisplayClass8_1.<CreateDynamicData>b__1(PdoTypeEntry x) in D:\dev\EtherCAT.NET\src\EtherCAT.NET\EcUtilities.cs:line 198
   at System.Linq.Enumerable.SelectArrayIterator`2.ToList()
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at EtherCAT.NET.EcUtilities.CreateDynamicData(String esiDirectoryPath, SlaveInfo slave) in D:\dev\EtherCAT.NET\src\EtherCAT.NET\EcUtilities.cs:line 195
   at SampleMaster.Program.<>c__DisplayClass0_0.<Main>b__2(SlaveInfo slave) in D:\dev\EtherCAT.NET\sample\SampleMaster\Program.cs:line 90
   at System.Collections.Generic.List`1.ForEach(Action`1 action)
   at SampleMaster.Program.Main(String[] args) in D:\dev\EtherCAT.NET\sample\SampleMaster\Program.cs:line 65
   at SampleMaster.Program.<Main>(String[] args)

ga5tan avatar May 09 '23 13:05 ga5tan

It seems this code: var subIndex = Convert.ToByte(x.SubIndex); does not like value '#x00' as subindex.

XML looks like this (assuming that's the part, cause there is couple of such Index and SubIndex combinations.

Is #x00 no good as SubIndex? because most of the numerical values seem to have #x prefix

<Index>#x603F</Index> <SubIndex>#x00</SubIndex>

ga5tan avatar May 09 '23 13:05 ga5tan

Unfortunately the XML files are often a little bit inconsistent.

If you replace the problematic code with var subIndex = (byte)EsiUtilities.ParseHexDecString(x.SubIndex); I would expect it to work.

Apollo3zehn avatar May 09 '23 13:05 Apollo3zehn

@Apollo3zehn thx, that helped. Now I got this: (no idea yet what is with Clocks yeet)

System.NullReferenceException: Object reference not set to an instance of an object.
   at EtherCAT.NET.Extension.DistributedClocksExtension.EvaluateSettings() in D:\dev\EtherCAT.NET\src\EtherCAT.NET\Extension\DistributedClocks\DistributedClocksExtension.cs:line 47
   at EtherCAT.NET.EcUtilities.<>c.<CreateDynamicData>b__8_0(SlaveExtension extension) in D:\dev\EtherCAT.NET\src\EtherCAT.NET\EcUtilities.cs:line 256
   at System.Collections.Generic.List`1.ForEach(Action`1 action)
   at EtherCAT.NET.EcUtilities.CreateDynamicData(String esiDirectoryPath, SlaveInfo slave) in D:\dev\EtherCAT.NET\src\EtherCAT.NET\EcUtilities.cs:line 254
   at SampleMaster.Program.<>c__DisplayClass0_0.<Main>b__2(SlaveInfo slave) in D:\dev\EtherCAT.NET\sample\SampleMaster\Program.cs:line 92
   at System.Collections.Generic.List`1.ForEach(Action`1 action)
   at SampleMaster.Program.Main(String[] args) in D:\dev\EtherCAT.NET\sample\SampleMaster\Program.cs:line 67
   at SampleMaster.Program.<Main>(String[] args)

ga5tan avatar May 09 '23 14:05 ga5tan

Could you please attach the relevant ESI file? There seems to be an unexpected syntax.

Apollo3zehn avatar May 09 '23 14:05 Apollo3zehn

It seems to be an extension. I thought I try to make Sample work, but 'All I really need' is to able to command grid of servos to go to specific position. HSD7_ES_EtherCAT_V120.zip attached smaller file

ga5tan avatar May 09 '23 14:05 ga5tan

I compared an oversampling terminal from Beckhoff (left) to yours (right): grafik.

The code expects one or more <Pdo> elements to be present, but there are none on the right. I am not sure if the problem is with EtherCAT.NET or with the ESI file.

You could try to comment out these lines: https://github.com/Apollo3zehn/EtherCAT.NET/blob/8f60d91c220909e030ac77a27edd6411d5abadf2/src/EtherCAT.NET/Extension/DistributedClocks/DistributedClocksExtension.cs#L47-L57

Apollo3zehn avatar May 09 '23 14:05 Apollo3zehn

Well, it almost looks like it working except this

`info: EtherCAT Master[0] Found 1 slaves: i7DS-**A30 (PDOs: 8 - CSA: 47163) info: EtherCAT Master[0] IO map configured (1 slave, 32 bytes) info: EtherCAT Master[0] DC system time diff. is <= 0 ns fail: EtherCAT Master[0] CheckSafeOpState failed (0x0501): One or more terminals did not reach SafeOp-state.

Application failed with unhandled exception:

System.Exception: CheckSafeOpState failed (0x0501): One or more terminals did not reach SafeOp-state. at EtherCAT.NET.EcUtilities.CheckErrorCode(IntPtr context, Int32 errorCode, String callerMemberName) in D:\dev\EtherCAT.NET\src\EtherCAT.NET\EcUtilities.cs:line 135 at EtherCAT.NET.EcMaster.Configure(SlaveInfo rootSlave) in D:\dev\EtherCAT.NET\src\EtherCAT.NET\EcMaster.cs:line 277 at SampleMaster.Program.Main(String[] args) in D:\dev\EtherCAT.NET\sample\SampleMaster\Program.cs:line 116 at SampleMaster.Program.<Main>(String[] args)`

would it be safe/advisable to comment this line?

EcUtilities.CheckErrorCode(this.Context, EcHL.CheckSafeOpState(this.Context), nameof(EcHL.CheckSafeOpState));

ga5tan avatar May 11 '23 08:05 ga5tan

I did that and got this:

`Slaves: 1 info: EtherCAT Master[0] Found 1 slaves: i7DS-**A30 (PDOs: 8 - CSA: 47163) info: EtherCAT Master[0] IO map configured (1 slave, 32 bytes) info: EtherCAT Master[0] DC system time diff. is <= 0 ns fail: EtherCAT Master[0] ConfigureSync01 failed (0x0000): The working counter is 0 (SOEM).

Application failed with unhandled exception:

System.Exception: ConfigureSync01 failed (0x0000): The working counter is 0 (SOEM). at EtherCAT.NET.EcUtilities.CheckErrorCode(IntPtr context, Int32 errorCode, String callerMemberName) in D:\dev\EtherCAT.NET\src\EtherCAT.NET\EcUtilities.cs:line 135 at EtherCAT.NET.EcMaster.ConfigureSync01(IList1 slaves) in D:\dev\EtherCAT.NET\src\EtherCAT.NET\EcMaster.cs:line 234 at EtherCAT.NET.EcMaster.Configure(SlaveInfo rootSlave) in D:\dev\EtherCAT.NET\src\EtherCAT.NET\EcMaster.cs:line 271 at SampleMaster.Program.Main(String[] args) in D:\dev\EtherCAT.NET\sample\SampleMaster\Program.cs:line 116 at SampleMaster.Program.<Main>(String[] args)

still no good :(

ga5tan avatar May 11 '23 08:05 ga5tan

That is the point where you would need to read out the status code of the slave:

https://github.com/Apollo3zehn/EtherCAT.NET/blob/8f60d91c220909e030ac77a27edd6411d5abadf2/src/SOEM.PInvoke/PInvoke/EcHL.cs#L341-L355

The alStatusCode tells you what is wrong. You can translate that code into an error description here:

https://infosys.beckhoff.com/index.php?content=../content/1031/ethercatsystem/1037010571.html&id=

Apollo3zehn avatar May 11 '23 10:05 Apollo3zehn

@Apollo3zehn weirdest thing. I added this Console.WriteLine(EcUtilities.GetSlaveStateDescription(master.Context, slaves.SelectMany(x => x.Descendants()).ToList())); but no error today.

Program just sits there with this output. Slaves: 1 info: EtherCAT Master[0] Found 1 slaves: i7DS-**A30 (PDOs: 8 - CSA: 47163) info: EtherCAT Master[0] IO map configured (1 slave, 32 bytes) info: EtherCAT Master[0] DC system time diff. is <= 0 ns

I guess it's time for real world example now. Read and write examples to enable servo, and move it 10mm. Any samples for that? I guess it quite depends on specific manufacturer of servo, right ?

Thank you for your help, I'll keep you posted when it moves :)

ga5tan avatar May 12 '23 08:05 ga5tan

Congrats :-) In the past I also had some weirdly behaving slaves where a power cycled helped to make them work. My guess is that due to some "playing around" they are in an undefined internal state which should be reset.

I have never controlled a servo, my focus is on measurements. Maybe you need to configure some SDO registers first or you are lucky and the defaults are fine.

If directly controlling the servo using PDOs does not work, you may configure the same project in TwinCAT and look there on the "startup" tab for the correct SDO commands (and then try to understand them using the servo's manual).

grafik

Apollo3zehn avatar May 12 '23 08:05 Apollo3zehn

I got the documentation which looks like this: image and this: image

So I believe I need to primarily manipulate address 0x2000 and 0x2001. Those are 16bit variables. Should I access them (for writing) like this? var myOutputs = new DigitalOut(slaves[0]);

or like this (and what do I need the filter for)? var datasetFilter = new byte[2]; EcUtilities.SdoRead(master.Context, 4, 0x8000, 6, ref datasetFilter);

or like this (I am not sure those registers are analogue) var pdoAnalogIn = slaves[0].DynamicData.Pdos; var varAnalogIn = pdoAnalogIn[0].Variables.Where(x => x.Name == "0x2000").First();

ga5tan avatar May 24 '23 12:05 ga5tan

Well actually I tried to read variables (according to the main page of this GIT) like this:

`foreach (var pdo in slaves[0].DynamicData.Pdos) {

                foreach (var variable in pdo.Variables)
                {
                    message.AppendLine($"pdo {pdo.Name} variable: {variable.DataPtr}");
                }
            }`

but foud out, that the app freezes on

master.Configure(rootSlave);

So I was never out of woods, it was just frozen in there. I will try to pinpoint the problem (freeze point) but it's a bit tricky as I dont have debugger on the remote machine, where servo is connected

ga5tan avatar May 24 '23 13:05 ga5tan