加入星計劃,您可以享受以下權益:

  • 創(chuàng)作內容快速變現(xiàn)
  • 行業(yè)影響力擴散
  • 作品版權保護
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入

基于STM32F103CBT6的AGV(自動導引車)安全距離檢測系統(tǒng)

05/15 10:02
2958
服務支持:
技術交流群

完成交易后在“購買成功”頁面掃碼入群,即可與技術大咖們分享疑惑和經(jīng)驗、收獲成長和認同、領取優(yōu)惠和紅包等。

虛擬商品不可退

當前內容為數(shù)字版權作品,購買后不支持退換且無法轉移使用。

加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論
放大
實物圖(3)
相關方案
  • 方案介紹
  • 推薦器件
  • 相關推薦
  • 電子產(chǎn)業(yè)圖譜
申請入駐 產(chǎn)業(yè)圖譜

前段時間一直在做超聲波的調試,很多模擬量的問題沒有解決這段時間降模擬量和通信做了調整,目前完成了Modbus-RTU數(shù)據(jù)通信以及超聲波測距的工作,整體的項目進展目前已經(jīng)基本完成了,所以這里來和大家做一下匯報,分享一下自己的成果,首先從整體的項目規(guī)劃以及框圖開始說起,可能會比較繁瑣一點,但是我還是覺得盡量詳細的介紹我們現(xiàn)在的東西,也許會對大家?guī)硪恍﹩l(fā)。

1 項目介紹

AGV在現(xiàn)在物流運輸和分揀中起到了重要作用,通常情況下是由上級電腦完成系統(tǒng)路徑的規(guī)劃,然后車輛按照分配路線將物流包裹配送到對應的區(qū)域內,從而完成大量包裹的分揀的工作,節(jié)約了很多人力成本,也避免了由于人為操作失誤造成物流停滯、延遲的負面影響。因此AGV在物流分揀的重要性可想而知。在AGV的整體路徑規(guī)劃中,AGV的智能性也將起到至關重要的作用,其中最主要的一點就是安全距離檢測,可以判斷對于障礙物的判斷,以及車輛急停、車輛會根據(jù)障礙物距離做出相應的減速、停止、轉向等動作。

2 硬件方案

整體的硬件方案是STM32F103CBT6作為主控,通過分時復用完成多多個超聲波探頭的然后通過RS485或者CAN總線完成數(shù)據(jù)的傳輸,通常情況下,RS485和CAN總線在實時性上是有一些距離的。目前的話只做了RS485這塊,支持Modbus_RTU的協(xié)議。整體還配備了溫度采集傳感器,可以通過溫度來進行聲音測距的溫度補償,計算出當前溫度的聲速,從而對測量距離進行修正。

2.1 硬件原理圖

整體的原理圖如上圖,采用八個國內的超聲波測距芯片,然后使用DCDC,完成12V到3.3V的電壓轉換,通過兩個8通道的選擇開關完成對每個傳感器的數(shù)據(jù)選擇和讀取,通過TTL串口實現(xiàn)數(shù)的采集。軟件內配置狀態(tài)機,可以正常的完成采集。

整體的電路板如上圖。每個傳感器都有自己的驅動芯片。

3 軟件流程圖

3.1 狀態(tài)機切換機制

狀態(tài)機是在控制最常用的一種機制,可以避免阻塞,完成程序的流暢運行,同樣避免了不必要的程序運行占用資源。目前我使用的狀態(tài)機一共設置了幾個狀態(tài),每個狀態(tài)有對應狀態(tài)的工作任務。
目前一共分為:空閑狀態(tài)、命令發(fā)送狀態(tài)、回復等待狀態(tài)、超時狀態(tài)、異常狀態(tài)。

3.2 代碼展示

3.2.1 狀態(tài)機代碼

