使用STM32F1定时器与霍尔传感器对无人机/无人车的主轴转速进行测量
国际标准中,国际标准单位为RPM(Revolutions Per Minute,转/分)。
测量算法
作者先后采用了两种方法对主轴转速进行了测量,第一种在规定时间(1秒)内对上升沿或下降沿的次数进行统计,在安装了三个霍尔传感器的基础上,每当发生第四次上升沿/下降沿的时候就代表完成了一圈的转动,此时圈数加一(或者用总的上升沿次数除以三得出转动圈数)。用一秒内的转动圈数乘以60即为标准转速RPM,简称为“计数法”;
第二种方法不是对跳变沿的个数进行采集,而是对两次跳变沿间的保持时间进行记录,每当判定完成一圈转动时,对时间进行记录,用60除以一圈的时间(换算为秒)即为实时的RPM,如果转速过快,可以对圈数和RPM进行累加,在main函数的循环进行显示时可以取平均值,然后清零,简称为“计时法”。
两种方法相比,前者:
当转速较慢时,例如RPM低于60,即1秒时间内转动时间小于1圈。此时计算出的转速一直为0;
该方法计时时间是一秒钟转的圈数,国际标准是以分钟为单位,在转换时需要进行乘60的操作,因此最终结果一定是60的倍数。可以通过拉长统计时间来提高精度,然而由于STM32内部定时器的上限以及实时显示频率的要求,注定表达不够精确;
结合实际实验数据表明,该方法存在较大的误差。
后者:
通过统计旋转一圈的时间,或对多圈时间进行记录和累加,不需受到固定时间的拘泥。
具体代码
代码库使用可以配合STMCUBEMX便捷开发的HAL库,该库的优点是使用便捷,开发周期短;缺点是封装性过高,函数使用不当时不宜排查问题。
涉及监测主轴转速算法的代码主要为所使用变量的定义、在定时器1的回调函数进行一次定时周期的累加,以及定时器针对霍尔输入引脚的上升沿捕获:
所用变量的定义:
unsigned char TIM1CH1_CAPTURE_STA=0; //输入捕获状态,用于累加定时器的周期个数。如果需要更长时间间隔,可以将STA数据类型变大
unsigned short TIM1CH1_CAPTURE_VAL; //当前定时器的输入捕获值
unsigned int count = 0; //统计总圈数,用于打印时计算平均转速,打印后清零。
float RPM = 0;
定时器回调函数,周期个数加一
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
//printf("HAL_TIM_PeriodElapsedCallback\n");
if(htim->Instance == TIM1)
{
TIM1CH1_CAPTURE_STA++;
}
}
上升沿回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
static unsigned char j = 0; //静态变量,只会初始化一次,用于统计三分之一圈的次数
unsigned int time = 0; //用于统计这一圈运动所用时间,单位微秒
//printf("上升沿\n");
j++;
if(j == 1) //这个算法其实忽略掉了每次j从0到1的时间,即舍弃了三分之一的圆周运动。这样做的原因是避免j == 4时的操作过多从而造成的定时器清零和下一个三分之一旋转开始的不同步,影响测量精度。根据与现有转速传感器的对比结果来看效果较好。
{
__HAL_TIM_SET_COUNTER(&htim1,0);
TIM1CH1_CAPTURE_STA = 0;
TIM1CH1_CAPTURE_VAL = 0;
}
if(j == 4) //第四次补货到了上升沿
{
count++; //用于main函数打印平均转速时用到的总圈数,该值+1.
TIM1CH1_CAPTURE_VAL = HAL_TIM_ReadCapturedValue(&htim1, TIM_CHANNEL_1);
time= TIM1CH1_CAPTURE_VAL + TIM1CH1_CAPTURE_STA*65536;
// printf("RPM 原始值 = %f\n",60/((float)time/1000000));
RPM += 60 / ((float)time/1000000); //在main打印之前累加RPM
// time = 0; 回调函数结束后自动释放该变量,无需清零。
j=0; //
}
}
主函数,打印转速信息
int main(void)
{
/* MCU Configuration--------------------------------------------------------*/
/* USER CODE BEGIN Init */
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start_IT(&htim1);
HAL_TIM_OC_Start_IT(&htim1, TIM_CHANNEL_1);//TIM1 CH1
/* USER CODE END 2 */
/* 其他初始化代码--------------------------------------------------------*/
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
printf("RPM:%f,count == %d\r\n",RPM/count,count);//´打印两次进入while(1)循环之间的平均RPM。
count = 0;
RPM = 0;
}
}
代码仅提供思路。如有不当与建议,欢迎指出。
实验部分
实验过程:以优利德(UNI-T)的光学转速传感器结合白色布条为标准数据进行实验,可以进行RPM与count的实时显示,实物图如下2所示。
电路板由一块核心板和靠近主轴的监测板组成。核心板以STMF103作为主控,将监测板上霍尔传感器的输入通过一个电压比较器输出给STM32的引脚完成监测。两者通过排插连接。
![](https://img-blog.csdnimg.cn/df2c534d3d7343b683aae1bd170c02f2.png#pic_center)
以电调为驱动,分别在不同PWM下记录转速数据,PWM为1400电机开始转动,上限为2200,其中的间隔为100。
实验结果如下:
PWM | 参考转速(RPM) | 霍尔转速(计时法) | 霍尔转速(计数法) |
---|---|---|---|
1400 | 816 | 815 | 1100 |
1500 | 950 | 945 | 1120 |
1600 | 1090 | 1086 | 1200 |
1700 | 1225 | 1223 | 1260 |
1800 | 1350 | 1353 | 1400 |
1900 | 1500 | 1490 | 1500 |
2000 | 1630 | 1625 | 1500 |
2100 | 1765 | 1762 | 1620 |
2200 | 1853 | 1855 | 1860 |
根据平均误差计算公式
求得计时法的平均转速误差为3.8RPM。在参考数据存在一定误差的情况下,精度较高。