【花雕动手做】迷你小龙虾 MimiClaw 主程序 mimi 改进与升级方案:从即时优化到架构演进

2026-04-2223
AI 快速预览详细 收起
MimiClaw 是基于 ESP32-S3 的 AI Agent 项目,支持 WS2812 和双电机差速控制。本文提供了从即时优化到架构演进的详细方案,包括启动流程健壮性增强、任务优先级与堆栈大小规范、内存监控增强、日志系统优化等多个方面。通过这些改进,可以显著提升系统的稳定性与可维护性。例如,引入 JSON 配置文件实现配置中心化,创建 power_manager 任务进行电源管理,以及增加模块初始化失败的回滚处理。

ESP32‑S3 智能体 MimiClaw 的主入口如下:

代码
/**
 * @file mimi.c  《驴友花雕二次开发版本》
 * @brief MimiClaw 主程序入口 - ESP32-S3 AI Agent(WS2812 + 双电机差速)
 */

#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_event.h"
#include "esp_system.h"
#include "esp_heap_caps.h"
#include "esp_spiffs.h"
#include "nvs_flash.h"

#include "mimi_config.h"
#include "bus/message_bus.h"
#include "wifi/wifi_manager.h"
#include "channels/telegram/telegram_bot.h"
#include "channels/feishu/feishu_bot.h"
#include "llm/llm_proxy.h"
#include "agent/agent_loop.h"
#include "memory/memory_store.h"
#include "memory/session_mgr.h"
#include "gateway/ws_server.h"
#include "cli/serial_cli.h"
#include "proxy/http_proxy.h"
#include "tools/tool_registry.h"
#include "cron/cron_service.h"
#include "heartbeat/heartbeat.h"
#include "skills/skill_loader.h"
#include "onboard/wifi_onboard.h"
#include "tools/tool_ws2812.h"
#include "tools/tool_motor.h"

static const char *TAG = "mimi";

static esp_err_t init_nvs(void) {
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_LOGW(TAG, "NVS erased");
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    return ret;
}

static esp_err_t init_spiffs(void) {
    esp_vfs_spiffs_conf_t conf = {
        .base_path = MIMI_SPIFFS_BASE,
        .max_files = 10,
        .format_if_mount_failed = true,
    };
    esp_err_t ret = esp_vfs_spiffs_register(&conf);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "SPIFFS mount failed");
        return ret;
    }
    size_t total = 0, used = 0;
    esp_spiffs_info(NULL, &total, &used);
    ESP_LOGI(TAG, "SPIFFS: total=%d, used=%d", (int)total, (int)used);
    return ESP_OK;
}

static void outbound_dispatch_task(void *arg) {
    ESP_LOGI(TAG, "Outbound dispatch started");
    while (1) {
        mimi_msg_t msg;
        if (message_bus_pop_outbound(&msg, UINT32_MAX) != ESP_OK) continue;
        if (strcmp(msg.channel, MIMI_CHAN_FEISHU) == 0) {
            feishu_send_message(msg.chat_id, msg.content);
        } else if (strcmp(msg.channel, MIMI_CHAN_TELEGRAM) == 0) {
            telegram_send_message(msg.chat_id, msg.content);
        } else if (strcmp(msg.channel, MIMI_CHAN_WEBSOCKET) == 0) {
            ws_server_send(msg.chat_id, msg.content);
        }
        free(msg.content);
    }
}

