From 2796eeebe014d4084a3ce9f5c70833a12d26fe0e Mon Sep 17 00:00:00 2001 From: Eric Schubert Date: Sun, 11 Oct 2026 14:36:06 -0500 Subject: [PATCH 1/2] Rebuild RP2040 support as additive-only port on current develop The previous RP2040-Support branch was based on V1.13.19 and was not a superset of develop: in shared files the old content won, silently reverting OAE board support, the test menu, CI tooling, and other features develop shipped since, with no merge conflicts to flag it. This starts fresh from current develop (through the Meade parser rewrite and coordinate-handling fixes) and re-applies only the RP2040-specific hunks as guarded additions: - New board pin files (JackW01, SKR Pico) and example local config, carried over unchanged. - Board IDs, config dispatch, and validation branches added additively for ARDUINO_ARCH_RP2040 alongside existing platforms. - RP2040 alarm-timer (InterruptCallback.cpp) and flash-backed EEPROM (EPROMStore.cpp) implementations, each in their own guarded branch. - platformio.ini: new common_rp2xxx/rp2040_* environments only; env:oaeboardv1 and all other environments left untouched. RP2040 envs exclude SSD1306_128x64_Display.cpp via src_filter since no RP2040 board supports that display and the file unconditionally pulls in a library outside the minimal RP2040 toolchain. - b_setup.hpp/c_buttons.hpp: USB CDC DTR fix, GPS/UART1 pin remapping, fan PWM, and shared-EN-pin handling, all gated behind ARDUINO_ARCH_RP2040; the previously unguarded toff(1)->toff(4) and UART baud (57600->115200) changes are now RP2040-only, preserving prior platform behavior elsewhere. - Added defaulted copy-assignment operators to the DayTime/ Declination/Latitude/Longitude coordinate types (both the core:: classes and the Latitude/Longitude Arduino overlays), needed to silence a deprecated-copy warning promoted to an error on the RP2040 toolchain; verified harmless on all other platforms via the native test suite. Every file not touched here was checked to be byte-identical to develop. rp2040_jackw01 and rp2040_skr_pico build clean; ramps builds clean; esp32/oaeboardv1/mksgenl* fail identically with and without this change (pre-existing, unrelated to this port); all 333 native unit tests pass. Smoke-tested on SKR Pico hardware. Co-Authored-By: Claude Sonnet 5 --- .gitignore | 3 + Configuration.hpp | 4 + ConfigurationValidation.hpp | 24 ++- .../Configuration_local_rp2040_skr_pico.hpp | 154 +++++++++++++++++ Constants.hpp | 4 + LocalConfiguration.hpp | 4 + boards/RP2040_JACKW01/pins_RP2040_JACKW01.hpp | 141 +++++++++++++++ .../RP2040_SKR_PICO/pins_RP2040_SKR_PICO.hpp | 163 ++++++++++++++++++ matrix_build.py | 38 +++- platformio.ini | 38 ++++ src/EPROMStore.cpp | 35 ++++ src/InterruptCallback.cpp | 47 +++++ src/Latitude.hpp | 1 + src/Longitude.hpp | 1 + src/Mount.cpp | 40 +++++ src/b_setup.hpp | 84 ++++++++- src/c_buttons.hpp | 7 + src/core/types/DayTime.hpp | 1 + src/core/types/Declination.hpp | 1 + src/core/types/Latitude.hpp | 1 + src/core/types/Longitude.hpp | 1 + 21 files changed, 784 insertions(+), 8 deletions(-) create mode 100644 Configuration_local_examples/Configuration_local_rp2040_skr_pico.hpp create mode 100644 boards/RP2040_JACKW01/pins_RP2040_JACKW01.hpp create mode 100644 boards/RP2040_SKR_PICO/pins_RP2040_SKR_PICO.hpp diff --git a/.gitignore b/.gitignore index a81693dc..84f88302 100644 --- a/.gitignore +++ b/.gitignore @@ -12,5 +12,8 @@ build_cache Configuration_local* MeadeToWikiOutput.txt +!Configuration_local_examples/ +!Configuration_local_examples/* + # macOS **/.DS_Store diff --git a/Configuration.hpp b/Configuration.hpp index bebb8c7c..353208bd 100644 --- a/Configuration.hpp +++ b/Configuration.hpp @@ -273,6 +273,10 @@ #include "boards/AVR_MKS_GEN_L_V2/pins_MKS_GEN_L_V2.h" #elif (BOARD == BOARD_AVR_MKS_GEN_L_V21) #include "boards/AVR_MKS_GEN_L_V21/pins_MKS_GEN_L_V21.h" +#elif (BOARD == BOARD_RP2040_JACKW01) + #include "boards/RP2040_JACKW01/pins_RP2040_JACKW01.hpp" +#elif (BOARD == BOARD_RP2040_SKR_PICO) + #include "boards/RP2040_SKR_PICO/pins_RP2040_SKR_PICO.hpp" #endif #include "Configuration_adv.hpp" diff --git a/ConfigurationValidation.hpp b/ConfigurationValidation.hpp index eb31aedb..190d306e 100644 --- a/ConfigurationValidation.hpp +++ b/ConfigurationValidation.hpp @@ -17,7 +17,7 @@ #endif // Platform -#if defined(ESP32) || defined(__AVR_ATmega2560__) +#if defined(ESP32) || defined(__AVR_ATmega2560__) || defined(ARDUINO_ARCH_RP2040) // Valid platform #else #error Unsupported platform configuration. Use at own risk. @@ -30,6 +30,8 @@ && ((DISPLAY_TYPE == DISPLAY_TYPE_NONE) || (DISPLAY_TYPE == DISPLAY_TYPE_LCD_KEYPAD) || (DISPLAY_TYPE_LCD_KEYPAD_I2C_MCP23008) \ || (DISPLAY_TYPE_LCD_KEYPAD_I2C_MCP23017)) // Valid display for ATmega +#elif defined(ARDUINO_ARCH_RP2040) && (DISPLAY_TYPE == DISPLAY_TYPE_NONE) +// Valid display for RP2040 #else #error Unsupported display configuration. Use at own risk. #endif @@ -81,7 +83,7 @@ #else #error Defined an AZ driver, but no AZ stepper. #endif -#elif defined(__AVR_ATmega2560__) +#elif defined(__AVR_ATmega2560__) || defined(ARDUINO_ARCH_RP2040) // Azimuth configuration #if (AZ_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART) #ifndef AZ_DRIVER_ADDRESS @@ -102,7 +104,7 @@ #else #error Defined an ALT driver, but no ALT stepper. #endif -#elif defined(__AVR_ATmega2560__) +#elif defined(__AVR_ATmega2560__) || defined(ARDUINO_ARCH_RP2040) // Altitude configuration #if (ALT_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART) #ifndef ALT_DRIVER_ADDRESS @@ -166,8 +168,8 @@ // External sensors #if (USE_GPS == 0) // Baseline configuration without GPS is valid -#elif defined(ESP32) || defined(__AVR_ATmega2560__) -// GPS is supported on ESP32 and ATmega +#elif defined(ESP32) || defined(__AVR_ATmega2560__) || defined(ARDUINO_ARCH_RP2040) +// GPS is supported on ESP32, ATmega and RP2040 #else #error Unsupported GPS configuration. Use at own risk. #endif @@ -238,6 +240,12 @@ // Required pin assignments missing (ATmega uses SoftwareSerial for this driver) #error Missing pin assignments for configured AZ DRIVER_TYPE_TMC2209_UART driver #endif + #if !defined(AZ_DIAG_PIN) + // AZ_DIAG_PIN (TMC2209 DIAG output) is used only for stallGuard-based homing. + // It is optional: omit it if your hardware does not wire the DIAG output to a GPIO. + // Without it, stallGuard homing is unavailable but all other AZ motion works normally. + #pragma message "AZ_DIAG_PIN not defined. StallGuard homing unavailable for AZ axis." + #endif #if !((defined(AZ_SERIAL_PORT_TX) && defined(AZ_SERIAL_PORT_RX)) || defined(AZ_SERIAL_PORT)) // Required pin assignments missing for UART serial #error Missing pin assignments for configured AZ DRIVER_TYPE_TMC2209_UART driver serial connection @@ -256,6 +264,12 @@ // Required pin assignments missing (ATmega uses SoftwareSerial for this driver) #error Missing pin assignments for configured ALT DRIVER_TYPE_TMC2209_UART driver #endif + #if !defined(ALT_DIAG_PIN) + // ALT_DIAG_PIN (TMC2209 DIAG output) is used only for stallGuard-based homing. + // It is optional: omit it if your hardware does not wire the DIAG output to a GPIO. + // Without it, stallGuard homing is unavailable but all other ALT motion works normally. + #pragma message "ALT_DIAG_PIN not defined. StallGuard homing unavailable for ALT axis." + #endif #if !((defined(ALT_SERIAL_PORT_TX) && defined(ALT_SERIAL_PORT_RX)) || defined(ALT_SERIAL_PORT)) // Required pin assignments missing for UART serial #error Missing pin assignments for configured ALT DRIVER_TYPE_TMC2209_UART driver serial connection diff --git a/Configuration_local_examples/Configuration_local_rp2040_skr_pico.hpp b/Configuration_local_examples/Configuration_local_rp2040_skr_pico.hpp new file mode 100644 index 00000000..16fe2038 --- /dev/null +++ b/Configuration_local_examples/Configuration_local_rp2040_skr_pico.hpp @@ -0,0 +1,154 @@ +/** + * @brief Local hardware configuration for a Raspberry Pi Pico (RP2040) + * on the BigTreeTech SKR Pico v1.0 printer controller board. + * + * This file is NOT tracked by Git and will survive branch changes. + * It is automatically included by LocalConfiguration.hpp when + * BOARD == BOARD_RP2040_SKR_PICO. + * + * Hardware summary + * ---------------- + * MCU : RP2040 (Raspberry Pi Pico) + * Board : BTT SKR Pico v1.0 + * Stepper slot : X -> RA (TMC2209, UART addr 0) + * Stepper slot : Y -> DEC (TMC2209, UART addr 2) + * Stepper slot : Z -> AZ (TMC2209, UART addr 1) + * Stepper slot : E0 -> ALT (TMC2209, UART addr 3) + * Motor rating : 0.9 deg / step (400 SPR), 470 mA + * Pulley : 16T aluminium GT2 + * RA homing : Hall sensor on GPIO4 (X-STOP / RA_DIAG_PIN) + * + * All pin assignments are in boards/RP2040_SKR_PICO/pins_RP2040_SKR_PICO.hpp. + * R_SENSE (0.11 ohm) is set globally in src/a_inits.hpp for all TMC2209_UART + * builds and does not need to be repeated here. + * + * Key difference from JackW01: each stepper driver has its own EN pin. + * AZ_ALWAYS_ON and ALT_ALWAYS_ON are NOT required on this board. + */ +#pragma once + +// ── Board ───────────────────────────────────────────────────────────────────── +#define BOARD BOARD_RP2040_SKR_PICO + +// ── Hemisphere ──────────────────────────────────────────────────────────────── +#define NORTHERN_HEMISPHERE 1 + +// ── Display (none) ──────────────────────────────────────────────────────────── +#define DISPLAY_TYPE DISPLAY_TYPE_NONE +#define INFO_DISPLAY_TYPE INFO_DISPLAY_TYPE_NONE + +// ── Stepper motor types ─────────────────────────────────────────────────────── +#define RA_STEPPER_TYPE STEPPER_TYPE_ENABLED +#define DEC_STEPPER_TYPE STEPPER_TYPE_ENABLED +#define AZ_STEPPER_TYPE STEPPER_TYPE_ENABLED +#define ALT_STEPPER_TYPE STEPPER_TYPE_ENABLED + +// ── Stepper driver types ────────────────────────────────────────────────────── +#define RA_DRIVER_TYPE DRIVER_TYPE_TMC2209_UART +#define DEC_DRIVER_TYPE DRIVER_TYPE_TMC2209_UART +#define AZ_DRIVER_TYPE DRIVER_TYPE_TMC2209_UART +#define ALT_DRIVER_TYPE DRIVER_TYPE_TMC2209_UART + +// ── Steps per revolution (0.9 deg motor = 400 full steps/rev) ───────────────── +#define RA_STEPPER_SPR 400 +#define DEC_STEPPER_SPR 400 +#define AZ_STEPPER_SPR 400 +#define ALT_STEPPER_SPR 400 + +// ── Pulley tooth count (16T aluminium GT2) ──────────────────────────────────── +#define RA_PULLEY_TEETH 16 +#define DEC_PULLEY_TEETH 16 +#define AZ_PULLEY_TEETH 16 +#define ALT_PULLEY_TEETH 16 + +// ── Microstepping ───────────────────────────────────────────────────────────── +// TMC2209 UART mode can switch microstepping dynamically at runtime. +// RA switches between slew (8×) and fine tracking (256×). +// DEC switches between slew (16×) and fine guiding (256×). +// AZ and ALT use a fixed microstepping mode (no dynamic switching). +#define RA_SLEW_MICROSTEPPING 8 // µsteps used while slewing RA +#define RA_TRACKING_MICROSTEPPING 256 // µsteps used for sidereal tracking +#define DEC_SLEW_MICROSTEPPING 16 // µsteps used while slewing DEC +#define DEC_GUIDE_MICROSTEPPING 256 // µsteps used for guide pulses +#define AZ_MICROSTEPPING 64 +#define ALT_MICROSTEPPING 4 + +// ── Motor direction ─────────────────────────────────────────────────────────── +// Set to 1 to reverse the direction of an axis if it moves the wrong way. +// Verify with manual move commands: :Mw#/:Me# (RA), :Mn#/:Ms# (DEC), +// :MAL#/:MAR# (AZ), :MAU#/:MAD# (ALT). Then set the appropriate flag to 1. +#define RA_INVERT_DIR 0 +#define DEC_INVERT_DIR 1 +#define AZ_INVERT_DIR 0 +#define ALT_INVERT_DIR 0 + +// ── StealthChop (silent mode) ───────────────────────────────────────────────── +// Configuration_adv.hpp defaults both to 0 (SpreadCycle = noisy). +// Set to 1 to enable StealthChop (silent) for RA tracking and DEC moves. +#define RA_UART_STEALTH_MODE 1 +#define DEC_UART_STEALTH_MODE 1 + +// ── Motor current ───────────────────────────────────────────────────────────── +// Motors are rated at 470 mA. Run at 75 % of rated current to reduce heat +// while maintaining adequate torque. RMS current is computed automatically: +// RMSCURRENT = RATING * (SETTING / 100) / sqrt(2) => ~249 mA RMS +// Do NOT define XXX_RMSCURRENT directly; Configuration_adv.hpp will error. +#define RA_MOTOR_CURRENT_RATING 470 // mA +#define RA_OPERATING_CURRENT_SETTING 75 // % + +#define DEC_MOTOR_CURRENT_RATING 470 // mA +#define DEC_OPERATING_CURRENT_SETTING 75 // % + +#define AZ_MOTOR_CURRENT_RATING 470 // mA +#define AZ_OPERATING_CURRENT_SETTING 75 // % + +#define ALT_MOTOR_CURRENT_RATING 470 // mA +#define ALT_OPERATING_CURRENT_SETTING 75 // % + +// ── AZ/ALT hold current ─────────────────────────────────────────────────────── +// AZ must hold position against backlash forces; use 40 % of run current. +// ALT is held by friction and gearing; bleed hold current to zero. +// These are percentages (0-100) converted to TMC2209 IHOLD by the firmware. +#define AZ_MOTOR_HOLD_SETTING 40 // % +#define ALT_MOTOR_HOLD_SETTING 0 // % + +// ── DEC axis travel limits ──────────────────────────────────────────────────── +// Physical limits measured from the home (level) position. +// These must be defined here; Configuration_adv.hpp defaults to 0.0f for +// non-OAM builds, which makes :Mn#/:Ms# target position 0 and do nothing. +#ifndef DEC_LIMIT_UP + #define DEC_LIMIT_UP 135.0f // 135° north of home +#endif +#ifndef DEC_LIMIT_DOWN + #define DEC_LIMIT_DOWN 35.0f // 35° south of home +#endif + +// ── RA Hall sensor auto-home ────────────────────────────────────────────────── +// Hall sensor is wired to GPIO4 (X-STOP input / RA_DIAG_PIN on SKR Pico). +// Active state LOW: sensor pulls GPIO4 LOW when the magnet is present. +// Search distance: 30° default (RA_HOMING_SENSOR_SEARCH_DEGREES in Configuration_adv.hpp). +// GPIO4 is configured INPUT (no pull-up); add external 10kΩ to 3.3V if sensor +// is open-drain, or change to INPUT_PULLUP in b_setup.hpp. +#define USE_HALL_SENSOR_RA_AUTOHOME 1 +#define RA_HOMING_SENSOR_PIN 4 // GPIO4 = RA_DIAG_PIN (X-STOP) +#define RA_HOMING_SENSOR_ACTIVE_STATE LOW // sensor pulls LOW when active + +// ── GPS ─────────────────────────────────────────────────────────────────────── +// ATGM336H-5N wired to left-side header: GPS TX→IO1, GPS RX→IO0, VCC→5V, GND. +// GPS_SERIAL_PORT, RP2040_GPS_TX_PIN, RP2040_GPS_RX_PIN defined in pins file. +// GPS_BAUD_RATE defaults to 9600 in Configuration_adv.hpp (matches module default). +#define USE_GPS 1 + +// ── FAN ─────────────────────────────────────────────────────────────────────── +// FAN1 power level as a percentage (0 = off, 100 = full speed). +// The pin and PWM are defined in pins_RP2040_SKR_PICO.hpp. +#define RP2040_FAN1_POWER_PERCENT 60 + +// Track immediately after boot +#define TRACK_ON_BOOT 0 + +// Uncomment to override defaults for stepper speeds and accelerations +//#define RA_STEPPER_SPEED 1200 // You can change the speed and acceleration of the steppers here. Max. Speed = 3000. +//#define RA_STEPPER_ACCELERATION 6000 +//#define DEC_STEPPER_SPEED 1300 // You can change the speed and acceleration of the steppers here. Max. Speed = 3000. +//#define DEC_STEPPER_ACCELERATION 6000 diff --git a/Constants.hpp b/Constants.hpp index e37811b2..56ccb6ce 100644 --- a/Constants.hpp +++ b/Constants.hpp @@ -21,6 +21,10 @@ #define BOARD_ESP32_ESP32DEV 1001 #define BOARD_OAE_V1 1002 +// RP2040 based boards +#define BOARD_RP2040_JACKW01 2101 +#define BOARD_RP2040_SKR_PICO 2201 + /** * Supported keypad/display types. Use one of these values for DISPLAY_TYPE configuration matching your used display and keypad. * diff --git a/LocalConfiguration.hpp b/LocalConfiguration.hpp index 14a00510..428fd3c7 100644 --- a/LocalConfiguration.hpp +++ b/LocalConfiguration.hpp @@ -18,6 +18,10 @@ #include "Configuration_local_esp32dev.hpp" #elif BOARD == BOARD_OAE_V1 && __has_include("Configuration_local_oae.hpp") #include "Configuration_local_oae.hpp" +#elif BOARD == BOARD_RP2040_JACKW01 && __has_include("Configuration_local_rp2040_jackw01.hpp") + #include "Configuration_local_rp2040_jackw01.hpp" +#elif BOARD == BOARD_RP2040_SKR_PICO && __has_include("Configuration_local_rp2040_skr_pico.hpp") + #include "Configuration_local_rp2040_skr_pico.hpp" #elif __has_include("Configuration_local.hpp") #include "Configuration_local.hpp" #endif \ No newline at end of file diff --git a/boards/RP2040_JACKW01/pins_RP2040_JACKW01.hpp b/boards/RP2040_JACKW01/pins_RP2040_JACKW01.hpp new file mode 100644 index 00000000..a467647b --- /dev/null +++ b/boards/RP2040_JACKW01/pins_RP2040_JACKW01.hpp @@ -0,0 +1,141 @@ +/** + * @brief Pin configuration for a Raspberry Pi Pico (RP2040/RP2350) mounted on + * the JackW01 pi-pico-printer-board carrier (https://github.com/jackw01/pi-pico-printer-board). + * + * Stepper slot mapping: + * X slot -> RA (TMC2209 UART address 0) + * Y slot -> DEC (TMC2209 UART address 1) + * Z slot -> AZ (TMC2209 UART address 2) + * E slot -> ALT (TMC2209 UART address 3) + * + * All four stepper enable lines are tied together to a single GPIO on this + * board (GPIO5). Define every axis EN pin to the same value so the firmware + * compiles cleanly; in practice enabling/disabling one axis affects all. + * Per-axis power management should be handled via the TMC2209 IHOLD register + * over UART rather than toggling EN. + * + * TMC2209 UART: all four drivers share a single-wire bus on UART1. + * TX -> GPIO8 (UART1 TX) + * RX -> GPIO9 (UART1 RX) + * Pin remapping must be applied before Serial2.begin() in platform setup: + * Serial2.setTX(RP2040_UART1_TX_PIN); + * Serial2.setRX(RP2040_UART1_RX_PIN); + */ + +#pragma once + +// ── RA axis (X slot, TMC2209 address 0) ────────────────────────────────────── +#ifndef RA_STEP_PIN + #define RA_STEP_PIN 7 +#endif +#ifndef RA_DIR_PIN + #define RA_DIR_PIN 6 +#endif +#ifndef RA_EN_PIN + #define RA_EN_PIN 5 // Shared with all axes on this board +#endif +#ifndef RA_DIAG_PIN + #define RA_DIAG_PIN 4 // X endstop input - used for Hall sensor RA homing +#endif + +// RA TMC2209 UART +#ifndef RA_SERIAL_PORT + #define RA_SERIAL_PORT Serial2 // UART1 via Philhower Serial2 +#endif +#ifndef RA_DRIVER_ADDRESS + #define RA_DRIVER_ADDRESS 0b00 // MS1=LOW, MS2=LOW +#endif + +// ── DEC axis (Y slot, TMC2209 address 2) ───────────────────────────────────── +#ifndef DEC_STEP_PIN + #define DEC_STEP_PIN 11 +#endif +#ifndef DEC_DIR_PIN + #define DEC_DIR_PIN 10 +#endif +#ifndef DEC_EN_PIN + #define DEC_EN_PIN 5 // Shared with all axes on this board +#endif +#ifndef DEC_DIAG_PIN + #define DEC_DIAG_PIN 3 // Y endstop input +#endif + +// DEC TMC2209 UART +#ifndef DEC_SERIAL_PORT + #define DEC_SERIAL_PORT Serial2 // Shared UART1 bus +#endif +#ifndef DEC_DRIVER_ADDRESS + #define DEC_DRIVER_ADDRESS 0b01 // MS1=HIGH, MS2=LOW -> address 1 +#endif + +// ── AZ axis (Z slot, TMC2209 address 1) ────────────────────────────────────── +#ifndef AZ_STEP_PIN + #define AZ_STEP_PIN 13 +#endif +#ifndef AZ_DIR_PIN + #define AZ_DIR_PIN 12 +#endif +#ifndef AZ_EN_PIN + #define AZ_EN_PIN 5 // Shared with all axes on this board +#endif + +// AZ TMC2209 UART +#ifndef AZ_SERIAL_PORT + #define AZ_SERIAL_PORT Serial2 // Shared UART1 bus +#endif +#ifndef AZ_DRIVER_ADDRESS + #define AZ_DRIVER_ADDRESS 0b10 // MS1=LOW, MS2=HIGH -> address 2 +#endif + +// ── ALT axis (Extruder slot, TMC2209 address 3) ─────────────────────────────── +#ifndef ALT_STEP_PIN + #define ALT_STEP_PIN 15 +#endif +#ifndef ALT_DIR_PIN + #define ALT_DIR_PIN 14 +#endif +#ifndef ALT_EN_PIN + #define ALT_EN_PIN 5 // Shared with all axes on this board +#endif + +// ALT TMC2209 UART +#ifndef ALT_SERIAL_PORT + #define ALT_SERIAL_PORT Serial2 // Shared UART1 bus +#endif +#ifndef ALT_DRIVER_ADDRESS + #define ALT_DRIVER_ADDRESS 0b11 // MS1=HIGH, MS2=HIGH -> address 3 +#endif + +// ── UART1 physical pin assignments ─────────────────────────────────────────── +// The JackW01 board routes UART to the TMC2209 drivers as follows: +// GPIO8 → R202 (1kΩ) → RESET/TX pad (UART1 TX) +// GPIO9 → R201 (100Ω) → MS3/RX pad (UART1 RX) +// +// BigTreeTech TMC2209 modules have an onboard resistor bridging their +// RESET/TX and MS3/RX pads to PDN_UART, so both JackW01 lines reach +// the TMC2209 PDN_UART pin. Standard two-wire hardware UART1 is used: +// TX: GPIO8 (native UART1 TX mux function) +// RX: GPIO9 (native UART1 RX mux function) +// +// b_setup.hpp calls Serial2.setTX()/setRX() before Serial2.begin() to +// remap UART1 to these pins. +#ifndef RP2040_UART1_TX_PIN + #define RP2040_UART1_TX_PIN 8 +#endif +#ifndef RP2040_UART1_RX_PIN + #define RP2040_UART1_RX_PIN 9 +#endif + +// All drivers use hardware UART (Serial2). +#define SW_SERIAL_UART 0 + +// ── Shared EN pin override ──────────────────────────────────────────────────── +// All four TMC2209 EN lines are wired together to GPIO5 on this board. +// After per-axis init leaves GPIO5 in an indeterminate state, b_setup.hpp will +// drive RP2040_SHARED_EN_PIN LOW once to enable all drivers together. +#define RP2040_SHARED_EN_PIN 5 + +// ── Debug serial port ───────────────────────────────────────────────────────── +#ifndef DEBUG_SERIAL_PORT + #define DEBUG_SERIAL_PORT Serial // USB CDC serial via Philhower core +#endif diff --git a/boards/RP2040_SKR_PICO/pins_RP2040_SKR_PICO.hpp b/boards/RP2040_SKR_PICO/pins_RP2040_SKR_PICO.hpp new file mode 100644 index 00000000..0f8c835a --- /dev/null +++ b/boards/RP2040_SKR_PICO/pins_RP2040_SKR_PICO.hpp @@ -0,0 +1,163 @@ +/** + * @brief Pin configuration for a Raspberry Pi Pico (RP2040) on the + * BigTreeTech SKR Pico v1.0 printer controller board. + * + * Hardware reference: https://github.com/bigtreetech/SKR-Pico + * Authoritative pin source: Klipper/SKR Pico klipper.cfg + * + * Stepper slot mapping (OAT axis -> board slot -> TMC2209 UART address): + * X slot -> RA (TMC2209 UART address 0) + * Y slot -> DEC (TMC2209 UART address 2) + * Z slot -> AZ (TMC2209 UART address 1) + * E0 slot -> ALT (TMC2209 UART address 3) + * + * Note: DEC uses address 2 and AZ uses address 1 — the opposite of the + * JackW01 board. This reflects the MS1/MS2 resistor strapping on + * the SKR Pico PCB. + * + * Each stepper driver has its own dedicated EN pin (unlike the JackW01 + * board where all EN lines share a single GPIO). No RP2040_SHARED_EN_PIN + * is needed; AZ_ALWAYS_ON / ALT_ALWAYS_ON are not required. + * + * TMC2209 UART: all four drivers share a two-wire bus on UART1. + * TX -> GPIO8 (UART1 TX, same physical assignment as JackW01) + * RX -> GPIO9 (UART1 RX, same physical assignment as JackW01) + * Pin remapping is applied in b_setup.hpp via: + * Serial2.setTX(RP2040_UART1_TX_PIN); + * Serial2.setRX(RP2040_UART1_RX_PIN); + * + * The SKR Pico has on-board TMC2209 ICs with proper PDN_UART wiring + * (both TX and RX reach each driver). No jumper is required. + * + * Endstop inputs (also usable as homing sensors): + * X-STOP -> GPIO4 (RA Hall sensor / diag input) + * Y-STOP -> GPIO3 + * Z-STOP -> GPIO25 + * E-STOP -> GPIO16 + * + * Additional I/O: + * BLTouch sensor -> GPIO22 + * BLTouch control -> GPIO29 + * NeoPixel data -> GPIO24 + */ + +#pragma once + +// ── RA axis (X slot, TMC2209 address 0) ────────────────────────────────────── +#ifndef RA_STEP_PIN + #define RA_STEP_PIN 11 +#endif +#ifndef RA_DIR_PIN + #define RA_DIR_PIN 10 +#endif +#ifndef RA_EN_PIN + #define RA_EN_PIN 12 // Individual EN pin (active LOW) +#endif +#ifndef RA_DIAG_PIN + #define RA_DIAG_PIN 4 // X-STOP input - used for Hall sensor RA homing +#endif + +// RA TMC2209 UART +#ifndef RA_SERIAL_PORT + #define RA_SERIAL_PORT Serial2 // UART1 via Philhower Serial2 +#endif +#ifndef RA_DRIVER_ADDRESS + #define RA_DRIVER_ADDRESS 0b00 // MS1=LOW, MS2=LOW -> address 0 +#endif + +// ── DEC axis (Y slot, TMC2209 address 2) ───────────────────────────────────── +#ifndef DEC_STEP_PIN + #define DEC_STEP_PIN 6 +#endif +#ifndef DEC_DIR_PIN + #define DEC_DIR_PIN 5 +#endif +#ifndef DEC_EN_PIN + #define DEC_EN_PIN 7 // Individual EN pin (active LOW) +#endif +#ifndef DEC_DIAG_PIN + #define DEC_DIAG_PIN 3 // Y-STOP input +#endif + +// DEC TMC2209 UART +#ifndef DEC_SERIAL_PORT + #define DEC_SERIAL_PORT Serial2 // Shared UART1 bus +#endif +#ifndef DEC_DRIVER_ADDRESS + #define DEC_DRIVER_ADDRESS 0b10 // MS1=LOW, MS2=HIGH -> address 2 +#endif + +// ── AZ axis (Z slot, TMC2209 address 1) ────────────────────────────────────── +#ifndef AZ_STEP_PIN + #define AZ_STEP_PIN 19 +#endif +#ifndef AZ_DIR_PIN + #define AZ_DIR_PIN 28 +#endif +#ifndef AZ_EN_PIN + #define AZ_EN_PIN 2 // Individual EN pin (active LOW) +#endif + +// AZ TMC2209 UART +#ifndef AZ_SERIAL_PORT + #define AZ_SERIAL_PORT Serial2 // Shared UART1 bus +#endif +#ifndef AZ_DRIVER_ADDRESS + #define AZ_DRIVER_ADDRESS 0b01 // MS1=HIGH, MS2=LOW -> address 1 +#endif + +// ── ALT axis (E0 slot, TMC2209 address 3) ──────────────────────────────────── +#ifndef ALT_STEP_PIN + #define ALT_STEP_PIN 14 +#endif +#ifndef ALT_DIR_PIN + #define ALT_DIR_PIN 13 +#endif +#ifndef ALT_EN_PIN + #define ALT_EN_PIN 15 // Individual EN pin (active LOW) +#endif + +// ALT TMC2209 UART +#ifndef ALT_SERIAL_PORT + #define ALT_SERIAL_PORT Serial2 // Shared UART1 bus +#endif +#ifndef ALT_DRIVER_ADDRESS + #define ALT_DRIVER_ADDRESS 0b11 // MS1=HIGH, MS2=HIGH -> address 3 +#endif + +// ── UART1 physical pin assignments ─────────────────────────────────────────── +// The SKR Pico routes UART1 to all four on-board TMC2209 ICs via a shared +// two-wire bus. GPIO8 and GPIO9 are the native UART1 TX/RX mux functions. +// b_setup.hpp calls Serial2.setTX()/setRX() before Serial2.begin(). +#ifndef RP2040_UART1_TX_PIN + #define RP2040_UART1_TX_PIN 8 +#endif +#ifndef RP2040_UART1_RX_PIN + #define RP2040_UART1_RX_PIN 9 +#endif + +// All drivers use hardware UART (Serial2). +#define SW_SERIAL_UART 0 + +// ── Debug serial port ───────────────────────────────────────────────────────── +#ifndef DEBUG_SERIAL_PORT + #define DEBUG_SERIAL_PORT Serial // USB CDC serial via Philhower core +#endif + +// ── GPS (UART0 on left-side header) ────────────────────────────────────────── +// Left-side 5-pin header: IO0=GPIO0, IO1=GPIO1, GND, 5V. +// RP2040 pin mux is fixed: GPIO0 = UART0 TX only, GPIO1 = UART0 RX only. +// GPS RX → GPIO0 / IO0 (RP2040 UART0 TX) +// GPS TX → GPIO1 / IO1 (RP2040 UART0 RX) +#define GPS_SERIAL_PORT Serial1 +#define RP2040_GPS_TX_PIN 0 // GPIO0 — UART0 TX → GPS RX +#define RP2040_GPS_RX_PIN 1 // GPIO1 — UART0 RX ← GPS TX + +// ── FAN outputs ─────────────────────────────────────────────────────────────── +// FAN1 connector: switched 12/24V via N-channel MOSFET gated by GPIO17. +// Power is set via analogWrite (0-100 %). Override RP2040_FAN1_POWER_PERCENT +// in your local config file to reduce fan speed. +#define RP2040_FAN1_PIN 17 +#ifndef RP2040_FAN1_POWER_PERCENT + #define RP2040_FAN1_POWER_PERCENT 100 +#endif diff --git a/matrix_build.py b/matrix_build.py index 8bc80b12..dad16c54 100644 --- a/matrix_build.py +++ b/matrix_build.py @@ -25,9 +25,13 @@ AVR_BOARDS = MKS_GENL_BOARDS + [ "ramps", ] +RP2040_BOARDS = [ + "rp2040_jackw01", + "rp2040_skr_pico", +] BOARDS = AVR_BOARDS + [ "esp32", -] +] + RP2040_BOARDS STEPPER_TYPES = [ "STEPPER_TYPE_NONE", @@ -176,6 +180,38 @@ def update_dict(orig, patch): "DISPLAY_TYPE_LCD_KEYPAD" ], }), + "rp2040_jackw01": update_dict(BUILD_FLAGS, { + "USE_GPS": [0], + "USE_GYRO_LEVEL": [0], + "DISPLAY_TYPE": [ + "DISPLAY_TYPE_NONE" + ], + "INFO_DISPLAY_TYPE": [ + "INFO_DISPLAY_TYPE_NONE" + ], + "FOCUS_DRIVER_TYPE": [ + "DRIVER_TYPE_NONE" + ], + "FOCUS_STEPPER_TYPE": [ + "STEPPER_TYPE_NONE" + ], + }), + "rp2040_skr_pico": update_dict(BUILD_FLAGS, { + "USE_GPS": [0], + "USE_GYRO_LEVEL": [0], + "DISPLAY_TYPE": [ + "DISPLAY_TYPE_NONE" + ], + "INFO_DISPLAY_TYPE": [ + "INFO_DISPLAY_TYPE_NONE" + ], + "FOCUS_DRIVER_TYPE": [ + "DRIVER_TYPE_NONE" + ], + "FOCUS_STEPPER_TYPE": [ + "STEPPER_TYPE_NONE" + ], + }), } SHORT_STRINGS = { diff --git a/platformio.ini b/platformio.ini index 8afeb09a..7b68d651 100644 --- a/platformio.ini +++ b/platformio.ini @@ -139,6 +139,44 @@ build_flags = -std=gnu++17 -D BOARD=BOARD_OAE_V1 -D ESP32BOARD +[common_rp2xxx] +extends = common_embedded +; Use maxgerhardt platform wrapper to access Earle Philhower arduino-pico core. +; The official platform-raspberrypi uses the Arduino-mbed core which has poorer +; library compatibility and no flexible UART pin remapping. +platform = https://github.com/maxgerhardt/platform-raspberrypi.git +board_build.core = earlephilhower +; SSD1306_128x64_Display.cpp includes SSD1306Wire.h unconditionally at the top of +; the file (not guarded by INFO_DISPLAY_TYPE), so it can't compile without that +; library. RP2040 boards don't support this display (ConfigurationValidation.hpp +; forces INFO_DISPLAY_TYPE_NONE), so exclude the file instead of pulling in an +; otherwise-unused, possibly RP2040-incompatible dependency. +src_filter = + ${common_embedded.src_filter} + - +lib_deps = + teemuatlut/TMCStepper @ ^0.7.1 + waspinator/AccelStepper @ ^1.61 + mikalhart/TinyGPSPlus @ ^1.0.2 +; TimerInterrupt is AVR-only (uses OCR1A etc.); RP2040 uses hardware/timer.h directly +lib_ignore = TimerInterrupt + +[env:rp2040_jackw01] +extends = common_rp2xxx +board = rpipico +build_flags = + ${env.build_flags} + -Wno-deprecated-declarations ; arduino-pico core deprecates the B00000000-style Arduino::Binary.h macros used throughout the shared Mount code + -D BOARD=BOARD_RP2040_JACKW01 + +[env:rp2040_skr_pico] +extends = common_rp2xxx +board = rpipico +build_flags = + ${env.build_flags} + -Wno-deprecated-declarations ; arduino-pico core deprecates the B00000000-style Arduino::Binary.h macros used throughout the shared Mount code + -D BOARD=BOARD_RP2040_SKR_PICO + [env:native] platform = native test_build_src = true diff --git a/src/EPROMStore.cpp b/src/EPROMStore.cpp index 5784c177..b4c2108d 100644 --- a/src/EPROMStore.cpp +++ b/src/EPROMStore.cpp @@ -84,6 +84,41 @@ uint8_t EEPROMStore::read(uint8_t location) return value; } +#elif defined(ARDUINO_ARCH_RP2040) + +// Initialize the flash-backed EEPROM emulation provided by the Philhower +// arduino-pico core. API is identical to the ESP32 path. +void EEPROMStore::initialize() +{ + LOG(DEBUG_EEPROM, "[EEPROM]: RP2040: Startup with %d bytes", STORE_SIZE); + EEPROM.begin(STORE_SIZE); + + displayContents(); +} + +// Update the given location with the given value +void EEPROMStore::update(uint8_t location, uint8_t value) +{ + LOG(DEBUG_EEPROM, "[EEPROM]: RP2040: Writing %x to %d", value, location); + EEPROM.write(location, value); +} + +// Complete the transaction (flush RAM cache to flash) +void EEPROMStore::commit() +{ + LOG(DEBUG_EEPROM, "[EEPROM]: RP2040: Committing"); + EEPROM.commit(); +} + +// Read the value at the given location +uint8_t EEPROMStore::read(uint8_t location) +{ + uint8_t value; + value = EEPROM.read(location); + LOG(DEBUG_EEPROM, "[EEPROM]: RP2040: Read %x from %d", value, location); + return value; +} + #else // Initialize the EEPROM storage in a platform-independent abstraction diff --git a/src/InterruptCallback.cpp b/src/InterruptCallback.cpp index 2a7d5694..18ab6601 100644 --- a/src/InterruptCallback.cpp +++ b/src/InterruptCallback.cpp @@ -20,6 +20,11 @@ PUSH_NO_WARNINGS #include "libs/TimerInterrupt/TimerInterrupt.h" POP_NO_WARNINGS + #elif defined(ARDUINO_ARCH_RP2040) + // Earle Philhower arduino-pico core exposes the Pico SDK alarm API. + // add_repeating_timer_us() fires a hardware alarm callback at a precise + // interval without relying on FreeRTOS or a second core. + #include #else #error Unrecognized board selected. Either implement interrupt code or define the board here. #endif @@ -47,5 +52,47 @@ void InterruptCallback::start() ITimer2.restartTimer(); } + #elif defined(ARDUINO_ARCH_RP2040) + +// Storage for the repeating timer handle and the user callback+payload. +static repeating_timer_t _rp2040_timer; +static interrupt_callback_p _rp2040_callback = nullptr; +static void *_rp2040_payload = nullptr; + +// The Pico SDK alarm callback signature returns bool; returning true keeps +// the timer repeating. +static bool rp2040_timer_isr(repeating_timer_t * /* rt */) +{ + if (_rp2040_callback) + { + _rp2040_callback(_rp2040_payload); + } + return true; // Keep repeating +} + +bool InterruptCallback::setInterval(float intervalMs, interrupt_callback_p callback, void *payload) +{ + _rp2040_callback = callback; + _rp2040_payload = payload; + + // Positive delay_us means the period is measured from callback-start to + // callback-start (fixed wall-clock rate), which is what the stepper + // controller needs for consistent timing. + int32_t intervalUs = static_cast(intervalMs * 1000.0f); + return add_repeating_timer_us(intervalUs, rp2040_timer_isr, nullptr, &_rp2040_timer); +} + +void InterruptCallback::stop() +{ + cancel_repeating_timer(&_rp2040_timer); +} + +void InterruptCallback::start() +{ + // Re-arm with the same interval. The stored callback/payload are still set. + int32_t intervalUs = static_cast(_rp2040_timer.delay_us); + add_repeating_timer_us(intervalUs, rp2040_timer_isr, nullptr, &_rp2040_timer); +} + #endif #endif \ No newline at end of file diff --git a/src/Latitude.hpp b/src/Latitude.hpp index c3ec1591..a3d1f271 100644 --- a/src/Latitude.hpp +++ b/src/Latitude.hpp @@ -15,6 +15,7 @@ class Latitude : public core::Latitude { } Latitude(const Latitude &other); + Latitude &operator=(const Latitude &) = default; Latitude(int h, int m, int s); Latitude(float inDegrees); diff --git a/src/Longitude.hpp b/src/Longitude.hpp index 19661c7f..4c2bd0d0 100644 --- a/src/Longitude.hpp +++ b/src/Longitude.hpp @@ -17,6 +17,7 @@ class Longitude : public core::Longitude { } Longitude(const Longitude &other); + Longitude &operator=(const Longitude &) = default; Longitude(int h, int m, int s); Longitude(float inDegrees); diff --git a/src/Mount.cpp b/src/Mount.cpp index 22911649..20429bd9 100644 --- a/src/Mount.cpp +++ b/src/Mount.cpp @@ -498,7 +498,11 @@ void Mount::configureRAdriver(Stream *serial, float rsense, byte driveraddress, _driverRA->rms_current(rmscurrent, 1.0f); //holdMultiplier = 1 to set ihold = irun _driverRA->pdn_disable(1); _driverRA->ihold(31); + #if defined(ARDUINO_ARCH_RP2040) + _driverRA->toff(4); // toff(1) is too short for StealthChop to engage reliably on RP2040 + #else _driverRA->toff(1); + #endif _driverRA->en_spreadCycle(RA_UART_STEALTH_MODE == 0); _driverRA->blank_time(24); _driverRA->microsteps(RA_TRACKING_MICROSTEPPING == 1 ? 0 : RA_TRACKING_MICROSTEPPING); // System starts in tracking mode @@ -537,7 +541,11 @@ void Mount::configureRAdriver(uint16_t RA_SW_RX, uint16_t RA_SW_TX, float rsense #endif LOG(DEBUG_STEPPERS, "[MOUNT]: Requested RA motor rms_current: %d mA", rmscurrent); _driverRA->rms_current(rmscurrent, 1.0f); //holdMultiplier = 1 to set ihold = irun + #if defined(ARDUINO_ARCH_RP2040) + _driverRA->toff(4); // toff(1) is too short for StealthChop to engage reliably on RP2040 + #else _driverRA->toff(1); + #endif _driverRA->en_spreadCycle(RA_UART_STEALTH_MODE == 0); _driverRA->blank_time(24); _driverRA->semin(0); //disable CoolStep so that current is consistent @@ -585,7 +593,11 @@ void Mount::configureDECdriver(Stream *serial, float rsense, byte driveraddress, _driverDEC->ihold(31); _driverDEC->iholddelay(15); _driverDEC->TPOWERDOWN(255); + #if defined(ARDUINO_ARCH_RP2040) + _driverDEC->toff(4); // toff(1) is too short for StealthChop to engage reliably on RP2040 + #else _driverDEC->toff(1); + #endif _driverDEC->en_spreadCycle(DEC_UART_STEALTH_MODE == 0); _driverDEC->blank_time(24); _driverDEC->microsteps( @@ -624,7 +636,11 @@ void Mount::configureDECdriver(uint16_t DEC_SW_RX, uint16_t DEC_SW_TX, float rse #endif LOG(DEBUG_STEPPERS, "[MOUNT]: Requested DEC motor rms_current: %d mA", rmscurrent); _driverDEC->rms_current(rmscurrent, 1.0f); //holdMultiplier = 1 to set ihold = irun + #if defined(ARDUINO_ARCH_RP2040) + _driverDEC->toff(4); // toff(1) is too short for StealthChop to engage reliably on RP2040 + #else _driverDEC->toff(1); + #endif _driverDEC->en_spreadCycle(DEC_UART_STEALTH_MODE == 0); _driverDEC->blank_time(24); _driverDEC->microsteps( @@ -668,7 +684,11 @@ void Mount::configureAZdriver(Stream *serial, float rsense, byte driveraddress, #endif LOG(DEBUG_STEPPERS, "[MOUNT]: Requested AZ motor rms_current: %d mA", rmscurrent); _driverAZ->rms_current(rmscurrent, AZ_MOTOR_HOLD_SETTING / 100.0); //holdMultiplier = 1 to set ihold = irun + #if defined(ARDUINO_ARCH_RP2040) + _driverAZ->toff(4); // toff(1) is too short for StealthChop to engage reliably on RP2040 + #else _driverAZ->toff(1); + #endif _driverAZ->en_spreadCycle(0); _driverAZ->blank_time(24); _driverAZ->microsteps(AZ_MICROSTEPPING == 1 ? 0 : AZ_MICROSTEPPING); // If 1 then disable microstepping @@ -706,7 +726,11 @@ void Mount::configureAZdriver(uint16_t AZ_SW_RX, uint16_t AZ_SW_TX, float rsense #endif LOG(DEBUG_STEPPERS, "[MOUNT]: Requested AZ motor rms_current: %d mA", rmscurrent); _driverAZ->rms_current(rmscurrent, AZ_MOTOR_HOLD_SETTING / 100.0); //holdMultiplier = 1 to set ihold = irun + #if defined(ARDUINO_ARCH_RP2040) + _driverAZ->toff(4); // toff(1) is too short for StealthChop to engage reliably on RP2040 + #else _driverAZ->toff(1); + #endif _driverAZ->en_spreadCycle(0); _driverAZ->blank_time(24); _driverAZ->microsteps(AZ_MICROSTEPPING == 1 ? 0 : AZ_MICROSTEPPING); // If 1 then disable microstepping @@ -749,7 +773,11 @@ void Mount::configureALTdriver(Stream *serial, float rsense, byte driveraddress, #endif LOG(DEBUG_STEPPERS, "[MOUNT]: Requested ALT motor rms_current: %d mA", rmscurrent); _driverALT->rms_current(rmscurrent, ALT_MOTOR_HOLD_SETTING / 100.0); //holdMultiplier = 1 to set ihold = irun + #if defined(ARDUINO_ARCH_RP2040) + _driverALT->toff(4); // toff(1) is too short for StealthChop to engage reliably on RP2040 + #else _driverALT->toff(1); + #endif _driverALT->en_spreadCycle(0); _driverALT->blank_time(24); _driverALT->microsteps(ALT_MICROSTEPPING == 1 ? 0 : ALT_MICROSTEPPING); // If 1 then disable microstepping @@ -787,7 +815,11 @@ void Mount::configureALTdriver(uint16_t ALT_SW_RX, uint16_t ALT_SW_TX, float rse #endif LOG(DEBUG_STEPPERS, "[MOUNT]: Requested ALT motor rms_current: %d mA", rmscurrent); _driverALT->rms_current(rmscurrent, ALT_MOTOR_HOLD_SETTING / 100.0); //holdMultiplier = 1 to set ihold = irun + #if defined(ARDUINO_ARCH_RP2040) + _driverALT->toff(4); // toff(1) is too short for StealthChop to engage reliably on RP2040 + #else _driverALT->toff(1); + #endif _driverALT->en_spreadCycle(0); _driverALT->blank_time(24); _driverALT->microsteps(ALT_MICROSTEPPING == 1 ? 0 : ALT_MICROSTEPPING); // If 1 then disable microstepping @@ -832,7 +864,11 @@ void Mount::configureFocusDriver(Stream *serial, float rsense, byte driveraddres #endif LOG(DEBUG_STEPPERS | DEBUG_FOCUS, "[FOCUS]: Requested Focus motor rms_current: %d mA", rmscurrent); _driverFocus->rms_current(rmscurrent, FOCUSER_MOTOR_HOLD_SETTING / 100.f); //holdMultiplier = 1 to set ihold = irun + #if defined(ARDUINO_ARCH_RP2040) + _driverFocus->toff(4); // toff(1) is too short for StealthChop to engage reliably on RP2040 + #else _driverFocus->toff(1); + #endif _driverFocus->en_spreadCycle(FOCUS_UART_STEALTH_MODE == 0); _driverFocus->blank_time(24); _driverFocus->microsteps(FOCUS_MICROSTEPPING == 1 ? 0 : FOCUS_MICROSTEPPING); // If 1 then disable microstepping @@ -878,7 +914,11 @@ void Mount::configureFocusDriver( #endif LOG(DEBUG_STEPPERS | DEBUG_FOCUS, "[FOCUS]: Requested Focus motor rms_current: %d mA", rmscurrent); _driverFocus->rms_current(rmscurrent, FOCUSER_MOTOR_HOLD_SETTING / 100.f); //holdMultiplier = 1 to set ihold = irun + #if defined(ARDUINO_ARCH_RP2040) + _driverFocus->toff(4); // toff(1) is too short for StealthChop to engage reliably on RP2040 + #else _driverFocus->toff(1); + #endif _driverFocus->en_spreadCycle(FOCUS_UART_STEALTH_MODE == 0); _driverFocus->blank_time(24); _driverFocus->microsteps(FOCUS_MICROSTEPPING == 1 ? 0 : FOCUS_MICROSTEPPING); // If 1 then disable microstepping diff --git a/src/b_setup.hpp b/src/b_setup.hpp index 76f10786..e2a3d355 100644 --- a/src/b_setup.hpp +++ b/src/b_setup.hpp @@ -126,9 +126,26 @@ void setup() #endif #else Serial.begin(SERIAL_BAUDRATE); + #if defined(ARDUINO_ARCH_RP2040) + // OATControl (and other apps using C# SerialPort) open the port with DTR=false. + // The Philhower USB CDC SerialUSB::write() gates TX on tud_cdc_connected() which + // requires DTR=true, so all responses are silently dropped for those hosts. + // ignoreFlowControl(true) bypasses the DTR check and always sends TX data. + Serial.ignoreFlowControl(true); + #endif #if DEBUG_LEVEL > 0 && DEBUG_SEPARATE_SERIAL == 1 DEBUG_SERIAL_PORT.begin(DEBUG_SERIAL_BAUDRATE); #endif + // RP2040 USB CDC: wait up to 3 s for the host to open the port so that + // LOG() calls below are not dropped (or do not block indefinitely). + // This only matters when DEBUG_LEVEL > 0 — in release builds LOG() is + // a no-op, so the wait is compiled out. + #if defined(ARDUINO_ARCH_RP2040) && DEBUG_LEVEL > 0 + { + uint32_t _cdcWaitStart = millis(); + while (!Serial && (millis() - _cdcWaitStart) < 3000UL) { /* spin */ } + } + #endif #endif #if TEST_VERIFY_MODE == 1 @@ -161,6 +178,10 @@ void setup() #if (INFO_DISPLAY_TYPE != INFO_DISPLAY_TYPE_NONE) int gpsLine = addConsoleText(F("Initialize GPS...")); #endif + #if defined(ARDUINO_ARCH_RP2040) && defined(RP2040_GPS_TX_PIN) && defined(RP2040_GPS_RX_PIN) + GPS_SERIAL_PORT.setTX(RP2040_GPS_TX_PIN); + GPS_SERIAL_PORT.setRX(RP2040_GPS_RX_PIN); + #endif GPS_SERIAL_PORT.begin(GPS_BAUD_RATE); #if (INFO_DISPLAY_TYPE != INFO_DISPLAY_TYPE_NONE) updateConsoleText(gpsLine, F("Initialize GPS... OK")); @@ -180,6 +201,11 @@ void setup() updateConsoleText(dewHeaterLine, F("Enable Dew Heater... OK")); #endif +#if defined(RP2040_FAN1_PIN) + pinMode(RP2040_FAN1_PIN, OUTPUT); + analogWrite(RP2040_FAN1_PIN, (RP2040_FAN1_POWER_PERCENT * 255) / 100); +#endif + #if (USE_RA_END_SWITCH == 1 || USE_DEC_END_SWITCH == 1) int endSwitchesLine = addConsoleText(F("Init End Switches...")); LOG(DEBUG_ANY, "[SYSTEM]: Init EndSwitches..."); @@ -187,6 +213,21 @@ void setup() updateConsoleText(endSwitchesLine, F("Init End Switches... OK")); #endif + ///////////////////////////////// + // RP2040: UART pin remapping + ///////////////////////////////// + // The Philhower arduino-pico core requires setTX()/setRX() to be called + // before begin() to remap UART pins away from their defaults. This must + // happen before any Serial2.begin() calls in the driver setup below. + // RP2040_UART1_TX_PIN / RP2040_UART1_RX_PIN are defined in the board's + // pins file only for RP2040 targets that use a non-default UART1 mapping. +#if defined(ARDUINO_ARCH_RP2040) && defined(RP2040_UART1_TX_PIN) && defined(RP2040_UART1_RX_PIN) + Serial2.setTX(RP2040_UART1_TX_PIN); + Serial2.setRX(RP2040_UART1_RX_PIN); + Serial2.setPollingMode(true); // Must be called before begin(); avoids IRQ/CoreMutex blocking in TMCStepper read path + Serial2.begin(115200); // TMCStepper HW-serial path never calls begin(); must do it here. +#endif + ///////////////////////////////// // Microstepping/driver pins ///////////////////////////////// @@ -213,7 +254,9 @@ void setup() #endif #ifdef RA_SERIAL_PORT - #ifdef OAE + #if defined(ARDUINO_ARCH_RP2040) + RA_SERIAL_PORT.begin(115200); // TMCStepper requires 115200 baud on the Philhower RP2040 core + #elif defined(OAE) RA_SERIAL_PORT.begin(57600, SERIAL_8N1, RA_RX_PIN, RA_TX_PIN); #else RA_SERIAL_PORT.begin(57600); // Start HardwareSerial comms with driver @@ -246,7 +289,9 @@ void setup() pinMode(DEC_DIAG_PIN, INPUT); #endif #ifdef DEC_SERIAL_PORT - #ifdef OAE + #if defined(ARDUINO_ARCH_RP2040) + DEC_SERIAL_PORT.begin(115200); // TMCStepper requires 115200 baud on the Philhower RP2040 core + #elif defined(OAE) DEC_SERIAL_PORT.begin(57600, SERIAL_8N1, DEC_RX_PIN, DEC_TX_PIN); #else DEC_SERIAL_PORT.begin(57600); // Start HardwareSerial comms with driver @@ -263,9 +308,15 @@ void setup() digitalWrite(AZ_EN_PIN, HIGH); // Logic HIGH to disable the driver initally #if AZ_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART // include TMC2209 UART pins + #if defined(AZ_DIAG_PIN) pinMode(AZ_DIAG_PIN, INPUT); + #endif #ifdef AZ_SERIAL_PORT + #if defined(ARDUINO_ARCH_RP2040) + AZ_SERIAL_PORT.begin(115200); // TMCStepper requires 115200 baud on the Philhower RP2040 core + #else AZ_SERIAL_PORT.begin(57600); // Start HardwareSerial comms with driver + #endif #endif #endif updateConsoleText(azLine, F("Init AZ axis... OK")); @@ -278,9 +329,15 @@ void setup() digitalWrite(ALT_EN_PIN, HIGH); // Logic HIGH to disable the driver initally #if ALT_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART // include TMC2209 UART pins + #if defined(ALT_DIAG_PIN) pinMode(ALT_DIAG_PIN, INPUT); + #endif #ifdef ALT_SERIAL_PORT + #if defined(ARDUINO_ARCH_RP2040) + ALT_SERIAL_PORT.begin(115200); // TMCStepper requires 115200 baud on the Philhower RP2040 core + #else ALT_SERIAL_PORT.begin(57600); // Start HardwareSerial comms with driver + #endif #endif #endif updateConsoleText(altLine, F("Init ALT axis... OK")); @@ -295,11 +352,25 @@ void setup() // include TMC2209 UART pins #ifdef FOCUS_SERIAL_PORT LOG(DEBUG_FOCUS, "[FOCUS]: setup(): focus TMC2209U starting comms"); + #if defined(ARDUINO_ARCH_RP2040) + FOCUS_SERIAL_PORT.begin(115200); // TMCStepper requires 115200 baud on the Philhower RP2040 core + #else FOCUS_SERIAL_PORT.begin(57600); // Start HardwareSerial comms with driver + #endif #endif #endif updateConsoleText(focusLine, F("Init Focuser... OK")); #endif + +#if defined(RP2040_SHARED_EN_PIN) + // On boards where all stepper EN lines share one GPIO (e.g. JackW01 carrier), + // the per-axis init sequence leaves that GPIO HIGH (logic disabled) after the + // AZ/ALT blocks run. Force it LOW here so every driver is enabled once all + // UART addresses have been configured. Per-axis power management is handled + // via the TMC2209 IHOLD register over UART rather than toggling this pin. + pinMode(RP2040_SHARED_EN_PIN, OUTPUT); + digitalWrite(RP2040_SHARED_EN_PIN, LOW); +#endif // end microstepping ------------------- #if USE_HALL_SENSOR_RA_AUTOHOME == 1 || USE_HALL_SENSOR_DEC_AUTOHOME == 1 @@ -535,6 +606,15 @@ void setup() #endif #endif +#if defined(RP2040_SHARED_EN_PIN) + // Re-assert EN LOW after all driver configs. Each configureXXXdriver() that + // fails its UART connection test calls digitalWrite(X_EN_PIN, HIGH) as a + // safety measure; on JackW01 all EN lines share one GPIO so all four failures + // leave that GPIO HIGH (motors disabled). Override it here unconditionally so + // the motors are always enabled after initialization. + digitalWrite(RP2040_SHARED_EN_PIN, LOW); +#endif + LOG(DEBUG_ANY, "[SYSTEM]: Energize Steppers... OK"); updateConsoleText(stepperLine, F("Energize Steppers... OK")); diff --git a/src/c_buttons.hpp b/src/c_buttons.hpp index d594cb2c..8c58c2cb 100644 --- a/src/c_buttons.hpp +++ b/src/c_buttons.hpp @@ -98,6 +98,13 @@ void loop() lcdMenu.setCursor(0, 1); #if SUPPORT_SERIAL_CONTROL == 1 + #if defined(ARDUINO_ARCH_RP2040) + // On RP2040, the Philhower core does not reliably call serialEvent() for the + // USB CDC Serial port when a host application opens the port and immediately + // sends data (e.g. OATControl). Poll explicitly on every loop() iteration so + // that commands are always processed regardless of inSerialControl state. + processSerialData(); + #endif if (inSerialControl) { if (lcdButtons.keyChanged(&lcd_key)) diff --git a/src/core/types/DayTime.hpp b/src/core/types/DayTime.hpp index 98c0638d..7ab5c3ca 100644 --- a/src/core/types/DayTime.hpp +++ b/src/core/types/DayTime.hpp @@ -18,6 +18,7 @@ class DayTime DayTime(); DayTime(const DayTime &other); + DayTime &operator=(const DayTime &) = default; DayTime(int h, int m, int s); // From hours (fractional) diff --git a/src/core/types/Declination.hpp b/src/core/types/Declination.hpp index de65d3e9..ca3185d5 100644 --- a/src/core/types/Declination.hpp +++ b/src/core/types/Declination.hpp @@ -15,6 +15,7 @@ class Declination : public DayTime public: Declination(); Declination(const Declination &other); + Declination &operator=(const Declination &) = default; Declination(int h, int m, int s); Declination(float inDegrees); diff --git a/src/core/types/Latitude.hpp b/src/core/types/Latitude.hpp index 168587ce..feb382b5 100644 --- a/src/core/types/Latitude.hpp +++ b/src/core/types/Latitude.hpp @@ -12,6 +12,7 @@ class Latitude : public DayTime public: Latitude(); Latitude(const Latitude &other); + Latitude &operator=(const Latitude &) = default; Latitude(int h, int m, int s); Latitude(float inDegrees); diff --git a/src/core/types/Longitude.hpp b/src/core/types/Longitude.hpp index 6c52e44e..f9722c1c 100644 --- a/src/core/types/Longitude.hpp +++ b/src/core/types/Longitude.hpp @@ -12,6 +12,7 @@ class Longitude : public DayTime public: Longitude(); Longitude(const Longitude &other); + Longitude &operator=(const Longitude &) = default; Longitude(int h, int m, int s); Longitude(float inDegrees); From 423b6eedd885fcd1f0112aabcd74d4d0d1fb5ccf Mon Sep 17 00:00:00 2001 From: Lutz Date: Sun, 11 Oct 2026 13:36:27 -0700 Subject: [PATCH 2/2] style: apply clang-format to the RP2040 files CI fails forked PRs that need formatting changes (the auto-fix commit only runs for branches in the main repository), so apply the project clang-format directly: brace placement in the CDC console wait, a trailing-comment column, nested #if indentation, and #define column alignment in the example configuration. No code changes. Co-Authored-By: Claude Code --- .../Configuration_local_rp2040_skr_pico.hpp | 24 +++++++++---------- src/b_setup.hpp | 10 ++++---- src/c_buttons.hpp | 4 ++-- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/Configuration_local_examples/Configuration_local_rp2040_skr_pico.hpp b/Configuration_local_examples/Configuration_local_rp2040_skr_pico.hpp index 16fe2038..a757cfe5 100644 --- a/Configuration_local_examples/Configuration_local_rp2040_skr_pico.hpp +++ b/Configuration_local_examples/Configuration_local_rp2040_skr_pico.hpp @@ -94,33 +94,33 @@ // RMSCURRENT = RATING * (SETTING / 100) / sqrt(2) => ~249 mA RMS // Do NOT define XXX_RMSCURRENT directly; Configuration_adv.hpp will error. #define RA_MOTOR_CURRENT_RATING 470 // mA -#define RA_OPERATING_CURRENT_SETTING 75 // % +#define RA_OPERATING_CURRENT_SETTING 75 // % -#define DEC_MOTOR_CURRENT_RATING 470 // mA -#define DEC_OPERATING_CURRENT_SETTING 75 // % +#define DEC_MOTOR_CURRENT_RATING 470 // mA +#define DEC_OPERATING_CURRENT_SETTING 75 // % #define AZ_MOTOR_CURRENT_RATING 470 // mA -#define AZ_OPERATING_CURRENT_SETTING 75 // % +#define AZ_OPERATING_CURRENT_SETTING 75 // % -#define ALT_MOTOR_CURRENT_RATING 470 // mA -#define ALT_OPERATING_CURRENT_SETTING 75 // % +#define ALT_MOTOR_CURRENT_RATING 470 // mA +#define ALT_OPERATING_CURRENT_SETTING 75 // % // ── AZ/ALT hold current ─────────────────────────────────────────────────────── // AZ must hold position against backlash forces; use 40 % of run current. // ALT is held by friction and gearing; bleed hold current to zero. // These are percentages (0-100) converted to TMC2209 IHOLD by the firmware. #define AZ_MOTOR_HOLD_SETTING 40 // % -#define ALT_MOTOR_HOLD_SETTING 0 // % +#define ALT_MOTOR_HOLD_SETTING 0 // % // ── DEC axis travel limits ──────────────────────────────────────────────────── // Physical limits measured from the home (level) position. // These must be defined here; Configuration_adv.hpp defaults to 0.0f for // non-OAM builds, which makes :Mn#/:Ms# target position 0 and do nothing. #ifndef DEC_LIMIT_UP - #define DEC_LIMIT_UP 135.0f // 135° north of home + #define DEC_LIMIT_UP 135.0f // 135° north of home #endif #ifndef DEC_LIMIT_DOWN - #define DEC_LIMIT_DOWN 35.0f // 35° south of home + #define DEC_LIMIT_DOWN 35.0f // 35° south of home #endif // ── RA Hall sensor auto-home ────────────────────────────────────────────────── @@ -129,9 +129,9 @@ // Search distance: 30° default (RA_HOMING_SENSOR_SEARCH_DEGREES in Configuration_adv.hpp). // GPIO4 is configured INPUT (no pull-up); add external 10kΩ to 3.3V if sensor // is open-drain, or change to INPUT_PULLUP in b_setup.hpp. -#define USE_HALL_SENSOR_RA_AUTOHOME 1 -#define RA_HOMING_SENSOR_PIN 4 // GPIO4 = RA_DIAG_PIN (X-STOP) -#define RA_HOMING_SENSOR_ACTIVE_STATE LOW // sensor pulls LOW when active +#define USE_HALL_SENSOR_RA_AUTOHOME 1 +#define RA_HOMING_SENSOR_PIN 4 // GPIO4 = RA_DIAG_PIN (X-STOP) +#define RA_HOMING_SENSOR_ACTIVE_STATE LOW // sensor pulls LOW when active // ── GPS ─────────────────────────────────────────────────────────────────────── // ATGM336H-5N wired to left-side header: GPS TX→IO1, GPS RX→IO0, VCC→5V, GND. diff --git a/src/b_setup.hpp b/src/b_setup.hpp index e2a3d355..2b2c21c0 100644 --- a/src/b_setup.hpp +++ b/src/b_setup.hpp @@ -143,7 +143,9 @@ void setup() #if defined(ARDUINO_ARCH_RP2040) && DEBUG_LEVEL > 0 { uint32_t _cdcWaitStart = millis(); - while (!Serial && (millis() - _cdcWaitStart) < 3000UL) { /* spin */ } + while (!Serial && (millis() - _cdcWaitStart) < 3000UL) + { /* spin */ + } } #endif #endif @@ -225,7 +227,7 @@ void setup() Serial2.setTX(RP2040_UART1_TX_PIN); Serial2.setRX(RP2040_UART1_RX_PIN); Serial2.setPollingMode(true); // Must be called before begin(); avoids IRQ/CoreMutex blocking in TMCStepper read path - Serial2.begin(115200); // TMCStepper HW-serial path never calls begin(); must do it here. + Serial2.begin(115200); // TMCStepper HW-serial path never calls begin(); must do it here. #endif ///////////////////////////////// @@ -307,7 +309,7 @@ void setup() pinMode(AZ_EN_PIN, OUTPUT); digitalWrite(AZ_EN_PIN, HIGH); // Logic HIGH to disable the driver initally #if AZ_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART - // include TMC2209 UART pins + // include TMC2209 UART pins #if defined(AZ_DIAG_PIN) pinMode(AZ_DIAG_PIN, INPUT); #endif @@ -328,7 +330,7 @@ void setup() pinMode(ALT_EN_PIN, OUTPUT); digitalWrite(ALT_EN_PIN, HIGH); // Logic HIGH to disable the driver initally #if ALT_DRIVER_TYPE == DRIVER_TYPE_TMC2209_UART - // include TMC2209 UART pins + // include TMC2209 UART pins #if defined(ALT_DIAG_PIN) pinMode(ALT_DIAG_PIN, INPUT); #endif diff --git a/src/c_buttons.hpp b/src/c_buttons.hpp index 8c58c2cb..c1c3a321 100644 --- a/src/c_buttons.hpp +++ b/src/c_buttons.hpp @@ -98,13 +98,13 @@ void loop() lcdMenu.setCursor(0, 1); #if SUPPORT_SERIAL_CONTROL == 1 - #if defined(ARDUINO_ARCH_RP2040) + #if defined(ARDUINO_ARCH_RP2040) // On RP2040, the Philhower core does not reliably call serialEvent() for the // USB CDC Serial port when a host application opens the port and immediately // sends data (e.g. OATControl). Poll explicitly on every loop() iteration so // that commands are always processed regardless of inSerialControl state. processSerialData(); - #endif + #endif if (inSerialControl) { if (lcdButtons.keyChanged(&lcd_key))