added sofwrtare for testing the hardware -> dependent of SOEM

main
Kynsight 4 weeks ago
parent f5be17275a
commit c452a91d02

@ -0,0 +1,55 @@
cmake_minimum_required(VERSION 3.10)
project(kyncat C)
# Set C standard
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
# Set output directory for the compiled binary
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}")
set(CMAKE_BINARY_DIRECTORY "${CMAKE_SOURCE_DIR}")
# SOEM Repository Info
set(SOEM_REPO "https://github.com/OpenEtherCATsociety/SOEM.git")
set(SOEM_PATH "${CMAKE_SOURCE_DIR}/SOEM")
# Check if SOEM exists, if not, clone it
if(NOT EXISTS ${SOEM_PATH}/CMakeLists.txt)
message(STATUS "SOEM not found! Cloning from ${SOEM_REPO}...")
execute_process(
COMMAND git clone --depth 1 ${SOEM_REPO} ${SOEM_PATH}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
RESULT_VARIABLE GIT_CLONE_RESULT
)
if(NOT GIT_CLONE_RESULT EQUAL 0)
message(FATAL_ERROR "Failed to clone SOEM repository!")
endif()
endif()
# Include SOEM as a subdirectory (it has its own CMakeLists.txt)
add_subdirectory(${SOEM_PATH})
# Include directories for SOEM
include_directories(
${SOEM_PATH}/soem
${SOEM_PATH}/osal
${SOEM_PATH}/osal/linux
${SOEM_PATH}/oshw/linux
)
# Define the source files for kyncat
set(SOURCES
main.c
slaveconfig.c
)
set(HEADERS
slaveconfig.h
)
# Create the executable and link against the SOEM static library
add_executable(kyncat ${SOURCES} ${HEADERS})
# Link SOEM library and required system libraries
target_link_libraries(kyncat soem pthread rt)

