查看: 465|回复: 0

[项目提交] 《2023 DigiKey 汽车应用创意挑战赛》-AGV安全距离检测系统

[复制链接]
  • TA的每日心情
    开心
    2024-4-7 13:52
  • 签到天数: 326 天

    连续签到: 1 天

    [LV.8]以坛为家I

    发表于 2024-1-4 23:51:43 | 显示全部楼层 |阅读模式
    分享到:
    1.png



    AGV安全距离检测系统



    前段时间一直在做超声波的调试,很多模拟量的问题没有解决这段时间降模拟量和通信做了调整,目前完成了Modbus-RTU的数据通信以及超声波测距的工作,整体的项目进展目前已经基本完成了,所以这里来和大家做一下汇报,分享一下自己的成果,首先从整体的项目规划以及框图开始说起,可能会比较繁琐一点,但是我还是觉得尽量详细的介绍我们现在的东西,也许会对大家带来一些启发。



    1 项目介绍AGV在现在物流运输和分拣中起到了重要作用,通常情况下是由上级电脑完成系统路径的规划,然后车辆按照分配路线将物流包裹配送到对应的区域内,从而完成大量包裹的分拣的工作,节约了很多人力成本,也避免了由于人为操作失误造成物流停滞、延迟的负面影响。因此AGV在物流分拣的重要性可想而知。在AGV的整体路径规划中,AGV的智能性也将起到至关重要的作用,其中最主要的一点就是安全距离检测,可以判断对于障碍物的判断,以及车辆急停、车辆会根据障碍物距离做出相应的减速、停止、转向等动作。

    2 硬件方案
    2.png



    整体的硬件方案是STM32F103CBT6作为主控,通过分时复用完成多多个超声波探头的然后通过RS485或者CAN总线完成数据的传输,通常情况下,RS485和CAN总线在实时性上是有一些距离的。目前的话只做了RS485这块,支持Modbus_RTU的协议。整体还配备了温度采集传感器,可以通过温度来进行声音测距的温度补偿,计算出当前温度的声速,从而对测量距离进行修正。


    2.1 硬件原理图
    3.png

    整体的原理图如上图,采用八个国内的超声波测距芯片,然后使用DCDC,完成12V到3.3V的电压转换,通过两个8通道的选择开关完成对每个传感器的数据选择和读取,通过TTL串口实现数的采集。软件内配置状态机,可以正常的完成采集。
    4.png
    整体的电路板如上图。每个传感器都有自己的驱动芯片。


    3 软件流程图

    3.1 状态机切换机制
    5.png

    状态机是在控制最常用的一种机制,可以避免阻塞,完成程序的流畅运行,同样避免了不必要的程序运行占用资源。目前我使用的状态机一共设置了几个状态,每个状态有对应状态的工作任务。
    目前一共分为:空闲状态、命令发送状态、回复等待状态、超时状态、异常状态。



    3.2 代码展示
    3.2.1 状态机代码

    1. void get_Data(struct CSB_Get  *CSB_Struct)
    2. {
    3.         int i=0;
    4.   unsigned int Status=CSB_Struct->Stttus;
    5.         unsigned int Data=0;
    6.         if(CSB_Struct->Channel_Count>CSB_Struct->Channel_MAX)
    7.                 {
    8.                                 CSB_Struct->Channel_Count=0;/*-- 如果当前通道计数大于 最大通道--那么这次就作废---*/
    9.                                 return ;
    10.                 }
    11.         else
    12.                 {
    13.                                 switch(Status)
    14.                                 {
    15.                                        
    16.                                         /*--------*/
    17.                                         case Status_Ideal:/*--数据采集之前的数据初始化工作 ---*/
    18.                                         {   
    19.                                                         for(i=0;i<CSB_Struct->Channel_MAX;i++)
    20.                                                         {
    21.                                                                 CSB_Struct->CSB_Data_Stable[i]=CSB_Struct->CSB_Curent_Data[i];
    22.                                                                 SysTemInfo.Sys_Data.CSB_Data[i]=CSB_Struct->CSB_Curent_Data[i]/1000;
    23.                                                         }
    24.                                                         select(CSB_Struct->Channel_Count);                    /*-- 选择发送通道 --*/                              
    25.                                                         CSB_Struct->TimeOut_Flag=0;                           /*-- 超时标志清零--*/
    26.                                                         CSB_Struct->UART_GetData_Flag=0;                      /*-- 串口接收数据标志清零--*/
    27.                                                         CSB_Struct->Uart_GetData_Count=0;                     /*-- 串口接收数量计数清零 ---*/
    28.                                                         CSB_Struct->CSB_Curent_Data[CSB_Struct->Channel_Count]=0;/*当前通道长度清零--*/
    29.                                                   CSB_Struct->TimeStart_Flag=1;
    30.                                                   CSB_Struct->TimeOutCount=0;
    31.                                                         CSB_Struct->Uart_Data[0]=0;
    32.                                                         CSB_Struct->Uart_Data[1]=0;
    33.                                                         CSB_Struct->Uart_Data[2]=0;
    34.                                                   CSB_Struct->Stttus=Status_SendCND;

    35.                                                
    36.                                         }break;
    37.                                         case Status_SendCND:
    38.                                         {   
    39.                                                         select(CSB_Struct->Channel_Count);                    /*-- 选择发送通道 --*/
    40.                                                   Send_Cmd();                                           /*-- 发送超声波的数据采集命令 --*/
    41.               timer_enable(TIMER1);                                 /*-- 开启定时器  -------*/
    42.                                                         CSB_Struct->Uart_Data[2]=0;
    43.                                                 CSB_Struct->Stttus=Status_WaitReply;
    44.                                                
    45.                                         }break;
    46.                                         case Status_WaitReply :
    47.                                         {
    48.                                           if(CSB_Struct->UART_GetData_Flag==1)
    49.                                                 {
    50.                                                         Data  =(Data|(CSB_Struct->Uart_Data[0]<<16) |(CSB_Struct->Uart_Data[1]<<8)|(CSB_Struct->Uart_Data[2]));
    51.                                                         CSB_Struct->CSB_Curent_Data[CSB_Struct->Channel_Count]=Data;
    52.                                                         CSB_Struct->Channel_Count++;
    53.                                                         CSB_Struct->Stttus=Status_Ideal;
    54.                                                 }
    55.                                                 /*-- 如果超时 --*/
    56.                                                 if(CSB_Struct->TimeOut_Flag==1)
    57.                                                 {
    58.                                                    CSB_Struct->Stttus=Status_TimeOut;
    59.                                                 }
    60.                                        
    61.                                        
    62.                                         }break;
    63.                                         case Status_TimeOut:  /*-- 直接跳转到空闲模式,继续下一个通道的测量 ----*/
    64.                                         {
    65.                                                
    66.                                                 CSB_Struct->Channel_Count++;
    67.                                                 CSB_Struct->TimeStart_Flag=0;
    68.                                                 CSB_Struct->TimeOutCount=0;
    69.                                                 timer_disable(TIMER1);                                 /*-- 开启定时器  -------*/
    70.                                           CSB_Struct->Stttus=Status_Ideal;
    71.                                         }break;
    72.                                         /*--------*/
    73.                                         default:
    74.                                         {
    75.                                                         CSB_Struct->TimeOut_Flag=0;                           /*-- 超时标志清零--*/
    76.                                                         CSB_Struct->UART_GetData_Flag=0;                      /*-- 串口接收数据标志清零--*/
    77.                                                         CSB_Struct->Uart_GetData_Count=0;                     /*-- 串口接收数量计数清零 ---*/
    78.                                                         CSB_Struct->Uart_Data[0]=0;
    79.                                                         CSB_Struct->Uart_Data[1]=0;
    80.                                                         CSB_Struct->Uart_Data[2]=0;
    81.                                                   CSB_Struct->Channel_Count=0;
    82.                                                   CSB_Struct->TimeStart_Flag=0;
    83.                                                   timer_disable(TIMER1);                                 /*-- 开启定时器  -------*/
    84.                                         }
    85.                                 }
    86.     }

    87. }
    复制代码



    3.2.2 通信代码展示 这里仅展示部分代码
    1.      case ReadMultRegister :    //--功能码:03   -- 读多个寄存器----
    2.                                                                 {
    3.                                                                            MB->ProtocalStr.MB_DataNum=MB->MB_RxData[MB_DataNum]<<8|MB->MB_RxData[MB_DataNum+1];
    4.                                                                            MB->ProtocalStr.CRCData=MB->MB_RxData[MB->MB_RxData_Len-1]<<8|MB->MB_RxData[MB->MB_RxData_Len-2];//--填入CRC数值--
    5.                                                                                        
    6.                                                                                         //--进入这里,说明地址和功能码都满足了,现在需要做的事判断输出数量是否在规定范围内--
    7.                                                                             //--IO数量的计算应当从起始地址+数量来计算--如果起始地址加上数量之后大于IO的点数,
    8.                                                                             //--此时应当报错处理--
    9.                                                                         DataLimit=MB->ProtocalStr.MB_StartAddr + MB->ProtocalStr.MB_DataNum;//--起始地址+读取数量---
    10.                                                                         if((DataLimit>=1)&&(DataLimit<MaxiunReadREG_Data))
    11.                                                                         {
    12.                                                                                 MB->MB_TxData[TX_MB_Addr]=MB->MB_RxData[MB_Addr];//--填充站号---
    13.                                                                                 MB->MB_TxData[TX_MB_FunCode]=MB->MB_RxData[MB_FunCode];//--填充功能码--
    14.                                                                                 //--读取线圈的函数----unsigned short        ReadMultReg_03(unsigned char *Buffer,unsigned short StartAddr,unsigned short Length)
    15.                                                                                 RTN_DataLen=ReadMultReg_03(&MB->MB_TxData[TX_MB_DataBase],MB->ProtocalStr.MB_StartAddr,MB->ProtocalStr.MB_DataNum);
    16.                                                                                 //--填充字节数--
    17.                                                                                 MB->MB_TxData[TX_MB_TxNum]=(unsigned char )(RTN_DataLen&0xff); //--填充字节数--
    18.                                                                                 //--开始填充数据--
    19.                                                                                 //计算CRC---校验和----校验是按照从包头开始 -- 一直到数据结束---
    20.                                                                                 CRC_Data=usMBCRC16( MB->MB_TxData, RTN_DataLen+3 );//--计算CRC的数值
    21.                                                        
    22.                                                                                 RTN_DataLen=RTN_DataLen+5;  //--这里是包含了CRC校验的----站号 +功能码 +数量+CRCData*2=5
    23.                                                                                 MB->MB_TxData_Len=RTN_DataLen;//--传入带发送的字节长度--
    24.                                                                                 MB->MB_TxData[RTN_DataLen-2]=(CRC_Data&0xff);  //--CRC-H
    25.                                                                                 MB->MB_TxData[RTN_DataLen-1]=((CRC_Data>>8)&0xff);  //--CRC-L
    26.                                                                                 //        完成数据包的组包
    27.                                                                                 //--        发送标志----
    28.                                                                                 MB->SendFlag=1;
    29.                                                                         }
    30.                                                                         else/*--说明--超出范围了---应当返回异常码------  --*/
    31.                                                                         {
    32.                                                                                   MB->MB_TxData[MB_Addr]=(0x80+ MB->MB_RxData[MB_FunCode]);//--填充站号--
    33.                                                           MB->MB_TxData[MB_FunCode]=MB_ERR_Output_Outof_RangeNum;//--填充功能码--错误码--               
    34.                                                                                   MB->MB_TxData_Len=2;
    35.                                                                                   MB->SendFlag=1;
    36.                                                                         }
    37.                                                                 }
    38.                                                                 break ;
    39.                                                                 //--
    40.                                                 case ReadinputRegister :   //--功能码:04   -- 读输入寄存器----
    41.                                                                 {
    42.                                                                            MB->ProtocalStr.MB_DataNum=MB->MB_RxData[MB_DataNum]<<8|MB->MB_RxData[MB_DataNum+1];
    43.                                                                            MB->ProtocalStr.CRCData=MB->MB_RxData[MB->MB_RxData_Len-1]<<8|MB->MB_RxData[MB->MB_RxData_Len-2];//--填入CRC数值--
    44.                                                                                 DataLimit=MB->ProtocalStr.MB_StartAddr + MB->ProtocalStr.MB_DataNum;//--起始地址+读取数量---
    45.                                                                                         if((DataLimit>=1)&&(DataLimit<MaxiunReadREG_Data))
    46.                                                                                         {
    47.                                                                                          
    48.                                                                                                                 MB->MB_TxData[TX_MB_Addr]=MB->MB_RxData[MB_Addr];//--填充站号---
    49.                                                                                                                 MB->MB_TxData[TX_MB_FunCode]=MB->MB_RxData[MB_FunCode];//--填充功能码--
    50.                                                                                                                 //--读取线圈的函数----unsigned short        ReadMultReg_03(unsigned char *Buffer,unsigned short StartAddr,unsigned short Length)
    51.                                                                                                                 RTN_DataLen=ReadInputReg_04(&MB->MB_TxData[TX_MB_DataBase],MB->ProtocalStr.MB_StartAddr,MB->ProtocalStr.MB_DataNum);
    52.                                                                                                                 //--填充字节数--
    53.                                                                                                                 MB->MB_TxData[TX_MB_TxNum]=(unsigned char )(RTN_DataLen&0xff); //--填充字节数--
    54.                                                                                                                 //--开始填充数据--
    55.                                                                                                                 //计算CRC---校验和----校验是按照从包头开始 -- 一直到数据结束---
    56.                                                                                                                 CRC_Data=usMBCRC16( MB->MB_TxData, RTN_DataLen+3 );//--计算CRC的数值
    57.                                                                                        
    58.                                                                                                                 RTN_DataLen=RTN_DataLen+5;  //--这里是包含了CRC校验的----站号 +功能码 +数量+CRCData*2=5
    59.                                                                                                     MB->MB_TxData_Len=RTN_DataLen;//--传入带发送的字节长度--
    60.                                                                                                                 MB->MB_TxData[RTN_DataLen-2]=(CRC_Data&0xff);  //--CRC-H
    61.                                                                                                                 MB->MB_TxData[RTN_DataLen-1]=((CRC_Data>>8)&0xff);  //--CRC-L
    62.                                                                                                                 //        完成数据包的组包
    63.                                                                                                                 //--        发送标志----
    64.                                                                                                                 MB->SendFlag=1;
    65.                                                                                         }
    66.                                                                                 else/*--说明--超出范围了---应当返回异常码------  --*/
    67.                                                                                         {
    68.                                                                                                   MB->MB_TxData[MB_Addr]=(0x80+ MB->MB_RxData[MB_FunCode]);//--填充站号--
    69.                           MB->MB_TxData[MB_FunCode]=MB_ERR_Output_Outof_RangeNum;//--填充功能码--错误码--               
    70.                                                                                                   MB->MB_TxData_Len=2;
    71.                                                                                                   MB->SendFlag=1;
    72.                                                                                         }
    73.                                                                  }
    74.                                                                 break ;

    75.                  //----
    76.                                                 case WriteSingelRegister : //--功能码:06   -- 写单个寄存器----
    77.                                                                 {
    78.                                                                  MB->ProtocalStr.MB_DataNum=1;
    79.                                                                                         //--站号-功能码-起始地址 - 数量  字节计数-- 寄存器数值--
    80.                                                           DataLimit=MB->ProtocalStr.MB_StartAddr+MB->ProtocalStr.MB_DataNum;
    81.                                                                 //--进入这里,说明地址和功能码都满足了,现在需要做的事判断输出数量是否在规定范围内--
    82.                                                                 if((MB->ProtocalStr.MB_DataNum>=1)&&(MB->ProtocalStr.MB_DataNum<=0x07D0))
    83.                                                                 {
    84.                                                                         //--站号-功能码-寄存器地址- 寄存器值
    85.                                                                         for(i=0;i<6;i++)
    86.                                                                           MB->MB_TxData[i]=MB->MB_RxData[i];
    87.                                                                         //--写多个寄存器的函数----unsigned short        WriteMultRegister_16(unsigned char *Buffer,unsigned short StartAddr,unsigned short Length)
    88.                                                                         RTN_DataLen=WriteSingelReg_06(&MB->MB_RxData[4],MB->ProtocalStr.MB_StartAddr,MB->ProtocalStr.MB_DataNum);
    89.                                                                   //--填充字节数--
    90. //                                                                        MB->MB_TxData[TX_MB_TxNum]=(unsigned char )(RTN_DataLen&0xff); //--填充字节数--
    91.                                                                         //--开始填充数据--
    92.                                                                         //计算CRC---校验和----校验是按照从包头开始 -- 一直到数据结束---
    93.                                                                         CRC_Data=usMBCRC16( MB->MB_TxData, RTN_DataLen+6 );//--计算CRC的数值
    94.                                                
    95.                                                                         RTN_DataLen=RTN_DataLen+8;  //--这里是包含了CRC校验的----站号 +功能码 +数量+CRCData*2=5
    96.                                                                         MB->MB_TxData_Len=RTN_DataLen;//--传入带发送的字节长度--
    97.                                                                         MB->MB_TxData[RTN_DataLen-2]=(CRC_Data&0xff);  //--CRC-H
    98.                                                                         MB->MB_TxData[RTN_DataLen-1]=((CRC_Data>>8)&0xff);  //--CRC-L
    99.                                                                         //        完成数据包的组包
    100.                                                                         //--        发送标志----
    101.                                                                         MB->SendFlag=1;
    102.                                                                 }
    103.                                                                 else/*--说明--超出范围了---应当返回异常码------  --*/
    104.                                                                 {
    105.                                                                     MB->MB_TxData[MB_Addr]=(0x80+ MB->MB_RxData[MB_FunCode]);//--填充站号--
    106.                                                                                 MB->MB_TxData[MB_FunCode]=MB_ERR_Output_Outof_RangeNum;//--填充功能码--错误码--               
    107.                                                                                 MB->MB_TxData_Len=2;
    108.                                                                                 MB->SendFlag=1;
    109.                                                                 }
    110.                                                                
    111.                                                                 }
    112.                                                                 break ;               
    复制代码



    4 实物测试图
    8.jpg


    9.jpg


    7.png


    由于电路没有处理好,所以目前可以稳定测试的距离在40cm以内,下面是Modbus-RTU 的测试界面。
    6.png







    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /2 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-5-7 03:39 , Processed in 0.117583 second(s), 17 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.