void app_main(void) {
    ESP_LOGI(TAG, "========================================");
    ESP_LOGI(TAG, "  MimiClaw - ESP32-S3 AI Agent");
    ESP_LOGI(TAG, "========================================");
    ESP_LOGI(TAG, "Internal free: %d bytes", (int)heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
    ESP_LOGI(TAG, "PSRAM free:    %d bytes", (int)heap_caps_get_free_size(MALLOC_CAP_SPIRAM));

    // 基础系统
    ESP_ERROR_CHECK(init_nvs());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    ESP_ERROR_CHECK(init_spiffs());

    // 核心子系统
    ESP_ERROR_CHECK(message_bus_init());
    ESP_ERROR_CHECK(memory_store_init());
    ESP_ERROR_CHECK(skill_loader_init());
    ESP_ERROR_CHECK(session_mgr_init());
    ESP_ERROR_CHECK(wifi_manager_init());
    ESP_ERROR_CHECK(http_proxy_init());
    ESP_ERROR_CHECK(telegram_bot_init());
    ESP_ERROR_CHECK(feishu_bot_init());
    ESP_ERROR_CHECK(llm_proxy_init());
    ESP_ERROR_CHECK(tool_registry_init());
    ESP_ERROR_CHECK(cron_service_init());
    ESP_ERROR_CHECK(heartbeat_init());
    ESP_ERROR_CHECK(agent_loop_init());

    // 可选:显式初始化 LED 和电机
    if (tool_ws2812_init() == ESP_OK) {
        ESP_LOGI(TAG, "WS2812 initialized (9 LEDs on GPIO48)");
    }
    if (tool_motor_init() == ESP_OK) {
        ESP_LOGI(TAG, "Motor driver initialized (2 motors, differential drive)");
    }

    // 串口命令行
    ESP_ERROR_CHECK(serial_cli_init());
    ESP_LOGI(TAG, "Serial CLI started");

    // WiFi 连接
    if (wifi_manager_start() == ESP_OK) {
        wifi_manager_scan_and_print();
        if (wifi_manager_wait_connected(30000) == ESP_OK) {
            ESP_LOGI(TAG, "WiFi connected: %s", wifi_manager_get_ip());
        } else {
            ESP_LOGW(TAG, "WiFi timeout");
        }
    } else {
        ESP_LOGW(TAG, "No WiFi credentials, enter onboarding");
        wifi_onboard_start(WIFI_ONBOARD_MODE_CAPTIVE);
        return;
    }
    wifi_onboard_start(WIFI_ONBOARD_MODE_ADMIN);

    // 启动网络服务
    xTaskCreatePinnedToCore(outbound_dispatch_task, "outbound", 16384, NULL, 5, NULL, 1);
    agent_loop_start();
    feishu_bot_start();
    ws_server_start();

    ESP_LOGI(TAG, "All services started! MimiClaw ready.");

    // 硬编码电机测试(等待系统稳定)
    vTaskDelay(pdMS_TO_TICKS(5000));
    ESP_LOGI(TAG, ">>> Testing left motor forward 2 seconds <<<");
    motor_control(0, 1);
    vTaskDelay(pdMS_TO_TICKS(2000));
    motor_control(0, 0);
    vTaskDelay(pdMS_TO_TICKS(1000));
    ESP_LOGI(TAG, ">>> Testing right motor forward 2 seconds <<<");
    motor_control(1, 1);
    vTaskDelay(pdMS_TO_TICKS(2000));
    motor_control(1, 0);
    ESP_LOGI(TAG, ">>> Motor test finished <<<");
}

/* FreeRTOS 堆栈溢出钩子函数 */
void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) {
    ESP_EARLY_LOGE(TAG, "!!! Stack overflow in task: %s !!!", pcTaskName ? pcTaskName : "unknown");
    while (1);
}

00 (1).jpg

 

## 一、立即改进(无需大规模重构)

 

1. 启动流程健壮性增强

 

02.jpg

2. 任务优先级与堆栈大小规范

03.jpg

3. 内存监控增强
app_main 开头打印了总空闲内存,但后续未跟踪碎片化。建议:

每 60 秒通过心跳任务打印一次 heap_caps_get_free_size(MALLOC_CAP_INTERNAL) 与 MALLOC_CAP_SPIRAM,用于远程监控。

引入 ESP Insights 或自定义内存水位告警。


4. 日志系统优化
使用 日志分级过滤:将 ESP_LOGI 改为 ESP_LOGD 以降低生产环境串口输出。

增加日志转发:将重要日志通过 message_bus 发送到管理员会话(便于远程调试)。


5. 模块初始化顺序显式化
当前初始化顺序虽合理,但缺少失败回滚。建议:

使用 状态机枚举 记录初始化阶段,便于定位重启原因。

为每个 *_init() 增加反初始化函数,在严重错误时可尝试优雅停机。

## 二、架构升级方案(中长期演进)

