基于 STM32F103C8 的超声波循迹送药机器人 Proteus 仿真

前言

本设计以 STM32F103C8 为控制核心,完成四轮送药机器人的循迹行驶、超声波避障、货物状态检测、RFID 状态检测和 OLED 信息显示。

系统使用两组 L298 驱动四个直流电机。PB0、PB1 接收两路循迹信号,HC-SR04 检测机器人前方距离,PA1 采集压力传感器模拟电压,PB5接收 RFID 状态信号。OLED 实时显示距离、RFID、行驶方向和货物状态。

本设计使用 Keil MDK 编写 STM32 标准外设库程序,使用 Proteus 完成电路搭建和功能仿真。

完整工程资料免费获取

点赞 + 收藏本文,并在评论区留言“超声波送药机器人”,即可免费获取完整工程网盘链接。

工程资料包含:Keil 源码、Proteus 仿真文件、可直接加载的 HEX 文件和项目演示视频。
闲鱼店铺:大嘴花电子
专注单片机仿真与实物定制,支持 STM32、51 单片机、Arduino、Proteus 仿真等。
有需要仿真文件、代码程序、实物制作的朋友都可以咨询。
价格优惠,沟通好需求后定制方案,谢谢支持!


一、系统运行效果

在这里插入图片描述

图 1 系统运行总图

图 1 中的系统处于正常直行状态,运行数据如下:

检测项目 当前数据
HC-SR04 距离 111 cm
RFID 状态 yes
行驶状态 straight
货物状态 NO
PA1 输入电压 0.725993 V

PA1 电压低于程序设定的 2.0 V 阈值,因此 OLED 显示 cargo:NO。HC-SR04 测得距离为 111 cm,高于 100 cm 避障阈值,机器人按照 PB0、PB1 的输入状态执行直行。


二、系统功能

本设计实现以下功能:

  1. HC-SR04 实时测量机器人前方距离;
  2. 前方距离小于 100 cm 时停止四个电机;
  3. PB0、PB1 控制直行、左转、右转和停止;
  4. PA1 采集压力传感器模拟电压;
  5. PA1 电压高于 2.0 V 时判定有货;
  6. PB10 输出货物检测结果;
  7. PB5 接收 RFID 识别状态;
  8. OLED 显示距离、RFID、行驶状态和货物状态;
  9. 两组 L298 分别驱动左侧和右侧四个电机。

系统控制顺序为:

读取超声波距离
        ↓
读取压力传感器电压
        ↓
读取 PB0、PB1 循迹信号
        ↓
读取 PB5 RFID 状态
        ↓
执行避障或循迹控制
        ↓
刷新 OLED 显示

避障控制优先于循迹控制。距离小于 100 cm 时,程序直接调用 Car_Stop(),PB0、PB1 的状态不再控制电机。


三、硬件组成

模块 数量 功能
STM32F103C8 1 系统控制核心
HC-SR04 1 超声波距离检测
0.96 英寸 OLED 1 系统数据显示
L298 2 四路电机方向控制
直流电机 4 左前、左后、右前、右后车轮
压力传感器模拟输入 1 货物状态检测
RFID 状态开关 1 RFID 识别结果输入
循迹状态开关 2 左右循迹信号输入
LED 1 PB10 货物状态输出指示
复位电路 1 STM32 手动复位
晶振电路 1 STM32 外部时钟

四、STM32 最小系统与压力检测

在这里插入图片描述

图 2 STM32 最小系统与压力检测电路

STM32F103C8 最小系统由主控芯片、复位电路、外部晶振和电源连接组成。

4.1 复位电路

NRST 引脚通过 10 kΩ 电阻连接高电平,按键按下后将 NRST 拉低,完成系统复位。电容 C3 用于上电复位。

4.2 外部晶振

外部晶振 X1 连接 PD0 和 PD1,两端分别连接 22 pF 电容。系统程序按照 72 MHz 主频配置 SysTick 和 TIM2。

4.3 压力传感器输入

RV1 模拟压力传感器输出,滑动端连接 PA1。PA1 对应 ADC1 通道 1。

ADC 为 12 位转换,参考电压为 3.3 V。2.0 V 对应的 ADC 阈值为:

2.0 ÷ 3.3 × 4095 = 2481.8

程序使用整数阈值 2482:

#define ADC_THRESHOLD_2V (2482U)

货物状态判断代码如下:

u8 ADC_CargoOut_UpdateByPA1_2V(void)
{
    u16 adc = ADC_ReadAverage(ADC_Channel_1, 10);

    if (adc > ADC_THRESHOLD_2V)
    {
        GPIO_SetBits(GPIOB, GPIO_Pin_10);
        return 1;
    }
    else
    {
        GPIO_ResetBits(GPIOB, GPIO_Pin_10);
        return 0;
    }
}

程序连续采样 10 次并计算平均值。ADC 值大于 2482 时,PB10 输出高电平,OLED 显示 cargo:YES;ADC 值不大于 2482 时,PB10 输出低电平,OLED 显示 cargo:NO

图 1 中 PA1 电压为 0.725993 V,货物检测结果为 cargo:NO


