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

El3314 Driver #121

Merged
merged 4 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
# swap files
*.swp
*.swo

*.swn
*.swb

# Ignore folders
build
Expand All @@ -17,4 +18,4 @@ bin
.doxyfile

# clang-format
.clang-format
.clang-format
29 changes: 17 additions & 12 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,32 @@ add_library(jsd-lib STATIC
jsd_common_device_types.c
jsd_elmo_common.c
jsd_epd_common.c
jsd_timer.c

# Devices
jsd_el3602.c
jsd_el3208.c
jsd_el2124.c
jsd_el2809.c
jsd_egd.c
jsd_el3356.c
jsd_jed0101.c
jsd_jed0200.c
jsd_timer.c
jsd_epd_nominal.c
jsd_epd_sil.c

jsd_ati_fts.c
jsd_el3104.c

jsd_el1008.c
jsd_el2124.c
jsd_el2809.c
jsd_el3104.c
jsd_el3162.c
jsd_el3202.c
jsd_el3208.c
jsd_el3314.c
jsd_el3318.c
jsd_el3162.c
jsd_el3356.c
jsd_el3602.c
jsd_el4102.c

jsd_ild1900.c
jsd_epd_nominal.c
jsd_epd_sil.c

jsd_jed0101.c
jsd_jed0200.c
)

