Stepper motor control

here i have arduino code program to control stepper motor with planetary reducer connected to loadcell, i use tb6600 driver 12V-2A power supply, my stepper motor has problem, every time it goes through the next round it jerks slightly, everyone tell me is the cause due to my code or interference or insufficient power supply? thank you very much!!

int microStep = 16;
float angleStep = 1.8;
float stepsPerRound = microStep * 360.0 / angleStep; // 3200 bước/vòng động cơ
int gearboxRatio = 14; // Hộp số 14:1

long stepsPerOutputRound = gearboxRatio * stepsPerRound; // Số bước thực tế để trục đầu ra hộp số quay 1 vòng

int speedV = 240;
float speeds = 1.0 / (speedV / 60.0 * stepsPerRound) / 2.0 * 1000000;


// -------------------- Hỗ trợ --------------------
void moveMotor(long stepCount, bool forward) {
    digitalWrite(EN_PIN, LOW); // Kích hoạt động cơ
    digitalWrite(DIR_PIN, forward ? HIGH : LOW); // Xác định chiều quay

    long lastStepTime = micros();
    for (long i = 0; i < stepCount; i++) {
        // Kiểm tra nếu nhấn nút 7 thì dừng ngay lập tức
        if (digitalRead(BUTTON_BACK) == LOW) {  
            stopMotor();
            returnToZeroWeight();
            return; 
        }

        while ((micros() - lastStepTime) < speeds); // Đợi để kiểm soát tốc độ
        lastStepTime = micros();

        digitalWrite(STEP_PIN, HIGH);
        delayMicroseconds(5);
        digitalWrite(STEP_PIN, LOW);
    }
}

void stopMotor() {
  digitalWrite(EN_PIN, HIGH);
}

void updateWeight() {
  currentWeight = scale.get_units();
}

void runHoldCycle() {
    unsigned long elapsedHoldTime = (millis() - holdStartTime) / 1000;
    lcd.setCursor(0, 1);
    lcd.print("Hold: ");
    lcd.print(holdTimes[currentHoldTimeIndex] - elapsedHoldTime);
    lcd.print("s ");

    // Khi hết thời gian giữ, bắt đầu quay về vị trí ban đầu
    if (elapsedHoldTime >= holdTimes[currentHoldTimeIndex]) {
        holding = false;
        returning = true;
    }

    // Khi quay về, cập nhật trọng lượng liên tục
    if (returning) {
        returnToZeroWeight(); // Gọi hàm mới để quay về đến khi trọng lượng = 0
    }
}

void runHoldCycleProgram2() {
    unsigned long elapsedHoldTime = (millis() - holdStartTime) / 1000;

    // Luôn cập nhật trọng lượng và hiển thị LCD
    updateWeight();
    displayWeight();

    lcd.setCursor(0, 1);
    lcd.print("Hold: ");
    lcd.print(holdTimeProgram2 - elapsedHoldTime);
    lcd.print("s ");

    // Khi hết thời gian giữ, tiếp tục di chuyển động cơ
    if (elapsedHoldTime >= holdTimeProgram2) {
        holding = false; // Kết thúc giữ, tiếp tục chu kỳ
    }
}

void runTreatmentCycleProgram2() {
    unsigned long elapsedTreatmentTime = (millis() - treatmentStartTime) / 1000;

    // Cập nhật trọng lượng liên tục
    updateWeight();
    displayWeight();

    // Nếu hết thời gian điều trị, quay về vị trí ban đầu
    if (elapsedTreatmentTime >= treatmentTimes[currentTreatmentTimeIndex]) {
        stopMotor();
        isRunning = false;
        returnToZeroWeight(); // Gọi hàm trả động cơ về đến khi trọng lượng = 0
        return;
    }

    // Nếu vẫn trong thời gian điều trị, tiếp tục di chuyển động cơ
    if (holding) {
        runHoldCycleProgram2();
    } else {
        if (movingToUpper) {
            // Quay động cơ lên ngưỡng trên
            if (currentWeight < upperLimits[currentUpperLimitIndex]) {
                moveMotor(stepsPerOutputRound, true);
                stepsTaken++;
            } else {
                stopMotor();
                holding = true;
                holdStartTime = millis();
                movingToUpper = false; // Đảo chiều quay về ngưỡng dưới
            }
        } else {
            // Quay động cơ xuống ngưỡng dưới
            if (currentWeight > lowerLimits[currentLowerLimitIndex]) {
                moveMotor(stepsPerOutputRound, false);
                stepsTaken++;
            } else {
                stopMotor();
                holding = true;
                holdStartTime = millis();
                movingToUpper = true; // Quay lên lại sau khi giữ
            }
        }
    }
}

void returnToStart(bool slow) {
  while (stepsTaken > 0) {
    moveMotor(stepsPerOutputRound, false); // Quay lùi về vị trí ban đầu
    stepsTaken--;
    if (slow) delay(10); // Di chuyển chậm khi quay về
  }
  stopMotor();
  stepsTaken = 0; // Đảm bảo không vượt quá vị trí step = 0
  resetToProgramSelection(); // Quay trực tiếp đến chọn chương trình
}

void returnToZeroWeight() {
    while (true) {
        updateWeight();
        displayWeight();

        if (currentWeight <= 0) {
            stopMotor();
            lcd.clear();
            lcd.setCursor(0, 0);
            lcd.print("Returned!");
            delay(1000);
            resetSystem(); // Reset hệ thống khi loadcell = 0
            return;
        }

        moveMotor(stepsPerOutputRound, false); // Quay lùi;
    }
}

void resetSystem() {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("System Reset...");
    delay(1000);
    digitalWrite(BUZZER_PIN, LOW); // Tắt còi báo động trước khi reset
    wdt_enable(WDTO_15MS); // Kích hoạt Watchdog Timer để reset sau 15ms
    while (1); // Chờ reset
}

The semicolon isn’t helping here..l

You may find using a stepper library properly will simplify and make your code run smoother.

1 Like

I would not do that, that can cause a jerk. I would set ENABLE low once at startup. The motor is stopped if you are not toggling STEP, so there is no need for an explicit stop.

If you need to disable the driver for some other reason, then the jerk is probably unavoidable.

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