【mcu-1268】基于STM32的智能配送机器人控制系统设计【单片机毕业设计项目参考】
一、功能介绍
项目名:基于STM32的智能配送机器人控制系统设计
项目编号:mcu-1268
单片机类型:STM32F103C8T6
具体功能:
1、通过RFID刷卡确认送餐坐标,当选择好坐标后,通过重量检测模块检测餐盘是否放在小车上,如果放在小车上,则开始送餐
2、通过一对红外循迹管进行循迹,在循迹过程中,通过超声波检测前方障碍物,当检测到障碍物距离小于设置最小值时,自动停车,并声光报警提醒,直到障碍物移除
3、通过另一个红外循迹管检测此时到达几号坐标,如果当前坐标是设置坐标,则小车停止,并语言播报“请取餐”,当拿走餐盘后,小车自动返回原点(另一个红外循迹管检测是否到达原点)
4、通过OLED显示测量的当前送餐情况“送餐中“”已送达“距离前方障碍物的距离;
5、通过4G模块将监测的数据上传到云平台然后下发到手机端,可以选择送餐的位置;
6、路线:6个定点,送一次回来一次
二、资料总览
实物资料

仿真资料

三、部分资料展示
1、实物展示
供电接口:TYPE-C
板子类型:PCB集成板,两层板(上下层覆铜接地)
器件类型:元器件基本上为插针式,个别芯片会使用贴片式。

2、仿真展示
仿真软件版本:proteus8.17
电路连线方式:网络标号连线方式
注意:部分实物元器件仿真中没有,仿真中会用其他工作原理相似的元件代替,这样可能导致实物程序和仿真程序不一样

3、原理图展示
软件版本:AD2013
电路连线方式:网络标号连线方式
注意:原理图只是画出了模块的引脚图,而并不是模块的内部结构图

4、PCB图展示
由原理图导出,两层板,上下覆铜接地。

5、系统框图
绘制软件:VISIO

6、软件设计流程
绘制软件:VISIO

