OpenEtherCATsociety / SOEM

Simple Open Source EtherCAT Master
Other
1.35k stars 685 forks source link

Regarding IO Mapping like Sycon.net Utility #861

Open ANANTH5354 opened 1 month ago

ANANTH5354 commented 1 month ago

Hello all, I hope you all doing well !

SOEM master code I am here compiled like (slaveinfo fun and simple test ) it working well.

======================================================================== Slaveinfo Starting slaveinfo ecinit on \Device\NPF{F4271784-7547-493D-8A78-8EBAC65E2F75} succeeded. 5 slaves found and configured. Calculated workcounter 7

Slave:1 Name:EK1100 Output size: 0bits Input size: 0bits State: 4 Delay: 0[ns] Has DC: 1 DCParentport:0

Slave:2 Name:EL3602 Output size: 0bits Input size: 96bits State: 4 Delay: 140[ns] Has DC: 1 DCParentport:1

Slave:3 Name:EL5152 Output size: 96bits Input size: 160bits State: 4 Delay: 285[ns] Has DC: 1 DCParentport:1

IOmap mapped successfully. End slaveinfo, close socket End program

Slave info

Here, I want to construct the slave configuration channels (AI, AO, DI, ,DO and Data Address, Data Length) and the code address table (IO mapping) (e.g., Sycon.net utility Address table). Would you please help me, anyone?

final output like that I want here, Address table PMX.zip

Thank you

ArthurKetels commented 1 month ago

Try : simple_test [network name] -map

ANANTH5354 commented 1 month ago

Okay.. I will check !!!

Could you provide me with some suggestions on how to formulate my questions.

Thank you

ANANTH5354 commented 1 month ago

Hello,

Here is the problem I'm having. I've tried using different logic, but I'm having trouble getting the address table to look like this: input data address, length data address, and output data address. This is a problem for me—the input address appears, but the exit address is hidden. Why?

the this my output:

Screenshot (22)

my code :

include

include

include

include

// OSAL threading and other necessary declarations OSAL_THREAD_HANDLE thread1; int expectedWKC; bool needlf; volatile int wkc; volatile int rtcnt; bool inOP; uint8_t currentgroup = 0;

include

include

include

include "ethercat.h" // Include your EtherCAT library header

// Global addresses for input and output uint32_t global_input_address = 0x0001; // Initialize starting input address uint32_t global_output_address = 0x1000; // Initialize starting output address //const char* outputFilePath = "C:/Users/ananth.kumaravel/Desktop/Address_Table_EMaster/Address_Table.csv"; // Specify the output file path

define MAX_SLAVES 64 // Maximum number of slaves

define OUTPUT_FILE_PATH "output.csv" // Set your output file path

