Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,113 @@ dkms.conf
/Release/objects.mk
/Release/rotary-controller-f4.list
/Release/sources.mk
/rotary-controller-f4.bin
/Makefile
/CMakeCache.txt
/cmake_install.cmake
/CMakeFiles/4.0.2/CompilerIdC/CMakeCCompilerId.c
/CMakeFiles/4.0.2/CompilerIdCXX/CMakeCXXCompilerId.cpp
/CMakeFiles/4.0.2/CMakeASMCompiler.cmake
/CMakeFiles/4.0.2/CMakeCCompiler.cmake
/CMakeFiles/4.0.2/CMakeCXXCompiler.cmake
/CMakeFiles/4.0.2/CMakeDetermineCompilerABI_C.bin
/CMakeFiles/4.0.2/CMakeDetermineCompilerABI_CXX.bin
/CMakeFiles/4.0.2/CMakeSystem.cmake
/CMakeFiles/4.0.3-dirty/CompilerIdC/CMakeCCompilerId.c
/CMakeFiles/4.0.3-dirty/CompilerIdCXX/CMakeCXXCompilerId.cpp
/CMakeFiles/4.0.3-dirty/CMakeASMCompiler.cmake
/CMakeFiles/4.0.3-dirty/CMakeCCompiler.cmake
/CMakeFiles/4.0.3-dirty/CMakeCXXCompiler.cmake
/CMakeFiles/4.0.3-dirty/CMakeDetermineCompilerABI_C.bin
/CMakeFiles/4.0.3-dirty/CMakeDetermineCompilerABI_CXX.bin
/CMakeFiles/4.0.3-dirty/CMakeSystem.cmake
/CMakeFiles/4.1.2/CompilerIdC/CMakeCCompilerId.c
/CMakeFiles/4.1.2/CompilerIdCXX/CMakeCXXCompilerId.cpp
/CMakeFiles/4.1.2/CMakeASMCompiler.cmake
/CMakeFiles/4.1.2/CMakeCCompiler.cmake
/CMakeFiles/4.1.2/CMakeCXXCompiler.cmake
/CMakeFiles/4.1.2/CMakeDetermineCompilerABI_C.bin
/CMakeFiles/4.1.2/CMakeDetermineCompilerABI_CXX.bin
/CMakeFiles/4.1.2/CMakeSystem.cmake
/CMakeFiles/4.2.1/CompilerIdC/CMakeCCompilerId.c
/CMakeFiles/4.2.1/CompilerIdCXX/CMakeCXXCompilerId.cpp
/CMakeFiles/4.2.1/CMakeASMCompiler.cmake
/CMakeFiles/4.2.1/CMakeCCompiler.cmake
/CMakeFiles/4.2.1/CMakeCXXCompiler.cmake
/CMakeFiles/4.2.1/CMakeDetermineCompilerABI_C.bin
/CMakeFiles/4.2.1/CMakeDetermineCompilerABI_CXX.bin
/CMakeFiles/4.2.1/CMakeSystem.cmake
/CMakeFiles/rotary-controller-f4.elf.dir/ASM.includecache
/CMakeFiles/rotary-controller-f4.elf.dir/build.make
/CMakeFiles/rotary-controller-f4.elf.dir/cmake_clean.cmake
/CMakeFiles/rotary-controller-f4.elf.dir/compiler_depend.make
/CMakeFiles/rotary-controller-f4.elf.dir/compiler_depend.ts
/CMakeFiles/rotary-controller-f4.elf.dir/depend.internal
/CMakeFiles/rotary-controller-f4.elf.dir/depend.make
/CMakeFiles/rotary-controller-f4.elf.dir/DependInfo.cmake
/CMakeFiles/rotary-controller-f4.elf.dir/flags.make
/CMakeFiles/rotary-controller-f4.elf.dir/link.txt
/CMakeFiles/rotary-controller-f4.elf.dir/progress.make
/CMakeFiles/clion-environment.txt
/CMakeFiles/cmake.check_cache
/CMakeFiles/CMakeConfigureLog.yaml
/CMakeFiles/CMakeDirectoryInformation.cmake
/CMakeFiles/InstallScripts.json
/CMakeFiles/Makefile.cmake
/CMakeFiles/Makefile2
/CMakeFiles/progress.marks
/CMakeFiles/TargetDirectories.txt
/cmake-build-release/.cmake/api/v1/query/cache-v2
/cmake-build-release/.cmake/api/v1/query/cmakeFiles-v1
/cmake-build-release/.cmake/api/v1/query/codemodel-v2
/cmake-build-release/.cmake/api/v1/query/toolchains-v1
/cmake-build-release/.cmake/api/v1/reply/cache-v2-75ccddff1f9462878f34.json
/cmake-build-release/.cmake/api/v1/reply/cmakeFiles-v1-efb40c770de9d5bf104a.json
/cmake-build-release/.cmake/api/v1/reply/codemodel-v2-1d0bfa3e0f2ca88c0356.json
/cmake-build-release/.cmake/api/v1/reply/directory-.-Release-f5ebdc15457944623624.json
/cmake-build-release/.cmake/api/v1/reply/index-2025-07-25T20-06-13-0400.json
/cmake-build-release/.cmake/api/v1/reply/target-rotary-controller-f4.elf-Release-23665a0d8e0985d66bdc.json
/cmake-build-release/.cmake/api/v1/reply/toolchains-v1-516567ce22d77594ccde.json
/cmake-build-release/CMakeFiles/3.31.6/CompilerIdC/CMakeCCompilerId.c
/cmake-build-release/CMakeFiles/3.31.6/CompilerIdCXX/CMakeCXXCompilerId.cpp
/cmake-build-release/CMakeFiles/3.31.6/CMakeASMCompiler.cmake
/cmake-build-release/CMakeFiles/3.31.6/CMakeCCompiler.cmake
/cmake-build-release/CMakeFiles/3.31.6/CMakeCXXCompiler.cmake
/cmake-build-release/CMakeFiles/3.31.6/CMakeDetermineCompilerABI_C.bin
/cmake-build-release/CMakeFiles/3.31.6/CMakeDetermineCompilerABI_CXX.bin
/cmake-build-release/CMakeFiles/3.31.6/CMakeSystem.cmake
/cmake-build-release/CMakeFiles/rotary-controller-f4.elf.dir/ASM.includecache
/cmake-build-release/CMakeFiles/rotary-controller-f4.elf.dir/build.make
/cmake-build-release/CMakeFiles/rotary-controller-f4.elf.dir/cmake_clean.cmake
/cmake-build-release/CMakeFiles/rotary-controller-f4.elf.dir/compiler_depend.make
/cmake-build-release/CMakeFiles/rotary-controller-f4.elf.dir/compiler_depend.ts
/cmake-build-release/CMakeFiles/rotary-controller-f4.elf.dir/depend.internal
/cmake-build-release/CMakeFiles/rotary-controller-f4.elf.dir/depend.make
/cmake-build-release/CMakeFiles/rotary-controller-f4.elf.dir/DependInfo.cmake
/cmake-build-release/CMakeFiles/rotary-controller-f4.elf.dir/flags.make
/cmake-build-release/CMakeFiles/rotary-controller-f4.elf.dir/link.txt
/cmake-build-release/CMakeFiles/rotary-controller-f4.elf.dir/progress.make
/cmake-build-release/CMakeFiles/clion-environment.txt
/cmake-build-release/CMakeFiles/clion-Release-log.txt
/cmake-build-release/CMakeFiles/cmake.check_cache
/cmake-build-release/CMakeFiles/CMakeConfigureLog.yaml
/cmake-build-release/CMakeFiles/CMakeDirectoryInformation.cmake
/cmake-build-release/CMakeFiles/Makefile.cmake
/cmake-build-release/CMakeFiles/Makefile2
/cmake-build-release/CMakeFiles/progress.marks
/cmake-build-release/CMakeFiles/TargetDirectories.txt
/cmake-build-release/cmake_install.cmake
/cmake-build-release/CMakeCache.txt
/cmake-build-release/Makefile
/cmake-build-release/rotary-controller-f4.bin
/.cmake/api/v1/query/cache-v2
/.cmake/api/v1/query/cmakeFiles-v1
/.cmake/api/v1/query/codemodel-v2
/.cmake/api/v1/query/toolchains-v1
/.cmake/api/v1/reply/cache-v2-f5e9ca3708de3f124d35.json
/.cmake/api/v1/reply/cmakeFiles-v1-281ea38263c07c7344ed.json
/.cmake/api/v1/reply/codemodel-v2-f943dd8c247e07984a15.json
/.cmake/api/v1/reply/directory-.-Release-9ad1a58d4644cf6543fa.json
/.cmake/api/v1/reply/index-2026-01-26T01-20-50-0476.json
/.cmake/api/v1/reply/target-rotary-controller-f4.elf-Release-abbd90adbbfbd406bb3c.json
/.cmake/api/v1/reply/toolchains-v1-516567ce22d77594ccde.json
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#THIS FILE IS AUTO GENERATED FROM THE TEMPLATE! DO NOT CHANGE!
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_VERSION 1)
cmake_minimum_required(VERSION 3.27)
cmake_minimum_required(VERSION 3.30)