7、部分程序展示
软件版本:keil5
/* USER CODE BEGIN Header */
/**********************************
作者:单片机俱乐部
网站:https://www.mcuclub.cn/
**********************************/
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "string.h"
#include "./DELAY/delay.h"
#include "./HC-SR04/hc-sr04.h"
#include "./MOTOR/motor.h"
#include "./HX711/hx711.h"
#include "./RFID/rfid.h"
#include "./4G/4g.h"
#include "./OLED/oled.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
uint8_t huart2_tx_buf[100];
#define Huart2_Send_Str(...) HAL_UART_Transmit(&huart2,huart2_tx_buf,sprintf((char *)huart2_tx_buf,__VA_ARGS__),0xffff) //重定义串口2发送函数
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
uint8_t key_num = 0; //按键键值
uint16_t time_num = 0; //计时值
char display_buf[32] = {0}; //显示数组
extern uint8_t air_4g_rx_buf[1024]; //4g接收数组
extern uint8_t air_4g_rx_finish; //4g接收完成标志位
uint8_t flag_begin_5s = 0; //5s计时开始标志位
uint8_t flag_finish_5s = 0;; //5s计时完成标志位
#define SPEED_YK 8 //遥控速度
#define SPEED_XJ 8 //循迹速度
uint16_t motor_speed = SPEED_YK; //直流电机速度值
uint8_t flag_control = 0; //控制标志位
uint8_t flag_direction = 0; //方向标志位
extern uint8_t flag_speed_control; //速度控制标志位
uint16_t distance_value = 0; //距离值
uint16_t distance_max = 60; //距离最大值
uint16_t distance_min = 30; //距离最小值
uint8_t rfid_cmd = 0; //RFID操作指令
uint8_t rfid_step = 0; //RFID状态步骤
uint8_t RFID_ID[4]; //RFID ID信息
uint8_t const RFID_DefKey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
uint8_t RFID_RwBuf[16]; //RFID数据
uint16_t rfid_time = 0; //RFID状态显示时间
uint8_t flag_maopi = 0; //毛皮标志位
uint32_t weight_maopi = 0; //毛皮重量
uint32_t weight_value = 0; //去皮重量
uint16_t flag_zh = 0; //桌号
uint16_t flag_zh_jl = 0; //桌号记录值
uint8_t flag_jd = 0; //计点
uint8_t flag_zt = 0; //状态
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
void Monitor_Function(void); //监测函数
void Display_Function(void); //显示函数
void Manage_Function(void); //处理函数
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/**********************************
函数名:监测函数
传参值:无
返回值:无
**********************************/
void Monitor_Function(void)
{
if(time_num % 100 == 0)
{
distance_value = Hcsr04_GetDistance(30); //获取距离值
if(flag_maopi < 3)
{
weight_maopi = Hx711_Get_Maopi();
flag_maopi++;
}
else
{
weight_value = Hx711_Get_Weight(weight_maopi);
if(weight_value < 10)
{
weight_value = 0;
}
}
switch(rfid_cmd)
{
case 0: //寻卡,成功后Temp数组为卡类型
if(RFID_PcdRequest(0x52, RFID_ID) == MI_OK)
{
rfid_cmd = 1;
}
else
{
if(RFID_PcdRequest(0x52, RFID_ID) == MI_OK)
rfid_cmd = 1;
else
{
RFID_PcdHalt();
rfid_cmd = 0;
}
}
break;
case 1: //防冲突,RFID_ID数组数据为卡序列号
if(RFID_PcdAnticoll(RFID_ID) == MI_OK)
{
rfid_cmd = 2;
}
else
{
RFID_PcdHalt();
rfid_cmd = 0;
}
break;
case 2: //选择卡
if(RFID_PcdSelect(RFID_ID) == MI_OK)
{
rfid_cmd = 3;
}
else
{
RFID_PcdHalt();
rfid_cmd = 0;
}
break;
case 3: //校验卡
if(RFID_PcdAuthState(0x60, 10, (unsigned char *)RFID_DefKey, RFID_ID) == MI_OK)
{
if(RFID_PcdRead(10, RFID_RwBuf) == MI_OK)
{
if(RFID_RwBuf[0] == 0x01) //卡1
{
flag_zh = 1;
flag_control = 5;
rfid_step = 0xfa;
}
else if(RFID_RwBuf[0] == 0x02) //卡2
{
flag_zh = 2;
flag_control = 5;
rfid_step = 0xfa;
}
else if(RFID_RwBuf[0] == 0x03) //卡3
{
flag_zh = 3;
flag_control = 5;
rfid_step = 0xfa;
}
else if(RFID_RwBuf[0] == 0x04) //卡4
{
flag_zh = 4;
flag_control = 5;
rfid_step = 0xfa;
}
else if(RFID_RwBuf[0] == 0x05) //卡5
{
flag_zh = 5;
flag_control = 5;
rfid_step = 0xfa;
}
else if(RFID_RwBuf[0] == 0x06) //卡6
{
flag_zh = 6;
flag_control = 5;
rfid_step = 0xfa;
}
else //无效卡
{
rfid_step = 0xfb;
}
}
rfid_time = 1;
}
else //终止卡操作
{
RFID_PcdHalt();
rfid_cmd = 0;
}
break;
}
}
Air_4G_GetData(); //获取4G下发数据
}
/**********************************
函数名:显示函数
传参值:无
返回值:无
**********************************/
void Display_Function(void)
{
if(time_num % 100 == 0)
{
Oled_ShowCHinese(1,0,"距离:"); //显示距离
sprintf(display_buf,"%dcm ",distance_value);
Oled_ShowString(1,6,display_buf);
if(flag_zh != 0) //显示状态
{
if(weight_value != 0)
{
if(flag_zh_jl < flag_zh)
{
Oled_ShowCHinese(2,0,"状态:送餐中");
flag_zt = 1;
}
else
{
Oled_ShowCHinese(2,0,"状态:已送达");
flag_zt = 2;
}
}
else
{
if(flag_zh_jl > 0)
{
Oled_ShowCHinese(2,0,"状态:返回中");
flag_zt = 3;
}
else
{
Oled_ShowCHinese(2,0,"状态:等待中");
flag_zt = 0;
}
}
}
else
{
Oled_ShowCHinese(2,0,"状态:等待中");
flag_zt = 0;
}
Oled_ShowCHinese(3,0,"桌号:"); //显示桌号
sprintf(display_buf,"%d ",flag_zh);
Oled_ShowString(3,6,display_buf);
Oled_ShowCHinese(4,0,"重量:"); //显示重量
sprintf(display_buf,"%dg ",weight_value);
Oled_ShowString(4,6,display_buf);
}
}
/**********************************
函数名:处理函数
传参值:无
返回值:无
**********************************/
void Manage_Function(void)
{
switch(flag_control)
{
case 0: //停止
motor_speed = SPEED_YK;
flag_direction = 0;
ALERT = 0;
break;
case 1: //前进
motor_speed = SPEED_YK;
if(distance_value < distance_min) //当检测到障碍物距离小于最小值,右转避开障碍物
{
flag_direction = 4;
ALERT = 0;
}
else if(distance_value < distance_max) //当检测到障碍物距离小于最大值大于最小值时,声光报警提醒
{
flag_direction = 1;
if(time_num % 200 == 0)
{
ALERT = !ALERT;
}
}
else //当检测到障碍物距离大于最大值时,取消声光报警,小车正常行驶
{
flag_direction = 1;
ALERT = 0;
}
break;
case 2: //后退
motor_speed = SPEED_YK;
flag_direction = 2;
ALERT = 0;
break;
case 3: //左转
motor_speed = SPEED_YK;
flag_direction = 3;
ALERT = 0;
break;
case 4: //右转
motor_speed = SPEED_YK;
flag_direction = 4;
ALERT = 0;
break;
case 5: //循迹模式
motor_speed = SPEED_XJ;
if(flag_zh != 0) //选择点位置
{
if(weight_value != 0) //有重量
{
if(flag_zh_jl < flag_zh) //还没到达指定地点
{
if(distance_value < distance_min) //当检测到障碍物距离小于最小值,小车停止,并声光报警
{
flag_direction = 0;
if(time_num % 200 == 0)
{
ALERT = !ALERT;
}
}
else //否则,取消声光报警
{
if(IR_L == 1) //如果左红外对管检测到黑线,小车左转
{
flag_direction = 3;
}
else if(IR_R == 1) //如果右红外对管检测到黑线,小车右转
{
flag_direction = 4;
}
else //否则,小车正常行驶
{
flag_direction = 1;
}
ALERT = 0;
}
if(IR_P == 1) //检测到一个点,记录值+1
{
Delay_ms(10);
if(IR_P == 1)
{
if(flag_jd == 0)
{
flag_zh_jl++;
flag_jd = 1;
}
}
}
else
{
flag_jd = 0;
}
}
else //到达指定地点,语音播报
{
flag_direction = 0;
if(time_num % 1500 == 0)
{
Huart2_Send_Str(" 请取餐");
}
}
}
else //重量为0
{
if(flag_zh_jl > 0) //返回途中
{
if(distance_value < distance_min) //当检测到障碍物距离小于最小值,小车停止,并声光报警
{
flag_direction = 0;
if(time_num % 200 == 0)
{
ALERT = !ALERT;
}
}
else //否则,取消声光报警
{
if(IR_L == 1) //如果左红外对管检测到黑线,小车左转
{
flag_direction = 3;
}
else if(IR_R == 1) //如果右红外对管检测到黑线,小车右转
{
flag_direction = 4;
}
else //否则,小车正常行驶
{
flag_direction = 1;
}
ALERT = 0;
}
if(IR_B == 1) //到达起始点,停车
{
Delay_ms(10);
if(IR_B == 1)
{
if(flag_zh_jl > 0)
{
flag_zh = 0;
flag_zh_jl = 0;
}
}
}
}
else
{
flag_direction = 0;
ALERT = 0;
}
}
}
else
{
flag_direction = 0;
ALERT = 0;
}
break;
default:
break;
}
if(flag_finish_5s == 1) //5秒上传一次数据
{
flag_begin_5s = 0;
Air_4G_SendData();
flag_begin_5s = 1;
}
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM1_Init();
MX_USART1_UART_Init();
MX_TIM2_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
Delay_Init(); //延时初始化
HC_SR04_Init(); //HC_SR04初始化
Motor_Init(); //电机初始化
Hx711_Init(); //HX711初始化
RFID_Init(); //RFID初始化
Oled_Init(); //OLED初始化
Oled_Clear_All(); //OLED清全屏函数
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
HAL_TIM_Base_Start_IT(&htim1); //启动定时器
HAL_UARTEx_ReceiveToIdle_IT(&HUART_4G, air_4g_rx_buf, sizeof(air_4g_rx_buf) / sizeof(air_4g_rx_buf[0])); //获取串口接收数据
Oled_ShowString(1,7,"4G");
Oled_ShowCHinese(2, 2, "初始化中");
Air_4G_Init(); //4G初始化
Oled_ShowString(3,4,"........");
Air_4G_MQTT_Init(); //MQTT初始化
Delay_ms(500);
Oled_ShowString(4,4,"........");
Delay_ms(500);
Air_4G_SendData(); //数据上报初始状态
flag_begin_5s = 1; //开启定时
Oled_Clear_All(); //清屏
while (1)
{
Monitor_Function(); //监测函数
Display_Function(); //显示函数
Manage_Function(); //处理函数
if(time_num % 100 == 0) //指示灯闪烁
{
SYSTEM_LED = !SYSTEM_LED;
}
Delay_ms(1); //计时
time_num++;
if(time_num >= 6000)
{
time_num = 0;
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/**********************************
函数名:定时器中断回调函数
传参值:无
返回值:无
**********************************/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
static uint16_t motor_zhiliu_count = 0;
static uint16_t time_count_5s = 0;
if(htim->Instance == htim1.Instance) //定时器1触发中断
{
if(flag_begin_5s == 1)
{
time_count_5s++;
if(time_count_5s >= 5000) //5s计时
{
time_count_5s = 0;
flag_finish_5s = 1;
}
}
else
{
time_count_5s = 0;
flag_finish_5s = 0;
}
if(rfid_time != 0) //RFID提示信息计时
{
rfid_time++;
}
if(rfid_time >= 2000)
{
rfid_time = 0;
rfid_step = 0;
rfid_cmd = 0;
}
motor_zhiliu_count++;
if(motor_zhiliu_count >= 100)
{
motor_zhiliu_count = 0;
}
switch(flag_direction)
{
case 0: //停止
MOTOR1_IN0 = 0;
MOTOR1_IN1 = 0;
MOTOR1_IN2 = 0;
MOTOR1_IN3 = 0;
MOTOR2_IN0 = 0;
MOTOR2_IN1 = 0;
MOTOR2_IN2 = 0;
MOTOR2_IN3 = 0;
break;
case 1: //前
if(motor_zhiliu_count < motor_speed)
{
MOTOR1_IN0 = 1;
MOTOR1_IN1 = 0;
MOTOR1_IN2 = 1;
MOTOR1_IN3 = 0;
MOTOR2_IN0 = 0;
MOTOR2_IN1 = 1;
MOTOR2_IN2 = 0;
MOTOR2_IN3 = 1;
}
else
{
MOTOR1_IN0 = 0;
MOTOR1_IN1 = 0;
MOTOR1_IN2 = 0;
MOTOR1_IN3 = 0;
MOTOR2_IN0 = 0;
MOTOR2_IN1 = 0;
MOTOR2_IN2 = 0;
MOTOR2_IN3 = 0;
}
break;
case 2: //后
if(motor_zhiliu_count < motor_speed)
{
MOTOR1_IN0 = 0;
MOTOR1_IN1 = 1;
MOTOR1_IN2 = 0;
MOTOR1_IN3 = 1;
MOTOR2_IN0 = 1;
MOTOR2_IN1 = 0;
MOTOR2_IN2 = 1;
MOTOR2_IN3 = 0;
}
else
{
MOTOR1_IN0 = 0;
MOTOR1_IN1 = 0;
MOTOR1_IN2 = 0;
MOTOR1_IN3 = 0;
MOTOR2_IN0 = 0;
MOTOR2_IN1 = 0;
MOTOR2_IN2 = 0;
MOTOR2_IN3 = 0;
}
break;
case 3: //左
if(motor_zhiliu_count < motor_speed)
{
MOTOR1_IN0 = 0;
MOTOR1_IN1 = 1;
MOTOR1_IN2 = 0;
MOTOR1_IN3 = 1;
MOTOR2_IN0 = 0;
MOTOR2_IN1 = 1;
MOTOR2_IN2 = 0;
MOTOR2_IN3 = 1;
}
else
{
MOTOR1_IN0 = 0;
MOTOR1_IN1 = 0;
MOTOR1_IN2 = 0;
MOTOR1_IN3 = 0;
MOTOR2_IN0 = 0;
MOTOR2_IN1 = 0;
MOTOR2_IN2 = 0;
MOTOR2_IN3 = 0;
}
break;
case 4: //右
if(motor_zhiliu_count < motor_speed)
{
MOTOR1_IN0 = 1;
MOTOR1_IN1 = 0;
MOTOR1_IN2 = 1;
MOTOR1_IN3 = 0;
MOTOR2_IN0 = 1;
MOTOR2_IN1 = 0;
MOTOR2_IN2 = 1;
MOTOR2_IN3 = 0;
}
else
{
MOTOR1_IN0 = 0;
MOTOR1_IN1 = 0;
MOTOR1_IN2 = 0;
MOTOR1_IN3 = 0;
MOTOR2_IN0 = 0;
MOTOR2_IN1 = 0;
MOTOR2_IN2 = 0;
MOTOR2_IN3 = 0;
}
break;
default:
break;
}
}
}
/**********************************
函数名:串口事件回调函数
传参值:huart:串口号 Size:数据大小
返回值:无
**********************************/
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
if(huart->Instance == HUART_4G.Instance) //4g串口触发中断
{
HAL_UARTEx_ReceiveToIdle_IT(&HUART_4G, air_4g_rx_buf, sizeof(air_4g_rx_buf) / sizeof(air_4g_rx_buf[0]));
air_4g_rx_finish = 1;
}
}
/**********************************
函数名:串口错误回调函数
传参值:huart:串口号
返回值:无
**********************************/
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
HAL_UART_DeInit(huart);
HAL_UART_Init(huart);
if(huart->Instance == HUART_4G.Instance)
{
HAL_UARTEx_ReceiveToIdle_IT(&HUART_4G, air_4g_rx_buf, sizeof(air_4g_rx_buf) / sizeof(air_4g_rx_buf[0]));
air_4g_rx_finish = 1;
}
}
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)