基于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)结论 发现宝藏 前些天…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...

使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...

【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...

【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...