基于STM32与Qt的自动平衡机器人:从控制到人机交互的的详细设计流程
一、项目概述
目标和用途
本项目旨在开发一款基于 STM32 控制的自动平衡机器人,结合步进电机和陀螺仪传感器,实现对平衡机器人的精确控制。该机器人可以用于教育、科研、娱乐等多个领域,帮助用户了解自动控制、机器人运动学等相关知识。
技术栈关键词
-
STM32 单片机
-
步进电机
-
陀螺仪传感器
-
AD 采集电路
-
Qt 人机界面
-
实时数据监控
二、系统架构
系统架构设计
本项目的系统架构设计包括以下主要组件:
-
控制单元: STM32 单片机
-
传感器模块: 陀螺仪传感器
-
驱动模块: 步进电机驱动器
-
人机交互界面: Qt 桌面应用程序
-
通信协议: UART 或 I2C
系统架构图
三、环境搭建和注意事项
环境搭建
-
硬件环境:
-
STM32 开发板(如 Nucleo 或 Discovery)
-
步进电机及驱动模块
-
陀螺仪传感器(如 MPU6050)
-
面包板及连接线
-
-
软件环境:
-
STM32CubeIDE 或 Keil MDK
-
Qt Creator
-
STM32 HAL 库
-
注意事项
-
确保电源供应稳定,避免电源波动导致的设备损坏。
-
在调试过程中,注意步进电机的工作电流,避免过载。
-
传感器的连接线要正确,防止接反导致数据采集错误。
四、代码实现过程
在本部分中,我们将详细介绍 STM32 自动平衡机器人的各个功能模块的代码实现,包括陀螺仪数据采集、步进电机控制以及 Qt 人机界面控制。每个模块的实现都将包含代码示例、说明和算法的详细介绍,最后将展示系统的时序图。
1. 陀螺仪数据采集模块
功能
该模块的主要功能是通过 I2C 总线读取陀螺仪传感器(如 MPU6050)的数据(角速度和角度),并进行滤波处理以提高数据的准确性。
代码实现
#include "mpu6050.h"
#include "i2c.h"#define MPU6050_ADDR 0x68 // MPU6050 I2C 地址void MPU6050_Init() {// 1. 初始化 I2CHAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDR << 1, 0x6B, I2C_MEMADD_SIZE_8BIT, (uint8_t[]){0}, 1, HAL_MAX_DELAY);// 2. 设置陀螺仪为正常工作模式HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDR << 1, 0x1B, I2C_MEMADD_SIZE_8BIT, (uint8_t[]){0}, 1, HAL_MAX_DELAY); // 设置为 ±250°/s
}void Read_Gyro_Data(float* gyro_x, float* gyro_y, float* gyro_z) {uint8_t data[6];// 读取陀螺仪数据HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDR << 1, 0x43, I2C_MEMADD_SIZE_8BIT, data, 6, HAL_MAX_DELAY);// 数据转换int16_t rawGyroX = (data[0] << 8) | data[1];int16_t rawGyroY = (data[2] << 8) | data[3];int16_t rawGyroZ = (data[4] << 8) | data[5];// 转换为角速度(°/s)*gyro_x = (float)rawGyroX / 131.0;*gyro_y = (float)rawGyroY / 131.0;*gyro_z = (float)rawGyroZ / 131.0;
}
代码说明
-
MPU6050_Init()函数用于初始化 MPU6050 陀螺仪,包括设置工作模式。 -
Read_Gyro_Data()函数读取陀螺仪的原始角速度数据,将其转换为实际的角速度(单位为 °/s)。 -
读取的数据通过 I2C 总线传输,使用 HAL 库函数
HAL_I2C_Mem_Read()和HAL_I2C_Mem_Write()进行数据的读写。
2. 步进电机控制模块
功能
该模块负责接收来自陀螺仪的数据,计算控制步进电机的速度和方向,从而实现机器人的平衡控制。
代码实现
#include "stepper_motor.h"#define STEPS_PER_ROTATION 200 // 步进电机每转一圈的步数
#define MAX_SPEED 1000 // 最大速度static int current_speed = 0;
static int current_direction = 1; // 1: 正转, -1: 反转void StepperMotor_SetSpeed(int speed) {if (speed > MAX_SPEED) speed = MAX_SPEED;if (speed < 0) speed = 0;current_speed = speed;// 根据 speed 设置定时器的频率__HAL_TIM_SET_PRESCALER(&htim1, (SystemCoreClock / (current_speed * STEPS_PER_ROTATION)) - 1);HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
}void StepperMotor_SetDirection(int direction) {current_direction = direction;// 方向引脚设置HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, current_direction > 0 ? GPIO_PIN_SET : GPIO_PIN_RESET);
}void StepperMotor_Run() {// 控制步进电机旋转while (1) {if (current_speed > 0) {// 产生脉冲信号控制步进电机HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);HAL_Delay(1); // 脉冲宽度HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);HAL_Delay(1); // 等待下一个脉冲}}
}
代码说明
-
StepperMotor_SetSpeed(int speed)函数设置步进电机的速度,使用定时器来生成定时脉冲信号来控制电机的转动速度。 -
StepperMotor_SetDirection(int direction)函数设置步进电机的转动方向,通过控制 GPIO 引脚的高低电平来设置电机的方向。 -
StepperMotor_Run()函数根据当前速度持续产生脉冲信号,从而使步进电机旋转。
3. Qt 人机界面控制模块
功能
Qt 人机界面模块用于实时显示被测转子的转速、转向和驱动脉冲频率,并提供控制按钮以启动、停止、加速、减速和改变方向。
代码实现
#include <QMainWindow>
#include <QTimer>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>class MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void startMotor();void stopMotor();void updateDisplay();private:QLabel *speedLabel;QLabel *directionLabel;QPushButton *startButton;QPushButton *stopButton;QTimer *timer;float currentSpeed;int currentDirection; // 1: 正转, -1: 反转
};MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), currentSpeed(0), currentDirection(1) {speedLabel = new QLabel("转速: 0");directionLabel = new QLabel("方向: 正转");startButton = new QPushButton("启动");stopButton = new QPushButton("停止");QVBoxLayout *layout = new QVBoxLayout();layout->addWidget(speedLabel);layout->addWidget(directionLabel);layout->addWidget(startButton);layout->addWidget(stopButton);QWidget *centralWidget = new QWidget();centralWidget->setLayout(layout);setCentralWidget(centralWidget);connect(startButton, &QPushButton::clicked, this, &MainWindow::startMotor);connect(stopButton, &QPushButton::clicked, this, &MainWindow::stopMotor);timer = new QTimer(this);connect(timer, &QTimer::timeout, this, &MainWindow::updateDisplay);timer->start(100); // 每100毫秒更新一次显示
}MainWindow::~MainWindow() {// 清理
}void MainWindow::startMotor() {currentSpeed = 100; // 启动电机currentDirection = 1; // 正转// 向 STM32 发送启动和速度指令
}void MainWindow::startMotor() {currentSpeed = 100; // 启动电机currentDirection = 1; // 正转// 向 STM32 发送启动和速度指令// 这里可以调用串口通信函数,发送控制命令// 例如: sendCommandToSTM32("START", currentSpeed, currentDirection);
}void MainWindow::stopMotor() {currentSpeed = 0; // 停止电机// 向 STM32 发送停止命令// 例如: sendCommandToSTM32("STOP");
}void MainWindow::updateDisplay() {// 更新转速和方向标签speedLabel->setText(QString("转速: %1").arg(currentSpeed));directionLabel->setText(currentDirection == 1 ? "方向: 正转" : "方向: 反转");// 这里可以读取 STM32 发送过来的实时数据并更新界面// 例如: currentSpeed = readSpeedFromSTM32();// 方向可能需要从 STM32 读取或根据计算结果更新
}
代码说明
-
startMotor()函数被点击时调用,设置当前速度和方向,并向 STM32 发送启动指令。 -
stopMotor()函数被点击时调用,停止电机并发送停止指令。 -
updateDisplay()函数定时更新界面上的转速和方向标签。这一部分可以通过读取 STM32 的串口数据实现实时更新。
4. 数据通信模块
功能
本模块实现 STM32 和 Qt 界面之间的数据通信,使用串口(UART)进行双向数据传输。
代码实现
#include "usart.h"void sendCommandToSTM32(const char* command) {HAL_UART_Transmit(&huart2, (uint8_t*)command, strlen(command), HAL_MAX_DELAY);
}void receiveDataFromSTM32(char* buffer, uint16_t size) {HAL_UART_Receive(&huart2, (uint8_t*)buffer, size, HAL_MAX_DELAY);
}
代码说明
-
sendCommandToSTM32(const char* command)函数用于向 STM32 发送指令。 -
receiveDataFromSTM32(char* buffer, uint16_t size)函数用于接收来自 STM32 的数据,存储在指定的缓冲区中。
5. 时序图
以下是系统时序图,展示了用户与 Qt 界面、Qt 界面与 STM32 之间的交互过程。
五、项目总结
主要功能
本项目的主要目标是设计并实现一款基于 STM32 的自动平衡机器人。项目的核心功能包括:
-
实时数据采集:
-
使用陀螺仪传感器(如 MPU6050)获取机器人的角速度和角度数据,实现对机器人的实时姿态监测。
-
通过 I2C 接口与 STM32 进行数据通信,确保数据的准确传输。
-
-
步进电机控制:
-
利用步进电机驱动模块,实现机器人的加速、减速及转向控制。
-
根据陀螺仪反馈的数据,动态调整电机的速度和方向,以保持机器人的平衡状态。
-
-
人机交互界面:
-
使用 Qt 框架设计用户界面,提供启动、停止、加速和减速等操作按钮。
-
实时显示机器人的转速、转向和驱动脉冲频率等信息,增强用户体验。
-
-
数据通信:
-
通过 UART 串口实现 STM32 和 Qt 界面之间的双向通信,支持实时数据传输。
-
确保用户可以通过界面直接控制机器人,并获取其状态信息。
-
相关文章:
基于STM32与Qt的自动平衡机器人:从控制到人机交互的的详细设计流程
一、项目概述 目标和用途 本项目旨在开发一款基于 STM32 控制的自动平衡机器人,结合步进电机和陀螺仪传感器,实现对平衡机器人的精确控制。该机器人可以用于教育、科研、娱乐等多个领域,帮助用户了解自动控制、机器人运动学等相关知识。 技…...
C#使用ZipFile的方法CreateFromDirectory
由于现在数据越来越大,虽然磁盘的大小也在增加,但是数据增加的速度是远超过磁盘的增加速度。 因为数据是一种思想的表现,特别是ChatGPT的AI出现,导致很多数据无限地使用机器化地产生,所以数据压缩还是很常有的事情,毕竟压缩之后可以减少磁盘空间的占用。 在C#里有一个专…...
Redis 哨兵模式的选举算法是什么?
Redis 哨兵模式中的选举算法主要用于在主节点出现故障时,从多个 Sentinel 节点中选出一个领导者(Leader)来执行故障转移操作。 Redis 哨兵的选举算法基于 Raft 算法的简化版本,但不完全等同于标准的 Raft 算法。以下是其主要过程: 一、发现主节点故障 当一个 Sentinel …...
Linux shell编程学习笔记80:gzip命令——让文件瘦身
0 引言 在 Linux shell编程学习笔记76:tar命令——快照 & 备份(上)-CSDN博客 Linux shell编程学习笔记77:tar命令——快照 & 备份(下)_linux 系统快照-CSDN博客 Linux shell编程学习笔记78&am…...
【字幕】恋上数据结构与算法之01为什么要学习数据结构与算法
视频地址:请查看01为什么要学习数据结构与算法_哔哩哔哩_bilibili 同志们好,我是小码哥的mj李明杰。非常欢迎大家来学习链上数据结构与算法,从今天开始呢就由我来带大家一起来学习和掌握这个数据结构与算法啊。在正式学习之前我们先来看一下…...
120页ppt丨集团公司战略规划内容、方法、步骤及战略规划案例研究
响应会员需求,晓零分享一份经典资料《120页ppt集团公司战略规划内容、方法、步骤及战略规划案例研究》,欢迎进入星球下载学习。 以下是对企业战略规划三个阶段八个步骤的详细解析: 一、阶段一:内外分析 项目启动和前期准备&…...
滚雪球学SpringCloud[2.3]:服务发现与负载均衡详解
全文目录: 前言1. Ribbon的使用与配置1.1 Ribbon 概述Ribbon 的核心功能: 1.2 Ribbon 的基本使用1.2.1 引入 Ribbon 依赖1.2.2 配置 RestTemplate 与 Ribbon1.2.3 示例:通过 Ribbon 调用服务 1.3 Ribbon 的配置选项 2. Ribbon的负载均衡策略2…...
商务英语口语之聚会宴饮常用口语柯桥培训到蓝天广场
吃饭一定要掌握的英语口语 邀请他人共进餐: Would you like to join me for dinner? 你愿意和我一起吃饭吗? Lets grab a bite to eat together. 我们一起去吃点东西吧。 How about having lunch with me? 和我一起吃午饭怎么样? 询问…...
【C#】VS插件
翻译 目前推荐较多的 可以单词发言,目前还在开发阶段 TranslateIntoChinese - Visual Studio Marketplace 下载量最高的(推荐) Visual-Studio-Translator - Visual Studio Marketplace 支持翻译的版本较多,在 Visual Studio 代码编辑器中通过 Googl…...
嵌入式C语言自我修养:C语言的面向对象编程思想
⭐关联知识点:C和C的区别 代码复用与分层思想 什么是代码复用呢? (1)函数级代码复用:定义一个函数实现某个功能,所有的程序都可以调用这个函数,不用自己再单独实现一遍,函数级的代…...
行车记录仪格式化了怎么恢复?专业恢复方法分享
行车记录仪作为现代驾驶的必备设备,它忠实记录着行车过程中的点点滴滴,是保障行车安全、处理交通事故的重要依据。然而,有时由于操作失误或其他原因,我们可能会不小心将行车记录仪进行格式化,导致宝贵的录像数据丢失。…...
C++中extern ”c“的理解
c中extern “C“的作用及理解_extern "c-CSDN博客...
红黑树的删除
文章目录 前言一.删除的节点左子树右子树都有二.删除的节点只有左/右子树删除调整操作 三.删除的节点没有孩子1.删除的节点为红色2.删除的节点为黑色1).兄弟节点为黑色(1).兄弟节点至少有一个红色的孩子节点LL型RR型RL型LR型 (2).兄弟节点没有孩子或所有孩子为黑色 2).兄弟节点…...
Vue3+setup实现父子组件单表增删改查写法模板
父组件写法 <el-card><!-- el-card 头部插槽 显示列表名和新增按钮 --><template #header><div class"table-header-container"><i class"fas fa-th" />角色列表(100)<span style"flex-grow…...
jmeter 录制APP脚本
一、手机 1、修改网络 代理选择手动→填写服务器主机名(电脑IP,如:192.1xx.x.xx)→服务器端口(任意未被占用端口,如:8888) 2、安装证书 手机浏览器访问服务器主机名:服务器端口&a…...
C++类与对象深度解析(一):从抽象到实践的全面入门指南
文章目录 C 类与对象——详细入门指南前言1. 类的定义1.1 类定义的基本格式示例代码解释 1.2 访问限定符示例代码解释 1.3 类域示例代码解释 1.4 成员命名规范常见的命名约定:示例:拓展: 1.5 class与struct的默认访问权限示例: 2.…...
docker拉取 jdk 8
docker pull openjdk:8docker run -d -it --name java-8 openjdk:8docker run -d -it --name java-8 openjdk:8 –name java-8 容器名,自定义的 openjdk:8 镜像名:标签名 , 使用 docker images 查看 2、查看已运行的容器实例: doc…...
机器学习VS深度学习
机器学习(Machine Learning, ML)和深度学习(Deep Learning, DL)是人工智能(AI)的两个子领域,它们有许多相似之处,但在技术实现和应用范围上也有显著区别。下面从几个方面对两者进行区…...
基于vue框架的宠物交流平台1n2n3(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。
系统程序文件列表 项目功能:会员,宠物信息,宠物类型,团队信息,申请领养,团队申请,领养宠物 开题报告内容 基于Vue框架的宠物交流平台开题报告 一、项目背景 随着现代生活节奏的加快与人们情感需求的日益增长,宠物已成为众多家庭不可或缺的重要成员。…...
Rust 所有权 借用与引用
文章目录 发现宝藏1. 所有权(Ownership)2. 引用(References)2.1 不可变引用2.2 可变引用2.3 引用的规则 3. 悬垂引用(Dangling References)4. 借用(Borrowing)结论 发现宝藏 前些天…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...
Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving
地址:LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂,正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…...