五、四轮电机驱动电路

在这里插入图片描述

图 3 两组 L298 与四个直流电机

系统使用两组 L298 控制四个直流电机。

5.1 左侧电机

电机 L298 输入 STM32 引脚
左前轮 IN1、IN2 PA2、PA3
左后轮 IN3、IN4 PA4、PA5

5.2 右侧电机

电机 L298 输入 STM32 引脚
右前轮 IN1、IN2 PA8、PA9
右后轮 IN3、IN4 PA10、PB6

L298 的 ENA、ENB 接高电平,四个电机由输入端控制前进和停止。

单个电机的控制关系如下:

IN-A IN-B 电机状态
0 0 停止
1 0 前进

电机底层控制函数如下:

static inline void Motor_Stop_2IN(GPIO_TypeDef *port,
                                  uint16_t inA,
                                  uint16_t inB)
{
    GPIO_ResetBits(port, inA);
    GPIO_ResetBits(port, inB);
}

static inline void Motor_Fwd_2IN(GPIO_TypeDef *port,
                                 uint16_t inA,
                                 uint16_t inB)
{
    GPIO_SetBits(port, inA);
    GPIO_ResetBits(port, inB);
}

整车动作表如下:

行驶动作 左侧电机 右侧电机
停止 停止 停止
直行 前进 前进
左转 停止 前进
右转 前进 停止

对应程序如下:

void Car_Stop(void)
{
    LF_Stop();
    LR_Stop();
    RF_Stop();
    RR_Stop();
}

void Car_Straight(void)
{
    LF_Fwd();
    LR_Fwd();
    RF_Fwd();
    RR_Fwd();
}

void Car_Left(void)
{
    LF_Stop();
    LR_Stop();
    RF_Fwd();
    RR_Fwd();
}

void Car_Right(void)
{
    RF_Stop();
    RR_Stop();
    LF_Fwd();
    LR_Fwd();
}

六、HC-SR04 超声波测距

在这里插入图片描述

图 4 HC-SR04 超声波模块

HC-SR04 与 STM32 的连接如下:

HC-SR04 引脚 STM32 引脚
Trig PA6
Echo PA7
VCC 电源
GND

PA6 输出 10 μs 触发脉冲:

static void Trig_10us(void)
{
    GPIO_ResetBits(GPIOA, GPIO_Pin_6);
    Delay_us(2);
    GPIO_SetBits(GPIOA, GPIO_Pin_6);
    Delay_us(10);
    GPIO_ResetBits(GPIOA, GPIO_Pin_6);
}

TIM2 的计数频率设置为 1 MHz,一个计数周期为 1 μs:

tim.TIM_Prescaler = 72 - 1;
tim.TIM_Period = 0xFFFF;
TIM_TimeBaseInit(TIM2, &tim);

程序记录 Echo 上升沿和下降沿对应的 TIM2 计数值,得到 Echo 高电平持续时间。距离计算代码为:

return (uint16_t)(pulse_us / 58);

测距函数在等待 Echo 上升沿和下降沿时分别设置 30000 次超时计数。超时后返回 0。

图 4 中 HC-SR04 仿真距离为 110.0 cm,OLED 显示整数距离 0111


七、OLED、RFID 与运行信息

在这里插入图片描述

图 5 RFID、OLED 与 HC-SR04 运行状态

OLED 使用软件 I2C 驱动:

OLED 引脚 STM32 引脚
SCL PB8
SDA PB9
VCC 电源
GND

OLED 显示四行数据:

显示行 内容
第 1 行 HC-SR04 距离
第 2 行 RFID 状态
第 3 行 行驶状态
第 4 行 货物状态

在这里插入图片描述

图 6 OLED 运行数据显示

图 6 显示内容为:

HC-SR04:0111
RFID:yes
straight
cargo: NO

PB5 配置为下拉输入。PB5 为高电平时显示 RFID:yes,PB5 为低电平时显示 RFID:wait

RFID 状态读取函数如下:

uint8_t IO_ReadPB5(void)
{
    return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_5) ? 1 : 0;
}

八、红外循迹输入

在这里插入图片描述

图 7 PB0、PB1 循迹输入

PB0、PB1 配置为上拉输入,两个开关模拟左右红外循迹模块的数字输出。

循迹控制表如下:

PB0 PB1 行驶状态 OLED 显示
1 1 直行 straight
1 0 左转 left
0 1 右转 right
0 0 停止 stop

控制程序如下:

if (b0 == 1 && b1 == 1)
{
    Car_Straight();
    OLED_ShowStateLine(s_straight);
}
else if (b0 == 1 && b1 == 0)
{
    Car_Left();
    OLED_ShowStateLine(s_left);
}
else if (b0 == 0 && b1 == 1)
{
    Car_Right();
    OLED_ShowStateLine(s_right);
}
else
{
    Car_Stop();
    OLED_ShowStateLine(s_stop);
}

图 1 中 PB0、PB1 均为高电平,四个电机同时前进,OLED 显示 straight


九、主程序控制逻辑

系统初始化代码如下:

OLED_Init();
OLED_Clear();
OLED_Update();

