#include <Stepper.h>
// 电机参数
const int motorStepsPerRevolution = 10000; // 电机总步数(完全展开)
const int motorSpeed = 160; // 电机速度(步/秒)
const int stepPin = 5; // 新的步进脉冲引脚(原23)
const int dirPin = 4; // 新的方向控制引脚(原22)
const int upButtonPin = 2; // 新的"向上"按钮引脚(原18)
const int downButtonPin = 0; // 新的"向下"按钮引脚(原19)
// 初始化步进电机
Stepper myStepper(motorStepsPerRevolution, stepPin, dirPin);
// 状态变量
volatile bool requestUp = false; // 向上移动请求(中断触发)
volatile bool requestDown = false; // 向下移动请求(中断触发)
int motorPosition = 0; // 当前电机位置(0-10000)
bool isMoving = false; // 电机是否正在移动
int targetPosition = 0; // 目标位置
// 中断服务函数
void IRAM_ATTR handleUpButton() {
if (motorPosition > 0 && !requestUp) {
requestUp = true; // 仅在未完全收缩时触发
requestDown = false; // 取消相反方向的请求
}
}
void IRAM_ATTR handleDownButton() {
if (motorPosition < motorStepsPerRevolution && !requestDown) {
requestDown = true; // 仅在未完全展开时触发
requestUp = false; // 取消相反方向的请求
}
}
void setup() {
Serial.begin(115200);
// 设置引脚模式
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
pinMode(upButtonPin, INPUT_PULLUP);
pinMode(downButtonPin, INPUT_PULLUP);
// 绑定中断(下降沿触发)
attachInterrupt(digitalPinToInterrupt(upButtonPin), handleUpButton, FALLING);
attachInterrupt(digitalPinToInterrupt(downButtonPin), handleDownButton, FALLING);
// 初始化电机状态
motorPosition = 0;
targetPosition = 0;
digitalWrite(dirPin, LOW); // 默认方向(收缩)
myStepper.setSpeed(motorSpeed);
Serial.println("System Ready. Current Position: 0");
}
void loop() {
// 处理移动请求
if (requestUp) {
targetPosition = 0; // 目标:完全收缩
digitalWrite(dirPin, LOW); // 方向:收缩
requestUp = false;
isMoving = true;
Serial.println("Moving UP (Retracting)...");
}
else if (requestDown) {
targetPosition = motorStepsPerRevolution; // 目标:完全展开
digitalWrite(dirPin, HIGH); // 方向:展开
requestDown = false;
isMoving = true;
Serial.println("Moving DOWN (Extending)...");
}
// 执行步进移动
if (isMoving) {
if (motorPosition != targetPosition) {
int stepDirection = (targetPosition > motorPosition) ? 1 : -1; // 计算方向
myStepper.step(stepDirection); // 移动1步
motorPosition += stepDirection; // 更新位置
// 边界检查
motorPosition = constrain(motorPosition, 0, motorStepsPerRevolution);
if (motorPosition == 0 || motorPosition == motorStepsPerRevolution) {
isMoving = false; // 到达极限位置停止
Serial.print(motorPosition == 0 ? "Fully Retracted." : "Fully Extended.");
Serial.print(" Position: ");
Serial.println(motorPosition);
}
}
else {
isMoving = false; // 到达目标位置
Serial.print("Movement Complete. Position: ");
Serial.println(motorPosition);
}
}
// 实时显示位置(每100ms更新一次)
static unsigned long lastUpdate = 0;
if (millis() - lastUpdate >= 100) {
lastUpdate = millis();
if (isMoving) { // 只有在移动时才频繁更新
Serial.print("Position: ");
Serial.println(motorPosition);
}
}
}