@ -0,0 +1,295 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "slaveconfig.h"
#include "ethercat.h"
#define EC_TIMEOUTMON 100
char IOmap[4096];
volatile int wkc;
OSAL_THREAD_HANDLE thread1;
int expectedWKC;
boolean needlf;
volatile int wkc;
uint8 currentgroup = 0;
/*!
* @brief Set the given Slave to given State
* @return 1 if No Error | 0 if Error
* */
uint8_t setSlaveState(uint8_t slave_index, uint16_t ethercat_state )
{
//printf("SET STATE: %s - Slave[%d] \n",ec_slave[slave_index].name, slave_index);
ec_slave[slave_index].state = ethercat_state;// ec_slave[0] refers to a special virtual slave that represents all slaves
ec_writestate(slave_index); // Same as above
ec_statecheck(slave_index, ethercat_state, EC_TIMEOUTSTATE);
if (ec_slave[slave_index].state == ethercat_state) {
{
// printf(" |- ");
// printState(ec_slave[slave_index].state);
}
return 1;
} else {
// printf(" |-> Failed\n");
return 0;
}
return 0;
}
/*
void searchForSlave()
{
for (int i = 1; i <= ec_slavecount; i++) {
if (strcmp(ec_slave[i].name, "EL2008") == 0) {
el2008_slave = i;
printf("Found EL2008 at slave %d.\n", i);
}
}
if (el2008_slave == -1) {
printf("EL2008 not found on the network.\n");
}
}
*/
void print_device_info() {
printf("--------------------------------------------------\n");
printf("EtherCAT Device Info Panel\n");
printf("--------------------------------------------------\n");
for (int i = 1; i <= ec_slavecount; i++) {
printf("Slave %d: %s\n", i, ec_slave[i].name);
printf(" Vendor ID: 0x%08X\n", ec_slave[i].eep_man);
printf(" Product Code: 0x%08X\n", ec_slave[i].eep_id);
printf(" Revision: 0x%08X\n", ec_slave[i].eep_rev);
printf(" ");
printState(ec_slave[i].state);
printf(" AL Status Code: 0x%04X\n", ec_slave[i].ALstatuscode);
// Print Process Data (PDOs)
printf(" Process Data:\n");
printf(" Inputs (%d bytes): ", ec_slave[i].Ibytes);
for (uint32_t j = 0; j < ec_slave[i].Ibytes; j++) {
printf("%02X ", ec_slave[i].inputs[j]);
}
printf("\n");
printf(" Outputs (%d bytes): ", ec_slave[i].Obytes);
for (uint32_t j = 0; j < ec_slave[i].Obytes; j++) {
printf("%02X ", ec_slave[i].outputs[j]);
}
printf("\n");
// Read available SDOs
printf(" SDO List:\n");
for (int sdo_index = 0x1000; sdo_index <= 0x1FFF; sdo_index++) {
uint32_t sdo_value;
int size = sizeof(sdo_value);
if (ec_SDOread(i, sdo_index, 0x00, FALSE, &size, &sdo_value, EC_TIMEOUTSAFE) > 0) {
printf(" Index 0x%04X: Value 0x%08X\n", sdo_index, sdo_value);
}
}
printf("--------------------------------------------------\n");
}
}
void setPin1Out()
{
uint8_t *outputs = (uint8_t *)ec_slave[3].outputs;
// Print current output state before modification
printf("Current output state: 0x%02X\n", outputs[0]);
// Set bit 0 (Channel 1 ON)
outputs[0] |= 1;
// Send process data to the slave
ec_send_processdata();
wkc = ec_receive_processdata(EC_TIMEOUTRET);
if (wkc >= expectedWKC) {
printf("Process data exchanged successfully.\n");
} else {
printf("Process data exchange failed. WKC: %d, expectedWKC: %d\n", wkc, expectedWKC);
}
// Print final output state
printf("Final output state: 0x%02X\n", outputs[0]);
// Print slave state and AL status code
printState(ec_slave[3].state);
}
/*!
* @brief Initialising Distributed Clocks. you should initialize Distributed Clocks (DC)
* after all slaves are configured and mapped,
* but before transitioning them to OPERATIONAL (EC_STATE_OPERATIONAL).
* @return 1 if No Error | 0 if Error
* */
uint8_t initDisributedClocks()
{
printf("Init Distributed Clocks\n");
if (ec_configdc()) {
printf(" |-> Succeeded \n");
return 1;
}else
{
printf(" |-> Failed \n");
return 0;
}
}
/*!
* @brief map process data objects (PDOs) of all detected EtherCAT slaves into a single memory buffer (IOmap).
* and groupe them into group[0] This will be important for the Slaves state intitalisation phase.
* @return 1 if No Error | 0 if Error
* */
uint8_t mapSlavesGrouped()
{
printf("Mapping Slaves\n");
if(ec_config_map(&IOmap)){
printf(" |-> Succeeded \n");
for (uint8_t i = 1; i <= ec_slavecount; i++) {
printf(" |-> (%s) - ",ec_slave[i].name);
printState(ec_slave[i].state);
}
return 1;
}else
{
printf(" |-> Failed \n");
return 0;
}
}
/*!
* @brief Enumerate and init all slaves.>
* @return 1 if No Error | 0 if Error
* */
uint8_t enumerateSlaves()
{
printf("Detection and enumeration \n");
if (ec_config_init(FALSE) > 0) {
printf(" |-> Succeeded \n");
printf(" |-> Slave Count: %d \n",ec_slavecount);
return 1;
}else
{
printf(" |-> Failed \n");
return 0;
}
}
/*!
* @brief Initialising network atapter for communication with slaves
* @param char *Ifname is the interface name
* @return 1 if No Error | 0 if Error
* */
uint8_t initNetworkAdapterSingle(char *ifname)
{
printf("Init Network Interface < %s >\n", ifname);
if (ec_init(ifname)) {
printf(" |-> Succeeded \n");
return 1;
}else
{
printf(" |-> Failed \n");
return 0;
}
}
void dataLoop()
{
ec_send_processdata();
wkc = ec_receive_processdata(EC_TIMEOUTRET);
if(wkc >= expectedWKC)
{
}
osal_usleep(5000);
}
int main(int argc, char *argv[]) {
if (argc > 1) {
// Init Network adapter
if(!initNetworkAdapterSingle(argv[1])){
printf("Unable to Initiate Network Adapter -> Quitting");
ec_close();
return 0;
}
if(!enumerateSlaves()){
printf("Unable to Enumerate Slaves -> Quitting");
ec_close();
return 0;
}
if(!mapSlavesGrouped()){
printf("Unable to Map Slaves -> Quitting");
ec_close();
return 0;
}
expectedWKC = (ec_group[0].outputsWKC * 2) + ec_group[0].inputsWKC;
printf("Calculated workcounter %d\n", expectedWKC);
if(!initDisributedClocks()){
printf("Unable to Initialise Distributed Clocks -> Quitting");
ec_close();
return 0;
}
for (uint8_t i = 1; i <= ec_slavecount; i++) {
printf("-----------------------------------------------------------------------\n");
print_device_info();
printf("-----------------------------------------------------------------------\n");
if(!setSlaveState(1,EC_STATE_INIT)){
printf("Unable chnage Slave mode -> Quitting");
ec_close();
return 0;
}
if(!setSlaveState(i,EC_STATE_PRE_OP)){
printf("Unable chnage Slave mode -> Quitting");
ec_close();
return 0;
}
if(!setSlaveState(i,EC_STATE_SAFE_OP)){
printf("Unable chnage Slave mode -> Quitting");
ec_close();
return 0;
}
if(!setSlaveState(i,EC_STATE_OPERATIONAL)){
printf("Unable chnage Slave mode -> Quitting");
ec_close();
}
printf("-----------------------------------------------------------------------\n");
}
setPin1Out();
for(uint16_t j = 0; j < 10000; j++)
{
ec_send_processdata();
wkc = ec_receive_processdata(EC_TIMEOUTRET);
if (wkc >= expectedWKC) {
} else {
printf("Process data exchange failed. WKC: %d, expectedWKC: %d\n", wkc, expectedWKC);
}
usleep(100);
}
ec_close();
} else {
printf("Usage : sudo %s <network interface name> need to be passed\n", argv[0]);
printf("Example : sudo %s eth0 \n", argv[0]);
}
return 0;
}

