
【学习向】ESP CyberDog - AI小智图传机器狗
简介
基于乐鑫平台的开源四足机器狗ESP CyberDog,创新实现AI语音交互去模块化、WiFi遥控与实时图传一体化集成,突破传统单一控制模式,通过仿生步态算法优化与模块化设计,打造低成本高扩展智能平台。
简介:基于乐鑫平台的开源四足机器狗ESP CyberDog,创新实现AI语音交互去模块化、WiFi遥控与实时图传一体化集成,突破传统单一控制模式,通过仿生步态算法优化与模块化设计,打造低成本高扩展智能平台。开源协议
:GPL 3.0
描述

本项目参加了智能机器狗实训营
作品获得进阶营一等奖
【QQ复刻交流】646681797、1035161350 口令:8083267A
20250820更新说明:修正了AI视觉模块PCB错误。另外,对于部分复刻中使用18650电池负载不够导致系统不断重启的问题,建议在5V升压后端增加大容量铝电解电容以稳定负载。
20250707更新说明:更新并开源了V2.0版本外壳,开源了固件及复刻资料。
20250603更新说明:更新了有关步态研究的图文说明。
20250512 软件更新说明:
> 1. 开源了V1.0版本固件。将小智ai机器狗和手机控制图传机器狗整合为一套代码。使用方法:在ai小智模式下,唤醒对话后说出 “切换系统”即可切换到图传模式。在图传模式下连接wifi并打开网页控制端,最下侧可以切换至ai小智模式。
> 2. 优化了手机控制端页面风格。
> 3. 由于作品复刻难度较大,复刻前先加qun交流。
20250507 更新说明:修订了开源文本,上传了包含脚部的3D外壳V1.0版本
一、项目背景
本项目基于乐鑫 IOT 开发环境,旨在打造一款低成本、高扩展性的开源四足机器狗,突破传统成品模块的功能限制,实现 “语音交互+无线遥控+实时图传” 的多维度智能控制,为开发者提供可复用的软硬件架构,推动人形机器人技术的普及与创新。
项目制作的 ESP CyberDog 机器狗具备以下功能:
-
接入 AI 小智,能够实现实时语音对话
-
支持 AI 小智语音控制机器狗运动
-
具备无线实时图传功能,图传帧率高
-
手机 HTML 页面遥控控制机器狗运动
-
智能炫彩灯,根据不同场景自动交互

二、核心内容
1. 运动系统:仿生四足步态控制
- 硬件方面采用 4 个SG90舵机,通过 PWM 输出脉冲信号,支持180°角度调节。
- 软件方面结合仿生步态,对原训练营步态进行了算法优化,BSP、控制层、动作层封装为 C++类函数,解耦了步态校正、角度镜像等参数,使用多阶段数组通过查表法定义多种动作模式,使用单阶段数组配合动作过度函数实现任意动作过度衔接。同时支持通过状态机、freeRTOS 事件组控制。
2. 语音交互:接入 AI小智模型
- 硬件方面参考乐鑫开发板的 audio 方案开发出低成本声觉拓展模块,避免串口接入其他三方音频模组,降低复刻成本和难度。
- 软件方面进行了深度的小智 bsp 适配支持。对声觉模块的底层和 api 进行移植,基于小智 IOT 控制接口开发拓展了机器狗行动、LED 彩灯、电池电量监测功能,同时将上述功能封装为独立的库函数,提供整齐的 api 接口便于其他项目移植应用。
3. 无线遥控:实施图传和动作控制
- 基于乐鑫芯片的无线通讯能力,在机器狗身上搭建了短距离无线服务器,开发了移动端遥控终端 html 页面,结合了 HTML/CSS/Script 开发实现响应式布局,实现了手机无线控制机器狗的功能。
- 依托视频流功能,实现了机器狗摄像头数据无线流式 MJPEG 传输,设备最大支持 800*600 分辨率 30fps 图像采集,通过 HTTP 多部分响应隔离图像流传输和控制功能,实现了视频级的图像传输速度,终端图传帧率效果好。

