• stm32超声波测距不准的解决方法(STM32 delay_us()产生1us)及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范围内的时候,是准确的

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

    1. void delay_us(uint32_t ii)
    2. {
    3. uint32_t temp;
    4. SysTick->LOAD=ii;
    5. SysTick->VAL=0x00;
    6. SysTick->CTRL=0x01;//2号位1使用内核时钟
    7. do
    8. {
    9. temp=SysTick->CTRL;
    10. }
    11. while(temp&0x01&&!(temp&(1<<16)));
    12. SysTick->CTRL=0X00;
    13. SysTick->VAL=0X00;
    14. }

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

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

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

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

    后来我又看到一些东西:

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

    总而言之:这个东西不太精确,但是可以用来判断附近是不是有物体,可以用于ros2下位机或者stm32智能小车的避障。

    1. int main(void)
    2. {
    3. int beginTime=0,endTime=0;
    4. int radari=0;
    5. int distance_cm;
    6. HAL_Init();
    7. SystemClock_Config();
    8. MX_GPIO_Init();
    9. /* USER CODE BEGIN 2 */
    10. /* USER CODE END 2 */
    11. /* Infinite loop */
    12. /* USER CODE BEGIN WHILE */
    13. while (1)
    14. {
    15. //
    16. radari=0;
    17. HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,1);
    18. delay_us(12); //实际花费了20us
    19. HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,0);
    20. while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_2)==0);
    21. while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_2)==1)
    22. {
    23. radari++;
    24. delay_us(50);
    25. }
    26. distance_cm=340.0/1000000*(50*radari)/2;//这个就是测量的距离
    27. radari=0;
    28. //
    29. }
    30. /* USER CODE END 3 */
    31. }

  • 相关阅读:
    python学习笔记:引用、浅拷贝和深拷贝(底层原理)
    中创生日会 | 烟火向星辰,所愿皆成真
    jxTMS设计思想之安全
    万应案例精选|抓紧抓实抓细,万应为安全生产全域监管护航
    mapper.xml中的sql标签
    Godot4实现游戏的多语言版本
    基于ABP和Magicodes实现Excel导出操作
    Spring - IOC注解开发
    自学WEB后端05-Node.js后端服务链接数据库redis
    机器视觉运动控制一体机应用例程|胶圈内嵌完整性检测
  • 原文地址:https://blog.csdn.net/geniusChinaHN/article/details/134352020