message(STATUS "SOEM INCLUDE DIRS: ${SOEM_INCLUDE_DIRS}")
Expand Down
9 changes: 9 additions & 0 deletions src/jsd.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "jsd/jsd_el3162.h"
#include "jsd/jsd_el3202.h"
#include "jsd/jsd_el3208.h"
#include "jsd/jsd_el3314.h"
#include "jsd/jsd_el3318.h"
#include "jsd/jsd_el3356.h"
#include "jsd/jsd_el3602.h"
Expand Down Expand Up @@ -468,6 +469,8 @@ const char* jsd_driver_type_to_string(jsd_driver_type_t driver_type) {
return "JSD_DRIVER_TYPE_EL3202";
case JSD_DRIVER_TYPE_EL3208:
return "JSD_DRIVER_TYPE_EL3208";
case JSD_DRIVER_TYPE_EL3314:
return "JSD_DRIVER_TYPE_EL3314";
case JSD_DRIVER_TYPE_EL3318:
return "JSD_DRIVER_TYPE_EL3318";
case JSD_DRIVER_TYPE_EL3356:
Expand Down Expand Up @@ -587,6 +590,9 @@ bool jsd_driver_is_compatible_with_product_code(jsd_driver_type_t driver_type,
case JSD_DRIVER_TYPE_EL3202:
is_compatible = jsd_el3202_product_code_is_compatible(product_code);
break;
case JSD_DRIVER_TYPE_EL3314:
is_compatible = jsd_el3314_product_code_is_compatible(product_code);
break;
case JSD_DRIVER_TYPE_EL3318:
is_compatible = jsd_el3318_product_code_is_compatible(product_code);
break;
Expand Down Expand Up @@ -654,6 +660,9 @@ bool jsd_init_single_device(jsd_t* self, uint16_t slave_id) {
case JSD_DRIVER_TYPE_EL3104:
return jsd_el3104_init(self, slave_id);
break;
case JSD_DRIVER_TYPE_EL3314:
return jsd_el3314_init(self, slave_id);
break;
case JSD_DRIVER_TYPE_EL3318:
return jsd_el3318_init(self, slave_id);
break;
Expand Down
167 changes: 167 additions & 0 deletions src/jsd_el3314.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
#include "jsd/jsd_el3314.h"

#include <assert.h>
#include <string.h>

#include "jsd/jsd_sdo.h"

const char* jsd_el3314_element_strings[] = {
[JSD_EL3314_ELEMENT_TYPE_K] = "TYPE_K",
[JSD_EL3314_ELEMENT_TYPE_J] = "TYPE_J",
[JSD_EL3314_ELEMENT_TYPE_L] = "TYPE_L",
[JSD_EL3314_ELEMENT_TYPE_E] = "TYPE_E",
[JSD_EL3314_ELEMENT_TYPE_T] = "TYPE_T",
[JSD_EL3314_ELEMENT_TYPE_N] = "TYPE_N",
[JSD_EL3314_ELEMENT_TYPE_U] = "TYPE_U",
[JSD_EL3314_ELEMENT_TYPE_B] = "TYPE_B",
[JSD_EL3314_ELEMENT_TYPE_R] = "TYPE_R",
[JSD_EL3314_ELEMENT_TYPE_S] = "TYPE_S",
[JSD_EL3314_ELEMENT_TYPE_C] = "TYPE_C",
};

const char* jsd_el3314_presentation_strings[] = {
[JSD_EL3314_PRESENTATION_SIGNED] = "Signed",
[1] = "unused presentation",
[JSD_EL3314_PRESENTATION_HIGH_RES] = "High Res",
};

/****************************************************
* Public functions
****************************************************/
const jsd_el3314_state_t* jsd_el3314_get_state(jsd_t* self, uint16_t slave_id) {
assert(self);
assert(jsd_el3314_product_code_is_compatible(
self->ecx_context.slavelist[slave_id].eep_id));

return &self->slave_states[slave_id].el3314;
}

void jsd_el3314_read(jsd_t* self, uint16_t slave_id) {
assert(self);
assert(jsd_el3314_product_code_is_compatible(
self->ecx_context.slavelist[slave_id].eep_id));

jsd_el3314_state_t* state = &self->slave_states[slave_id].el3314;
jsd_el3314_config_t* config = &self->slave_configs[slave_id].el3314;

jsd_el3314_txpdo_t* txpdo =
(jsd_el3314_txpdo_t*)self->ecx_context.slavelist[slave_id].inputs;

int ch;
for (ch = 0; ch < JSD_EL3314_NUM_CHANNELS; ch++) {
state->adc_value[ch] = txpdo->channel[ch].value;
state->output_eu[ch] =
jsd_el3314_output_from_config(txpdo->channel[ch].value, config, ch);

state->underrange[ch] = (txpdo->channel[ch].flags >> 0) & 0x01;
state->overrange[ch] = (txpdo->channel[ch].flags >> 1) & 0x01;
state->error[ch] = (txpdo->channel[ch].flags >> 6) & 0x01;
state->txPDO_state[ch] = (txpdo->channel[ch].flags >> 14) & 0x01;
state->txPDO_toggle[ch] = (txpdo->channel[ch].flags >> 15) & 0x01;
}
}

/****************************************************
* Private functions
****************************************************/

bool jsd_el3314_init(jsd_t* self, uint16_t slave_id) {
assert(self);
assert(jsd_el3314_product_code_is_compatible(
self->ecx_context.slavelist[slave_id].eep_id));
assert(self->ecx_context.slavelist[slave_id].eep_man ==
JSD_BECKHOFF_VENDOR_ID);

ec_slavet* slaves = self->ecx_context.slavelist;
ec_slavet* slave = &slaves[slave_id];

slave->PO2SOconfigx = jsd_el3314_PO2SO_config;

return true;
}

int jsd_el3314_PO2SO_config(ecx_contextt* ecx_context, uint16_t slave_id) {
assert(ecx_context);
assert(jsd_el3314_product_code_is_compatible(
ecx_context->slavelist[slave_id].eep_id));

// cast the void* to slave_config
jsd_slave_config_t* slave_configs =
(jsd_slave_config_t*)ecx_context->userdata;

jsd_slave_config_t* config = &slave_configs[slave_id];

// Reset to factory default
uint32_t reset_word = JSD_BECKHOFF_RESET_WORD;
if (!jsd_sdo_set_param_blocking(ecx_context, slave_id, JSD_BECKHOFF_RESET_SDO,
JSD_BECKHOFF_RESET_SUBIND, JSD_SDO_DATA_U32,
&reset_word)) {
return 0;
}

MSG("Configuring slave no: %u, SII inferred name: %s", slave_id,
ecx_context->slavelist[slave_id].name);
MSG("\t Configured name: %s", config->name);

int ch;
for (ch = 0; ch < JSD_EL3314_NUM_CHANNELS; ch++) {
MSG("\t Ch%d Config:", ch);
MSG("\t\tElement: %s",
jsd_el3314_element_strings[config->el3314.element[ch]]);
MSG("\t\tFilter: %s",
jsd_beckhoff_filter_strings[config->el3314.filter[ch]]);
MSG("\t\tPresentation: %s",
jsd_el3314_presentation_strings[config->el3314.presentation[ch]]);

// register is 0x80n0, where n is channel number (e.g. ch4 = 0x8040)
uint32_t sdo_channel_index = 0x8000 + (0x10 * ch);

uint16_t element = config->el3314.element[ch];
if (!jsd_sdo_set_param_blocking(ecx_context, slave_id, sdo_channel_index,
0x19, JSD_SDO_DATA_U16, &element)) {
return 0;
}

uint16_t filter = config->el3314.filter[ch];
if (!jsd_sdo_set_param_blocking(ecx_context, slave_id, sdo_channel_index,
0x15, JSD_SDO_DATA_U16, &filter)) {
return 0;
}

uint8_t presentation = config->el3314.presentation[ch];
if (!jsd_sdo_set_param_blocking(ecx_context, slave_id, sdo_channel_index,
0x02, JSD_SDO_DATA_U8, &presentation)) {
return 0;
}
}

config->PO2SO_success = true;
return 1;
}

double jsd_el3314_output_from_config(int16_t adc_value,
jsd_el3314_config_t* config,
uint16_t channel) {
assert(config->presentation[channel] < JSD_EL3314_NUM_PRESENTATIONS);
assert(config->element[channel] < JSD_EL3314_NUM_ELEMENTS);

double temp_scale_factor = 1;

switch (config->presentation[channel]) {
case JSD_EL3314_PRESENTATION_SIGNED:
temp_scale_factor = 0.1;
break;
case JSD_EL3314_PRESENTATION_HIGH_RES:
temp_scale_factor = 0.01;
break;
default:
WARNING("Bad/Unsupported presentation setting");
break;
}

return (double)adc_value * temp_scale_factor;
}

bool jsd_el3314_product_code_is_compatible(uint32_t product_code) {
return product_code == JSD_EL3314_PRODUCT_CODE;
}
63 changes: 63 additions & 0 deletions src/jsd_el3314.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#ifndef JSD_EL3314_H
#define JSD_EL3314_H

#ifdef __cplusplus
extern "C" {
#endif

#include "jsd/jsd_el3314_pub.h"

/**
* @brief Private IOmap channel struct used to retreive input data from SOEM
* IOmap
*/
typedef struct __attribute__((__packed__)) {
uint16_t flags;
int16_t value;
} jsd_el3314_channel_txpdo_t;

/**
* @brief Private IOmap struct used to retreive input data from SOEM IOmap
*/
typedef struct __attribute__((__packed__)) {
jsd_el3314_channel_txpdo_t channel[JSD_EL3314_NUM_CHANNELS];
} jsd_el3314_txpdo_t;

/** @brief Initializes el3314 and registers the PO2SO function
*
* @param self pointer JSD context
* @param slave_id index of device on EtherCAT bus
* @return true on success, false on failure
*/
bool jsd_el3314_init(jsd_t* self, uint16_t slave_id);

/**
* @brief Configuration function called by SOEM upon a PreOp to SafeOp state
* transition that (re)configures el3314 device settings
*
* @param ecx_context SOEM context pointer
* @param slave_id index of device on EtherCAT bus
* @return 1 on success, 0 on failure
*/
int jsd_el3314_PO2SO_config(ecx_contextt* ecx_context, uint16_t slave_id);

/**
* @brief Computes the state output_eu field using device config
*/
double jsd_el3314_output_from_config(int16_t adc_value,
jsd_el3314_config_t* config,
uint16_t channel);

/**
* @brief Checks whether a product code is compatible with EL3314.
*
* @param product_code The product code to be checked
* @return True if the product code is compatible, false otherwise.
*/
bool jsd_el3314_product_code_is_compatible(uint32_t product_code);

#ifdef __cplusplus
}
#endif

#endif
31 changes: 31 additions & 0 deletions src/jsd_el3314_pub.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#ifndef JSD_EL3314_PUB_H
#define JSD_EL3314_PUB_H

#ifdef __cplusplus
extern "C" {
#endif

#include "jsd/jsd_pub.h"

/**
* @brief Reads EL3314 state
*
* @param self Pointer to JSD context
* @param slave_id id of EL3314 device
* @return Pointer to EL3314 state
*/
const jsd_el3314_state_t* jsd_el3314_get_state(jsd_t* self, uint16_t slave_id);

/**
* @brief Converts raw PDO data to state data
*
* @param self pointer to JSD context
* @param slave_id id of EL3314 device
*/
void jsd_el3314_read(jsd_t* self, uint16_t slave_id);

#ifdef __cplusplus
}
#endif

#endif
Loading
Loading