三、项目创新点
- AI语音交互去模块化:传统方案依赖成品语音模块(如科大讯飞LD3320),功能固定且成本高(约50元); 本项目直接在ESP32-S3上运行轻量化AI模型,仅需麦克风+扬声器(成本<20元),扩展性远超成品模块。
- 多模态控制的一体化集成:市面上同类项目通常仅支持单一控制方式(如纯遥控或纯语音),且图传需额外模块(如树莓派+WiFi图传套装,成本>200元); 本项目通过ESP32-S3单芯片实现 WiFi遥控+实时图传+语音交互 三大功能,总硬件成本控制在150元以内,且无需外部设备,手机即为主控终端,显著降低使用门槛。
- 舵机控制的仿生学优化:深度研究并重构了仿生步态,对原训练营步态进行了算法优化,解耦了步态校正、角度镜像等参数,使用多阶段数组通过查表法定义多种动作模式,使用单阶段数组配合动作过度函数实现任意动作过度衔接。同时支持通过状态机、freeRTOS 事件组控制。
四、硬件设计:模块化架构

项目贯彻了作者一如既往的模块化设计思维,将硬件封装为主控模块、视觉模块、声觉模块、供电模块四类,在原有主控模块实现机器狗行走和屏幕交互的基础上,方便不同模块组合拓展机器狗的视觉功能、音频交互功能、无线供电功能。各模块简要说明如下:
| 模块 | 核心组件 | 功能描述 | 设计优势 |
|---|---|---|---|
| 主控模块 | ESP32-S3-WROOM-1-N8R8模组+0.96 寸 OLED+四路舵机接口 | 可实现基本的机器狗行走做动作、灯光控制、屏幕画面及表情显示 | 集成度高,算力满足AI推理与多任务处理,基础功能健全 |
| 声觉模块 | 模拟 mic+ES8311 + NS4150B+8Ω/3W 喇叭 | 单声道麦克风近场输入,官方 BSP 深度适配 ESP IDF 开发环境 | 低功耗、体积小,适合嵌入式场景,模块完整隔离数字模拟电路,外接电路简单 |
| 视觉模块 | OV2640 摄像头 | 支持最大分辨率1600×1200 和 JPEG硬件压缩,板载多路 LDO 供电 | 低功耗、体积小,适合嵌入式场景,模块完整隔离数字模拟电路,外接电路简单 |
| 电源模块 | 18650电池座 +外接接口 | 支持插接单节 18650、3.7V锂电池,容量可选 | 插接设计可随意更换,省去充电停机烦恼 |
各模块电路分析不再赘述,详见往期项目介绍。
五、软件设计:模块化封装
软件基于 ESP IDF 框架开发,进行了独立模块的功能封装,提供独立 API 接口,实现了软件库随硬件模块随意移植适配的功能。各模块功能概述如下:
1. 运动控制模块
研究了简单的四足仿生步态,对原训练营步态进行了算法优化:
1.1 类定义及主要功能
class ServoController
{
public:
static ServoController &GetInstance();
...
esp_err_t start();
ActionState GetState() const { return state_; }
void SetState(ActionState new_state);
void servo_send_event(EventBits_t event);
private:
...
ServoController();
~ServoController();
void InitLedc(); // LEDC初始化
void SetServoAngle(int index, int angle); // 设置单个舵机角度
void StopAction(); // 复位舵机到躺下状态
static void servo_control_task(void *arg); // 舵机控制任务
// 过渡到目标角度
template
void TransitionTo(const int target[4][Stages], int steps = 10, int delay_ms = 20);
// 多阶段动作函数
template
void RunActionCore(const int (&angles)[4][Stages], int loops = 1, int delay_ms = 100);
// 单阶段动作函数
template
void ExecuteSingleStage(const int (&angles)[4][Stages]);
};
1.2 BSP 底层驱动调校解耦
// 全局BSP参数
static int servo_offsets[4] = {0, 0, 0, 0}; // 舵机偏移量,校正参数数组
static int servo_direction_flags[4] = {1, -1, 1, -1}; // 舵机方向标志,0度在前。1正常,-1反转
1.3 动作状态阶段数组
步态优化部分,对四足四自由度机器狗的动作步态进行拆解:
1. 前进步态分为8阶段实现,后退步态反向执行。
- 前进

- 后退

2. 左转和右转步态分4阶段实现,封装函数为8阶段(2个周期)。
- 左转

- 右转

3. 其他步态/动作暂时没写,此处将原理摆出以供探讨研究。
- 招手

