In a project I haven't talked too much about here on Cemetech yet, I'm building a set of physical controls for Train Simulator, including gauges, buttons, throttle/brake, etc. (build log part 1 and build log part 2). In part 1, I describe my process of tearing down a cheap aftermarket tachometer and reusing its two H-bridges and stepper motor with a Raspberry Pi Pico controller.
It works pretty well (photos in the log above), but the microstepping does not produce consistently sized angular steps: the microsteps close to a full step are small, and the microsteps midway between full steps are large. I wracked my brain quite a bit in January, and performed testing (including sanity checking by measuring and charting current draw through a single coil with PWM duty cycle from 0% to 100% versus a theoretical current assuming a 5mA drop through the attached current limiting resistor and finding it to be linear). Any debugging approaches would be greatly appreciated.
My microstepping table is generated as follows:
Code:
This table is used as follows with this PIO program:
Code:
It works pretty well (photos in the log above), but the microstepping does not produce consistently sized angular steps: the microsteps close to a full step are small, and the microsteps midway between full steps are large. I wracked my brain quite a bit in January, and performed testing (including sanity checking by measuring and charting current draw through a single coil with PWM duty cycle from 0% to 100% versus a theoretical current assuming a 5mA drop through the attached current limiting resistor and finding it to be linear). Any debugging approaches would be greatly appreciated.
My microstepping table is generated as follows:
Code:
size_t increments = 0;
for(size_t phase = 0; phase < 4; ++phase) {
for(size_t microstep = 0; microstep < MICROSTEPS; ++microstep, ++increments) {
double angle = increments * (M_PI / 2. / MICROSTEPS);
microstepping_store[phase][microstep][0] = (int)(100. * std::sin(angle));
microstepping_store[phase][microstep][1] = (int)(100. * std::cos(angle));
}
}
microstepping_store[2][0][0] = -0;
This table is used as follows with this PIO program:
Code:
void PicoStepper::stepMotor(int step, int microstep) {
int coil0 = microstepping_store[step][microstep][0];
int coil2 = microstepping_store[step][microstep][1];
int phase0 = 0;
int count0 = (coil0 >= 0 ? coil0 : -coil0);
count0 = (count0 > 0) ? (count0 - count0Offset) : 0;
int phase2 = 0;
int count2 = coil2 >= 0 ? coil2 : -coil2;
count2 = (count2 > 0) ? (count2 - count2Offset) : 0;
if (coil0 > 0) {
phase0 = 0b1000;
} else if (coil0 < 0) {
phase0 = 0b0100;
}
if (coil2 > 0) {
phase2 = 0b0010;
} else if (coil2 < 0) {
phase2 = 0b0001;
}
const int phase1 = phase0 | phase2;
int count1 = maxPWM - count0 - count2 - count1Offset;
pio_sm_put(pio_, sm_, (count2 << 25) | (phase2 << 21) | (count1 << 15) | (phase1 << 11) | (count0 << 4) | phase0);
}