void get_Data(struct CSB_Get  *CSB_Struct)
{
        int i=0;
  unsigned int Status=CSB_Struct->Stttus;
        unsigned int Data=0;
        if(CSB_Struct->Channel_Count>CSB_Struct->Channel_MAX)
                {
                                CSB_Struct->Channel_Count=0;/*-- 如果當前通道計數(shù)大于 最大通道--那么這次就作廢---*/
                                return ;
                }
        else
                {
                                switch(Status)
                                {
                                        
                                        /*--------*/
                                        case Status_Ideal:/*--數(shù)據(jù)采集之前的數(shù)據(jù)初始化工作 ---*/
                                        {   
                                                        for(i=0;i<CSB_Struct->Channel_MAX;i++)
                                                        {
                                                                CSB_Struct->CSB_Data_Stable[i]=CSB_Struct->CSB_Curent_Data[i];
                                                                SysTemInfo.Sys_Data.CSB_Data[i]=CSB_Struct->CSB_Curent_Data[i]/1000;
                                                        }
                                                        select(CSB_Struct->Channel_Count);                    /*-- 選擇發(fā)送通道 --*/                              
                                                        CSB_Struct->TimeOut_Flag=0;                           /*-- 超時標志清零--*/
                                                        CSB_Struct->UART_GetData_Flag=0;                      /*-- 串口接收數(shù)據(jù)標志清零--*/
                                                        CSB_Struct->Uart_GetData_Count=0;                     /*-- 串口接收數(shù)量計數(shù)清零 ---*/
                                                        CSB_Struct->CSB_Curent_Data[CSB_Struct->Channel_Count]=0;/*當前通道長度清零--*/
                                                  CSB_Struct->TimeStart_Flag=1;
                                                  CSB_Struct->TimeOutCount=0;
                                                        CSB_Struct->Uart_Data[0]=0;
                                                        CSB_Struct->Uart_Data[1]=0;
                                                        CSB_Struct->Uart_Data[2]=0;
                                                  CSB_Struct->Stttus=Status_SendCND;

                                                
                                        }break;
                                        case Status_SendCND:
                                        {   
                                                        select(CSB_Struct->Channel_Count);                    /*-- 選擇發(fā)送通道 --*/
                                                  Send_Cmd();                                           /*-- 發(fā)送超聲波的數(shù)據(jù)采集命令 --*/
              timer_enable(TIMER1);                                 /*-- 開啟定時器  -------*/
                                                        CSB_Struct->Uart_Data[2]=0;
                                                CSB_Struct->Stttus=Status_WaitReply;
                                                
                                        }break;
                                        case Status_WaitReply :
                                        {
                                          if(CSB_Struct->UART_GetData_Flag==1)
                                                {
                                                        Data  =(Data|(CSB_Struct->Uart_Data[0]<<16) |(CSB_Struct->Uart_Data[1]<<8)|(CSB_Struct->Uart_Data[2]));
                                                        CSB_Struct->CSB_Curent_Data[CSB_Struct->Channel_Count]=Data;
                                                        CSB_Struct->Channel_Count++;
                                                        CSB_Struct->Stttus=Status_Ideal;
                                                }
                                                /*-- 如果超時 --*/
                                                if(CSB_Struct->TimeOut_Flag==1)
                                                {
                                                   CSB_Struct->Stttus=Status_TimeOut;
                                                }
                                        
                                        
                                        }break;
                                        case Status_TimeOut:  /*-- 直接跳轉到空閑模式,繼續(xù)下一個通道的測量 ----*/
                                        {
                                                
                                                CSB_Struct->Channel_Count++;
                                                CSB_Struct->TimeStart_Flag=0;
                                                CSB_Struct->TimeOutCount=0;
                                                timer_disable(TIMER1);                                 /*-- 開啟定時器  -------*/
                                          CSB_Struct->Stttus=Status_Ideal;
                                        }break;
                                        /*--------*/
                                        default:
                                        {
                                                        CSB_Struct->TimeOut_Flag=0;                           /*-- 超時標志清零--*/
                                                        CSB_Struct->UART_GetData_Flag=0;                      /*-- 串口接收數(shù)據(jù)標志清零--*/
                                                        CSB_Struct->Uart_GetData_Count=0;                     /*-- 串口接收數(shù)量計數(shù)清零 ---*/
                                                        CSB_Struct->Uart_Data[0]=0;
                                                        CSB_Struct->Uart_Data[1]=0;
                                                        CSB_Struct->Uart_Data[2]=0;
                                                  CSB_Struct->Channel_Count=0;
                                                  CSB_Struct->TimeStart_Flag=0;
                                                  timer_disable(TIMER1);                                 /*-- 開啟定時器  -------*/
                                        }
                                }
    }

}

