From fcaec82fa886d4df0e4afa16bc3867615d6795de Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Mon, 9 May 2022 14:20:20 +0100 Subject: [PATCH 1/4] modifications to encoder module - encoder can now be enabled without module dependencies - moved additional encoder callbacks to module (via listeners) - added RPM example in BESC spindle - fixed module send_pins_states default handler --- CHANGELOG.md | 2 ++ uCNC/cnc_hal_config.h | 19 ++++++++---- uCNC/src/cnc_hal_config_helper.h | 11 +++++++ uCNC/src/core/io_control.c | 2 +- uCNC/src/hal/boards/avr/boardmap_ramps14.h | 5 ++++ uCNC/src/hal/tools/tools/spindle_besc.c | 34 ++++++++++++++++++++++ uCNC/src/module.c | 10 ++++++- uCNC/src/modules/encoder.c | 21 ++++++++----- 8 files changed, 89 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e9e8a99c1..dc2268976 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,8 @@ - improved BESC spindle control with added default values for throttle down, neutral and full positions (#200) - improved BESC value range calculation (#202) - modified tool speed feedback. Each tool reports speed directly and can customize the way the speed is reported (#203) +- simplified Encoder module. Can be enabled without extra modules +- added BESC RPM counter based on Encoder module ### Fixed diff --git a/uCNC/cnc_hal_config.h b/uCNC/cnc_hal_config.h index e13f51345..1c245acd3 100644 --- a/uCNC/cnc_hal_config.h +++ b/uCNC/cnc_hal_config.h @@ -110,22 +110,31 @@ extern "C" #define LED DOUT31 -// these modules must be enabled to use encoders -#if defined(ENABLE_IO_MODULES) && defined(ENABLE_INTERPOLATOR_MODULES) && defined(ENABLE_MAIN_LOOP_MODULES) && (defined(ENABLE_PROTOCOL_MODULES) || !defined(ENABLE_EXTRA_SYSTEM_CMDS)) /* Sets the number of encoders to be used (max of 8) */ #define ENCODERS 0 - /** * To use the encoder counter 2 definitions are needed * ENCx_PULSE -> must be set to an input PIN with interrupt on change enabled capabilities * ENCx_DIR -> a regular input PIN that detects the direction of the encoding step * Defined encoders must match the number of encoders and numeral defined above. * For example if ENCODERS is set to 2 it expects to find the definitions for ENC0 and ENC1. Number skipping is not allowed (exemple Set ENC0 and ENC2 but not ENC1) + * + * It's also possible to assing an encoder to a stepper motor by defining the STEPx_ENCODER and the encoder index like this + * #define STEP0_ENCODER 0 //assigns encoder 0 to stepper 0 + * + * The encoder can work as a simple counter (used in speed encoders) by setting the same HAL pin for both PULSE and DIR functions - Counter mode + * + * For encoders to work as STEP encoders ENABLE_INTERPOLATOR_MODULES and ENABLE_MAIN_LOOP_MODULES must be enabled * */ -// #define ENC0_PULSE DIN0 -// #define ENC0_DIR DIN8 +#if ENCODERS > 0 +// Counter mode +#define ENC0_PULSE DIN0 +#define ENC0_DIR DIN0 +// Encoder mode +// #define ENC1_PULSE DIN1 +// #define ENC1_DIR DIN8 #endif // these modules must be enabled to use pid diff --git a/uCNC/src/cnc_hal_config_helper.h b/uCNC/src/cnc_hal_config_helper.h index 479243866..1b41e967d 100644 --- a/uCNC/src/cnc_hal_config_helper.h +++ b/uCNC/src/cnc_hal_config_helper.h @@ -131,6 +131,17 @@ extern "C" #define ENCODERS 0 #endif +#if ENCODERS > 0 +#if (defined(STEP0_ENCODER) || defined(STEP1_ENCODER) || defined(STEP2_ENCODER) || defined(STEP3_ENCODER) || defined(STEP4_ENCODER) || defined(STEP5_ENCODER)) +#if (!defined(ENABLE_INTERPOLATOR_MODULES) || !defined(ENABLE_MAIN_LOOP_MODULES)) +#error "Stepper encoders require ENABLE_INTERPOLATOR_MODULES and ENABLE_MAIN_LOOP_MODULES to be enabled" +#endif +#endif +#if defined(ENABLE_IO_MODULES) +#warning "Encoder module is enable. Generic input change event will not be available" +#endif +#endif + #ifndef PID_CONTROLLERS #define PID_CONTROLLERS 0 #endif diff --git a/uCNC/src/core/io_control.c b/uCNC/src/core/io_control.c index 172bc98a1..3fd274460 100644 --- a/uCNC/src/core/io_control.c +++ b/uCNC/src/core/io_control.c @@ -151,7 +151,7 @@ void mcu_probe_changed_cb(void) void __attribute__((weak)) mcu_inputs_changed_cb(void) { #ifdef ENABLE_IO_MODULES - void mod_input_change_hook(void); + mod_input_change_hook(void); #endif } diff --git a/uCNC/src/hal/boards/avr/boardmap_ramps14.h b/uCNC/src/hal/boards/avr/boardmap_ramps14.h index e04f11f56..b3ba1bf58 100644 --- a/uCNC/src/hal/boards/avr/boardmap_ramps14.h +++ b/uCNC/src/hal/boards/avr/boardmap_ramps14.h @@ -167,6 +167,11 @@ extern "C" #define SERVO3_BIT 5 #define SERVO3_PORT B + // SERVO3 pin supports ISR and can be used as an encoder/counter + // #define DIN0_BIT 5 + // #define DIN0_PORT B + // #define DIN0_ISR 0 + #ifdef __cplusplus } #endif diff --git a/uCNC/src/hal/tools/tools/spindle_besc.c b/uCNC/src/hal/tools/tools/spindle_besc.c index 00467b6c9..0327be3f7 100644 --- a/uCNC/src/hal/tools/tools/spindle_besc.c +++ b/uCNC/src/hal/tools/tools/spindle_besc.c @@ -37,6 +37,11 @@ #define THROTTLE_FULL 255 #define THROTTLE_RANGE (THROTTLE_FULL - THROTTLE_DOWN) +// #define HAS_RPM_COUNTER +#ifdef HAS_RPM_COUNTER +#define RPM_ENCODER 0 +#endif + static uint8_t spindle_speed; void spindle_besc_startup() @@ -91,7 +96,36 @@ void spindle_besc_set_coolant(uint8_t value) uint16_t spindle_besc_get_speed(void) { + + // this show how to use an encoder (in this case encoder 0) configured as a counter + // to take real RPM readings of the spindle + // the reading is updated every 5 seconds + +#if (defined(HAS_RPM_COUNTER) && (ENCODERS > RPM_ENCODER)) + extern int32_t encoder_get_position(uint8_t i); + extern void encoder_reset_position(uint8_t i, int32_t position); + static uint32_t last_time = 0; + static uint16_t lastrpm = 0; + uint16_t rpm = lastrpm; + uint32_t current_time = mcu_millis(); + + uint32_t elapsed = (current_time - last_time); + + // updates speed read every 5s + if (elapsed > 5000) + { + float timefact = 60000.f / (float)elapsed; + float newrpm = timefact * (float)encoder_get_position(0); + last_time = current_time; + encoder_reset_position(0, 0); + rpm = (uint16_t)newrpm; + lastrpm = rpm; + } + + return rpm; +#else return spindle_speed; +#endif } const tool_t __rom__ spindle_besc = { diff --git a/uCNC/src/module.c b/uCNC/src/module.c index fd58c95e9..772389e25 100644 --- a/uCNC/src/module.c +++ b/uCNC/src/module.c @@ -128,7 +128,7 @@ WEAK_HOOK(send_pins_states) { // for now only encoder module uses this hook and overrides it // it actually overrides the mcu callback to be faster - DEFAULT_HANDLER(input_change); + DEFAULT_HANDLER(send_pins_states); } #endif @@ -227,8 +227,16 @@ void mod_init(void) #endif #if ENCODERS > 0 +#ifdef ENABLE_INTERPOLATOR_MODULES + ADD_LISTENER(itp_reset_rt_position_delegate, encoders_itp_reset_rt_position, itp_reset_rt_position_event); +#endif +#ifdef ENABLE_MAIN_LOOP_MODULES ADD_LISTENER(cnc_reset_delegate, encoders_reset_position, cnc_reset_event); #endif +#ifdef ENABLE_PROTOCOL_MODULES + ADD_LISTENER(send_pins_states_delegate, encoder_print_values, send_pins_states_event); +#endif +#endif #ifdef ENABLE_TMC_DRIVERS extern void tmcdrivers_init(void); diff --git a/uCNC/src/modules/encoder.c b/uCNC/src/modules/encoder.c index 3a1d715ec..d132013c3 100644 --- a/uCNC/src/modules/encoder.c +++ b/uCNC/src/modules/encoder.c @@ -230,9 +230,11 @@ int32_t encoder_get_position(uint8_t i) { return encoders_pos[i]; } + + return 0; } -void mod_send_pins_states_hook(void) +void encoder_print_values(void) { for (uint8_t i = 0; i < ENCODERS; i++) { @@ -242,6 +244,8 @@ void mod_send_pins_states_hook(void) } } +CREATE_LISTENER(send_pins_states_delegate, encoder_print_values); + void encoder_reset_position(uint8_t i, int32_t position) { __ATOMIC__ @@ -261,16 +265,13 @@ void encoders_reset_position(void) } } -// overrides the default mod_cnc_reset_hook -// may be modified in the future -void mod_cnc_reset_hook(void) -{ - encoders_reset_position(); -} +#ifdef ENABLE_MAIN_LOOP_MODULES +CREATE_LISTENER(cnc_reset_delegate, encoders_reset_position); +#endif // overrides the default mod_itp_reset_rt_position_hook // may be modified in the future -void mod_itp_reset_rt_position_hook(float *origin) +void encoders_itp_reset_rt_position(float *origin) { #if STEPPER_COUNT > 0 #ifdef STEP0_ENCODER @@ -304,4 +305,8 @@ void mod_itp_reset_rt_position_hook(float *origin) #endif } +#ifdef ENABLE_INTERPOLATOR_MODULES +CREATE_LISTENER(itp_reset_rt_position_delegate, encoders_itp_reset_rt_position); +#endif + #endif From 46145e7c6b9062649189afa69fcce35bc2a13f49 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Mon, 9 May 2022 14:42:27 +0100 Subject: [PATCH 2/4] added main loop input check - added main loop input check --- uCNC/src/cnc.c | 4 +++ uCNC/src/cnc_hal_config_helper.h | 43 ++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/uCNC/src/cnc.c b/uCNC/src/cnc.c index ed69db26d..6c11662c5 100644 --- a/uCNC/src/cnc.c +++ b/uCNC/src/cnc.c @@ -824,6 +824,10 @@ static void cnc_io_dotasks(void) mcu_limits_changed_cb(); #endif mcu_controls_changed_cb(); +#if (DIN_ONCHANGE_MASK != 0 && ENCODERS < 1) + // extra call in case generic inputs are running with ISR disabled. Encoders need propper ISR to work. + mcu_inputs_changed_cb(); +#endif if (cnc_status_report_lock) { diff --git a/uCNC/src/cnc_hal_config_helper.h b/uCNC/src/cnc_hal_config_helper.h index 1b41e967d..b9597de21 100644 --- a/uCNC/src/cnc_hal_config_helper.h +++ b/uCNC/src/cnc_hal_config_helper.h @@ -1716,6 +1716,49 @@ extern "C" #define LIMITS_INV_MASK (LIMIT_X_INV_MASK | LIMIT_Y_INV_MASK | LIMIT_Z_INV_MASK | LIMIT_A_INV_MASK | LIMIT_B_INV_MASK | LIMIT_B_INV_MASK) #define LIMITS_DUAL_INV_MASK (LIMIT_X2_INV_MASK | LIMIT_Y2_INV_MASK | LIMIT_Z2_INV_MASK) +#if (DIN0 < 0) +#define DIN0_MASK 0 +#else +#define DIN0_MASK 1 +#endif +#if (DIN1 < 0) +#define DIN1_MASK 0 +#else +#define DIN1_MASK 2 +#endif +#if (DIN2 < 0) +#define DIN2_MASK 0 +#else +#define DIN2_MASK 4 +#endif +#if (DIN3 < 0) +#define DIN3_MASK 0 +#else +#define DIN3_MASK 8 +#endif +#if (DIN4 < 0) +#define DIN4_MASK 0 +#else +#define DIN4_MASK 16 +#endif +#if (DIN5 < 0) +#define DIN5_MASK 0 +#else +#define DIN5_MASK 32 +#endif +#if (DIN6 < 0) +#define DIN6_MASK 0 +#else +#define DIN6_MASK 64 +#endif +#if (DIN7 < 0) +#define DIN7_MASK 0 +#else +#define DIN7_MASK 128 +#endif + +#define DIN_ONCHANGE_MASK (DIN0_MASK | DIN1_MASK | DIN2_MASK | DIN3_MASK | DIN4_MASK | DIN5_MASK | DIN6_MASK | DIN7_MASK) + #if (PROBE < 0 && !defined(DISABLE_PROBE)) #define DISABLE_PROBE #endif From abf8907df0fb2ea61e1387f5d7e852a130306c2f Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Mon, 9 May 2022 21:24:28 +0100 Subject: [PATCH 3/4] fix encoder build error fix build error by checking if module is enabled --- uCNC/src/modules/encoder.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/uCNC/src/modules/encoder.c b/uCNC/src/modules/encoder.c index d132013c3..dbebd14cc 100644 --- a/uCNC/src/modules/encoder.c +++ b/uCNC/src/modules/encoder.c @@ -234,6 +234,8 @@ int32_t encoder_get_position(uint8_t i) return 0; } +#ifdef ENABLE_PROTOCOL_MODULES + void encoder_print_values(void) { for (uint8_t i = 0; i < ENCODERS; i++) @@ -246,6 +248,8 @@ void encoder_print_values(void) CREATE_LISTENER(send_pins_states_delegate, encoder_print_values); +#endif + void encoder_reset_position(uint8_t i, int32_t position) { __ATOMIC__ From 5bd269811eada97901b7fba90e755436ff2da776 Mon Sep 17 00:00:00 2001 From: Paciente8159 Date: Tue, 10 May 2022 08:57:26 +0100 Subject: [PATCH 4/4] Update spindle_besc.c --- uCNC/src/hal/tools/tools/spindle_besc.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/uCNC/src/hal/tools/tools/spindle_besc.c b/uCNC/src/hal/tools/tools/spindle_besc.c index 0327be3f7..f5cca3629 100644 --- a/uCNC/src/hal/tools/tools/spindle_besc.c +++ b/uCNC/src/hal/tools/tools/spindle_besc.c @@ -107,20 +107,26 @@ uint16_t spindle_besc_get_speed(void) static uint32_t last_time = 0; static uint16_t lastrpm = 0; uint16_t rpm = lastrpm; - uint32_t current_time = mcu_millis(); - uint32_t elapsed = (current_time - last_time); + uint32_t elapsed = (mcu_millis() - last_time); + int32_t read = encoder_get_position(0); // updates speed read every 5s - if (elapsed > 5000) + if (read > 0) { float timefact = 60000.f / (float)elapsed; - float newrpm = timefact * (float)encoder_get_position(0); - last_time = current_time; + float newrpm = timefact * (float)read; + last_time = mcu_millis(); encoder_reset_position(0, 0); rpm = (uint16_t)newrpm; lastrpm = rpm; } + else if (elapsed > 60000) + { + last_time = mcu_millis(); + rpm = 0; + lastrpm = 0; + } return rpm; #else