第七章-编码器测速 STM32pwm输出 STM32f103c8t6引脚功能 STM32蓝牙通信 STM32 pwm输出 STM32超声波测距 嵌入式软件开发 STM32cubemx 好家伙VCC

标题第七章-编码器测速

7.1-认识编码器

编码器:一般按照电机尾部、用于测量电机转速、方向、位置。
在这里插入图片描述
那么编码器的输出信号具体是什么?我们如何根据输出信号测量转速 和方向?

转速: 单位时间测量到的脉冲数量(比如根据每秒测量到多少个脉冲来计算转速)

旋转方向: 两通道信号的相对电平关系
在这里插入图片描述

7.2单片机定时器的编码器功能

那么我们已经知道编码器输出的波形,我们如何通过单片机读取波形,然后计算出速度那?

这里STM32单片机的定时器和通用定时器具有编码器接口模式、在STM32中文参考手册13章中有详细介绍

STM32中文参考手册-第200页
在这里插入图片描述
STM32中文参考手册-第267页
在这里插入图片描述
STM32中文参考手册-第226页
在这里插入图片描述
这个是计数方向与编码器信号的关系、我们拆开来看

仅在TI1计数、电机正转、对原始数据二倍频
在这里插入图片描述
仅在TI1计数、电机反转、对原始数据二倍频
在这里插入图片描述
在TI1和TI2都计数

可以看到这样就对原始数据四倍频了

在这里插入图片描述
计数方向
在这里插入图片描述

7.3-获得单位时间计数器值变化量

在这里插入图片描述
上一次说的方法:

这次编码器计数值 = 计数器值+计数溢出次数 * 计数最大器计数最大值

计数器两次变化值 = 这次编码器计数值 - 上次编码器计数值

然后根据这个单位变化量计算速度

还有一种方法:

计数器变化量 = 当前计数器值

每次计数值清空

然后根据这个变化量 计算速度

然后我们再看具体到哪一款电机和编码器上如何测速
在这里插入图片描述
在STM32中文参考手册-第119页
在这里插入图片描述
在这里插入图片描述
设置TIM2

在这里插入图片描述
设置ITM2滤波器
在这里插入图片描述
在这里插入图片描述
同理设置TIM4
在这里插入图片描述
设置TIM4滤波器
在这里插入图片描述
在这里插入图片描述
设置引脚上拉
在这里插入图片描述
生成代码
开启定时器和定时中断
在这里插入图片描述

  HAL_TIM_Encoder_Start(&htim2,TIM_CHANNEL_ALL);//开启定时器2
  HAL_TIM_Encoder_Start(&htim4,TIM_CHANNEL_ALL);//开启定时器4
  HAL_TIM_Base_Start_IT(&htim2);				//开启定时器2 中断
  HAL_TIM_Base_Start_IT(&htim4);                //开启定时器4 中断

在定义两个变量保存计数器值
在这里插入图片描述

short Encoder1Count = 0;//编码器计数器值
short Encoder2Count = 0;

每2ms读取计数器值->清零计数器
在这里插入图片描述

	Motor_Set(0,0);
	//1.保存计数器值
	Encoder1Count =(short)__HAL_TIM_GET_COUNTER(&htim4);
	Encoder2Count =(short)__HAL_TIM_GET_COUNTER(&htim2);
	//2.清零计数器值
	__HAL_TIM_SET_COUNTER(&htim4,0);
	__HAL_TIM_SET_COUNTER(&htim2,0);
	
	printf("Encoder1Count:%d\r\n",Encoder1Count);
	printf("Encoder2Count:%d\r\n",Encoder2Count);	
	
	HAL_Delay(2);

接好电池、烧录代码、串口一连接电脑

用手转动电机1或者电机2 、串口助手可以看到输出信息了
在这里插入图片描述

7.4-主函数周期测量转速

上面我们测量出来了溢出值,我们再根据当前计数器值就可以测量出计数器变化量,我们通过单位时间变量就可以计算出转速

下面是电机和编码器的参数
在这里插入图片描述
我们先测试的结论是否有问题?

  1. 编码器计数器会不会在计数时间内溢出?
  2. 车轮旋转一周,单片机编码器计数器计数多少?9.6乘11乘4
  3. 根据计算方法计算电机转速

定义两个float变量
在这里插入图片描述

float Motor1Speed = 0.00;
float Motor2Speed = 0.00;

下面是代码(一定要把主函数没有用的删除掉)
在这里插入图片描述

	//计算速度
	Motor1Speed = (float)Encode1Count*100/9.6/11/4;
	Motor2Speed = (float)Encode2Count*100/9.6/11/4;
	
	printf("Motor1Speed:%.2f\r\n",Motor1Speed);
	printf("Motor2Speed:%.2f\r\n",Motor2Speed);