- 摇摆

查表法的动作数组如下,注意此时已经将镜像、角度通过初始设置调整了。
// 动作角度数组(统一维度:[腿][阶段],4腿×阶段)
// 前进(多阶段步态)
static const int forwardAngles[4][8] = {
{90, 130, 130, 90, 50, 50, 90, 90}, // 左前
{50, 50, 90, 90, 90, 130, 130, 90}, // 右前
{50, 50, 90, 90, 90, 130, 130, 90}, // 左后
{90, 130, 130, 90, 50, 50, 90, 90}, // 右后
};
// 后退(多阶段步态)
static const int backwardAngles[4][8] = {
{90, 50, 50, 90, 130, 130, 90, 90},
{130, 130, 90, 90, 90, 50, 50, 90},
{130, 130, 90, 90, 90, 50, 50, 90},
{90, 50, 50, 90, 130, 130, 90, 90},
};
// 左转(多阶段步态)
static const int leftTurnAngles[4][8] = {
{130, 130, 90, 90, 130, 130, 90, 90},
{90, 130, 130, 90, 90, 130, 130, 90},
{90, 50, 50, 90, 90, 50, 50, 90},
{50, 50, 90, 90, 50, 50, 90, 90},
};
// 右转(多阶段步态)
static const int rightTurnAngles[4][8] = {
{90, 130, 130, 90, 90, 130, 130, 90},
{130, 130, 90, 90, 130, 130, 90, 90},
{50, 50, 90, 90, 50, 50, 90, 90},
{90, 50, 50, 90, 90, 50, 50, 90},
};
// 挥手,未验证(多阶段步态)
static const int waveHandAngles[4][6] = {
{90, 90, 90, 90, 90, 90},
{100, 120, 100, 80, 100, 120},
{90, 90, 90, 90, 90, 90},
{90, 90, 90, 90, 90, 90}};
// 单阶段动作数组
static const int sitDownAngles[4][1] = {{100}, {100}, {20}, {20}}; // 坐下
static const int lieDownAngles[4][1] = {{0}, {0}, {0}, {0}}; // 躺下
static const int StandUpAngles[4][1] = {{90}, {90}, {90}, {90}}; // 起立
1.4 动作过度函数实现任意动作过度衔接
template
void ServoController::TransitionTo(const int target[4][Stages], int steps, int delay_ms)
{
int start[4] = {current_angles[0], current_angles[1], current_angles[2], current_angles[3]};
for (int step = 0; step <= steps; step++)
{
for (size_t i = 0; i < 4; i++)
{
int angle = start[i] + (target[i][0] - start[i]) * step / steps;
SetServoAngle(i, angle);
}
vTaskDelay(pdMS_TO_TICKS(delay_ms));
}
}
2. AI小智 Board 适配
为小智板级支持包 BSP 适配了 esp32s3 模组、ES8311 驱动、电池电量监测 PowerManager、OLED 的 SSD1306 驱动以及 LVGL 支持、ServoController的 IOT 底层、LED Strip的彩灯控制。
class CyberDogEs8311AudioCodec : public Es8311AudioCodec
{
public:
CyberDogEs8311AudioCodec(void *i2c_master_handle, i2c_port_t i2c_port, int input_sample_rate, int output_sample_rate,
gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din,
gpio_num_t pa_pin, uint8_t es8311_addr, bool use_mclk = true);
void EnableOutput(bool enable) override;
};
class ESP_AI_CYBER_DOG : public WifiBoard
{
private:
i2c_master_bus_handle_t i2c_bus_;
CircularStrip *led_strip_;
Display *display_;
esp_lcd_panel_io_handle_t panel_io_ = nullptr;
esp_lcd_panel_handle_t panel_ = nullptr;
PowerManager *power_manager_;
void InitializeI2c();
void InitializePowerManager();
void InitializeSsd1306Display();
void InitializeIot();
public:
ESP_AI_CYBER_DOG();
virtual Led *GetLed() override;//重写控制函数
virtual AudioCodec *GetAudioCodec() override;
virtual Display *GetDisplay() override;
virtual bool GetBatteryLevel(int &level, bool &charging, bool &discharging) override;
};//重写控制函数
DECLARE_BOARD(ESP_AI_CYBER_DOG);
3. 无线遥控控制
该功能为独立工程项目,目的在于验证上述模块封装功能的实用性。
3.1 BSP 驱动
/* power */
#define BATTERY (GPIO_NUM_7) //adc1 channel6
/* I2C */
#define BSP_I2C_SDA (GPIO_NUM_1)
#define BSP_I2C_SCL (GPIO_NUM_2)
/* WS2812 */
#define BSP_WS2812 (GPIO_NUM_17)
/* Camera */
#define BSP_CAMERA_RST (GPIO_NUM_18)
#define BSP_CAMERA_PWDN (GPIO_NUM_8)
#define BSP_CAMERA_XCLK (GPIO_NUM_3)
#define BSP_CAMERA_PCLK (GPIO_NUM_12)
#define BSP_CAMERA_VSYNC (GPIO_NUM_19)
#define BSP_CAMERA_HSYNC (GPIO_NUM_20) // HREF
#define BSP_CAMERA_D0 (GPIO_NUM_14)
#define BSP_CAMERA_D1 (GPIO_NUM_21)
#define BSP_CAMERA_D2 (GPIO_NUM_47)
#define BSP_CAMERA_D3 (GPIO_NUM_13)
#define BSP_CAMERA_D4 (GPIO_NUM_11)
#define BSP_CAMERA_D5 (GPIO_NUM_9)
#define BSP_CAMERA_D6 (GPIO_NUM_10)
#define BSP_CAMERA_D7 (GPIO_NUM_46)
/* Audio */
#define BSP_I2S_BCLK (GPIO_NUM_39) // CCLK
#define BSP_I2S_MCLK (GPIO_NUM_40) // MCLK
#define BSP_I2S_WS (GPIO_NUM_45) // LCLK
#define BSP_I2S_DOUT (GPIO_NUM_48) // DO To Codec ES8311
#define BSP_I2S_DSIN (GPIO_NUM_38) // DI From Codec ES8311
#define BSP_POWER_AMP_IO (GPIO_NUM_5) // PA-en
/* Servo */
#define LEGS_IO_FRONT_LEFT (GPIO_NUM_41)
#define LEGS_IO_FRONT_RIGHT (GPIO_NUM_15)
#define LEGS_IO_BEHIND_LEFT (GPIO_NUM_42)
#define LEGS_IO_BEHIND_RIGHT (GPIO_NUM_6)
/*************************************************************************************************
*
* I2C 接口
*
**************************************************************************************************
* 连接到I2C外围设备如下:
* - OLED: SSD1315/SSD1306
* - 摄像头sccb: OV2640
* - 音频编解码芯片: ES8311
**************************************************************************************************/
#define BSP_I2C_NUM (0)
#define BSP_I2C_SPEED (100 * 1000)
esp_err_t bsp_i2c_init(void); // 初始化I2C主机总线
esp_err_t bsp_i2c_deinit(void); // 卸载I2C并释放资源
i2c_master_bus_handle_t bsp_i2c_get_handle(void); // 获取I2C句柄
esp_err_t bsp_i2c_probe(uint16_t address); // 检测设备是否连接至总线
/**************************************************************************************************
*
* OLED 显示屏
*
**************************************************************************************************/
#include "esp_lvgl_port.h"
#include "lvgl.h"
#define EXAMPLE_LCD_H_RES 128 //宽
#define EXAMPLE_LCD_V_RES 64 //高
#define EXAMPLE_LCD_PIXEL_CLOCK_HZ (400 * 1000)
#define EXAMPLE_I2C_HW_ADDR 0x3C
#define BSP_LCD_DRAW_BUFF_SIZE (EXAMPLE_LCD_H_RES * EXAMPLE_LCD_V_RES) // BSP_LCD_V_RES
#define BSP_LCD_DRAW_BUFF_DOUBLE (false) // 双缓存
lv_display_t *oled_init_with_lvgl(void);
void bsp_display_rotate(lv_display_t *disp, lv_disp_rotation_t rotation); // 屏幕旋转
bool bsp_display_lock(uint32_t timeout_ms); // 获取lvgl互斥体
void bsp_display_unlock(void); // 释放LVGL互斥体
void example_lvgl_demo_ui(lv_display_t *disp);
/**************************************************************************************************
*
* 摄像头:OV2640
*
*********************************************************************************************/
#define BSP_CAMERA_VFLIP 1 // 垂直翻转
#define BSP_CAMERA_HMIRROR 0 // 水平镜像
#define BSP_CAMERA_FRAME_SIZE FRAMESIZE_VGA // 图像大小
#define BSP_CAMERA_PIXEL_FORMAT PIXFORMAT_JPEG // 色彩模式
#define BSP_CAMERA_FB_LOCATION CAMERA_FB_IN_PSRAM // PSRAM
#define BSP_CAMERA_XCLK_FREQ_HZ (20 * 1000 * 1000)
#define BSP_CAMERA_DEFAULT_CONFIG \
{ \
.pin_pwdn = BSP_CAMERA_PWDN, \
.pin_reset = GPIO_NUM_NC, \
.pin_xclk = BSP_CAMERA_XCLK, \
.pin_sccb_sda = GPIO_NUM_NC, \
.pin_sccb_scl = GPIO_NUM_NC, \
.pin_d7 = BSP_CAMERA_D7, \
.pin_d6 = BSP_CAMERA_D6, \
.pin_d5 = BSP_CAMERA_D5, \
.pin_d4 = BSP_CAMERA_D4, \
.pin_d3 = BSP_CAMERA_D3, \
.pin_d2 = BSP_CAMERA_D2, \
.pin_d1 = BSP_CAMERA_D1, \
.pin_d0 = BSP_CAMERA_D0, \
.pin_vsync = BSP_CAMERA_VSYNC, \
.pin_href = BSP_CAMERA_HSYNC, \
.pin_pclk = BSP_CAMERA_PCLK, \
.xclk_freq_hz = BSP_CAMERA_XCLK_FREQ_HZ, \
.ledc_timer = LEDC_TIMER_0, \
.ledc_channel = LEDC_CHANNEL_0, \
.pixel_format = BSP_CAMERA_PIXEL_FORMAT, \
.frame_size = BSP_CAMERA_FRAME_SIZE, \
.jpeg_quality = 10, \
.fb_count = 4, \
.fb_location = BSP_CAMERA_FB_LOCATION, \
.sccb_i2c_port = BSP_I2C_NUM, \
}
void bsp_camera_ov2640_init(); // 摄像头硬件初始化(一般测试使用)
/**************************************************************************************************
*
* 音频编解码:ES8311
*
**************************************************************************************************
*
* 使用 espressif__esp_codec_dev 库实现
*
* 仅初始化扬声器使用 bsp_audio_codec_speaker_init(),在其内部已经初始化了I2S和 bsp_audio_init().
* 仅初始化麦克风使用 bsp_audio_codec_microphone_init() ,同上
* 同时初始化麦克风和扬声器使用 bsp_audio_codec_microphone_speaker_init(),同上
*
* 扬声器或麦克风初始化后,使用esp编解码器开发的功能播放录音音频, API详见 esp_codec_dev.h
*
**************************************************************************************************/
#define BSP_I2S_NUM (I2S_NUM_0) // 配置通道绑定总线端口
#define EXAMPLE_SAMPLE_RATE (16000)
#define EXAMPLE_MCLK_MULTIPLE (384) // If not using 24-bit data width, 256 should be enough
#define EXAMPLE_MCLK_FREQ_HZ (EXAMPLE_SAMPLE_RATE * EXAMPLE_MCLK_MULTIPLE)
#define EXAMPLE_VOICE_VOLUME (90)
#define EXAMPLE_MIC_GAIN (0)
void example_app_es8311_main(void);
3.2 各模块功能及任务调度方式
extern "C" void app_main(void)
{
xQueueIFrame = xQueueCreate(2, sizeof(camera_fb_t *));
if (xQueueIFrame == NULL)
{
ESP_LOGE(TAG, "Failed to create xQueueIFrame");
return;
}
/* Board */
Board::GetInstance();//OLED/CAMERA驱动
/* Power Manager */
PowerManager::GetInstance();
/* ServoController */
ServoController::GetInstance().start();
/* wifi */
app_wifi_main();
/* camera */
BaseType_t task_created = xTaskCreatePinnedToCore(camera_task, "camera_task", 1024 * 10, NULL, 5, NULL, 0);
if (task_created != pdPASS)
{
ESP_LOGE(TAG, "Failed to create camera_task");
return;
}
/* httpd server */
esp_err_t err = start_httpd(xQueueIFrame,true);
if (err != ESP_OK)
{
ESP_LOGE(TAG, "Failed to start stream server: %s", esp_err_to_name(err));
return;
}
}
4. HTML 开发
4.1 页面主体
(该部分代码会导致工程无法提交,暂时不放)
4.2 通讯逻辑
// 处理视频流图像加载失败的函数,将图像隐藏,并在状态提示区域显示加载失败的提示信息
function handleStreamError(img) {
img.style.display = "none";
document.getElementById("status-tip").textContent = "视频流加载失败,请检查设备连接!";
}
// 发送控制命令的函数
function sendCommand(command) {
const btn = event.target.closest('.control-btn');
if (btn.disabled) return;
btn.disabled = true;
const statusTip = document.getElementById("status-tip");
statusTip.textContent = `发送 ${command} 命令...`;
// 使用 fetch API 发送 POST 请求到控制接口
fetch('http://192.168.4.1/control', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ command: command }),
})
.then(response => {
if (!response.ok) throw new Error('命令发送失败');
return response.text();
})
.then(() => {
statusTip.textContent = "命令发送成功";
})
.catch(error => {
statusTip.textContent = `命令发送失败:${error.message}`;
})
.finally(() => {
btn.disabled = false;
});
}
// 检查设备连接状态的函数
function checkConnection() {
// 使用 fetch API 发送 HEAD 请求到控制接口
fetch('http://192.168.4.1/control', { method: 'POST' })
.then(response => {
if (response.ok) {
document.getElementById("status-tip").textContent = "设备连接正常";
}
})
.catch(() => {
document.getElementById("status-tip").textContent = "设备未连接,请检查 Wi-Fi";
});
}
// 获取电量和网络信号的函数
function getDeviceInfo() {
const batteryLevel = document.getElementById('battery-level');
const networkSignal = document.getElementById('network-signal');
// 发送请求获取电量和网络信号
fetch('http://192.168.4.1/device_info')
.then(response => {
if (!response.ok) throw new Error('无法获取设备信息');
return response.json();
})
.then(data => {
batteryLevel.textContent = `${data.battery}%-${data.voltage}V`;
networkSignal.textContent = `${data.network}dBm`;
})
.catch(error => {
batteryLevel.textContent = '加载失败';
networkSignal.textContent = '加载失败';
});
}
window.onload = function () {
checkConnection();
getDeviceInfo();
setInterval(getDeviceInfo, 5000);// 每隔 5 秒更新一次设备信息
};
六、项目价值与意义
- 技术创新:证明低成本硬件平台可实现复杂 AI 交互与多模态控制,为嵌入式 AI 应用提供参考范式。
- 工程实践:通过模块化设计与分层架构,验证 “硬件可替换、软件可扩展” 的开发思路,提升系统鲁棒性。
- 开源共享:项目成果可直接复用至其他机器人项目(如六足机器人、机械臂),降低行业开发成本,推动智能硬件普及。
总之, ESP CyberDog 不仅是一款功能完整的四足机器狗,更是一个开放的技术验证平台。通过软硬件深度整合与创新,项目展现了嵌入式系统与 AI 技术结合的无限可能,为智能机器人领域的爱好者与开发者提供了可落地的实践案例。
设计图
未生成预览图,请在编辑器重新保存一次BOM
暂无BOM
克隆工程工程成员
知识产权声明&复刻说明
本项目为开源硬件项目,其相关的知识产权归创作者所有。创作者在本平台上传该硬件项目仅供平台用户用于学习交流及研究,不包括任何商业性使用,请勿用于商业售卖或其他盈利性的用途;如您认为本项目涉嫌侵犯了您的相关权益,请点击上方“侵权投诉”按钮,我们将按照嘉立创《侵权投诉与申诉规则》进行处理。
请在进行项目复刻时自行验证电路的可行性,并自行辨别该项目是否对您适用。您对复刻项目的任何后果负责,无论何种情况,本平台将不对您在复刻项目时,遇到的任何因开源项目电路设计问题所导致的直接、间接等损害负责。


评论