# specify cross-compilers and tools
set(CMAKE_C_COMPILER arm-none-eabi-gcc)
Expand Down
16 changes: 16 additions & 0 deletions Core/Inc/Ramps.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,29 @@ typedef struct {
uint16_t servoMode; // Servo modes: 0=disabled, 1=sync/index, 2=jog
} fastData_t;


typedef struct {
uint16_t threadRequest; // host writes 1 to request latch+wait
uint16_t threadReset; // host writes 1 to reset the threading state
uint16_t spindleScaleIndex; // host sets which scale to watch
uint16_t threadPhaseActive; // 0 = not latched yet, 1 = latched
uint16_t threadEnabled; // firmware uses as waiting flag
uint16_t spindlePhaseTolerance; // encoder-count tolerance for phase matching
int32_t threadRemainingSteps; // SIGNED distance remaining
uint32_t threadStartSteps; // servo.currentSteps at latch
uint32_t spindleCountsPerRev; // spindle scale counts per revolution
int32_t threadPhaseRef; // firmware stores latched phase
int32_t currentThreadPhase; // current phase for debug purposes
} assistedThreadingData_t;

typedef struct {
uint32_t executionInterval;
uint32_t executionIntervalPrevious;
uint32_t executionIntervalCurrent;
uint32_t executionCycles;
servo_t servo;
input_t scales[SCALES_COUNT];
assistedThreadingData_t assistedThreadingData;
fastData_t fastData;
} rampsSharedData_t;

