Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Iam just started using SOEM. Iam a beginner. When Iam trying to control AKD motor control drive which is a slave I couldn't able to write the control word using ec_SDOwrite().I dont know is there any other things i Should do.Slave is in operational mode.Can somebody Please help on this topic. I have given the datasheet also #69

Closed
ETA-TECH opened this issue Jan 9, 2017 · 17 comments
Labels

Comments

@ETA-TECH
Copy link

ETA-TECH commented Jan 9, 2017

Kollmorgen AKD EtherCat Communications Manual.pdf

@nakarlsson
Copy link
Contributor

First, I don't think this is a SOEM issue.

Second, you have to figure out why the Write fail

  • Check for CoE error with boolean error flag EcatError and print function ec_elist2string
    Or
  • Take a wireshak log, it should give you a hint. The slave should reply with an Abort.

@ETA-TECH
Copy link
Author

ETA-TECH commented Jan 9, 2017

I will try that and will give you feedback

@ETA-TECH
Copy link
Author

There is no error in the flag and ec_elist2string function. But one more observation is that the status word from the device is saying that not ready to switch on. Is this any configuration issue. This is how Iam doing simpletest()

int i,IOmap_size,chk,oloop, iloop;
uint16 status[1];
int pointer_2=sizeof(status);
uint16 uint16val;
char error;

if (ecx_init(ectx, ifname) <= 0) {
        printf("ecx_init on %s failed\n", ifname);
        return 1;
}

while(TRUE)
{
ecx_config_init(ectx, FALSE);
printf("found %d slaves\n", *(ectx->slavecount));

/* slavelist[0] is not used */
for (i=1; i <= *(ectx->slavecount); i++) {
        ec_slavet* slave = ectx->slavelist + i;
        printf("slave %d (%s): state = %02x\n", i, slave->name, slave->state);
}
for (i=1; i <= *(ectx->slavecount); i++) {
        if (configure_syncmaster(ectx, i)) {
                printf("configure_syncmaster failed for slave %d\n", i);
                return 1;
        }
}

ecx_statecheck(ectx, 0 /* all slaves */, EC_STATE_PRE_OP, EC_TIMEOUTSTATE * 4);
ecx_readstate(ectx);
printf("ecx_statcheck state = %02x\n", ectx->slavelist->state);
for ( i=1; i <= *(ectx->slavecount); i++) {
        ec_slavet* slave = ectx->slavelist + i;
        printf("slave %d (%s): state = %02x status = %02x (%s)\n", i, slave->name, slave->state, slave->ALstatuscode, ec_ALstatuscode2string(slave->ALstatuscode));
}

IOmap_size = ecx_config_map_group(ectx, IOmap, /* group= */ 0 );
if (IOmap_size <= 0) {
        printf("ecx_config_map_group on %s failed\n", ifname);

        return 1;
}
printf("mapped %d bytes\n", IOmap_size);

ecx_configdc(ectx);

ecx_statecheck(ectx, 0 , EC_STATE_SAFE_OP,  EC_TIMEOUTSTATE * 4);/* all slaves */
ecx_readstate(ectx);
printf( "ecx_statcheck state = %02x\n", ectx->slavelist->state);
for ( i=1; i <= *(ectx->slavecount); i++) {
        ec_slavet* slave = ectx->slavelist + i;
        printf("slave %d (%s): state = %02x status = %02x (%s)\n", i, slave->name, slave->state, slave->ALstatuscode, ec_ALstatuscode2string(slave->ALstatuscode));
}
ec_slave[0].state = EC_STATE_OPERATIONAL;

/* send one valid process data to make outputs in slaves happy*/
ec_send_processdata();
ec_receive_processdata(EC_TIMEOUTRET);

/* request OP state for all slaves */
ec_writestate(0);
chk = 40;

/* wait for all slaves to reach OP state */
do
{
   ec_send_processdata();
   ec_receive_processdata(EC_TIMEOUTRET);
   ec_statecheck(0, EC_STATE_OPERATIONAL, 100000);
}
while (chk-- && (ec_slave[0].state != EC_STATE_OPERATIONAL));

if (ec_slave[0].state == EC_STATE_OPERATIONAL )
{
   printf("Operational state reached for all slaves.\n");
   inOP = TRUE;

   /* cyclic loop */
   for(i = 1; i <= 1000; i++)
   {
      ec_send_processdata();
      wkc = ec_receive_processdata(EC_TIMEOUTRET);
      ec_SDOread(1,0x6041,0,FALSE,&pointer_2,&status, EC_TIMEOUTRXM);

      CONSOLEUtilsPrintf("status=%d\n", status[0]);
      uint16val=0xf;
      //wkc=ecx_SDOwrite(ectx, 1,0x6040, 0,TRUE, sizeof(uint16val), &uint16val, EC_TIMEOUTRXM);
      ec_SDOwrite(1, 0x6040, 0, FALSE, sizeof(uint16val), &uint16val, EC_TIMEOUTRXM);

      ec_elist2string();
      //printf("%s\n", error);
           if(wkc >= expectedWKC)
           {
               printf("Processdata cycle %4d, WKC %d , O:", i, wkc);

               for(j = 0 ; j < oloop; j++)
               {
                   printf(" %2.2x", *(ec_slave[0].outputs + j));
               }

               printf(" I:");
               for(j = 0 ; j < iloop; j++)
               {
                   printf(" %2.2x", *(ec_slave[0].inputs + j));
               }
               printf(" T:%lld\r",ec_DCtime);
               needlf = TRUE;
           }
           usleep(5000);

       }
       inOP = FALSE;
   }

}
ecx_close(ectx);