编译烧录代码就会输出结果
在这里插入图片描述

7.5-定时器中断定时测量速度

上面我们实现:在主函数周期,读取计数器值然后计算速度,但是如果函数加入其他内容这个周期时间就很难保证。

所以这节我们通过定时器,周期读取计数器,计算速度。复制一份工程开始搞!
在这里插入图片描述
我们先开启定时器、2ms进入一次定时器中断,中断回调函数执行咱们的代码即可。

为什么充分利用单片机 我们使用TIM1

  1. 设置内部时钟源
  2. 使能自动重装载
    在这里插入图片描述
    开启定义更新中断
    在这里插入图片描述
    代码开启定时器1 中断

在这里插入图片描述

  HAL_TIM_Base_Start_IT(&htim1);                //开启定时器1 中断

定时器回调函数中添加 速度计算内容
在这里插入图片描述

/*******************
*  @brief  定时器回调函数
*  @param  
*  @return  
*
*******************/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim == &htim1)//htim1 500HZ  2ms 中断一次
	{
		TimerCount++;
		if(TimerCount %5 == 0)//每10ms执行一次
		{
			Encode1Count = (short)__HAL_TIM_GET_COUNTER(&htim4);
			Encode2Count = (short)__HAL_TIM_GET_COUNTER(&htim2);
			__HAL_TIM_SET_COUNTER(&htim4,0);
			__HAL_TIM_SET_COUNTER(&htim2,0);
			
			Motor1Speed = (float)Encode1Count*100/9.6/11/4;
			Motor2Speed = (float)Encode2Count*100/9.6/11/4;

			TimerCount=0;
		}
	}
}

把之前的变量定义放这里
在这里插入图片描述

short Encode1Count = 0;
short Encode2Count = 0;
float Motor1Speed = 0.00;
float Motor2Speed = 0.00;
uint16_t TimerCount=0;

主函数就输出速度大小就可以了
在这里插入图片描述

	printf("Motor1Speed:%.2f\r\n",Motor1Speed);
	printf("Motor2Speed:%.2f\r\n",Motor2Speed);

把变量需要声明一下
在这里插入图片描述

extern float Motor1Speed ;
extern float Motor2Speed ;

然后打开串口助手
在这里插入图片描述
注:

根据电机和实际小车调整速度测量与占空比设置函数
在这里插入图片描述
在这里插入图片描述
我们第七章这样就完成了 ,把程序烧录电机就可以完成测速了。
下篇第八章我们讲解 PID速度控制

1. 小车开源笔记资料:
我用夸克网盘分享了「V3小车笔记网盘」,点击链接即可保存。打开「夸克APP」,无需下载在线播放视频,畅享原画5倍速,支持电视投屏。
链接:https://pan.quark.cn/s/959b889e058b
2.小车实物或者更多最新资料:
https://item.taobao.com/item.htm?id=811175824266&pisk=frNHu_4FKJkIvsTuuCcCEX7mzo69AHGSPud-2bnPQco69uhKwVlZk4dE8DRe7R4bqDQ5dXeiqlriYBF-9zrgok2pv6ipru4SXud8J726Zra79wGRRXaINbSADshuRyG7W7pYYWxa74awT0JeiYyTPbSAD_bhCncja8hTullQsYb2pHeVxW6nemxKmuePZQnZ0yoUJyFwHvJQ-cDxh5u3M0UFPQRzs2D3we3f5wHLUrMb9SCk1XU0Qfu34sSE_rygkvVhmBnSE5q3EkQJFV2uzSGI6U5U7Xmn35FFVTmZ_yHzZvjVQlHoxRPEIURz7fiKe8qhxpiUplDj7A8lGVExbyNUIata8onnTVkOgZ4ZURFIhWIwtjybJXezb1A30gJ2QKPbmQgNy5JWFvusSm3U67YDehXMzNbM3-ME525ASNvWFvusSmQGSK7sLVgFM&spm=a21xtw.29178619.product_shelf.3.6043fc79LdVbgq
3.小车最新视频:
https://www.bilibili.com/video/BV16x4y1M7EN/?spm_id_from=333.337.search-card.all.click

