[etherlab-users] cannot read domain data

Patrik Roth Patrik.Roth at gmx.de
Tue Oct 9 14:14:17 CEST 2018


Hallo EtherLab-User,

vielleicht kann mir jemand von Euch weiterhelfen.
Folgende Probleme stehen bei mir an:

Ich bin am Testen von /ethercat-hg/examples/user/main.c. Ich kann die
Eingänge noch nicht lesen. Ich gehen davon aus, daß es ein Problem mit
Domain1 gibt, da der WC und State auf 0 bleiben.
Wenn das Programm ./ec_user_example gestartet wurde gab es folgende
Ausgaben --> siehe unten "Terminal Output:"
Weiterhin konnten während dem Programmlauf folgende Daten abgerufen werden:
$ ethercat domain -v
Domain0: LogBaseAddr 0x00000000, Size   1, WorkingCounter 0/1
  SlaveConfig 0:1, SM0 ( Input), LogAddr 0x00000000, Size 1
    00

Mit Hilfe der Terminaleingabe konnte ich vom Beckhoff EK1100 (=Slave0) und
EL1008 (=Slave1) mit dem folgenden Befehl den ersten Eingang von Slave1
abfragen:
$ ethercat -p1 reg_read 0x1000 -t uint8
0x00 0
r$ ethercat -p1 reg_read 0x1000 -t uint8
0x01 1
--> Dies deutet doch darauf hin, daß soweit alles in Ordnung ist?

Siehe unten " Protokoll dmesg:" und das Kodebeispiel (siehe "CodeExample:")
von Ihrer Seite, welches ich auf die Hardware EK1100 (=Slave0) und EL1008
(=Slave1) angepaßt habe.
Somit wären ich jetzt soweit um den EtherCatMaster nahezu voll auf Ubuntu
12.04 i386 einzusetzen.

Weiterhin konnte ich noch ein EL4004 Slave2 und ein EL3255 Slave3 anhängen.
Alle Slaves gingen in operational Status. auch hier war das Problem, daß
ich keine Daten mit den Befehlen EC_READ... bzw. EC_WRITE... lesen oder
schrieben konnte. Auch hier blieb die Domain mit WC und State auf 0.

Könnt Ihr mir helfen die Domain1 zum Laufen zu bekommen?

Viele Grüße
Patrik Roth


Anhang:


Terminal Output:
============

root at pr-VirtualBox:/home/pr/ethercat-hg/examples/user# ./ec_user_example
Configuring PDOs...
Activating master...
...ok!
Domain data registered ok.
Using priority 99.
Starting RT task with dt = 70 ms.
Domain1: WC 0.
Domain1: State 0.
2 slave(s).
Master: AL states 0x02 = PREOP
Link is up.
EL1008 DigIn State 0x02.
EL1008 DigIn: online.
.dig_in_value = 0
...Master: AL states 0x08 = OP
EL1008 DigIn State 0x08.
EL1008 DigIn: operational.
.......

Protokoll dmesg:
============