Iam getting the log
[CortexA9] Network Added: If-1:192.168.2.3
Network Added: If-2:192.168.1.2
found 1 slaves
slave 1 (AKD): state = 01
ecx_statcheck state = 02
slave 1 (AKD): state = 02 status = 00 (No error)
mapped 4 bytes
ecx_statcheck state = 04
slave 1 (AKD): state = 04 status = 00 (No error)
Operational state reached for all slaves.
Iam using TI AM4379

@ETA-TECH
Copy link
Author

Also device is giving a warning PLL unlocked

@nakarlsson
Copy link
Contributor

Yes , it sounds like a configuration issue. Often you need to configure the slave before entering SAFEOP. For SOEM that is between config_init and config_map.

@ETA-TECH
Copy link
Author

KKK. Now i got PLL locked from the slave and slave is in operational state. Which are the other conditions to be checked to find whether communication is proper before writing to the slave.

@nakarlsson
Copy link
Contributor

Since you can enter OP you're "good" from an EtherCAT configurations perspective, but since you can't operate the drive its pre-conditions is not set and you can not enter drives' "operational" state. With that I can't help you, you need to consult the RM.

@ETA-TECH
Copy link
Author

Thanks. From the xml file can we figure out the preconditions which has to be set for the drive.

@ETA-TECH
Copy link
Author

ETA-TECH commented Jan 10, 2017 via email

@nakarlsson
Copy link
Contributor

Reference manual or similar, in your case Kollmorgen AKD EtherCat Communications Manual I guess.

@nakarlsson
Copy link
Contributor

Any progress?

@ETA-TECH
Copy link
Author

sorry. I was not in the office for a while. Now I could able to control the drive in all modes.

@ETA-TECH
Copy link
Author

Now Iam trying EK1100 ethercat coupler and some DI DO modules along with the drive. Is there any way to access Slave IO's with out the function ec_config_map(&IOmap). Because when Iam using this function drive is loosing the syncronisation

@nakarlsson
Copy link
Contributor

You might be able to read/write a the CoE PDO or a physical RAM address via FPRD/WR.

@nakarlsson
Copy link
Contributor

Any updates?

@nakarlsson
Copy link
Contributor

Nothing new.

@rafaelkrause
Copy link

