As promised, I did a quick sketch showing the principle. For the sketch I assumed a leadscrew with 5mm pitch, 1600 microsteps per leadscrew revolution, and a spindle encoder with 1600 counts per rev.
For cutting a M6 thread (1mm pitch) we get a ratio of leadscrew steps to encoder counts of 0.2.
For cutting a M4 thread (0.7mm pitch) we get a ratio of 0.14
Having the spindle running at 50rpm the encoder will generate a frequency of 1333.33 Hz. And the stepper should run at
1333.33 x 0.20 = 266.66 Hz for the M6 thread and at
1333.33 x 0.14 = 186.66 Hz for the M4 thread.
The algorithm reads out the current spindle position(encoder value) in loop. If this value changed it calls doBresenhamStep which decides if the stepper should make a step or not based on the required ratio. Of course the ratio can be any (float) value.
I measured the generated step frequencies at a spindle speed of 50rpm with a logic analyzer and get 266.6 Hz for the M6 and 186.66 for the M3 which corresponds exactly to the expected values (see attached screen shots). Of course the ratios will stay constant regardless of the actual spindle speed (see attached acceleration.png).
If possible, I suggest to replace the encoder by one with more resolution to improve the performance.
Here the sketch. I simulated the spindle encoder by a stepper, please delete the corresponding code and replace by reading out your encoder instead of reading out the stepper in getEncoderValue. Hope the comments are clear enough to understand the code.
#include "Arduino.h"
void setupBresenham(float ratio);
void doBresenhamStep();
uint32_t getEncoderValue();
// pins ---------------------------------
constexpr unsigned pinStp = 2; // leadscrew stepper STP pin
constexpr unsigned pinDir = 3; // leadscrew stepper DIR pin
// Thread properties ---------------------
constexpr float pitchM3 = 0.5f; // mm per rev
constexpr float pitchM4 = 0.7f;
constexpr float pitchM5 = 0.8f;
constexpr float pitchM6 = 1.0f; // and so on... You get the idea...
// Spindle properties ----------------------
constexpr unsigned encCounts = 1600;// encoder counts per rev
// Leadscrew properties ------------------
constexpr float pitch = 5.0; // mm per rev (assumed)
constexpr unsigned spr = 1600; // steps per leadScrew revolution
constexpr float spmm = spr / pitch; // steps per mm of the top slide
// Ratio of encoder counts to leadscrew steps for the given thread
constexpr float ratio = pitchM6 * spmm / encCounts; // change for other threads
// The following block is only required to simulate your spindle encoder by a stepper,
// Delete if you use your encoder
#include "TeensyStep.h"
constexpr unsigned rpm = 50; // spindle speed
constexpr unsigned encFreq = encCounts * rpm / 60; //Frequency of the encoder pulses
Stepper spindle(0, 1);
RotateControl ctrl;
//---------------------------------------------------------------------------------
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
pinMode(pinStp, OUTPUT);
pinMode(pinDir, OUTPUT);
setupBresenham(ratio); // calculate the required Bresenham paramters for the stepper/encoder ratio
// simulate the spindle encoder
spindle.setMaxSpeed(encFreq);
ctrl.rotateAsync(spindle);
}
int32_t oldEncVal = 0;
void loop()
{
int32_t curEncVal = getEncoderValue(); // get the current encoder value
if (curEncVal != oldEncVal)
{
// add some checks that the difference is only one, otherwise get a faster controller :-)
doBresenhamStep();
oldEncVal = curEncVal;
}
}
// Helpers =================================================================================
int32_t master_A, slave_A, slave_B;
uint32_t getEncoderValue()
{ // read out the current spindle position in the simulation
return spindle.getPosition(); // replace this by the code to readout the real spindle encoder
}
void setupBresenham(float ratio)
{
master_A = 10000; // any value
slave_A = master_A * ratio;
slave_B = 2 * slave_A - master_A; // start value for Bm
}
void doBresenhamStep()
{
if (slave_B >= 0)
{
digitalWrite(pinStp, HIGH); // do a step
delayMicroseconds(10);
digitalWrite(pinStp, LOW);
slave_B -= master_A;
}
slave_B += slave_A;
}