Motor_Init();
IO_Init();
HCSR04_TIM_Init();
ADC_InitPA1();
ADC_CargoOut_InitPB10();

主循环依次读取距离、货物状态、循迹状态和 RFID 状态:

while (1)
{
    uint16_t dist = HCSR04_TIM_GetDistanceCM();
    uint8_t hasCargo = ADC_CargoOut_UpdateByPA1_2V();
    uint8_t b0 = IO_ReadB0();
    uint8_t b1 = IO_ReadB1();
    uint8_t rfid = IO_ReadPB5();

    OLED_Clear();
    OLED_ShowDistanceLine(dist);

    if (dist != 0 && dist < 100)
    {
        Car_Stop();
        OLED_ShowStateLine(s_obst);
    }
    else
    {
        if (b0 == 1 && b1 == 1)
        {
            Car_Straight();
            OLED_ShowStateLine(s_straight);
        }
        else if (b0 == 1 && b1 == 0)
        {
            Car_Left();
            OLED_ShowStateLine(s_left);
        }
        else if (b0 == 0 && b1 == 1)
        {
            Car_Right();
            OLED_ShowStateLine(s_right);
        }
        else
        {
            Car_Stop();
            OLED_ShowStateLine(s_stop);
        }
    }

    OLED_ShowCargoLine(hasCargo);

    if (rfid)
        OLED_ShowString(0, 16, s_rfid_yes, OLED_8X16);
    else
        OLED_ShowString(0, 16, s_rfid_wait, OLED_8X16);

    OLED_Update();
    Delay_ms(100);
}

距离有效且小于 100 cm 时,OLED 显示 obstacle,四个电机停止。距离为 0 或不小于 100 cm 时,程序执行 PB0、PB1 对应的循迹动作。


十、工程目录

代码
├─ Hardware
│  ├─ adc.c
│  ├─ adc.h
│  ├─ HCSR04.c
│  ├─ HCSR04.h
│  ├─ IO.c
│  ├─ IO.h
│  ├─ Motor.c
│  ├─ Motor.h
│  ├─ OLED.c
│  ├─ OLED.h
│  ├─ OELD_Data.c
│  └─ OELD_Data.h
├─ System
│  ├─ Delay.c
│  ├─ Delay.h
│  └─ sys
├─ Start
├─ library
├─ user
│  ├─ main.c
│  ├─ stm32f10x_conf.h
│  ├─ stm32f10x_it.c
│  └─ stm32f10x_it.h
├─ Objects
│  └─ project.hex
└─ project.uvprojx

各模块职责如下:

文件 职责
main.c 系统初始化和主循环控制
HCSR04.c 超声波触发、计时和距离计算
Motor.c 四轮电机初始化和动作控制
IO.c PB0、PB1、PB5 输入读取
adc.c PA1 ADC 采集和货物状态输出
OLED.c OLED 软件 I2C 驱动和数据显示
Delay.c SysTick 微秒、毫秒和秒级延时

十一、Keil 编译与 Proteus 运行

11.1 Keil 编译

  1. 打开 代码/project.uvprojx
  2. 选择 Target 1
  3. 执行 Build;
  4. 编译完成后生成 代码/Objects/project.hex

工程编译结果为:

Program Size: Code=4684 RO-data=2880 RW-data=0 ZI-data=2048
0 Error(s), 0 Warning(s)

【图片插入位置:Keil Build Output 编译成功截图,画面保留 0 Error(s), 0 Warning(s)

11.2 Proteus 运行

  1. 打开 仿真/新工程 [Autosaved].pdsprj
  2. 双击 STM32F103C8;
  3. Program File 选择 代码/Objects/project.hex
  4. 启动仿真;
  5. 调节 RV1 改变 PA1 输入电压;
  6. 调节 HC-SR04 距离值;
  7. 切换 PB0、PB1 检查四种行驶状态;
  8. 切换 PB5 检查 RFID 显示状态。

【图片插入位置:Proteus 中 STM32F103C8 的 Program File 配置截图】


十二、运行结果

本次仿真运行状态如下:

  1. HC-SR04 距离设定为 110.0 cm;
  2. OLED 显示距离 0111
  3. PB5 为高电平,OLED 显示 RFID:yes
  4. PB0、PB1 均为高电平,OLED 显示 straight
  5. 四个电机执行前进;
  6. PA1 电压为 0.725993 V;
  7. PA1 电压低于 2.0 V 阈值,OLED 显示 cargo:NO
  8. PB10 输出低电平,LED 熄灭。

系统运行结果与程序控制逻辑一致。


十三、总结

本设计完成了基于 STM32F103C8 的超声波循迹送药机器人 Proteus 仿真。

系统通过 HC-SR04 完成距离检测,通过 PB0、PB1 完成循迹动作选择,通过 PA1 ADC 完成货物状态检测,通过 PB5 完成 RFID 状态输入,通过两组 L298 完成四轮电机控制,并通过 OLED 集中显示系统运行数据。

项目完整使用了 STM32 GPIO、ADC、通用定时器、SysTick 延时和软件 I2C,形成了传感器采集、控制决策、电机执行和状态显示的完整控制流程。


Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