前言

每年到了毕设和创客大赛季,后台都会收到很多学生朋友的提问:“想做一个能跟着声音走的智能小车,有没有简单易上手的方案?”

说实话,声源跟随小车看似简单,但传统实现方式门槛极高:需要 4-6 颗麦克风组成阵列,移植复杂的 TDOA 算法,还要花大量时间调参校准。对于没有专业声学和算法基础的学生来说,光是搞定声源定位这一个功能,就要耗费半个月以上的时间,最后还可能因为效果太差影响整个项目。

直到我接触到了AR1105 3 麦六向定位模组,才发现原来声源跟随可以这么简单。不需要懂任何声学原理,不需要写一行算法代码,只需要会用单片机读写 IO 口,就能在 3 天内做出一个稳定可用的声源跟随小车。

本文将从硬件选型、电路连接、代码编写到调试优化,手把手教你从零开始制作一款声源跟随智能小车,全程无坑,所有代码可直接复制使用,特别适合毕设、课程设计和创客比赛项目。

一、方案选型:为什么 AR1105 是学生党的最佳选择?

在做这个项目之前,我也调研了市面上常见的几种声源定位方案,最终选择了 AR1105,核心原因就是它完美匹配了学生党 “低成本、易上手、开发快” 的需求:

表格

方案类型 开发难度 开发周期 硬件成本 定位效果
传统 4 麦 + 软件算法 极高 15-30 天 100-200 元 一般,量产一致性差
成品语音识别模块 中等 7-10 天 50-80 元 只能识别特定指令,无法定位方向
AR1105 3 麦模组 极低 1-3 天 30-50 元 六向定位,稳定可靠

AR1105 最香的地方在于,它把所有复杂的声学和算法问题都封装在了模组内部,对外只提供 6 个简单的 IO 口。哪个方向有声音,对应的 IO 口就会输出高电平。对于我们来说,使用它就像使用一个普通的按键传感器一样简单。

二、硬件准备清单

制作这款声源跟随小车,你只需要准备以下这些常见的硬件材料,总成本不到 150 元:

表格

器件名称 型号 / 规格 数量 备注
主控板 STM32F103C8T6 最小系统板 1 块 也可以用 51 单片机、Arduino 等
声源定位模组 AR1105 1 个 含 3 颗数字麦克风
电机驱动模块 L298N 或 TB6612 1 块 TB6612 体积更小,功耗更低
直流减速电机 3V-6V,带编码器可选 2 个 普通减速电机即可
小车底盘 两轮差速底盘 1 套 含轮子、电池盒
锂电池 18650 锂电池 2 节(7.4V) 2 节 也可以用 3 节 AA 电池
杜邦线 公对母、母对母 若干
其他 开关、螺丝、热熔胶 若干

三、硬件连接教程

整个电路连接非常简单,只需要按照下表将各个模块对应连接起来即可,不需要任何复杂的外围电路。

1. 整体连接框图

plaintext

锂电池 → 开关 → 电机驱动模块电源输入
电机驱动模块5V输出 → STM32最小系统板5V引脚
电机驱动模块5V输出 → AR1105模组第1脚(+5V)

STM32 PB0-PB5 → AR1105第3-8脚(方向IO)
STM32 PA0-PA3 → 电机驱动模块IN1-IN4
电机驱动模块OUT1-OUT4 → 左右两个电机

2. AR1105 与 STM32 引脚对应表

这是最核心的连接部分,一定要接对:

表格

AR1105 引脚 功能 STM32 引脚
1 +5V 电源输入 5V
2 GND GND
3 0° 方向输出 PB0
4 60° 方向输出 PB1
5 120° 方向输出 PB2
6 180° 方向输出 PB3
7 240° 方向输出 PB4
8 300° 方向输出 PB5

重要提示

  • AR1105 的电源必须是稳定的 5V,电压低于 4V 会导致工作异常
  • 所有模块的 GND 必须连接在一起,否则会出现电平识别错误
  • 数字麦克风不需要额外供电,由 AR1105 第 19 脚自动供电