<think>好的,用户需要关于2021年电子设计竞赛中基于STM32F103C8T6的送药小车的资料或实现方案。首先,我需要回顾已有的引用内容,看看有没有相关的信息。根据引用[2],有关于基于STM32F103C8T6的循迹避障小车的详细制作过程,可能部分技术可以迁移到送药小车上。引用[3]和[4]提到了PWM控制电机和L298N驱动模块的使用,这些在电机控制方面是通用的。送药小车可能需要循迹、避障、精准控制等功能,所以需要整合这些模块。 接下来,用户需要设计方案、实现代码和硬件原理图。设计方案部分,应该包括系统架构,比如主控、传感器、驱动模块、通信等。硬件选型方面,主控已经确定是STM32F103C8T6,电机驱动可能用L298N或TB6612,传感器可能需要红外循迹、超声波避障、编码器测速等。软件设计部分需要模块化,比如电机控制、PID算法、路径规划等。 实现代码方面,可以引用已有的PWM控制代码,如引用[3]中的PWM配置,以及引用[4]中的定时器使用。可能需要添加任务调度,比如使用FreeRTOS来管理不同的任务,如循迹、避障、通信等。此外,送药小车可能需要机械臂或舵机来搬运药品,这部分可以参考引用[2]中的舵机控制方法。 硬件原理图部分,需要整合主控、电机驱动、传感器、电源管理等模块。例如,主控的GPIO连接电机驱动模块,PWM信号控制电机速度,ADC读取传感器数据,UART或I2C用于外设通信。 用户可能没有提到的但需要考虑的问题包括电源管理,确保电池供电稳定,以及小车的机械结构是否稳固。此外,调试和测试步骤也很重要,比如逐步验证各个模块的功能,再进行整体联调。 最后,生成相关问题时要围绕送药小车的设计、实现和优化,比如硬件选型、控制算法、通信协议等,帮助用户深入理解可能遇到的挑战和解决方案。</think>### 基于STM32F103C8T6的送药小车设计方案 #### 1. **系统架构设计** - **主控芯片**: STM32F103C8T6(72MHz主频,丰富外设资源)[^2][^4] - **核心功能模块**: - **运动控制**: 通过PWM驱动步进电机或直流电机(L298N或TB6612驱动模块)[^3][^4] - **路径规划**: 红外循迹模块(如TCRT5000)结合超声波避障(HC-SR04)[^4] - **药品装载**: 舵机(SG90)控制机械臂或药盒开关 - **通信**: 可选蓝牙/WiFi模块实现远程指令接收 #### 2. **硬件选型与原理图** - **电机驱动**: - 若需高精度控制,建议使用TB6612(支持双路电机,集成PWM调速)[^3] - 接线示例: $$ \text{STM32 PA6/PA7} \rightarrow \text{TB6612 PWM输入} \\ \text{PB12-PB15} \rightarrow \text{方向控制引脚} $$ - **传感器**: - 循迹模块:5路TCRT5000,通过GPIO读取模拟信号 - 避障模块:HC-SR04超声波,使用定时器捕获回波时间 - **电源管理**: 5V转3.3V模块为MCU供电,锂电池直接驱动电机 #### 3. **软件实现(关键代码片段)** - **PWM电机调速**(基于TIM3通道1): ```c void PWM_Init(void) { GPIO_InitTypeDef gpio; TIM_TimeBaseInitTypeDef tim; TIM_OCInitTypeDef oc; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); gpio.GPIO_Pin = GPIO_Pin_6; gpio.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &gpio); tim.TIM_Period = 7199; // 10kHz PWM tim.TIM_Prescaler = 0; TIM_TimeBaseInit(TIM3, &tim); oc.TIM_OCMode = TIM_OCMode_PWM1; oc.TIM_OutputState = TIM_OutputState_Enable; oc.TIM_Pulse = 3600; // 50%占空比 TIM_OC1Init(TIM3, &oc); TIM_Cmd(TIM3, ENABLE); } ``` - **超声波测距**(使用TIM2捕获): ```c float Get_Distance(void) { Trig_High(); // 触发信号 while(!Echo_Status); // 等待回波高电平 TIM_SetCounter(TIM2, 0); while(Echo_Status); // 等待回波结束 return TIM_GetCounter(TIM2) * 0.034 / 2; // 单位:cm } ``` #### 4. **关键算法** - **PID控制**(速度闭环): $$ u(t) = K_p e(t) + K_i \int_0^t e(\tau)d\tau + K_d \frac{de(t)}{dt} $$ 实现代码需结合编码器反馈调节PWM占空比 - **路径规划**: 基于状态机的传感器融合决策(如遇障碍时切换备选路线) #### 5. **调试建议** 1. 分模块验证:先调试电机驱动与基础运动 2. 添加OLED显示实时数据(如速度、距离) 3. 使用逻辑分析仪检查PWM波形稳定性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

好家伙VCC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值