@ -0,0 +1,40 @@
#include "slaveconfig.h"
#include <stdio.h>
/*!
* @brief Prints the state in which the Slave is and also give basic infomations about that state.
* @param uint16_t state is the state flag of the slave which will be masked to ist 8 LSB's
* @link https://infosys.beckhoff.com/english.php?content=../content/1033/ethercatsystem/1036980875.html&id=
* @return void
* */
void printState(uint16_t state)
{
uint8_t state_masked = state & 0x0F; // Mask first byte
switch (state_masked) {
case EC_STATE_INIT:
printf("State: INIT (0x%02X) - No communication yet.\n", state_masked);
break;
case EC_STATE_PRE_OP:
printf("State: PRE-OP (0x%02X) - Configuration possible.\n", state_masked);
break;
case EC_STATE_SAFE_OP:
printf("State: SAFE-OP (0x%02X) - Inputs work, outputs disabled.\n", state_masked);
break;
case EC_STATE_OPERATIONAL:
printf("State: OPERATIONAL (0x%02X) - Fully active.\n", state_masked);
break;
case EC_STATE_BOOT:
printf("State: BOOTSTRAP (0x%02X) - Firmware update mode.\n", state_masked);
break;
default:
printf("State: UNKNOWN STATE (0x%02X)\n", state_masked);
break;
}
}

@ -0,0 +1,30 @@
/*
* Licensed under the GNU General Public License version 2 with exceptions. See
* LICENSE file in the project root for full license information
*/
/** \file
* \brief
* Headerfile for ethercatbase.c
*/
#ifndef _slave_config_
#define _slave_config_
#include "ethercat.h"
/*!
* @brief Prints the state in which the Slave is and also give basic infomations about that state.
* @param uint16_t state is the state flag of the slave which will be masked to ist 8 LSB's
* @link https://infosys.beckhoff.com/english.php?content=../content/1033/ethercatsystem/1036980875.html&id=
* @return void
* */
void printState(uint16_t state);
/*!
* @brief Set the given Slave to given State
* @return 1 if No Error | 0 if Error
* */
//uint8_t setSlaveState(uint8_t slave_index, uint16_t ethercat_state);
#endif
Loading…
Cancel
Save