3. 麦克风安装注意事项

为了保证最好的定位效果,麦克风的安装一定要遵循以下规则:

  1. 三颗麦克风按等边三角形排列,拾音孔中心间距精确 10mm
  2. 麦克风拾音孔朝上,安装在小车顶部的前端位置
  3. 麦克风周围不要有任何遮挡物,远离电机和车轮的振动源
  4. 可以用热熔胶将麦克风固定在 PCB 板上,确保安装牢固

四、软件代码编写:50 行代码搞定声源跟随

AR1105 的软件开发极其简单,整个核心逻辑只需要 50 行代码就能实现。以下是基于 STM32F103 的完整代码,可直接复制使用。

1. 引脚定义与初始化

c

运行

#include "stm32f10x.h"
#include "delay.h"

// 方向IO定义
#define DIR_PORT GPIOB
#define DIR_0 GPIO_Pin_0
#define DIR_60 GPIO_Pin_1
#define DIR_120 GPIO_Pin_2
#define DIR_180 GPIO_Pin_3
#define DIR_240 GPIO_Pin_4
#define DIR_300 GPIO_Pin_5

// 电机控制IO定义
#define MOTOR_PORT GPIOA
#define IN1 GPIO_Pin_0
#define IN2 GPIO_Pin_1
#define IN3 GPIO_Pin_2
#define IN4 GPIO_Pin_3

// 初始化所有IO
void Init_ALL(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
    
    // 方向IO初始化(浮空输入)
    GPIO_InitStruct.GPIO_Pin = DIR_0|DIR_60|DIR_120|DIR_180|DIR_240|DIR_300;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(DIR_PORT, &GPIO_InitStruct);
    
    // 电机IO初始化(推挽输出)
    GPIO_InitStruct.GPIO_Pin = IN1|IN2|IN3|IN4;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(MOTOR_PORT, &GPIO_InitStruct);
    
    Delay_Init();
}

2. 电机控制函数

c

运行

// 小车前进
void Car_Forward(void)
{
    GPIO_SetBits(MOTOR_PORT, IN1);
    GPIO_ResetBits(MOTOR_PORT, IN2);
    GPIO_SetBits(MOTOR_PORT, IN3);
    GPIO_ResetBits(MOTOR_PORT, IN4);
}

// 小车左转
void Car_Left(void)
{
    GPIO_ResetBits(MOTOR_PORT, IN1);
    GPIO_ResetBits(MOTOR_PORT, IN2);
    GPIO_SetBits(MOTOR_PORT, IN3);
    GPIO_ResetBits(MOTOR_PORT, IN4);
}

// 小车右转
void Car_Right(void)
{
    GPIO_SetBits(MOTOR_PORT, IN1);
    GPIO_ResetBits(MOTOR_PORT, IN2);
    GPIO_ResetBits(MOTOR_PORT, IN3);
    GPIO_ResetBits(MOTOR_PORT, IN4);
}

// 小车停止
void Car_Stop(void)
{
    GPIO_ResetBits(MOTOR_PORT, IN1|IN2|IN3|IN4);
}

3. 主函数:声源跟随核心逻辑

c

运行

int main(void)
{
    uint8_t dir;
    
    Init_ALL();
    
    while(1)
    {
        // 读取声源方向
        if(GPIO_ReadInputDataBit(DIR_PORT, DIR_0)) dir = 0;
        else if(GPIO_ReadInputDataBit(DIR_PORT, DIR_60)) dir = 60;
        else if(GPIO_ReadInputDataBit(DIR_PORT, DIR_120)) dir = 120;
        else if(GPIO_ReadInputDataBit(DIR_PORT, DIR_180)) dir = 180;
        else if(GPIO_ReadInputDataBit(DIR_PORT, DIR_240)) dir = 240;
        else if(GPIO_ReadInputDataBit(DIR_PORT, DIR_300)) dir = 300;
        else dir = 0xFF;
        
        // 根据方向控制小车运动
        switch(dir)
        {
            case 0: Car_Forward(); break;      // 正前方有声音,前进
            case 60: Car_Right(); break;       // 右前方有声音,右转
            case 120: Car_Right(); Delay_Ms(200); Car_Forward(); break;
            case 240: Car_Left(); Delay_Ms(200); Car_Forward(); break;
            case 300: Car_Left(); break;       // 左前方有声音,左转
            default: Car_Stop(); break;        // 无声音,停止
        }
        
        Delay_Ms(50);
    }
}