....
[68494.069601] EtherCAT 0: Starting EtherCAT-OP thread.
[68494.070777] EtherCAT DEBUG 0: mmap()
[68494.070783] EtherCAT DEBUG 0: Vma fault, offset = 0, page = f5c4f4e0
[68494.072847] EtherCAT DEBUG 0: Operation thread running with fsm
interval = 4000 us, max data size=45000
[68494.072850] EtherCAT WARNING 0: 2 datagrams TIMED OUT!
[68494.072851] EtherCAT WARNING 0: 3 datagrams UNMATCHED!
[68494.600065] EtherCAT DEBUG 0: Configuration changed (aborting state check).
[68494.600068] EtherCAT WARNING 0: No app_time received up to now, but
master already active.
[68494.600070] EtherCAT DEBUG 0: Requesting OP...
[68494.885533] EtherCAT DEBUG 0-0: Changing state from PREOP to OP.
[68494.885548] EtherCAT DEBUG 0-0: Configuring...
[68495.160439] EtherCAT DEBUG 0-0: Now in INIT.
[68495.160442] EtherCAT DEBUG 0-0: Clearing FMMU configurations...
[68495.301231] EtherCAT DEBUG 0-0: Clearing sync manager configurations...
[68495.441572] EtherCAT DEBUG 0-0: Clearing DC assignment...
[68495.580722] EtherCAT DEBUG 0-0: Slave does not support mailbox communication.
[68495.860731] EtherCAT DEBUG 0-0: Now in PREOP.
[68496.280306] EtherCAT DEBUG 0-0: Now in SAFEOP.
[68496.560606] EtherCAT DEBUG 0-0: Now in OP. Finished configuration.
[68496.701521] EtherCAT DEBUG 0-1: Changing state from PREOP to OP.
[68496.701526] EtherCAT DEBUG 0-1: Configuring...
[68496.980530] EtherCAT DEBUG 0-1: Now in INIT.
[68496.980533] EtherCAT DEBUG 0-1: Clearing FMMU configurations...
[68497.120941] EtherCAT DEBUG 0-1: Clearing sync manager configurations...
[68497.259666] EtherCAT DEBUG 0-1: Clearing DC assignment...
[68497.400368] EtherCAT DEBUG 0-1: Slave does not support mailbox communication.
[68497.609884] EtherCAT DEBUG 0-1: Now in PREOP.
[68497.609889] EtherCAT DEBUG 0-1: SM0: Addr 0x1000, Size   1, Ctrl 0x00, En 1
[68497.749859] EtherCAT DEBUG 0 0:1: FMMU: LogAddr 0x00000000, Size
1, PhysAddr 0x1000, SM0, Dir in
[68498.029911] EtherCAT DEBUG 0-1: Now in SAFEOP.
[68498.309726] EtherCAT DEBUG 0-1: Now in OP. Finished configuration.
[68498.452126] EtherCAT 0: Slave states on main device: OP.

CodeExample: \examples\user\main.c abgeändert
============

/*****************************************************************************
 *
 *  $Id$
 *
 *  Copyright (C) 2007-2009  Florian Pose, Ingenieurgemeinschaft IgH
 *
 *  This file is part of the IgH EtherCAT Master.
 *
 *  The IgH EtherCAT Master is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License version 2, as
 *  published by the Free Software Foundation.
 *
 *  The IgH EtherCAT Master is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
 *  Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with the IgH EtherCAT Master; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *  ---
 *
 *  The license mentioned above concerns the source code only. Using the
 *  EtherCAT technology and brand is only permitted in compliance with the
 *  industrial property and similar rights of Beckhoff Automation GmbH.
 *
 ****************************************************************************/

#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h> /* clock_gettime() */
#include <sys/mman.h> /* mlockall() */
#include <sched.h> /* sched_setscheduler() */

/****************************************************************************/

#include "ecrt.h"

/****************************************************************************/

uint8_t getBit(unsigned int wert, uint8_t bitPos) {
    // patrik.roth at gmx.de, 02.10.2018
    return ((((uint8_t)wert) >> bitPos) & 0x01); // shift right mit Maske
}

/** Task period in ns. */
//#define PERIOD_NS   (1000000)
#define PERIOD_NS     (70000000) // = 70 ms, PR

#define MAX_SAFE_STACK (8 * 1024) /* The maximum stack size which is
                                     guranteed safe to access without
                                     faulting */

/****************************************************************************/

/* Constants */
#define NSEC_PER_SEC (1000000000)
#define FREQUENCY (NSEC_PER_SEC / PERIOD_NS)

/****************************************************************************/

// EtherCAT
static ec_master_t *master = NULL;
static ec_master_state_t master_state = {};

static ec_domain_t *domain1 = NULL;
static ec_domain_state_t domain1_state = {};

static ec_slave_config_t *sc_dig_in = NULL;
static ec_slave_config_state_t sc_dig_in_state = {};


/****************************************************************************/


// process data
static uint8_t *domain1_pd = NULL;

#define BusCouplerPos  0, 0 // alias, position io
#define DigInSlavePos  0, 1

#define Beckhoff_EK1100 0x00000002, 0x044c2c52 //Vendor Id, Product code
#define Beckhoff_EL1008 0x00000002, 0x03f03052 //dig_in

// offsets for PDO entries
static unsigned int off_dig_in;


const static ec_pdo_entry_reg_t domain1_regs[] = {
    {DigInSlavePos,  Beckhoff_EL1008, 0x6000, 1, &off_dig_in},
    {}
};

static uint counter = 0;

/*****************************************************************************/

/* Master 0, Slave 1, "EL1008"
 * Vendor ID:       0x00000002
 * Product code:    0x03f03052
 * Revision number: 0x00100000
 */