1. 启动配置中心化
现状:所有初始化参数散落在各组件头文件或 menuconfig 中,调整需重编译。

升级方案:引入JSON 配置文件(存于 SPIFFS 或 LittleFS),在 app_main 早期加载:

代码
typedef struct {
    struct {
        bool enable_ws2812;
        bool enable_motor;
    } hardware;
    struct {
        int outbound_stack_size;
        int agent_priority;
    } tasks;
} app_config_t;

好处:同一固件可适配不同硬件变体(有无电机、LED),现场调试无需重刷固件。

 

 

2. 引入统一电源管理任务
电机与 WS2812 是耗电大户,当前无节电策略。升级方案:

创建 power_manager 任务,监听 MESSAGE_TYPE_IDLE 事件。

空闲超过 30 秒自动关闭 LED、使电机驱动进入低功耗模式。

 

3. 双核任务绑定优化
ESP32‑S3 为双核,当前仅将 outbound_dispatch_task 固定到 Core 1。建议:

Core 0:协议栈(PRO CPU)——处理 WiFi、LWIP、HTTP 服务。

Core 1:应用(APP CPU)——运行 Agent 推理、电机控制、LED 动画。

在 sdkconfig 中启用 CONFIG_FREERTOS_UNICORE=n,并通过 xTaskCreatePinnedToCore 显式分配。

 

4. 安全启动与固件 OTA 支持
当前缺失 OTA 能力,无法远程升级。应在 app_main 中增加:

代码
#if CONFIG_MIMI_OTA_ENABLED
xTaskCreate(ota_monitor_task, "ota", 8192, NULL, 1, NULL);
#endif

5. 外设自检与看门狗集成
添加硬件自检阶段(LED、电机、IMU 等),结果上报云端。

启用 任务看门狗 (TWDT) 监控 agent_loop_task、outbound_dispatch_task,防止死锁导致整机失联。

 

6. 通信总线抽象
outbound_dispatch_task 中硬编码了 if (strcmp) 分支,扩展新通道(如 WhatsApp、Discord)需修改此处。升级为注册回调机制:
 

代码
typedef void (*outbound_handler_t)(const char *chat_id, const char *content);
void register_outbound_channel(const char *name, outbound_handler_t handler);

## 三、具体代码修改示例(部分关键改进)

 

改进 app_main 中的 WiFi 配网逻辑

 

代码
// 原代码
wifi_onboard_start(WIFI_ONBOARD_MODE_ADMIN);  // 总是启动

// 改进后
if (wifi_manager_get_state() != WIFI_STATE_CONNECTED) {
    wifi_onboard_start(WIFI_ONBOARD_MODE_CAPTIVE);
    // 等待配网完成(阻塞或事件驱动)
} else {
    // 仅当用户通过 CLI 请求时才启动 ADMIN 模式
    ESP_LOGI(TAG, "WiFi already connected, admin onboard skipped");
}

移除电机硬编码测试

代码
// 使用条件编译
#if CONFIG_MIMI_FACTORY_TEST_ENABLE
    vTaskDelay(pdMS_TO_TICKS(5000));
    run_factory_motor_test();
#endif

增加模块初始化失败的回滚处理

代码
#define CHECK_INIT(expr, label) do { \
    if ((expr) != ESP_OK) { \
        ESP_LOGE(TAG, "Init failed at %s", #expr); \
        goto label; \
    } \
} while(0)

// 在 app_main 中使用
if (0) {
cleanup_memory:
    memory_store_deinit();
cleanup_bus:
    message_bus_deinit();
}

## 四、升级后启动时序图(推荐流程)

 

04.jpg

## 五、总结

 

上述改进与升级方案覆盖了稳定性、可维护性、扩展性、功耗与安全五个维度。短期内可先实施第一部分“立即改进”以提升现场部署可靠性;中长期建议按架构升级路径迭代,最终使 MimiClaw 成为一个模块化、可配置、支持 OTA 的生产级 AI Agent 固件。

 

000-3.jpg
 

创作许可协议

本项目采用 None(不开放任何权利,保留所有权利) 进行许可。

评论(0)
- 没有更多了 -