171 lines
6.0 KiB
C
171 lines
6.0 KiB
C
/**
|
|
* @file main.c
|
|
* @brief EDC 步进电机网页控制 (ESP-IDF)
|
|
*
|
|
* 硬件接线:
|
|
* ESP32 TX (GPIO6) -> 电机 RX
|
|
* ESP32 RX (GPIO7) -> 电机 TX
|
|
* ESP32 GPIO5 -> 电磁铁
|
|
* ESP32 GPIO4 -> 舵机
|
|
* ESP32 GPIO11 -> 协议 UART TX (→ MPU) (UART0)
|
|
* ESP32 GPIO12 -> 协议 UART RX (← MPU) (UART0)
|
|
* ESP32 GPIO2 -> I2C SDA (← MPU)
|
|
* ESP32 GPIO3 -> I2C SCL
|
|
* ESP32 GPIO27 -> RGB LED (WS2812)
|
|
* ESP32 GPIO8 -> 按钮 (低电平有效, 触发识别)
|
|
* ESP32 GPIO9 -> 无源蜂鸣器 (经三极管驱动)
|
|
* ESP32 GND -> 电机 GND / MPU GND
|
|
*
|
|
* 注: 日志控制台已切换到 USB Serial/JTAG (COM 口监视),
|
|
* UART0 (GPIO11/12) 专用于 MPU 协议通讯。
|
|
*
|
|
* WiFi: 连接 ICE (密码 12345678), 获取 IP 后用浏览器打开控制页面
|
|
*/
|
|
|
|
#include "emm_v5.h"
|
|
#include "magnet.h"
|
|
#include "servo.h"
|
|
#include "web_ctrl.h"
|
|
#include "protocol.h"
|
|
#include "rgb.h"
|
|
#include "actuator.h"
|
|
#include "key.h"
|
|
#include "buzzer.h"
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "esp_log.h"
|
|
|
|
static const char *TAG = "MAIN";
|
|
|
|
/* ---- 按钮识别任务 ---- */
|
|
#define RECOGNIZE_TIMEOUT_MS 20000
|
|
#define RECOGNIZE_POLL_MS 100
|
|
/* 归零速度: XY 用 ACTUATOR_EXEC_VEL/ACC (3000/250), Z 用 ACTUATOR_EXEC_Z_VEL/Z_ACC (低速);
|
|
等待时间按最大行程 + 速度/加速度实时计算 */
|
|
|
|
static void button_recognize_task(void *pvParam)
|
|
{
|
|
while (1) {
|
|
if (key_is_pressed()) {
|
|
ESP_LOGI(TAG, "按钮按下, 归零后再发送 RECOGNIZE ...");
|
|
buzzer_beep(2000, 100); /* 短音: 识别开始 */
|
|
|
|
/* ---- 归零: 舵机抬起 + Z 回 0° (低速, 最坏行程 270°) ---- */
|
|
actuator_servo_up();
|
|
actuator_motor_angle(ACTUATOR_ADDR_ANGLE, 0.0f,
|
|
ACTUATOR_EXEC_Z_VEL, ACTUATOR_EXEC_Z_ACC, true);
|
|
vTaskDelay(pdMS_TO_TICKS(actuator_angle_settle_ms(
|
|
ACTUATOR_ANGLE_LIMIT_DEG,
|
|
ACTUATOR_EXEC_Z_VEL, ACTUATOR_EXEC_Z_ACC)));
|
|
|
|
/* ---- XY 回零: X=0, Y=330 (按最坏行程实时计算等待) ---- */
|
|
uint32_t xy_settle = actuator_mm_settle_ms(ACTUATOR_LIMIT_X_MAX,
|
|
ACTUATOR_EXEC_VEL,
|
|
ACTUATOR_EXEC_ACC);
|
|
uint32_t y_settle = actuator_mm_settle_ms(ACTUATOR_LIMIT_Y_MAX,
|
|
ACTUATOR_EXEC_VEL,
|
|
ACTUATOR_EXEC_ACC);
|
|
if (y_settle > xy_settle) xy_settle = y_settle;
|
|
|
|
actuator_motor_mm(ACTUATOR_ADDR_X, 0.0f,
|
|
ACTUATOR_EXEC_VEL, ACTUATOR_EXEC_ACC, true);
|
|
actuator_motor_mm(ACTUATOR_ADDR_Y1, 330.0f,
|
|
ACTUATOR_EXEC_VEL, ACTUATOR_EXEC_ACC, true);
|
|
vTaskDelay(pdMS_TO_TICKS(xy_settle));
|
|
|
|
ESP_LOGI(TAG, "归零完成, 发送 RECOGNIZE ...");
|
|
|
|
/* 清除旧 Cycle 记录 */
|
|
actuator_clear_last_cycle();
|
|
|
|
/* 发送识别指令 */
|
|
edc_proto_send_recognize();
|
|
|
|
/* 等待 MPU 回传 Cycle, 超时则发送 REQUEST */
|
|
bool got_cycle = false;
|
|
int loops = RECOGNIZE_TIMEOUT_MS / RECOGNIZE_POLL_MS;
|
|
for (int i = 0; i < loops; i++) {
|
|
vTaskDelay(pdMS_TO_TICKS(RECOGNIZE_POLL_MS));
|
|
if (actuator_is_last_cycle_valid()) {
|
|
got_cycle = true;
|
|
ESP_LOGI(TAG, "RECOGNIZE 成功, 已收到 Cycle");
|
|
buzzer_beep_twice(2000, 150); /* 双短音: 识别成功 */
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!got_cycle) {
|
|
ESP_LOGW(TAG, "RECOGNIZE 超时 (%d ms), 发送 CYCLE_REQUEST",
|
|
RECOGNIZE_TIMEOUT_MS);
|
|
buzzer_beep(880, 500); /* 长低音: 识别失败/超时 */
|
|
edc_proto_send_request();
|
|
}
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(50));
|
|
}
|
|
}
|
|
|
|
void app_main(void)
|
|
{
|
|
/* 初始化 RGB LED (GPIO27, 最先启动, 指示系统状态) */
|
|
rgb_init(GPIO_NUM_27);
|
|
rgb_set(32, 32, 0); /* 黄色 (低亮), 表示启动中 */
|
|
|
|
/* 初始化执行器 (步进电机 + 舵机) */
|
|
actuator_init();
|
|
|
|
/* 初始化电磁铁 (GPIO5) */
|
|
magnet_init(GPIO_NUM_5);
|
|
|
|
/* 初始化按钮 (GPIO8, 低电平有效, 触发识别) */
|
|
key_init(GPIO_NUM_8);
|
|
|
|
/* 初始化无源蜂鸣器 (GPIO9, 提示音) */
|
|
buzzer_init(GPIO_NUM_9);
|
|
|
|
/* 初始化通讯协议 (I2C 从机 GPIO2/3 + UART0 GPIO11/12) */
|
|
edc_proto_init(NULL);
|
|
|
|
/* 启动协议接收任务 */
|
|
xTaskCreate(edc_proto_task, "proto", 4096, NULL, 2, NULL);
|
|
|
|
/* 启动按钮识别任务 */
|
|
xTaskCreate(button_recognize_task, "btn", 2048, NULL, 1, NULL);
|
|
|
|
/* 上电延时 2 秒, 等待电机闭环初始化完毕 */
|
|
ESP_LOGI(TAG, "等待电机初始化...");
|
|
vTaskDelay(pdMS_TO_TICKS(2000));
|
|
|
|
/* 启动 WiFi + HTTP 网页控制服务器 */
|
|
web_ctrl_init();
|
|
|
|
/* 系统就绪: 黄灯 (低亮) */
|
|
rgb_set(32, 32, 0);
|
|
rgb_set_state(RGB_STATE_IDLE);
|
|
buzzer_beep(2000, 120); /* 启动/就绪: 短促一声 */
|
|
ESP_LOGI(TAG, "系统就绪, 等待网页指令...");
|
|
|
|
/* 结束提示: 每轮只响一次, 防止慢闪循环重复响 */
|
|
bool done_beeped = false;
|
|
|
|
while (1) {
|
|
/* 根据系统状态选择闪烁颜色 */
|
|
rgb_state_t st = rgb_get_state();
|
|
if (st == RGB_STATE_DONE) {
|
|
/* 绿灯慢闪: Cycle 执行完毕 */
|
|
if (!done_beeped) {
|
|
buzzer_beep_triple(2000, 100); /* 执行结束: 急促三响 */
|
|
done_beeped = true;
|
|
}
|
|
rgb_set(0, 32, 0);
|
|
} else {
|
|
/* 黄灯慢闪: 待机 */
|
|
done_beeped = false;
|
|
rgb_set(32, 32, 0);
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(500));
|
|
rgb_off();
|
|
vTaskDelay(pdMS_TO_TICKS(500));
|
|
}
|
|
}
|