ec_pdo_entry_info_t slave_1_pdo_entries[] = {
    {0x6000, 0x01, 1}, /* Input */
    {0x6010, 0x01, 1}, /* Input */
    {0x6020, 0x01, 1}, /* Input */
    {0x6030, 0x01, 1}, /* Input */
    {0x6040, 0x01, 1}, /* Input */
    {0x6050, 0x01, 1}, /* Input */
    {0x6060, 0x01, 1}, /* Input */
    {0x6070, 0x01, 1}, /* Input */
};

ec_pdo_info_t slave_1_pdos[] = {
    {0x1a00, 1, slave_1_pdo_entries + 0}, /* Channel 1 */
    {0x1a01, 1, slave_1_pdo_entries + 1}, /* Channel 2 */
    {0x1a02, 1, slave_1_pdo_entries + 2}, /* Channel 3 */
    {0x1a03, 1, slave_1_pdo_entries + 3}, /* Channel 4 */
    {0x1a04, 1, slave_1_pdo_entries + 4}, /* Channel 5 */
    {0x1a05, 1, slave_1_pdo_entries + 5}, /* Channel 6 */
    {0x1a06, 1, slave_1_pdo_entries + 6}, /* Channel 7 */
    {0x1a07, 1, slave_1_pdo_entries + 7}, /* Channel 8 */
};

ec_sync_info_t slave_1_syncs[] = {
    {0, EC_DIR_INPUT, 8, slave_1_pdos + 0, EC_WD_DISABLE},
    {0xff}
};

/*****************************************************************************/

void check_domain1_state(void)
{
    static uint8_t once = 1;
    ec_domain_state_t ds;
    ecrt_domain_state(domain1, &ds);
    if ((ds.working_counter != domain1_state.working_counter) | once)
        printf("Domain1: WC %u.\n", ds.working_counter);
    if ((ds.wc_state != domain1_state.wc_state) | once) {
        printf("Domain1: State %u.\n", ds.wc_state);
        once = 0;
    }
    domain1_state = ds;
}

/*****************************************************************************/

void check_master_state(void)
{
    ec_master_state_t ms;
    ecrt_master_state(master, &ms);
    if (ms.slaves_responding != master_state.slaves_responding)
        printf("%u slave(s).\n", ms.slaves_responding);
    if (ms.al_states != master_state.al_states) {
        printf("Master: AL states 0x%02X =", ms.al_states);
        if (getBit(ms.al_states,0)) printf(" INIT");
        if (getBit(ms.al_states,1)) printf(" PREOP");
        if (getBit(ms.al_states,2)) printf(" SAFEOP");
        if (getBit(ms.al_states,3)) printf(" OP");
        printf("\n");
    }
    if (ms.link_up != master_state.link_up)
        printf("Link is %s.\n", ms.link_up ? "up" : "down");
    master_state = ms;
}

/*****************************************************************************/

void check_slaveDigIn_config_states(void)
{ //todo: siehe "MMT Ethercat User Guide.pdf" für zusammenfassen der
checkSlave...
    ec_slave_config_state_t s;
    ecrt_slave_config_state(sc_dig_in, &s); // Segmentation fault (core dumped)
    if (s.al_state != sc_dig_in_state.al_state)
        printf("EL1008 DigIn State 0x%02X.\n", s.al_state);
    if (s.online != sc_dig_in_state.online)
        printf("EL1008 DigIn: %s.\n", s.online ? "online" : "offline");
    if (s.operational != sc_dig_in_state.operational)
        printf("EL1008 DigIn: %soperational.\n", s.operational ? "" : "Not ");
    sc_dig_in_state = s;
}

/*****************************************************************************/

void cyclic_task() // lesen und schreiben der Prozessdaten
{
    // receive process data
    ecrt_master_receive(master);
    ecrt_domain_process(domain1);

    // check process data state
    check_domain1_state();

    if (counter) {
        counter--;
    } else { // do this at 1 Hz
        counter = FREQUENCY;

        // check for master state (optional)
        check_master_state();

        // check for slave configuration state(s) (optional)
        check_slaveDigIn_config_states();

        printf("."); //Lebenszeichen für Terminal
        fflush(stdout);
    }

    // read/write process data
    // dig_in
    uint8_t dig_in_value = EC_READ_U8(domain1_pd + off_dig_in);//& 0x0F;
    //uint8_t dig_in_value = EC_READ_BIT(domain1_pd + off_dig_in,1);
    static uint16_t dig_in_value_alt = -1;
    if (dig_in_value != dig_in_value_alt) {
        printf("dig_in_value = %u\n", dig_in_value);
        dig_in_value_alt = dig_in_value;
    }

    // send process data
    ecrt_domain_queue(domain1);
    ecrt_master_send(master);
}