Expand Down
128 changes: 126 additions & 2 deletions Core/Src/Ramps.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,12 +224,124 @@ static inline void updateJogPosition(rampsHandler_t *data) {
shared->servo.desiredSteps += positionIncrement;
}

static inline int32_t getSpindlePhase(
int32_t encoderPosition,
uint32_t countsPerRev
) {
if (countsPerRev == 0) {
return 0;
}

int32_t phase = encoderPosition % (int32_t)countsPerRev;
if (phase < 0) {
phase += countsPerRev;
}

return phase;
}

static inline int32_t computeServoStepTolerance(const rampsSharedData_t *shared)
{
// Maximum possible step movement in ONE control cycle
int32_t maxStepThisCycle =
(int32_t)(
fabsf(shared->servo.currentSpeed) *
(float)shared->executionInterval /
100000000.0f
);

// +1 to account for truncation / integer rounding
return maxStepThisCycle + 1;
}

static inline void applyAssistedThreading(rampsSharedData_t *shared)
{
uint16_t sp = shared->assistedThreadingData.spindleScaleIndex;
if (sp >= SCALES_COUNT) sp = 0;
input_t *spindleScale = &shared->scales[sp];

shared->assistedThreadingData.currentThreadPhase =
getSpindlePhase(
spindleScale->position,
shared->assistedThreadingData.spindleCountsPerRev
);

// Check for thread reset
if (shared->assistedThreadingData.threadReset == 1) {
shared->assistedThreadingData.threadPhaseActive = 0;
shared->assistedThreadingData.threadEnabled = 0;
shared->assistedThreadingData.threadReset = 2; // set to 2 to indicate reset done
spindleScale->syncEnable = 0;
}

// Threading-phase request handling
if (shared->assistedThreadingData.threadRequest == 1 && shared->assistedThreadingData.threadEnabled == 0) {
// latch only if we don't already have a reference
if (shared->assistedThreadingData.threadPhaseActive == 0) {
shared->assistedThreadingData.threadPhaseRef =
getSpindlePhase(
spindleScale->position,
shared->assistedThreadingData.spindleCountsPerRev
);
shared->assistedThreadingData.threadPhaseActive = 1;
}

shared->assistedThreadingData.threadEnabled = 1; // firmware is now waiting for match
shared->assistedThreadingData.threadRequest = 0; // clear request so host sees acknowledgement
}

// If firmware is waiting on the phase, check for match
if (shared->assistedThreadingData.threadEnabled == 1) {
int32_t delta =
shared->assistedThreadingData.currentThreadPhase -
shared->assistedThreadingData.threadPhaseRef;

// wrap-aware delta
int32_t half = shared->assistedThreadingData.spindleCountsPerRev / 2;
if (delta > half) delta -= shared->assistedThreadingData.spindleCountsPerRev;
if (delta < -half) delta += shared->assistedThreadingData.spindleCountsPerRev;

int32_t tol = (int32_t)(shared->assistedThreadingData.spindlePhaseTolerance); // host-configurable tolerance (counts)

if (delta == 0 || (delta <= tol && delta >= -tol)) {
// matched -> start requested threading move
spindleScale->syncEnable = 1; // enable sync motion for the spindle scale

shared->assistedThreadingData.threadStartSteps = shared->servo.currentSteps;

shared->assistedThreadingData.threadPhaseActive = 1;

// clear waiting flags
shared->assistedThreadingData.threadEnabled = 0;
// clear the request so host can detect completion
shared->assistedThreadingData.threadRequest = 0;
}
}

if (shared->assistedThreadingData.threadEnabled == 0 && shared->assistedThreadingData.threadPhaseActive == 1) {
int32_t traveled = shared->servo.currentSteps - shared->assistedThreadingData.threadStartSteps;

int32_t remaining =
shared->assistedThreadingData.threadRemainingSteps - traveled;

int32_t tol = computeServoStepTolerance(shared);

if (remaining == 0 || (remaining <= tol && remaining >= -tol)) {
// completed move, clear phase reference
shared->assistedThreadingData.threadPhaseActive = 0;
spindleScale->syncEnable = 0;
}
}
}