3.2.2 通信代碼展示 這里僅展示部分代碼

     case ReadMultRegister :    //--功能碼:03   -- 讀多個寄存器----
                                                                {
                                                                           MB->ProtocalStr.MB_DataNum=MB->MB_RxData[MB_DataNum]<<8|MB->MB_RxData[MB_DataNum+1];
                                                                           MB->ProtocalStr.CRCData=MB->MB_RxData[MB->MB_RxData_Len-1]<<8|MB->MB_RxData[MB->MB_RxData_Len-2];//--填入CRC數(shù)值--
                                                                                        
                                                                                        //--進入這里,說明地址和功能碼都滿足了,現(xiàn)在需要做的事判斷輸出數(shù)量是否在規(guī)定范圍內--
                                                                            //--IO數(shù)量的計算應當從起始地址+數(shù)量來計算--如果起始地址加上數(shù)量之后大于IO的點數(shù),
                                                                            //--此時應當報錯處理--
                                                                        DataLimit=MB->ProtocalStr.MB_StartAddr + MB->ProtocalStr.MB_DataNum;//--起始地址+讀取數(shù)量---
                                                                        if((DataLimit>=1)&&(DataLimit<MaxiunReadREG_Data))
                                                                        {
                                                                                MB->MB_TxData[TX_MB_Addr]=MB->MB_RxData[MB_Addr];//--填充站號---
                                                                                MB->MB_TxData[TX_MB_FunCode]=MB->MB_RxData[MB_FunCode];//--填充功能碼--
                                                                                //--讀取線圈的函數(shù)----unsigned short        ReadMultReg_03(unsigned char *Buffer,unsigned short StartAddr,unsigned short Length)
                                                                                RTN_DataLen=ReadMultReg_03(&MB->MB_TxData[TX_MB_DataBase],MB->ProtocalStr.MB_StartAddr,MB->ProtocalStr.MB_DataNum);
                                                                                //--填充字節(jié)數(shù)--
                                                                                MB->MB_TxData[TX_MB_TxNum]=(unsigned char )(RTN_DataLen&0xff); //--填充字節(jié)數(shù)--
                                                                                //--開始填充數(shù)據(jù)--
                                                                                //計算CRC---校驗和----校驗是按照從包頭開始 -- 一直到數(shù)據(jù)結束---
                                                                                CRC_Data=usMBCRC16( MB->MB_TxData, RTN_DataLen+3 );//--計算CRC的數(shù)值
                                                        
                                                                                RTN_DataLen=RTN_DataLen+5;  //--這里是包含了CRC校驗的----站號 +功能碼 +數(shù)量+CRCData*2=5
                                                                                MB->MB_TxData_Len=RTN_DataLen;//--傳入帶發(fā)送的字節(jié)長度--
                                                                                MB->MB_TxData[RTN_DataLen-2]=(CRC_Data&0xff);  //--CRC-H
                                                                                MB->MB_TxData[RTN_DataLen-1]=((CRC_Data>>8)&0xff);  //--CRC-L
                                                                                //        完成數(shù)據(jù)包的組包
                                                                                //--        發(fā)送標志----
                                                                                MB->SendFlag=1;
                                                                        }
                                                                        else/*--說明--超出范圍了---應當返回異常碼------  --*/
                                                                        {
                                                                                  MB->MB_TxData[MB_Addr]=(0x80+ MB->MB_RxData[MB_FunCode]);//--填充站號--
                                                          MB->MB_TxData[MB_FunCode]=MB_ERR_Output_Outof_RangeNum;//--填充功能碼--錯誤碼--                
                                                                                  MB->MB_TxData_Len=2;
                                                                                  MB->SendFlag=1;
                                                                        }
                                                                }
                                                                break ;
                                                                //--
                                                case ReadinputRegister :   //--功能碼:04   -- 讀輸入寄存器----
                                                                {
                                                                           MB->ProtocalStr.MB_DataNum=MB->MB_RxData[MB_DataNum]<<8|MB->MB_RxData[MB_DataNum+1];
                                                                           MB->ProtocalStr.CRCData=MB->MB_RxData[MB->MB_RxData_Len-1]<<8|MB->MB_RxData[MB->MB_RxData_Len-2];//--填入CRC數(shù)值--
                                                                                DataLimit=MB->ProtocalStr.MB_StartAddr + MB->ProtocalStr.MB_DataNum;//--起始地址+讀取數(shù)量---
                                                                                        if((DataLimit>=1)&&(DataLimit<MaxiunReadREG_Data))
                                                                                        {
                                                                                         
                                                                                                                MB->MB_TxData[TX_MB_Addr]=MB->MB_RxData[MB_Addr];//--填充站號---
                                                                                                                MB->MB_TxData[TX_MB_FunCode]=MB->MB_RxData[MB_FunCode];//--填充功能碼--
                                                                                                                //--讀取線圈的函數(shù)----unsigned short        ReadMultReg_03(unsigned char *Buffer,unsigned short StartAddr,unsigned short Length)
                                                                                                                RTN_DataLen=ReadInputReg_04(&MB->MB_TxData[TX_MB_DataBase],MB->ProtocalStr.MB_StartAddr,MB->ProtocalStr.MB_DataNum);
                                                                                                                //--填充字節(jié)數(shù)--
                                                                                                                MB->MB_TxData[TX_MB_TxNum]=(unsigned char )(RTN_DataLen&0xff); //--填充字節(jié)數(shù)--
                                                                                                                //--開始填充數(shù)據(jù)--
                                                                                                                //計算CRC---校驗和----校驗是按照從包頭開始 -- 一直到數(shù)據(jù)結束---
                                                                                                                CRC_Data=usMBCRC16( MB->MB_TxData, RTN_DataLen+3 );//--計算CRC的數(shù)值
                                                                                        
                                                                                                                RTN_DataLen=RTN_DataLen+5;  //--這里是包含了CRC校驗的----站號 +功能碼 +數(shù)量+CRCData*2=5
                                                                                                    MB->MB_TxData_Len=RTN_DataLen;//--傳入帶發(fā)送的字節(jié)長度--
                                                                                                                MB->MB_TxData[RTN_DataLen-2]=(CRC_Data&0xff);  //--CRC-H
                                                                                                                MB->MB_TxData[RTN_DataLen-1]=((CRC_Data>>8)&0xff);  //--CRC-L
                                                                                                                //        完成數(shù)據(jù)包的組包
                                                                                                                //--        發(fā)送標志----
                                                                                                                MB->SendFlag=1;
                                                                                        }
                                                                                else/*--說明--超出范圍了---應當返回異常碼------  --*/
                                                                                        {
                                                                                                  MB->MB_TxData[MB_Addr]=(0x80+ MB->MB_RxData[MB_FunCode]);//--填充站號--
                          MB->MB_TxData[MB_FunCode]=MB_ERR_Output_Outof_RangeNum;//--填充功能碼--錯誤碼--                
                                                                                                  MB->MB_TxData_Len=2;
                                                                                                  MB->SendFlag=1;
                                                                                        }
                                                                 }
                                                                break ;

                 //----
                                                case WriteSingelRegister : //--功能碼:06   -- 寫單個寄存器----
                                                                {
                                                                 MB->ProtocalStr.MB_DataNum=1;
                                                                                        //--站號-功能碼-起始地址 - 數(shù)量  字節(jié)計數(shù)-- 寄存器數(shù)值--
                                                          DataLimit=MB->ProtocalStr.MB_StartAddr+MB->ProtocalStr.MB_DataNum;
                                                                //--進入這里,說明地址和功能碼都滿足了,現(xiàn)在需要做的事判斷輸出數(shù)量是否在規(guī)定范圍內--
                                                                if((MB->ProtocalStr.MB_DataNum>=1)&&(MB->ProtocalStr.MB_DataNum<=0x07D0))
                                                                {
                                                                        //--站號-功能碼-寄存器地址- 寄存器值
                                                                        for(i=0;i<6;i++)
                                                                          MB->MB_TxData[i]=MB->MB_RxData[i];
                                                                        //--寫多個寄存器的函數(shù)----unsigned short        WriteMultRegister_16(unsigned char *Buffer,unsigned short StartAddr,unsigned short Length)
                                                                        RTN_DataLen=WriteSingelReg_06(&MB->MB_RxData[4],MB->ProtocalStr.MB_StartAddr,MB->ProtocalStr.MB_DataNum);
                                                                  //--填充字節(jié)數(shù)--
//                                                                        MB->MB_TxData[TX_MB_TxNum]=(unsigned char )(RTN_DataLen&0xff); //--填充字節(jié)數(shù)--
                                                                        //--開始填充數(shù)據(jù)--
                                                                        //計算CRC---校驗和----校驗是按照從包頭開始 -- 一直到數(shù)據(jù)結束---
                                                                        CRC_Data=usMBCRC16( MB->MB_TxData, RTN_DataLen+6 );//--計算CRC的數(shù)值
                                                
                                                                        RTN_DataLen=RTN_DataLen+8;  //--這里是包含了CRC校驗的----站號 +功能碼 +數(shù)量+CRCData*2=5
                                                                        MB->MB_TxData_Len=RTN_DataLen;//--傳入帶發(fā)送的字節(jié)長度--
                                                                        MB->MB_TxData[RTN_DataLen-2]=(CRC_Data&0xff);  //--CRC-H
                                                                        MB->MB_TxData[RTN_DataLen-1]=((CRC_Data>>8)&0xff);  //--CRC-L
                                                                        //        完成數(shù)據(jù)包的組包
                                                                        //--        發(fā)送標志----
                                                                        MB->SendFlag=1;
                                                                }
                                                                else/*--說明--超出范圍了---應當返回異常碼------  --*/
                                                                {
                                                                    MB->MB_TxData[MB_Addr]=(0x80+ MB->MB_RxData[MB_FunCode]);//--填充站號--
                                                                                MB->MB_TxData[MB_FunCode]=MB_ERR_Output_Outof_RangeNum;//--填充功能碼--錯誤碼--                
                                                                                MB->MB_TxData_Len=2;
                                                                                MB->SendFlag=1;
                                                                }
                                                                
                                                                }
                                                                break ;                

4 實物測試圖

由于電路沒有處理好,所以目前可以穩(wěn)定測試的距離在40cm以內,下面是Modbus-RTU 的測試界面。

 

推薦器件

更多器件
器件型號 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊 ECAD模型 風險等級 參考價格 更多信息
NC7SZ126M5X 1 Texas Instruments LVC/LCX/Z SERIES, 1-BIT DRIVER, TRUE OUTPUT, PDSO5, PLASTIC, SOT-23, 5 PIN
$0.43 查看
NC7WZ17P6X 1 Fairchild Semiconductor Corporation Buffer, LVC/LCX/Z Series, 2-Func, 1-Input, CMOS, PDSO6, 1.25 MM, ROHS COMPLIANT, EIAJ, SC-88A, SC-70, 6 PIN
$0.23 查看
NC7SZ04M5X 1 Texas Instruments LVC/LCX/Z SERIES, 1-INPUT INVERT GATE, PDSO5, THERMALLY ENHANCED, PLASTIC, SOT-23, 5 PIN
$0.4 查看

相關推薦

電子產(chǎn)業(yè)圖譜