/****************************************************************************/

void stack_prefault(void)
{
    unsigned char dummy[MAX_SAFE_STACK];
    memset(dummy, 0, MAX_SAFE_STACK);
}

/****************************************************************************/

int main(int argc, char **argv)
{
    ec_slave_config_t *sc;
    struct timespec wakeup_time;
    int ret = 0;

    master = ecrt_request_master(0);
    if (!master) {
        fprintf(stderr, "Unable to get requested master.\n");
        return -1;
    }

    domain1 = ecrt_master_create_domain(master);
    if (!domain1) {
        fprintf(stderr, "Unable to create process data domain.\n");
        return -1;
    }

    if (!(sc_dig_in = ecrt_master_slave_config(
                    master, DigInSlavePos, Beckhoff_EL1008))) {
        fprintf(stderr, "Failed to get slave configuration.\n");
        return -1;
    }

    printf("Configuring PDOs...\n");
    if (ecrt_slave_config_pdos(sc_dig_in, EC_END, slave_1_syncs)) {
        fprintf(stderr, "Failed to configure PDOs.\n");
        return -1;
    }

    // Create configuration for bus coupler
    sc = ecrt_master_slave_config(master, BusCouplerPos, Beckhoff_EK1100);
    if (!sc) {
        fprintf(stderr, "Failed to get EK1100 configuration.\n");
        return -1;
    }

    if (ecrt_domain_reg_pdo_entry_list(domain1, domain1_regs)) {
        fprintf(stderr, "PDO entry registration failed!\n");
        return -1;
    }

    printf("Activating master...\n");
    if (ecrt_master_activate(master)) {
        fprintf(stderr,"activation failed.\n");
        return -1;
    }
    printf("...ok!\n");

    if (!(domain1_pd = ecrt_domain_data(domain1))) {
        fprintf(stderr,"Domain data initialization failed.\n");
        return -1;
    }
    printf("Domain data registered ok.\n");

    /* Set priority */

    struct sched_param param = {};
    param.sched_priority = sched_get_priority_max(SCHED_FIFO);

    printf("Using priority %i.\n", param.sched_priority);
    if (sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
        perror("sched_setscheduler() failed\n");
    }

    /* Lock memory */
#if 1 // EXTERNAL_MEMORY
    // Möglichkeit 1
    if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
        fprintf(stderr, "Warning: Failed to lock memory: %s\n",
                strerror(errno));
    }
    stack_prefault();

    //Möglichkeit 2, siehe mini.c
//    unsigned int size;
//    if ((size = ecrt_domain_size(domain1))) {
//        if (!(domain1_pd = (uint8_t *) kmalloc(size, GFP_KERNEL))) {
//            printf("Failed to allocate %u bytes of process data"
//                    " memory!\n", size);
//           return -1;
//        }
//        ecrt_domain_external_memory(domain1, domain1_pd);
//    }
#endif

    printf("Starting RT task with dt = %u ms.\n", PERIOD_NS/1000000);

    clock_gettime(CLOCK_MONOTONIC, &wakeup_time);
    wakeup_time.tv_sec += 1; /*1=default, 0.1 start in future */
    wakeup_time.tv_nsec = 0;

    while (1) {
        ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME,
                &wakeup_time, NULL);
        if (ret) {
            fprintf(stderr, "clock_nanosleep(): %s\n", strerror(ret));
            break;
        }

        cyclic_task(); // wird alle PERIOD_NS aufgerufen

        wakeup_time.tv_nsec += PERIOD_NS;
        while (wakeup_time.tv_nsec >= NSEC_PER_SEC) {
            wakeup_time.tv_nsec -= NSEC_PER_SEC;
            wakeup_time.tv_sec++;
        }
    }
    printf("Ende While-Schleife.");

    return ret;
}

/****************************************************************************/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.etherlab.org/pipermail/etherlab-users/attachments/20181009/d868b4cf/attachment-0002.htm>


More information about the Etherlab-users mailing list