「一动一定」结构
- 定刀片:固定在舵机机身侧面、或末端执行器的固定支架上,全程保持不动;
- 动刀片:牢牢固定在舵机的输出舵盘上,跟随舵机轴做 0°~ 指定角度的往复旋转;
- 舵机归零时,两刀片完全张开,形成足够的开口容纳葡萄果梗;舵机旋转到目标角度时,两刀刃重合交错,剪断果梗。
- 适配硬件:Arduino Uno + MG996R 金属舵机
- 接线对应:舵机信号线 → D9
- 依赖库:Arduino 官方
Servo.h库 - 标准动作时序:上电归零 → 待机检测→到位触发→剪切→复位回归
舵机线序定义
- 红色线:电源正极(VCC,MG996R 支持 4.8V~7.2V,推荐 6V)
- 棕色 / 黑色线:电源负极(GND)
- 橙色 / 黄色 / 白色线:信号控制线(接收 PWM 脉冲信号,控制角度)
FSR 压力传感器
FSR 是压敏电阻型器件,本身不能直接输出可检测的电压,必须串联定值电阻组成分压电路,才能被 Arduino 模拟口正确读取。
- 标准接法:FSR 一端接 5V,另一端同时接 A0 模拟口和 10kΩ 电阻,电阻另一端接 GND
- 工作原理:FSR 受压后阻值降低,分压点电压升高,
analogRead()读取的数值随之变大 - 灵敏度调节:如果果梗压力很小、读数变化不明显,可将分压电阻换成 20kΩ~100kΩ 提升检测灵敏度
运行代码
1.压力校准调试版
先通过串口监视器读取实时压力值,确定触发阈值
#define FSR_PIN A0 void setup() { Serial.begin(9600); Serial.println("=== FSR压力校准模式 ==="); Serial.println("请观察数值:空载时数值小,按压时数值变大"); } void loop() { int pressureValue = analogRead(FSR_PIN); Serial.print("当前压力值:"); Serial.println(pressureValue); delay(200); // 每200ms刷新一次 }校准方法:
- 空载(刀片无接触)时,记录基础数值(通常为 0~50);
- 手动将葡萄果梗放到剪切位轻轻顶住,记录此时的压力数值;
- 取「空载值 + 果梗值」的中间值作为触发阈值,例如空载 30、果梗顶住 280,阈值可设为150
2.正式触发运行版
#include <Servo.h> Servo cutterServo; // 引脚定义 #define CUTTER_PIN 9 #define FSR_PIN A0 // 舵机角度参数 #define CUTTER_OPEN 10 // 张开位(留余量,避开0°死区) #define CUTTER_CLOSE 110 // 剪切闭合位(根据机械校准) // 时间参数(单位:ms) #define MOVE_TIME 600 // 舵机转动到位时间 #define HOLD_TIME 200 // 剪切保压时间 #define SHIELD_TIME 1000 // 剪切后屏蔽时间 #define CALI_TIME 2000 // 上电校准时长 // 压力参数 #define CHECK_TIMES 3 // 连续确认次数 #define PRESSURE_OFFSET 100 // 触发偏移量(基准值+偏移量=阈值) // 状态机状态 enum CutterState { STATE_IDLE, // 待机检测 STATE_CLOSING, // 闭合中 STATE_HOLDING, // 保压中 STATE_OPENING, // 复位张开中 STATE_SHIELD // 屏蔽期 }; CutterState currentState = STATE_IDLE; unsigned long stateTimer = 0; // 压力基准值 int basePressure = 0; void setup() { Serial.begin(9600); cutterServo.attach(CUTTER_PIN); // 上电归零张开 cutterServo.write(CUTTER_OPEN); delay(MOVE_TIME); // 自动校准空载基准 Serial.println("=== 正在自动校准空载压力 ==="); long sum = 0; int count = 0; unsigned long caliStart = millis(); while (millis() - caliStart < CALI_TIME) { sum += analogRead(FSR_PIN); count++; delay(10); } basePressure = sum / count; Serial.print("空载基准值:"); Serial.println(basePressure); Serial.print("触发阈值:"); Serial.println(basePressure + PRESSURE_OFFSET); Serial.println("系统就绪,等待果梗触发..."); } void loop() { unsigned long now = millis(); switch (currentState) { case STATE_IDLE: // 连续检测防抖 if (checkPressureTrigger()) { Serial.println("果梗到位,开始剪切"); cutterServo.write(CUTTER_CLOSE); stateTimer = now; currentState = STATE_CLOSING; } break; case STATE_CLOSING: if (now - stateTimer >= MOVE_TIME) { stateTimer = now; currentState = STATE_HOLDING; } break; case STATE_HOLDING: if (now - stateTimer >= HOLD_TIME) { cutterServo.write(CUTTER_OPEN); stateTimer = now; currentState = STATE_OPENING; } break; case STATE_OPENING: if (now - stateTimer >= MOVE_TIME) { stateTimer = now; currentState = STATE_SHIELD; Serial.println("剪切完成,进入屏蔽期"); } break; case STATE_SHIELD: if (now - stateTimer >= SHIELD_TIME) { currentState = STATE_IDLE; Serial.println("回到待机状态"); } break; } } // 压力触发检测(防抖) bool checkPressureTrigger() { int threshold = basePressure + PRESSURE_OFFSET; for (int i = 0; i < CHECK_TIMES; i++) { int val = analogRead(FSR_PIN); if (val < threshold) { return false; } delay(5); } return true; }