电子说
这是全网最详细、性价比最高的STM32实战项目入门教程,通过合理的硬件设计和详细的视频笔记介绍,硬件使用STM32F103主控资料多方便学习,通过3万字笔记、12多个小时视频、20多章节代码手把手教会你如何开发和调试。让你更快掌握嵌入式系统开发。
V3.3.0-STM32智能小车
视频:
https://www.bilibili.com/video/BV16x4y1M7EN/?spm_id_from=333.337.search-card.all.click
V3:HAL库开发、功能:PID速度控制、PID循迹、PID跟随、遥控、避障、PID角度控制、视觉控制、电磁循迹、RTOS等功能。
编码器:一般按照电机尾部、用于测量电机转速、方向、位置。
那么编码器的输出信号具体是什么?我们如何根据输出信号测量转速 和方向?
转速: 单位时间测量到的脉冲数量(比如根据每秒测量到多少个脉冲来计算转速)
旋转方向: 两通道信号的相对电平关系
那么我们已经知道编码器输出的波形,我们如何通过单片机读取波形,然后计算出速度那?
这里STM32单片机的定时器和通用定时器具有****编码器接口模式 、在STM32中文参考手册13章中有详细介绍
STM32中文参考手册-第200页
STM32中文参考手册-第267页
STM32中文参考手册-第226页
这个是计数方向与编码器信号的关系、我们拆开来看
仅在TI1计数、电机正转、对原始数据二倍频
仅在TI1计数、电机反转、对原始数据二倍频
在TI1和TI2都计数
可以看到这样就对原始数据四倍频了
计数方向
上一次说的方法:
这次编码器计数值 = 计数器值+计数溢出次数 * 计数最大器计数最大值
计数器两次变化值 = 这次编码器计数值 - 上次编码器计数值
然后根据这个单位变化量计算速度
还有一种方法:
计数器变化量 = 当前计数器值
每次计数值清空
然后根据这个变化量 计算速度
然后我们再看具体到哪一款电机和编码器上如何测速
在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:%drn",Encoder1Count);
printf("Encoder2Count:%drn",Encoder2Count);
HAL_Delay(2);
接好电池、烧录代码、串口一连接电脑
用手转动电机1或者电机2 、串口助手可以看到输出信息了
上面我们测量出来了溢出值,我们再根据当前计数器值就可以测量出计数器变化量,我们通过单位时间变量就可以计算出转速
下面是电机和编码器的参数
我们先测试的结论是否有问题?
定义两个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:%.2frn",Motor1Speed);
printf("Motor2Speed:%.2frn",Motor2Speed);
编译烧录代码就会输出结果
上面我们实现:在主函数周期,读取计数器值然后计算速度,但是如果函数加入其他内容这个周期时间就很难保证。
所以这节我们通过定时器,周期读取计数器,计算速度。复制一份工程开始搞!
我们先开启定时器、2ms进入一次定时器中断,中断回调函数执行咱们的代码即可。
为什么充分利用单片机 我们使用TIM1
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:%.2frn",Motor1Speed);
printf("Motor2Speed:%.2frn",Motor2Speed);
把变量需要声明一下
extern float Motor1Speed ;
extern float Motor2Speed ;
然后打开串口助手
注:
根据电机和实际小车调整速度测量与占空比设置函数
我们第七章这样就完成了 ,把程序烧录电机就可以完成测速了。
下篇第八章我们讲解 PID速度控制
审核编辑 黄宇
全部0条评论
快来发表一下你的评论吧 !