typedef struct { int type; // 1: AI, 2: AO, 3: DI, 4: DO unsigned int address; // Address for both input and output int length; // Length for input or output } ChannelInfo;

// Function to identify channel types (AI, AO, DI, DO) int identify_channel_type(const char* slave_name, int channel_index) { // Example logic, replace with actual identification logic based on your hardware if (channel_index < 8) { // Assume first 8 are AI and the next are DI return (slave_name[0] == 'E') ? 1 : 3; // AI if slave name starts with 'E', else DI } else { return (slave_name[0] == 'E') ? 2 : 4; // AO if slave name starts with 'E', else DO } }

void get_channel_data_info(int slave, int channel_index, ChannelInfo channel_info, const char slave_name) { // Identify the channel type channel_info->type = identify_channel_type(slave_name, channel_index);

// Assign input or output address based on the channel type
if (channel_info->type == 1 || channel_info->type == 3) {  // AI or DI (Input channels)
    channel_info->address = global_input_address;
    global_input_address += (channel_info->type == 1) ? 8 : 2; // 8 bytes for AI, 2 bytes for DI
}
else if (channel_info->type == 2 || channel_info->type == 4) {  // AO or DO (Output channels)
    channel_info->address = global_output_address;
    global_output_address += (channel_info->type == 2) ? 8 : 4; // 8 bytes for AO, 4 bytes for DO
}

// Assign the length based on the channel type
channel_info->length = (channel_info->type == 1) ? 8 :
    (channel_info->type == 2) ? 8 :
    (channel_info->type == 3) ? 2 :
    (channel_info->type == 4) ? 4 : 0;

// Set addresses and lengths for channels that do not support them
if (channel_info->type == 4) { // DO channel
    channel_info->address = 0; // Set address to 0 for DO
    channel_info->length = 0;   // Set length to 0 for DO
}

}

void slaveinfo(char* ifname) { int cnt, total_slaves = 0; printf("Starting slaveinfo\n");

if (ec_init(ifname)) {
    printf("ec_init on %s succeeded.\n", ifname);
    if (ec_config(FALSE, &IOmap) > 0) {
        ec_configdc();
        total_slaves = ec_slavecount;  // Count total slaves
        printf("%d slaves found and configured.\n", total_slaves);

        // Open the CSV file for writing
        FILE* file;
        int result = fopen_s(&file, OUTPUT_FILE_PATH, "w");
        if (result != 0) {
            perror("Error opening file");
            return;
        }

        // Write headers in CSV file for both input and output side
        fprintf(file, "Slave Name, Station Address, Channel Name, Channel Type, Input Address, Input Length, Output Address, Output Length\n");

        // Iterate over each slave
        for (cnt = 1; cnt <= total_slaves; cnt++) {
            printf("Slave %d: %s\n", cnt, ec_slave[cnt].name);
            printf("Station Address 0x%04X\n", ec_slave[cnt].configadr);

            int slave_channels = 0; // Reset channel count for this slave

            // Determine the number of channels for the slave based on its type
            if (strstr(ec_slave[cnt].name, "EL2809") != NULL)
                slave_channels = 16; // 16 DO channels
            else if (strstr(ec_slave[cnt].name, "EL5152") != NULL)
                slave_channels = 2;  // 2 DI channels
            else if (strstr(ec_slave[cnt].name, "EL3602") != NULL)
                slave_channels = 2;  // 2 AI channels
            else if (strstr(ec_slave[cnt].name, "EL9512") != NULL)
                slave_channels = 4;  // 4 AO channels
            else if (strstr(ec_slave[cnt].name, "EL3356") != NULL)
                slave_channels = 1;  // 1 AI channel
            else if (strstr(ec_slave[cnt].name, "EK1100") != NULL)
                slave_channels = 0;  // EK1100 has no channels
            else if (strstr(ec_slave[cnt].name, "EL1809") != NULL)
                slave_channels = 16; // 16 DI channels
            else if (strstr(ec_slave[cnt].name, "EL4134") != NULL)
                slave_channels = 4;  // 4 AO channels
            else
                slave_channels = 0;  // Unknown number of channels

            // Iterate over each channel for the slave
            for (int channel_index = 0; channel_index < slave_channels; channel_index++) {
                ChannelInfo channel_info;
                get_channel_data_info(cnt, channel_index, &channel_info, ec_slave[cnt].name);

                // Prepare channel name based on the channel index
                char channel_name[50];
                snprintf(channel_name, sizeof(channel_name), "ch%d.%d", cnt, channel_index + 1);

                // Determine input and output addresses/lengths
                uint32_t input_address = (channel_info.type == 1 || channel_info.type == 3) ? channel_info.address : 0;
                int input_length = (channel_info.type == 1 || channel_info.type == 3) ? channel_info.length : 0;
                uint32_t output_address = (channel_info.type == 2 || channel_info.type == 4) ? channel_info.address : 0;
                int output_length = (channel_info.type == 2 || channel_info.type == 4) ? channel_info.length : 0;

                // Write channel information to the CSV file
                fprintf(file, "%s,0x%04X,%s,%s,0x%04X,%d,0x%04X,%d\n",
                    ec_slave[cnt].name,
                    ec_slave[cnt].configadr,
                    channel_name,
                    channel_info.type == 1 ? "AI" :
                    channel_info.type == 2 ? "AO" :
                    channel_info.type == 3 ? "DI" :
                    channel_info.type == 4 ? "DO" : "Unknown",
                    input_address,
                    input_length,
                    output_address,
                    output_length);

                // Print the channel information to the console
                printf("Channel Name: %s, Channel Type: %s, Input Address: 0x%04X, Input Length: %d bytes, Output Address: 0x%04X, Output Length: %d bytes\n",
                    channel_name,
                    channel_info.type == 1 ? "AI" :
                    channel_info.type == 2 ? "AO" :
                    channel_info.type == 3 ? "DI" :
                    channel_info.type == 4 ? "DO" : "Unknown",
                    input_address,
                    input_length,
                    output_address,
                    output_length);
            }
        }

        fclose(file);
        printf("\nFile created at: %s\n", OUTPUT_FILE_PATH);
    }
    else {
        printf("No slaves found!\n");
    }
    printf("End slaveinfo, close socket\n");
    ec_close();
}

}

===========================================================

thank you

ANANTH5354 commented 1 month ago

And soem.lib visual studio 2022 version Release mode only perform well but Debug mode not performing like linker error shows how to fix this issue!!! Screenshot (23)

Thank you