Jitter on Stepper motor using A4988 Driver, some of the time

Hardware:

Setup: I've adjusted the VRef of the driver based on the formula VRef = Imot * 8 * Rsen. With the values of Imot = .5 (max = .6), Rsen = .068. A 12-Volt power supply is being used to supply power to the breadboard hat for the Arduino.

The Arduino code is being activated by a Python GUI, that is sending commands to the Arduino to make adjustments to the code in order to manipulate delay between steps, step size, and enable/disable. here is a simplified version of the Arduino code.

#include "src/Laser_Welder_8124.h"

void setup() {
    // 
    Serial.begin(115200);

    pinMode(STEPPER_DIR, OUTPUT);
    pinMode(STEPPER_STEP, OUTPUT);
   
    pinMode(STEPPER_ENABLE, OUTPUT);
    pinMode(STEPPER_MS1, OUTPUT);
    pinMode(STEPPER_MS2, OUTPUT);
    pinMode(STEPPER_MS3, OUTPUT);

    digitalWrite(STEPPER_MS1, HIGH);
    digitalWrite(STEPPER_MS2, HIGH);
    digitalWrite(STEPPER_MS3, HIGH);

    digitalWrite(STEPPER_DIR, HIGH);
    digitalWrite(STEPPER_ENABLE, HIGH);
}

void loop() {
    
    curMillis = millis();
    commsCheck();
    singleStep();
}

void commsCheck(){

    if(Serial.available() > 0){
        
        int rlen = Serial.readBytes(incomingMsg, MSGSIZE);
        byte cmd = incomingMsg[CMD_POS];

        int val = incomingMsg[VAL_POS];

        switch(cmd){
            case 0xC0:{
                enableStepperMotor(val);
                break;
            }
            case 0xC1:{

                toggleStepperDirection(cmdLookup[2].pin, val);
                break;
            }
            case 0xC2:{

                cmdLookup[0].state = val;
                millisBetweenSteps = val;
            
                break;
            }
            case 0xC7:{

                setStepSize(val);
                break;
            }
        }
    }
}

void setStepSize(int val){

    switch(val){
        case 0xD0:{
            stepSize(HIGH, HIGH, HIGH);
            break;
        }
        case 0xD1:{
            stepSize(HIGH, HIGH, LOW);
            break;
        }
        case 0xD2:{
            stepSize(LOW, HIGH, LOW);
            break;
        }
        case 0xD3:{
            stepSize(HIGH, LOW, LOW);
            break;
        }
        case 0xD4:{
            stepSize(LOW, LOW, LOW);
            break;
        }
    }
}

void stepSize(int MS1, int MS2, int MS3){
    digitalWrite(STEPPER_MS1, MS1);
    digitalWrite(STEPPER_MS2, MS2);
    digitalWrite(STEPPER_MS3, MS3);
}

void toggleStepperDirection(int pin, int val)
{

    if (val == 0){
        cmdLookup[1].state = CW;
        digitalWrite(STEPPER_DIR, LOW);
    }
    else{
        cmdLookup[1].state = CCW;
        digitalWrite(STEPPER_DIR, HIGH);
    }
}

void singleStep() {

    if (curMillis - prevStepMillis >= millisBetweenSteps) {

        prevStepMillis = curMillis;
        digitalWrite(STEPPER_STEP, HIGH);
        digitalWrite(STEPPER_STEP, LOW);
    }
}

This works, for the most part.

I'm using the GUI to pass a value from 1-255 to represent a delay between steps in milliseconds.

If I set the time between steps to 1 ms, then it runs smoothly on all step sizes. However, when I start to play with the time delay, I get all sorts of jitter, at different time delays with different step sizes. How do I go about smoothing out the motor so I can use a range of delays across different step sizes?

I've attached a video link to show you what I'm seeing.

Video Link of Motor behavior

should there some delay between setting the pin HIGH and LOW?

1 Like

I thought of that as well, however starting with a 1ms delay and working my way up to a 10ms, the issue increased, including with the 1ms delay between steps.

void singleStep() {

    if (curMillis - prevStepMillis >= millisBetweenSteps) {

        prevStepMillis = curMillis;
        digitalWrite(STEPPER_STEP, HIGH);
        delay(1);
        digitalWrite(STEPPER_STEP, LOW);

the steppers i've used didn't work when stepped faster than 1msec.
not sure how faster micro-steppers can run.

there's a problem adding a delay if it's > millisBetweenSteps because then there's no delay between setting the pin LOW and HIGH

what about simply toggling the pin

digitalWrite (STEPPER_STEP,  ! digitalRead (STEPPER_STEP));

yes it will step half as fast as millisBetweenSteps but now it's under control. rename it halfStep()

1 Like

So if I'm understanding you correctly, you are just suggesting replacing the following code

digitalWrite(STEPPER_STEP, HIGH);
digitalWrite(STEPPER_STEP, LOW);

with
digitalWrite (STEPPER_STEP, ! digitalRead (STEPPER_STEP));

which would look like

void halfStep() {

    if (curMillis - prevStepMillis >= millisBetweenSteps) {

        prevStepMillis = curMillis;
        digitalWrite (STEPPER_STEP,  ! digitalRead (STEPPER_STEP));
    }
}

unfortunately, this doesn't change the jitter issue. I would have been perfectly happy with the speeds to be half, as I don't need to go this fast at all. However, with the amount of jitter at the slower speeds it's going to be an issue.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.