void SynchroRefreshTimerIsr(rampsHandler_t *data) {
// HAL_GPIO_TogglePin(SPARE_1_GPIO_PORT, SPARE_1_PIN);
// HAL_GPIO_WritePin(SPARE_2_GPIO_PORT, SPARE_1_PIN, GPIO_PIN_SET);
uint32_t start = DWT->CYCCNT;
// Reset the step pin as soon as possible
HAL_GPIO_WritePin(STEP_GPIO_PORT, STEP_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(STEP_GPIO_PORT, SPARE_2_PIN, GPIO_PIN_RESET);
rampsSharedData_t *shared = &(data->shared);
shared->executionIntervalPrevious = shared->executionIntervalCurrent;
shared->executionIntervalCurrent = DWT->CYCCNT;
Expand Down Expand Up @@ -259,7 +371,13 @@ void SynchroRefreshTimerIsr(rampsHandler_t *data) {
shared->fastData.scaleCurrent[i] = shared->scales[i].position;
}

if (shared->fastData.servoMode == 1) updateIndexingPosition(data);
if (shared->fastData.servoMode == 1){
if (shared->assistedThreadingData.threadEnabled == 1 || shared->assistedThreadingData.threadRequest == 1 || shared->assistedThreadingData.threadPhaseActive == 1) {
applyAssistedThreading(shared);
}
updateIndexingPosition(data);
}

if (shared->fastData.servoMode == 2) updateJogPosition(data);

if (shared->fastData.servoMode != 0 && servoCyclesCounter == 0) {
Expand All @@ -278,6 +396,7 @@ void SynchroRefreshTimerIsr(rampsHandler_t *data) {

if (direction == data->servoPreviousDirection && change != 0) {
HAL_GPIO_WritePin(STEP_GPIO_PORT, STEP_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(STEP_GPIO_PORT, SPARE_2_PIN, GPIO_PIN_SET);
shared->servo.currentSteps += direction;
}

Expand All @@ -292,12 +411,17 @@ void SynchroRefreshTimerIsr(rampsHandler_t *data) {

_Noreturn void userLedTask(__attribute__((unused)) void *argument) {
uint16_t oldInCnt = 0;
uint8_t blinkInterval = 0;

for (;;) {
osDelay(50);
blinkInterval = (blinkInterval + 1) % 10;
if (blinkInterval == 0) {
HAL_GPIO_TogglePin(USR_LED_GPIO_Port, USR_LED_Pin);
}

if (oldInCnt != RampsModbusData.u16InCnt) {
oldInCnt = RampsModbusData.u16InCnt;
HAL_GPIO_TogglePin(USR_LED_GPIO_Port, USR_LED_Pin);
HAL_GPIO_WritePin(USR_LED_GPIO_Port, USR_LED_Pin, GPIO_PIN_RESET);
osDelay(25);
HAL_GPIO_WritePin(USR_LED_GPIO_Port, USR_LED_Pin, GPIO_PIN_SET);
Expand Down
Loading