4. 代码说明

  • 整个代码没有任何复杂的算法,只是简单地读取 IO 口电平,然后根据电平状态控制电机转动
  • 我只实现了最基础的跟随逻辑,你可以根据自己的需求进行扩展,比如增加调速功能、避障功能等
  • 代码中的延时时间可以根据实际情况调整,以获得最流畅的跟随效果

五、调试与优化指南

代码烧录完成后,你就可以开始调试你的声源跟随小车了。以下是我总结的几个调试技巧和常见问题的解决方法:

1. 基础功能测试

  • 先不要安装电机,只给 AR1105 和 STM32 供电
  • 分别在 6 个方向拍手,观察对应的 IO 口是否会输出高电平(可以用万用表测量)
  • 如果所有方向都能正常响应,说明 AR1105 工作正常,可以安装电机进行下一步调试

2. 跟随效果优化

  • 如果小车转向不灵敏,可以适当减小延时时间
  • 如果小车频繁抖动,可以增加一个简单的防抖逻辑:只有当同一个方向连续检测到 2-3 次声音时,才执行转向操作
  • 如果小车在某个方向的跟随效果不好,检查一下该方向的麦克风是否被遮挡,或者安装是否牢固

3. 常见问题解决

  • 问题 1:所有方向都没有反应 解决方法:检查电源是否正常,GND 是否连接正确,AR1105 引脚是否接反

  • 问题 2:只有个别方向有反应 解决方法:检查对应方向的麦克风是否损坏,焊接是否牢固,拾音孔是否被堵塞

  • 问题 3:定位不准确,频繁误判 解决方法:检查麦克风间距是否严格为 10mm,是否有振动源靠近麦克风,电源是否有噪声

六、项目扩展思路

这个基础版的声源跟随小车已经可以满足毕设和创客比赛的基本要求了。如果你想让你的项目更出彩,可以尝试以下几个扩展方向:

  1. 增加语音识别功能:在后端加上一个 LD3320 语音识别模块,让小车不仅能跟着声音走,还能听懂你的指令
  2. 增加避障功能:加上一个超声波传感器,让小车在跟随声音的同时,能够自动避开障碍物
  3. 增加蓝牙遥控功能:加上一个 HC-05 蓝牙模块,用手机 APP 控制小车的运动
  4. 增加 LED 指示灯:在每个方向加上一个 LED 灯,当检测到该方向有声音时,对应的 LED 灯点亮
  5. 升级为全向移动小车:使用麦克纳姆轮底盘,实现更灵活的运动

结语

整个项目从硬件组装到代码调试,我只用了 3 天时间就完成了,最终的跟随效果非常好:在安静的室内,3 米内可以准确跟随声音来源,转向流畅自然。

AR1105 这款模组真的是学生党的福音,它把原本需要专业知识才能实现的声源定位功能,变成了一个像按键一样简单易用的传感器。它让我们不用再在复杂的算法上浪费时间,可以把更多的精力放在项目的创意和功能实现上。

如果你正在为毕设或创客项目发愁,不妨试试这个方案。相信我,它一定会让你事半功倍。如果在制作过程中遇到任何问题,欢迎在评论区留言,我会尽力为你解答。

Logo

免费领 150 小时云算力,进群参与显卡、AI PC 幸运抽奖

更多推荐