Hi everyone, I need to control the stepper motor based on the weight obtained from the loadcell: after selecting the traction force, holding time, treatment time, press start, the motor starts running (the motor runs slowly because the function is to pull the spine, it cannot be pulled suddenly), when it reaches the set force, hold, the timer counts down until the holding time is over, the motor returns to its original position according to the initial pulling speed. While pulling, when pressing the emergency stop button, the motor will stop. But after selecting the force, the motor does not rotate. Please help me fix the code, God will bless good people, thank you!!!
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "HX711.h"
// Chân điều khiển động cơ bước
#define STEP1_PIN 10
#define DIR1_PIN 11
#define EN1_PIN 13
// Chân load cell
#define LOADCELL_DOUT_PIN 3
#define LOADCELL_SCK_PIN 2
// Chân nút nhấn
#define BUTTON_THRESHOLD 4
#define BUTTON_HOLDTIME 5
#define BUTTON_STARTSTOP 6
#define BUTTON_EMERGENCY 7
// Load cell
HX711 scale;
float calibration_factor = -7050.0; // Hệ số hiệu chuẩn
float weightThresholds[] = {1.02, 1.53, 2.04}; // Ngưỡng trọng lượng (kg)
int currentThresholdIndex = 0;
// Giữ thời gian (giây)
unsigned int holdTimes[] = {10, 15, 20};
int currentHoldTimeIndex = 0;
// LCD I2C
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Biến điều khiển
bool isRunning = false;
bool holding = false;
bool returning = false;
bool emergencyStop = false;
unsigned long holdStartTime = 0;
// Lọc trọng lượng
const int numReadings = 10;
float readings[numReadings];
int readIndex = 0;
float total = 0;
float averageWeight = 0;
void setup() {
Serial.begin(9600);
// Thiết lập các chân điều khiển
pinMode(STEP1_PIN, OUTPUT);
pinMode(DIR1_PIN, OUTPUT);
pinMode(EN1_PIN, OUTPUT);
pinMode(BUTTON_THRESHOLD, INPUT_PULLUP);
pinMode(BUTTON_HOLDTIME, INPUT_PULLUP);
pinMode(BUTTON_STARTSTOP, INPUT_PULLUP);
pinMode(BUTTON_EMERGENCY, INPUT_PULLUP);
// Load cell
scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
scale.set_scale(calibration_factor);
scale.tare();
// Tắt động cơ ban đầu
digitalWrite(EN1_PIN, HIGH);
digitalWrite(STEP1_PIN, LOW);
digitalWrite(DIR1_PIN, LOW);
// LCD
lcd.begin();
lcd.backlight();
lcd.print("System Ready");
delay(2000);
clearReadings();
updateLCD();
}
void loop() {
// Cập nhật giá trị trọng lượng
updateWeight();
// Dừng khẩn cấp
if (digitalRead(BUTTON_EMERGENCY) == LOW) {
handleEmergencyStop();
return;
}
// Hiển thị trọng lượng và ngưỡng
lcd.setCursor(0, 0);
lcd.print("W: ");
lcd.print(averageWeight, 2);
lcd.print("kg Th: ");
lcd.print(weightThresholds[currentThresholdIndex], 2);
lcd.print("kg ");
// Xử lý nút nhấn
handleButtons();
// Xử lý logic động cơ khi chạy
if (isRunning && !holding && !returning) {
if (averageWeight < weightThresholds[currentThresholdIndex]) {
moveMotor(true); // Quay động cơ để kéo tải trọng
} else {
stopMotor();
holding = true;
holdStartTime = millis();
Serial.println("Holding position...");
}
}
// Thời gian giữ
if (holding) {
unsigned long elapsedHoldTime = (millis() - holdStartTime) / 1000;
unsigned int remainingHoldTime = holdTimes[currentHoldTimeIndex] - elapsedHoldTime;
if (remainingHoldTime > 0) {
lcd.setCursor(0, 1);
lcd.print("Hold: ");
lcd.print(remainingHoldTime);
lcd.print("s ");
} else {
holding = false;
returning = true;
Serial.println("Returning to initial position...");
}
}
// Trả động cơ về vị trí ban đầu
if (returning) {
if (averageWeight > 0.1) { // Giả sử 0.1kg là trọng lượng gần bằng 0
moveMotor(false); // Quay động cơ ngược lại
} else {
stopMotor();
returning = false;
isRunning = false;
Serial.println("Returned to initial position.");
lcd.setCursor(0, 1);
lcd.print("System Ready ");
}
}
}
// Cập nhật giá trị trọng lượng trung bình
void updateWeight() {
total -= readings[readIndex];
readings[readIndex] = scale.get_units();
total += readings[readIndex];
readIndex = (readIndex + 1) % numReadings;
averageWeight = total / numReadings;
}
// Xử lý các nút nhấn
void handleButtons() {
static unsigned long lastButtonPress = 0;
if (digitalRead(BUTTON_THRESHOLD) == LOW && millis() - lastButtonPress > 300) {
lastButtonPress = millis();
currentThresholdIndex = (currentThresholdIndex + 1) % 3;
updateLCD();
Serial.print("Threshold changed to: ");
Serial.println(weightThresholds[currentThresholdIndex]);
}
if (digitalRead(BUTTON_HOLDTIME) == LOW && millis() - lastButtonPress > 300) {
lastButtonPress = millis();
currentHoldTimeIndex = (currentHoldTimeIndex + 1) % 3;
updateLCD();
Serial.print("Hold time changed to: ");
Serial.println(holdTimes[currentHoldTimeIndex]);
}
if (digitalRead(BUTTON_STARTSTOP) == LOW && millis() - lastButtonPress > 300) {
lastButtonPress = millis();
isRunning = !isRunning;
if (isRunning) {
Serial.println("System Started");
} else {
Serial.println("System Stopped");
stopMotor();
}
}
}
// Điều khiển quay động cơ
void moveMotor(bool forward) {
digitalWrite(EN1_PIN, LOW);
digitalWrite(DIR1_PIN, forward ? HIGH : LOW);
digitalWrite(STEP1_PIN, HIGH);
delayMicroseconds(500); // Tạo xung
digitalWrite(STEP1_PIN, LOW);
delayMicroseconds(500);
}
// Dừng động cơ
void stopMotor() {
digitalWrite(EN1_PIN, HIGH);
Serial.println("Motor Stopped.");
}
// Dừng khẩn cấp
void handleEmergencyStop() {
emergencyStop = true;
isRunning = false;
holding = false;
returning = false;
stopMotor();
Serial.println("Emergency Stop Activated!");
lcd.setCursor(0, 1);
lcd.print("EMERGENCY STOP ");
delay(500);
}
// Làm sạch bộ nhớ đọc giá trị trọng lượng
void clearReadings() {
for (int i = 0; i < numReadings; i++) {
readings[i] = 0;
}
total = 0;
averageWeight = 0;
}
// Cập nhật hiển thị LCD
void updateLCD() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Th: ");
lcd.print(weightThresholds[currentThresholdIndex], 2);
lcd.print("kg Hold: ");
lcd.print(holdTimes[currentHoldTimeIndex]);
lcd.print("s");
}
