解决STM32超声波测距不准问题及智能小车超声波测距代码(C语言版本)

首先要说明一下原理:使用stm32无法准确产生1us的时间,

(后来发现仿真器不一定可靠,有时候仿真器看到不正确,实际运行没有问题,这就要通过实验来确定)

但是超声波测距一定要依赖时间,时间不准,距离一定不准,这是要肯定的,但是在不准确的情况下,要测量一个比较准确的时间,那么只能够把误差控制在一定范围内,这就是基本思想。

经过实验,获得实验数据如下:

这是delay_us(50)时候获取的实验数据:

这是delay_us(100)时候获取的实验数据:

可以发现结论并不像我们预想的那样平均delay_us(1)会产生非常的的误差,因为delay_us(1)花费了20us的时间,误差20倍是无论如何不可接受的。如果要画出一条曲线来表示,那么会类似于一条这样的:

写到这里就不用再怎么写了,已经很清楚了

下面写一点废话:通过观察可以发现:超声波测距在距离进的时候不准确,因为此时通过观察曲线可知,误差很大,当距离远的时候精度会诸将提高,直到超出测量范围。可以预料到精度会再次下降,如果要画出来一条曲线应该类似于这个样子;

此图片中不包含2线之间的相对关系

再来看这个表:

假设声波不受温度映像设此时为340m/s,那么100us来回的距离,那个检测到的物体离我们的距离是多少:340 /1000 000   x   100  / 2  =0.017m=1.7cm,也就是说此时候的距离是1.7厘米,也就是说当物体离我们1.7cm时候,误差和已经控制在10%,而且会越来越小,所以超声波模块有效测量距离应该符合说明书上面的:2cm–3m,即是说当物体处于2cm–3m范围内的时候,是准确的

(我真的好奇怪,为什么书上面说超声波测量距离有几百米,但是卖家说有效距离只有3米)

这个就是我用的delay_us函数,使用了内部时钟8MHZ

void delay_us(uint32_t ii)
{
	uint32_t temp;
	SysTick->LOAD=ii;
	SysTick->VAL=0x00;
	SysTick->CTRL=0x01;//2号位1使用内核时钟
	do
	{
		temp=SysTick->CTRL;
	}
	while(temp&0x01&&!(temp&(1<<16)));
	SysTick->CTRL=0X00;
	SysTick->VAL=0X00;
}

那个实在不好意思说一点,本来8MHZ按照我的理解,那个ii应该要乘以8就是Systick->LOAD=ii*8;

但是不知道为什么这里就是表现为不用乘以8的时候是对的,即使用这个函数产生1s的时间,还是对的,所以我就不管了,方正就是这样就可以用了

那么是不是便宜的单片机质量不合格?

不是这样的,当使用keil arm模拟的时候得出了同样的结论,所以可以判定这个算子是正确的,只是暂时不知道原因

后来我又看到一些东西:

  • 观点一:超声波测量最好是测量一个平面,才会准确些,另外超声波并不是测量一个点到点距离,超声波测量是与中轴线有一个角度的,它是一个圆锥形的发散出去,所以旁边的东西都可能影响到。你如果想测量点的话,用激光可能还好些
  • 观点2:超声波测距本来测平面的东西就准确,人体是不规则的,超声波测不准,而且超声波测距不适合远距离,测人体可以用人体红外模块
  • 观点3:反射声波的物体的形状和材质会有影响,多次测量移除最大最小值取平均
  • 总而言之:这个东西不太精确,但是可以用来判断附近是不是有物体,可以用于ros2下位机或者stm32智能小车的避障。

    int main(void)
    {
    	int beginTime=0,endTime=0;
    	int radari=0;
    	int distance_cm;
      HAL_Init();
      SystemClock_Config();
      MX_GPIO_Init();
      /* USER CODE BEGIN 2 */
    	
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
    		//
    		radari=0;
    		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,1);
    		delay_us(12);  //实际花费了20us
    
    		while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_2)==0);
    		while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_2)==1)
    		{
    			radari++;
    			delay_us(50);
    		}
    		distance_cm=340.0/1000000*(50*radari)/2;//这个就是测量的距离
    		radari=0;
    		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,0);
    		//
      }
      /* USER CODE END 3 */
    }
    

    物联沃分享整理
    物联沃-IOTWORD物联网 » 解决STM32超声波测距不准问题及智能小车超声波测距代码(C语言版本)

    发表评论