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 diff --git a/ardufocus/a4988.cpp b/ardufocus/a4988.cpp index 5805baf..99443f9 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); - 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); @@ -64,13 +67,13 @@ 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() { - m_mode = 0x00; + m_mode = 1; IO::write(m_pinout.ms1, LOW); IO::write(m_pinout.ms2, LOW); IO::write(m_pinout.ms3, LOW); @@ -81,13 +84,13 @@ 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() { - m_mode = 0xFF; + m_mode = 2; IO::write(m_pinout.ms1, HIGH); IO::write(m_pinout.ms2, LOW); IO::write(m_pinout.ms3, LOW); @@ -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 = 4; + 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_eighth_step() +{ + m_mode = 8; + 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 = 16; + 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..7cf6102 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_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/config.h b/ardufocus/config.h index 2e45e4d..a10a718 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 @@ -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 --------------------------------------------------------- @@ -204,10 +217,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 +236,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 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(); 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