暂时留着

xxx

非常好,既然你目前 **暂时不需要使用超声波**,我们可以彻底释放 `Trig` 和 `Echo` 所占用的引脚(原为 GPIO 27 和 GPIO 34),并进一步优化整体引脚布局,为后续扩展 **I²C、UART、SPI 或其他传感器** 出更多空间。 --- ### ✅ 目标 1. **完全移除超声波相关代码和引脚占用** 2. **确保 I²C 接口安全保:SDA=21, SCL=22** 3. **释放 GPIO 27 和 GPIO 34,可用于未来功能扩展** 4. **保持电机、红外等核心功能不变** --- ### ✅ 当前已使用与可释放引脚 | 引脚 | 原用途 | 是否可释放 | 说明 | |------|--------|------------|------| | 12 | 左电机正转 | ❌ 使用中 | 必需 | | 13 | 左电机反转 | ❌ 使用中 | 必需 | | 14 | 右电机正转 | ❌ 使用中 | 必需 | | 15 | 右电机反转 | ❌ 使用中 | 必需 | | 32 | 红外1 | ❌ 使用中 | 巡线必需 | | 33 | 红外2 | ❌ 使用中 | 巡线必需 | | 25 | 红外3 | ❌ 使用中 | 巡线必需 | | 26 | 红外4 | ❌ 使用中 | 巡线必需 | | 27 | 超声波 Trig | ✅ 可释放 | 暂不使用 | | 34 | 超声波 Echo | ✅ 可释放 | 暂不使用 | | 21 | I²C SDA | ✅ 保 | 不接其他 | | 22 | I²C SCL | ✅ 保 | 不接其他 | > 📌 所有非必要外设均已移除,系统更简洁稳定! --- ## ✅ 最终精简版代码(无超声波,仅巡线 + 预通信接口) ```cpp #include <Arduino.h> // ==================== 核心功能引脚定义 ==================== // 电机控制 (L9110S) #define LEFT_FORWARD 12 #define LEFT_BACKWARD 13 #define RIGHT_FORWARD 14 #define RIGHT_BACKWARD 15 // 四路红外传感器 #define IR_LEFTMOST 32 #define IR_LEFT 33 #define IR_RIGHT 25 #define IR_RIGHTMOST 26 // I2C 保引脚(用于后续 OLED、MPU6050 等) #define I2C_SDA 21 #define I2C_SCL 22 // 可选串口扩展(如蓝牙、GPS) #define UART2_TX 5 #define UART2_RX 4 // ==================== 巡线参数 ==================== const int BASE_SPEED = 120; // 基础速度 const int MAX_SPEED = 200; const int MIN_SPEED = 80; // PID 控制参数(建议调试时调整) float Kp = 18.0, Ki = 0.0, Kd = 80.0; float integral = 0, last_error = 0; // ==================== setup() 初始化 ==================== void setup() { Serial.begin(115200); // 调试输出 Serial2.begin(9600, SERIAL_8N1, UART2_RX, UART2_TX); // 扩展串口 // 设置电机引脚 pinMode(LEFT_FORWARD, OUTPUT); pinMode(LEFT_BACKWARD, OUTPUT); pinMode(RIGHT_FORWARD, OUTPUT); pinMode(RIGHT_BACKWARD, OUTPUT); // 设置红外传感器为输入 pinMode(IR_LEFTMOST, INPUT); pinMode(IR_LEFT, INPUT); pinMode(IR_RIGHT, INPUT); pinMode(IR_RIGHTMOST, INPUT); // 初始化 PWM 控制 initPWM(); delay(1000); Serial.println("✅ 巡线小车启动完成"); Serial.println("📌 I2C 已预: SDA=21, SCL=22"); Serial.println("📌 UART2 已启用: TX=5, RX=4"); Serial.println("📌 所有超声波引脚已释放(GPIO 27 & 34 可用)"); } // ==================== 读取红外传感器状态 ==================== int readSensors() { bool onLine[4] = { digitalRead(IR_LEFTMOST) == LOW, digitalRead(IR_LEFT) == LOW, digitalRead(IR_RIGHT) == LOW, digitalRead(IR_RIGHTMOST) == LOW }; // 判断位置并返回误差值 (-3 ~ +3) if (onLine[0] && !onLine[1] && !onLine[2] && !onLine[3]) return -3; // 极左 if (!onLine[0] && onLine[1] && !onLine[2] && !onLine[3]) return -2; // 偏左 if (!onLine[0] && !onLine[1] && onLine[2] && !onLine[3]) return 2; // 偏右 if (!onLine[0] && !onLine[1] && !onLine[2] && onLine[3]) return 3; // 极右 if (!onLine[0] && onLine[1] && onLine[2] && !onLine[3]) return -1; // 中偏左 if (!onLine[0] && !onLine[1] && onLine[2] && onLine[3]) return 1; // 中偏右 if (onLine[0] && onLine[1] && !onLine[2] && !onLine[3]) return -1; if (!onLine[0] && onLine[1] && onLine[2] && onLine[3]) return 1; if (onLine[0] && onLine[1] && onLine[2] && onLine[3]) return 0; // 全黑(交叉或终点) if (!onLine[0] && !onLine[1] && !onLine[2] && !onLine[3]) return 0; // 全白(脱线) return 0; } // ==================== PWM 初始化 ==================== void initPWM() { ledcSetup(0, 5000, 8); // 左正 ledcSetup(1, 5000, 8); // 左反 ledcSetup(2, 5000, 8); // 右正 ledcSetup(3, 5000, 8); // 右反 ledcAttachPin(LEFT_FORWARD, 0); ledcAttachPin(LEFT_BACKWARD, 1); ledcAttachPin(RIGHT_FORWARD, 2); ledcAttachPin(RIGHT_BACKWARD, 3); } // ==================== 电机控制函数 ==================== void setMotorSpeed(int leftSpeed, int rightSpeed) { leftSpeed = constrain(leftSpeed, 0, 255); rightSpeed = constrain(rightSpeed, 0, 255); // 左电机 if (leftSpeed > 0) { ledcWrite(0, leftSpeed); ledcWrite(1, 0); } else { ledcWrite(0, 0); ledcWrite(1, -leftSpeed); } // 右电机 if (rightSpeed > 0) { ledcWrite(2, rightSpeed); ledcWrite(3, 0); } else { ledcWrite(2, 0); ledcWrite(3, -rightSpeed); } } // ==================== 主循环:纯巡线 ==================== void loop() { int error = readSensors(); // PID 计算 float derivative = error - last_error; integral += error; float power_diff = Kp * error + Ki * integral + Kd * derivative; last_error = error; // 计算左右轮速度 int leftSpeed = BASE_SPEED - power_diff; int rightSpeed = BASE_SPEED + power_diff; // 限幅 leftSpeed = constrain(leftSpeed, MIN_SPEED, MAX_SPEED); rightSpeed = constrain(rightSpeed, MIN_SPEED, MAX_SPEED); // 驱动电机 setMotorSpeed(leftSpeed, rightSpeed); // 实时调试信息 Serial.print("Err:"); Serial.print(error); Serial.print(" | L:"); Serial.print(leftSpeed); Serial.print(" R:"); Serial.print(rightSpeed); Serial.println(); // 可通过 UART2 接收外部命令(例如切换模式) if (Serial2.available()) { String cmd = Serial2.readStringUntil('\n'); Serial.print("🔹 收到指令: "); Serial.println(cmd); // 示例处理 if (cmd == "STOP") setMotorSpeed(0, 0); if (cmd == "FORWARD") setMotorSpeed(150, 150); } delay(20); // 小延时,避免过快刷新 } ``` --- ### ✅ 当前空闲可用的引脚(可扩展新功能) | 引脚 | 可用途 | |------|-------| | 27 | 可用于 SPI CS、数字输入、LED 指示灯 | | 34 | 输入专用 → 可接按键、限位开关、模拟比较输出 | | 35 | 输入专用 → 可接另一路传感器 | | 4 | UART2 RX(已用) | | 5 | UART2 TX(已用) | | 23 | 完全空闲 → 可用于 SPI CLK 或额外控制信号 | > 💡 提示:GPIO 34/35 是输入专用,不能输出,但非常适合接按钮、比较器输出等。 --- ### ✅ 后续扩展建议 | 功能 | 推荐引脚 | 接口类型 | |------|----------|---------| | OLED 显示屏 | SDA=21, SCL=22 | I²C | | MPU6050 陀螺仪 | 同上 | I²C | | 蓝牙模块 HC-05 | TX=5, RX=4 | UART2 | | 按键/急停开关 | GPIO 34 | 数字输入 | | RGB 指示灯 | GPIO 27 | PWM 输出 | | SPI Flash 或传感器 | GPIO 23(SCK), 19(MISO), 26(MOSI), 自定义 CS | SPI | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值