From 5ca85df56d80ef7731afbb21feb2457e8ec02cf0 Mon Sep 17 00:00:00 2001 From: Jens Scheidtmann Date: Sun, 21 Nov 2021 16:39:33 +0100 Subject: [PATCH 1/6] Ignore more PlatformIO local files and VSCode files. --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 8bde315..d888eae 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ .pioenvs .piolibdeps ardufocus/localcfg.h +.vscode +.pio +workspace.code-workspace \ No newline at end of file From 5554ca1b57fc4b18457660025630cd0049fc6840 Mon Sep 17 00:00:00 2001 From: Jens Scheidtmann Date: Sun, 21 Nov 2021 19:10:36 +0100 Subject: [PATCH 2/6] Make serial monitor do echo and send only on enter. --- platformio.ini | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 85a5b09..4a31421 100644 --- a/platformio.ini +++ b/platformio.ini @@ -68,7 +68,11 @@ src_build_flags = ${common.src_build_flags} lib_deps = ${common.lib_deps_external} ; Uncomment this line if you have upgraded the bootloader ; on your Arduino Nano -upload_speed = 115200 +;upload_speed = 115200 +monitor_flags = + --echo +monitor_filters = colorize, send_on_enter # , debug + [env:nano328pb] platform = atmelavr From 0f1c4ef79982c67fd9e4c72d4ccf12c873df8368 Mon Sep 17 00:00:00 2001 From: Jens Scheidtmann Date: Sun, 21 Nov 2021 19:11:03 +0100 Subject: [PATCH 3/6] Configure breadboard pins for my layout --- ardufocus/config.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ardufocus/config.h b/ardufocus/config.h index 2e45e4d..23432d9 100644 --- a/ardufocus/config.h +++ b/ardufocus/config.h @@ -136,7 +136,7 @@ // - Max speed: 1000 // - Min speed: 250 // -#define MOTOR1_MAX_SPEED 150 +#define MOTOR1_MAX_SPEED 250: #define MOTOR1_MIN_SPEED 25 @@ -204,10 +204,12 @@ // This is the most basic user interface, it uses two keys to move the focuser // IN (FWD) and out (BWD). A third key (SWT) can be used to select the active // motor on a dual motor configuration. -//#define USE_UI_KAP +#define USE_UI_KAP // Use the following setings to select the input pins connected to each one of // the switches. The third button is optional. +// 16 = A2 on Arduino Nano +// 17 = A3 on Arduino Nano #define UI_KAP_FWD_BUTTON_PIN 16 #define UI_KAP_BWD_BUTTON_PIN 17 //#define UI_KAP_SWT_BUTTON_PIN 18 @@ -221,13 +223,14 @@ // GND --- | SWITCH | --- INPUT_PIN // -------- // +// So, if you want to use active high logic on the input button switches, define this: //#define UI_KAP_INVERT_BUTTON_LOGIC // The options bellow allows you to have one LED per button, the LED will light // up when the button is pressed. The third button (SWT) will be lit when the // first motor is active, and off when the second motor is active. -//#define UI_KAP_FWD_BUTTON_LED_PIN 13 -//#define UI_KAP_BWD_BUTTON_LED_PIN 13 +#define UI_KAP_FWD_BUTTON_LED_PIN 3 +#define UI_KAP_BWD_BUTTON_LED_PIN 4 //#define UI_KAP_SWT_BUTTON_LED_PIN 13 // Pin A0 is channel 0 (..) pin A3 is channel 3 From 075c5c4c39d3d4c6d40eb90f7b4b8de7703c8aa9 Mon Sep 17 00:00:00 2001 From: Jens Scheidtmann Date: Sun, 21 Nov 2021 19:18:05 +0100 Subject: [PATCH 4/6] Add higher resolution methods for A4988 --- ardufocus/a4988.cpp | 71 ++++++++++++++++++++++++++++++++++++++++----- ardufocus/a4988.h | 11 +++++++ 2 files changed, 74 insertions(+), 8 deletions(-) diff --git a/ardufocus/a4988.cpp b/ardufocus/a4988.cpp index 5805baf..ce8cc5a 100644 --- a/ardufocus/a4988.cpp +++ b/ardufocus/a4988.cpp @@ -20,8 +20,9 @@ #include "a4988.h" /** - * @brief [brief description] - * @details [long description] + * @brief Initialize Arduino pins for A4988 step stick according to pinout in config.h + * @details Configure Arduino pins, so we are able to drive the stepper motor. + * This routine sets the step resolution. * */ void a4988::init() @@ -35,9 +36,11 @@ void a4988::init() IO::set_as_output(m_pinout.sleep); IO::set_as_output(m_pinout.direction); + // Step resolution: Full step IO::write(m_pinout.ms1, LOW); IO::write(m_pinout.ms2, LOW); IO::write(m_pinout.ms3, LOW); + IO::write(m_pinout.step, LOW); IO::write(m_pinout.direction, LOW); @@ -64,8 +67,8 @@ void a4988::halt() /** - * @brief [brief description] - * @details [long description] + * @brief Set microstepping resolution: Full step + * @details Use the microstepping resolution pins to configure a "full step" per pulse. * */ void a4988::set_full_step() @@ -81,8 +84,8 @@ void a4988::set_full_step() /** - * @brief [brief description] - * @details [long description] + * @brief Set microstepping resolution: half step + * @details Use the microstepping resolutions pins to configure a "half step" per pulse resolution. * */ void a4988::set_half_step() @@ -96,6 +99,56 @@ void a4988::set_half_step() util::delay_2us(); } +/** + * @brief Set microstepping resolution: half step + * @details Use the microstepping resolutions pins to configure a "half step" per pulse resolution. + * + */ +void a4988::set_quarter_step() +{ + m_mode = 0xFF; + IO::write(m_pinout.ms1, LOW); + IO::write(m_pinout.ms2, HIGH); + IO::write(m_pinout.ms3, LOW); + + // A4988: 400ns, A8825: 1.3us + util::delay_2us(); +} + +/** + * @brief Set microstepping resolution: half step + * @details Use the microstepping resolutions pins to configure a "half step" per pulse resolution. + * + */ +void a4988::set_eigth_step() +{ + m_mode = 0xFF; + IO::write(m_pinout.ms1, HIGH); + IO::write(m_pinout.ms2, HIGH); + IO::write(m_pinout.ms3, LOW); + + // A4988: 400ns, A8825: 1.3us + util::delay_2us(); +} + +/** + * @brief Set microstepping resolution: half step + * @details Use the microstepping resolutions pins to configure a "half step" per pulse resolution. + * + */ +void a4988::set_sixteenth_step() +{ + m_mode = 0xFF; + IO::write(m_pinout.ms1, HIGH); + IO::write(m_pinout.ms2, HIGH); + IO::write(m_pinout.ms3, HIGH); + + // A4988: 400ns, A8825: 1.3us + util::delay_2us(); +} + +// Disable 'implicit fall-through' warning, as the switch statements fall-through on purpose. +#pragma GCC diagnostic ignored "-Wimplicit-fallthrough=" /** * @brief [brief description] @@ -141,11 +194,13 @@ bool a4988::step_ccw() return step(); } } +// Restore warnings to command line parameters. +#pragma GCC diagnostic pop /** - * @brief [brief description] - * @details [long description] + * @brief Move the stepper motor one step. + * @details Writes a pulse on the output pin, to advance the motor according to the set resolution. * */ bool a4988::step() diff --git a/ardufocus/a4988.h b/ardufocus/a4988.h index 155931d..326b0f0 100644 --- a/ardufocus/a4988.h +++ b/ardufocus/a4988.h @@ -50,6 +50,14 @@ class a4988: public stepper * DIR |o --- o| GND * `-----------ยด * + * Pin description according to A4988 data sheet, e.g. https://pdf1.alldatasheet.com/datasheet-pdf/view/338780/ALLEGRO/A4988.html + * + * ENA: Enable (negated logic) + * RST: Reset (negated logic) + * SLP: Sleep (negated logic) + * MS1,MS2,MS3: Microstepping resolution, LLL = full step, HLL = half step, LHL = quarter, HHL = eighth, HHH = 1/16th step. + * DIR: Direction + * STP: Step */ protected: @@ -64,6 +72,9 @@ class a4988: public stepper virtual void sleep(); virtual void set_full_step(); virtual void set_half_step(); + virtual void set_quarter_step(); + virtual void set_eigth_step(); + virtual void set_sixteenth_step(); virtual speed bool step_cw(); virtual speed bool step_ccw(); From 9d4e2938ba6be35430c98dc990acbd1a9c3154cf Mon Sep 17 00:00:00 2001 From: Jens Scheidtmann Date: Sun, 21 Nov 2021 21:47:47 +0100 Subject: [PATCH 5/6] Fix MOTOR1_MAX_SPEED --- ardufocus/config.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/ardufocus/config.h b/ardufocus/config.h index 23432d9..a10a718 100644 --- a/ardufocus/config.h +++ b/ardufocus/config.h @@ -136,7 +136,7 @@ // - Max speed: 1000 // - Min speed: 250 // -#define MOTOR1_MAX_SPEED 250: +#define MOTOR1_MAX_SPEED 250 #define MOTOR1_MIN_SPEED 25 @@ -175,6 +175,19 @@ // any acceleration control. The default value is 10 steps of left undefined. //#define ACCEL_MIN_STEPS 10 +// ---------------------------------------------------------------------------- +// Microstepping Resolution --------------------------------------------------- +// ---------------------------------------------------------------------------- +// +// Moonlite protocol supports two differnt speed modes for controlling the focuser: +// "Full step mode" and "half step mode". Here you can configure, which microstepping is +// considered a "full step". Allowed values are 1,2,4,8 for full steps, half steps, +// quarter steps or eighth steps respectively. Half mode is the next one. +// (Note: At the moment this is a global setting for all stepper motors and +// is not supported by the ULN2003 driver, for which it must be one) +#define STEPPER_FULLSTEP_MICRORES 8 + + // ---------------------------------------------------------------------------- // TEMPERATURE SENSOR --------------------------------------------------------- From 4b0a77e008f30fd9d391a037ddb7a645e7c69717 Mon Sep 17 00:00:00 2001 From: Jens Scheidtmann Date: Sun, 21 Nov 2021 22:01:30 +0100 Subject: [PATCH 6/6] Support configuring microstepping in the A4988 driver --- ardufocus/a4988.cpp | 22 +++++++++++----------- ardufocus/a4988.h | 2 +- ardufocus/api.h | 44 ++++++++++++++++++++++++++++++++++++++++---- ardufocus/assert.h | 13 +++++++++++++ ardufocus/stepper.h | 4 ++++ ardufocus/uln2003.h | 4 ++++ 6 files changed, 73 insertions(+), 16 deletions(-) diff --git a/ardufocus/a4988.cpp b/ardufocus/a4988.cpp index ce8cc5a..99443f9 100644 --- a/ardufocus/a4988.cpp +++ b/ardufocus/a4988.cpp @@ -36,11 +36,11 @@ void a4988::init() IO::set_as_output(m_pinout.sleep); IO::set_as_output(m_pinout.direction); - // Step resolution: Full step - IO::write(m_pinout.ms1, LOW); - IO::write(m_pinout.ms2, LOW); - IO::write(m_pinout.ms3, LOW); - + // Step resolution: Sixteenth step + IO::write(m_pinout.ms1, HIGH); + IO::write(m_pinout.ms2, HIGH); + IO::write(m_pinout.ms3, HIGH); + IO::write(m_pinout.step, LOW); IO::write(m_pinout.direction, LOW); @@ -73,7 +73,7 @@ void a4988::halt() */ void a4988::set_full_step() { - m_mode = 0x00; + m_mode = 1; IO::write(m_pinout.ms1, LOW); IO::write(m_pinout.ms2, LOW); IO::write(m_pinout.ms3, LOW); @@ -90,7 +90,7 @@ void a4988::set_full_step() */ void a4988::set_half_step() { - m_mode = 0xFF; + m_mode = 2; IO::write(m_pinout.ms1, HIGH); IO::write(m_pinout.ms2, LOW); IO::write(m_pinout.ms3, LOW); @@ -106,7 +106,7 @@ void a4988::set_half_step() */ void a4988::set_quarter_step() { - m_mode = 0xFF; + m_mode = 4; IO::write(m_pinout.ms1, LOW); IO::write(m_pinout.ms2, HIGH); IO::write(m_pinout.ms3, LOW); @@ -120,9 +120,9 @@ void a4988::set_quarter_step() * @details Use the microstepping resolutions pins to configure a "half step" per pulse resolution. * */ -void a4988::set_eigth_step() +void a4988::set_eighth_step() { - m_mode = 0xFF; + m_mode = 8; IO::write(m_pinout.ms1, HIGH); IO::write(m_pinout.ms2, HIGH); IO::write(m_pinout.ms3, LOW); @@ -138,7 +138,7 @@ void a4988::set_eigth_step() */ void a4988::set_sixteenth_step() { - m_mode = 0xFF; + m_mode = 16; IO::write(m_pinout.ms1, HIGH); IO::write(m_pinout.ms2, HIGH); IO::write(m_pinout.ms3, HIGH); diff --git a/ardufocus/a4988.h b/ardufocus/a4988.h index 326b0f0..7cf6102 100644 --- a/ardufocus/a4988.h +++ b/ardufocus/a4988.h @@ -73,7 +73,7 @@ class a4988: public stepper virtual void set_full_step(); virtual void set_half_step(); virtual void set_quarter_step(); - virtual void set_eigth_step(); + virtual void set_eighth_step(); virtual void set_sixteenth_step(); virtual speed bool step_cw(); virtual speed bool step_ccw(); diff --git a/ardufocus/api.h b/ardufocus/api.h index 1cb1c78..b1badbe 100644 --- a/ardufocus/api.h +++ b/ardufocus/api.h @@ -211,13 +211,31 @@ class api { switch(idx) { case MOTOR_ONE: #ifdef MOTOR1_HAS_DRIVER - g_motor1->set_full_step(); + g_motor1->set_step_mode(0); + // We rely on the compiler to optimize away the ifs, where the condition is false. + if (STEPPER_FULLSTEP_MICRORES == 1) + g_motor1->set_full_step(); + if (STEPPER_FULLSTEP_MICRORES == 2) + g_motor1->set_half_step(); + if (STEPPER_FULLSTEP_MICRORES == 4) + g_motor1->set_quarter_step(); + if (STEPPER_FULLSTEP_MICRORES == 8) + g_motor1->set_eighth_step(); #endif break; case MOTOR_TWO: #ifdef MOTOR2_HAS_DRIVER - g_motor2->set_full_step(); + g_motor2->set_step_mode(0); + // We rely on the compiler to optimize away the ifs, where the condition is false. + if (STEPPER_FULLSTEP_MICRORES == 1) + g_motor2->set_full_step(); + if (STEPPER_FULLSTEP_MICRORES == 2) + g_motor2->set_half_step(); + if (STEPPER_FULLSTEP_MICRORES == 4) + g_motor2->set_quarter_step(); + if (STEPPER_FULLSTEP_MICRORES == 8) + g_motor2->set_eighth_step(); #endif break; @@ -230,13 +248,31 @@ class api { switch(idx) { case MOTOR_ONE: #ifdef MOTOR1_HAS_DRIVER - g_motor1->set_half_step(); + g_motor1->set_step_mode(0xff); + // We rely on the compiler to optimize away the ifs, where the condition is false. + if (STEPPER_FULLSTEP_MICRORES == 1) + g_motor1->set_half_step(); + if (STEPPER_FULLSTEP_MICRORES == 2) + g_motor1->set_quarter_step(); + if (STEPPER_FULLSTEP_MICRORES == 4) + g_motor1->set_eighth_step(); + if (STEPPER_FULLSTEP_MICRORES == 8) + g_motor1->set_sixteenth_step(); #endif break; case MOTOR_TWO: #ifdef MOTOR2_HAS_DRIVER - g_motor2->set_half_step(); + g_motor2->set_step_mode(0xff); + // We rely on the compiler to optimize away the ifs, where the condition is false. + if (STEPPER_FULLSTEP_MICRORES == 1) + g_motor2->set_half_step(); + if (STEPPER_FULLSTEP_MICRORES == 2) + g_motor2->set_quarter_step(); + if (STEPPER_FULLSTEP_MICRORES == 4) + g_motor2->set_eighth_step(); + if (STEPPER_FULLSTEP_MICRORES == 8) + g_motor2->set_sixteenth_step(); #endif break; diff --git a/ardufocus/assert.h b/ardufocus/assert.h index 7c96768..1ce6b27 100644 --- a/ardufocus/assert.h +++ b/ardufocus/assert.h @@ -213,6 +213,19 @@ #endif #endif +// Microstepping behaviour sanity checks +#if !(STEPPER_FULLSTEP_MICRORES == 1 || STEPPER_FULLSTEP_MICRORES == 2 || STEPPER_FULLSTEP_MICRORES == 4 || STEPPER_FULLSTEP_MICRORES == 8) + #error The STEPPER_FULLSTEP_MICRORES must be 1,2,4 or 8. +#endif + +#if (STEPPER_FULLSTEP_MICRORES > 1) && defined(MOTOR1_HAS_DRIVER) && !defined(MOTOR1_USE_A4988_DRIVER) + #error STEPPER_FULLSTEP_MICRORES > 1 is only supported by the A4988 driver. Check MOTOR1 driver. +#endif + +#if (STEPPER_FULLSTEP_MICRORES > 1) && defined(MOTOR2_HAS_DRIVER) && !defined(MOTOR2_USE_A4988_DRIVER) + #error STEPPER_FULLSTEP_MICRORES > 1 is only supported by the A4988 driver. Check MOTOR2 driver. +#endif + // USER INTERFACE: Keyboard --------------------------------------------------- #if defined(USE_UI_KAP) #if defined(UI_KAP_BUTTON_DEBOUNCE) && (UI_KAP_BUTTON_DEBOUNCE < 1 || UI_KAP_BUTTON_DEBOUNCE > 255) diff --git a/ardufocus/stepper.h b/ardufocus/stepper.h index b1790f2..0793dae 100644 --- a/ardufocus/stepper.h +++ b/ardufocus/stepper.h @@ -76,7 +76,11 @@ class stepper virtual inline void sleep() { ; } virtual inline void set_full_step() { ; } virtual inline void set_half_step() { ; } + virtual inline void set_quarter_step() { ; } + virtual inline void set_eighth_step() { ; } + virtual inline void set_sixteenth_step() { ; } + virtual inline void set_step_mode(uint8_t mode) { m_mode = mode; } virtual inline uint8_t get_step_mode() { return m_mode; } virtual inline bool step_cw() { return false; } diff --git a/ardufocus/uln2003.h b/ardufocus/uln2003.h index f968bfa..92e960b 100644 --- a/ardufocus/uln2003.h +++ b/ardufocus/uln2003.h @@ -50,6 +50,10 @@ class uln2003: public stepper virtual void sleep(); virtual void set_full_step(); virtual void set_half_step(); + // Not supported. + virtual inline void set_quarter_step() { ; }; + virtual inline void set_eighth_step() { ; }; + virtual inline void set_sixteenth_step() { ; }; virtual speed bool step_cw(); virtual speed bool step_ccw();