Hi !! I'm posting the AKD Mapping that works for us in case any one got problems with AKD comunication. It's based on a configuration that we use at CodeSys. We have tested using the example simple_test.c.


 int AKDsetup(uint16 slave)
  {

     int retval = 0;
    uint8 u8val;
    uint16 u16val;
    uint32 u32val;  

    //Clean Output PDOs Indexes
    u8val = 0;
    retval += ec_SDOwrite(slave, 0x1c13, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM); // Clean SM3 PDOs (0x1c12)
    
    //Clean Input PDOs
    retval += ec_SDOwrite(slave, 0x1a00, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);    // Clean 0x1a00 PDOs Entry    
    retval += ec_SDOwrite(slave, 0x1a01, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);    // Clean 0x1a01 PDOs Entry
    retval += ec_SDOwrite(slave, 0x1a02, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);    // Clean 0x1a02 PDOs Entry
    retval += ec_SDOwrite(slave, 0x1a03, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);    // Clean 0x1a03 PDOs Entry    

    //Configure new INPUT PDOs (On Master Perspective)
    //PDO 01
    u32val = 0x60410010; // Status Word
    retval += ec_SDOwrite(slave, 0x1a00, 0x01, FALSE, sizeof(u32val), &u32val, EC_TIMEOUTRXM);  // Set Object 0x6041:00:10 (Index,SubIndex,BitLength) to 0x1a00:01 entry
    u32val = 0x60630020; // Feedback Position
    retval += ec_SDOwrite(slave, 0x1a00, 0x02, FALSE, sizeof(u32val), &u32val, EC_TIMEOUTRXM);  // Set Object 0x6063:00:20 (Index,SubIndex,BitLength) to 0x1a00:02 entry
    u8val = 2;
    retval += ec_SDOwrite(slave, 0x1a00, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);    // Set number of objects into PDO 0x1a00.
   //PDO 02
    u32val = 0x606C0020; // Actual Velocity
    retval += ec_SDOwrite(slave, 0x1a01, 0x01, FALSE, sizeof(u32val), &u32val, EC_TIMEOUTRXM);  
    u32val = 0x60770010; // Actual Torque
    retval += ec_SDOwrite(slave, 0x1a01, 0x02, FALSE, sizeof(u32val), &u32val, EC_TIMEOUTRXM);  
    u8val = 2;
    retval += ec_SDOwrite(slave, 0x1a01, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);    
   //PDO 03
    u32val = 0x60FD0020; // Digital Inputs 
    retval += ec_SDOwrite(slave, 0x1a02, 0x01, FALSE, sizeof(u32val), &u32val, EC_TIMEOUTRXM);  
    u32val = 0x34700410; // Analog Input
    retval += ec_SDOwrite(slave, 0x1a02, 0x02, FALSE, sizeof(u32val), &u32val, EC_TIMEOUTRXM);  
    u8val = 2;
    retval += ec_SDOwrite(slave, 0x1a02, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);    
 
   //Set SM3 PDOs
    u16val = 0x1a00; //PDO 1
    retval += ec_SDOwrite(slave, 0x1c13, 0x01, FALSE, sizeof(u16val), &u16val, EC_TIMEOUTRXM); // Set SM2 PDOs (0x1c13) with 0x1600 PDO
    u16val = 0x1a01; //PDO 2
    retval += ec_SDOwrite(slave, 0x1c13, 0x02, FALSE, sizeof(u16val), &u16val, EC_TIMEOUTRXM); // Set SM2 PDOs (0x1c13) with 0x1600 PDO
    u16val = 0x1a02; //PDO 3
    retval += ec_SDOwrite(slave, 0x1c13, 0x03, FALSE, sizeof(u16val), &u16val, EC_TIMEOUTRXM); // Set SM2 PDOs (0x1c13) with 0x1600 PDO
    u8val = 3;
    retval += ec_SDOwrite(slave, 0x1c13, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM); // Set SM3 number of PDOs


   //Clean Output PDOs Indexes
   u8val = 0;
   retval += ec_SDOwrite(slave, 0x1c12, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM); // Clean SM2 PDOs (0x1c13)

   //Clean Output PDOs
    u8val = 0;
    retval += ec_SDOwrite(slave, 0x1600, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);    // Clean 0x1600 PDOs Entry
    retval += ec_SDOwrite(slave, 0x1601, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);    // Clean 0x1601 PDOs Entry
    retval += ec_SDOwrite(slave, 0x1602, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);    // Clean 0x1602 PDOs Entry
    retval += ec_SDOwrite(slave, 0x1603, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);    // Clean 0x1603 PDOs Entry

    //Configure new OUTPUTs PDOs (On Master Perspective)
    //PDO 01
    u32val = 0x60400010; // Control Word
    retval += ec_SDOwrite(slave, 0x1600, 0x01, FALSE, sizeof(u32val), &u32val, EC_TIMEOUTRXM);  // Set Object 0x6040:00:10 (Index,SubIndex,BitLength) to 0x1600:01 entry
    u32val = 0x60c10120; // Command Position (From Firmware Version 1.8.5), for earlier Firware use 0x607A:00. Another used name is Interpolation Data Record
    retval += ec_SDOwrite(slave, 0x1600, 0x02, FALSE, sizeof(u32val), &u32val, EC_TIMEOUTRXM);  // Set Object 0x6063:00:20 (Index,SubIndex,BitLength) to 0x1600:02 entry
    u8val = 2;
    retval += ec_SDOwrite(slave, 0x1600, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);    // Set number of objects into PDO 0x1600.
   //PDO 02
    u32val = 0x60FE0120; // Digital Outputs
    retval += ec_SDOwrite(slave, 0x1601, 0x01, FALSE, sizeof(u32val), &u32val, EC_TIMEOUTRXM);  
    u32val = 0x34700310; // Analog Output (Write)
    retval += ec_SDOwrite(slave, 0x1601, 0x02, FALSE, sizeof(u32val), &u32val, EC_TIMEOUTRXM);  
    u8val = 2;
    retval += ec_SDOwrite(slave, 0x1601, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM);    
    
    //Set SM2 Pdos
    u16val = 0x1600; //PDO 1
    retval += ec_SDOwrite(slave, 0x1c12, 0x01, FALSE, sizeof(u16val), &u16val, EC_TIMEOUTRXM); // Set SM3 PDOs (0x1c12) with 0x1600 PDO
    u16val = 0x1601; //PDO 2
    retval += ec_SDOwrite(slave, 0x1c12, 0x02, FALSE, sizeof(u16val), &u16val, EC_TIMEOUTRXM); // Set SM3 PDOs (0x1c12) with 0x1600 PDO
    u8val = 2;
    retval += ec_SDOwrite(slave, 0x1c12, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM); // Set SM3 number of PDOs  
       
    //Set Startup Commands
    u8val = 0x07;
    retval += ec_SDOwrite(slave, 0x6060, 0x00, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM); // Set Operation Mode (Sync Position)
    u8val = 0x04;
    retval += ec_SDOwrite(slave, 0x60C2, 0x01, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM); // Set Cycle time Units (4 * Cycle Expoent)
    u8val = -3;
    retval += ec_SDOwrite(slave, 0x60C2, 0x02, FALSE, sizeof(u8val), &u8val, EC_TIMEOUTRXM); // Set Cycle Expoent -> -3 means 10Exp-3 that is equal to milliseconds
    u32val = 0x30000;
    retval += ec_SDOwrite(slave, 0x60FE, 0x02, FALSE, sizeof(u32val), &u32val, EC_TIMEOUTRXM); // Set Digital Output Mask (To Enable use of Drive Outputs)


    //Print Ethercat Errors
    while(EcatError) printf("%s", ec_elist2string());


    printf("AKD Slave %d set, retval = %d\n", slave, retval);
    return 1;
}

and Link it with Slave configuration

 if((ec_slavecount >= 1))
         {
             for(int slc = 1; slc <= ec_slavecount; slc++)
             {
                
                 .....
                 if(slave == AKD)
                {
                     ec_slave[slc].PO2SOconfig = &AKDsetup;
                 }
             }
         }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants