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..a757cfe5 --- /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..2b2c21c0 100644 --- a/src/b_setup.hpp +++ b/src/b_setup.hpp @@ -126,9 +126,28 @@ 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 +180,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 +203,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 +215,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 +256,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 +291,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 @@ -262,10 +309,16 @@ 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 #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")); @@ -277,10 +330,16 @@ 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 #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 +354,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 +608,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..c1c3a321 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);