xld0932 发表于 2022-2-27 20:53

【安信可UWB室内定位模组NodeMCU-BU01】05.移植准备:测距功能代码分析

<div class='showpostmsg'><p>上一篇帖子我们通过阅读代码分析了原厂对于NodeMCU-BU01的初始化配置过程,通过USART中断入口函数定位到了AT指令解析运行及相对应的功能调用函数的具体实现;这篇帖子我们来看一下,这份功能代码是怎么一个测距流程的&hellip;&hellip;</p>

<p>首先我们还是先看一下对应的AT指令功能调用函数的实现部分(仅与测距相关的部分):</p>

<p>&nbsp;</p>

<p>1、AT+anchor_tag指令:这个AT指令的功能,是将当前的NodeMCU-BU01设置为基站还是标签模式,将设置数据写入到FLASH的USER_FLASH_BASE地址进行存储;</p>

<pre>
<code class="language-cpp">int AT_CmdFunc_ANCHOR_TAG(int opt,int argc, char *argv[])
{
        //phy_printf("aliGenie set opt:%d\r\n",opt);
        if(opt==EXECUTE_CMD)
        {
               
               
                        uint16_t write=66;
                        FLASH_WriteMoreData(USER_FLASH_BASE,&amp;write,1);
               
               
        }
        else if(opt==SET_CMD)
        {
                char *get=NULL;
                get=strtok(argv,",");
                uint16_t Set=atoi(get);
                uint16_t write={0};
               
                if(Set==1)
                {
                        //uint16_t write=1;
                        write=1;
                        //FLASH_WriteMoreData(USER_FLASH_BASE,&amp;write,1);
                }
                else if(Set==0)
                {
                        write=0;
                        //uint16_t write=0;
                        //FLASH_WriteMoreData(USER_FLASH_BASE,&amp;write,1);
                       
                }
                else
                {
                        return -1;
                }
               
                get=NULL;
                get=strtok(NULL,",");
                Set=atoi(get);
                if(Set&gt;=0 &amp;&amp; Set&lt;=255)
                {
                        write=Set;
                       
                }
                else
                {
                        return -1;
                }
               
                FLASH_WriteMoreData(USER_FLASH_BASE,write,2);
               
        }
        else if(opt==QUERY_CMD)
        {
                uint16_t buff={0};
                FLASH_ReadMoreData(USER_FLASH_BASE,buff,3);
       
                printf("buff0:%d\r\n",buff);
                printf("buff1:%d\r\n",buff);
                printf("buff2:%d\r\n",buff);
               
        }
       
       
        return 1;
}</code></pre>

<p>&nbsp;</p>

<p>2、AT+interval指令:这个AT指令的功能是设定测距的间隔时间,单位是毫秒,设置值范围在5~50之间,而AT指令的参数,被赋值到ANCHOR_REFRESH_COUNT_set这个全局变量中进行存储;</p>

<pre>
<code class="language-cpp">int AT_CmdFunc_interval(int opt,int argc, char *argv[])
{
        //phy_printf("aliGenie set opt:%d\r\n",opt);
        if(opt==EXECUTE_CMD)
        {
               
        }
        else if(opt==SET_CMD)
        {
                char *get=NULL;
                get=strtok(argv,",");
                uint16_t Set=atoi(get);
                if(Set&gt;=5&amp;&amp; Set&lt;=50)
                {
                        ANCHOR_REFRESH_COUNT_set=Set;
                }
                else
                {
                        return -1;
                }
       
        }
        else if(opt==QUERY_CMD)
        {
               
               
        }
       
       
        return 1;
}</code></pre>

<p>&nbsp;</p>

<p>3、AT+switchdis指令:这个AT指令的功能就是控制测距的使能,控制开始进行测距和停止测距,而AT指令的设置参数被保存在SWITCH_DIS这个全局变量中;</p>

<pre>
<code class="language-cpp">int AT_CmdFunc_ondis(int opt,int argc, char *argv[])
{
        //phy_printf("aliGenie set opt:%d\r\n",opt);
        if(opt==EXECUTE_CMD)
        {
               
        }
        else if(opt==SET_CMD)
        {
               
                char *get=NULL;
                get=strtok(argv,",");
                uint16_t Set=atoi(get);
               
                if(Set==1)
                {
                        SWITCH_DIS=1;
                }
                else if(Set==0)
                {
                        SWITCH_DIS=0;
                }
                else
                {
                        return -1;
                }
       
        }
        else if(opt==QUERY_CMD)
        {
               
               
        }
       
       
        return 1;
}</code></pre>

<p>&nbsp;</p>

<p>那测距过程,是如何通过这些AT指令来相互配合实现的呢?</p>

<p>&nbsp;</p>

<p>首先,我们还是看MAIN函数的实现:在进行外设初始化完成后,接着对DW1000进行复位操作,在低SPI速率的情况下,对DWT进行初始化操作,等初始化完成后再提升SPI的通讯速率;然后就是配置DWT的设置参数;接着从FLASH中读取AT配置的工作模式,如果在没有配置的情况下,默认为基站模式;接下来就是根据工作模式来进行不同的函数调用;</p>

<pre>
<code class="language-cpp">int main(void)
{
    uint8 anthor_index = 0;
    uint8 tag_index = 0;

    uint8 Semaphore_Enable = 0 ;
    uint8 Waiting_TAG_Release_Semaphore = 0;
    int8 frame_len = 0;
                //lable1:
    /* Start with board specific hardware init. */
    peripherals_init();
       
    printf("hello dwm1000!\r\n");

    /* Reset and initialise DW1000.
   * For initialisation, DW1000 clocks must be temporarily set to crystal speed. After initialisation SPI rate can be increased for optimum
   * performance. */

        reset_DW1000(); /* Target specific drive of RSTn line into DW1000 low for a period. */
    spi_set_rate_low();

               
    if(dwt_initialise(DWT_LOADUCODE) == -1)
    {
      printf("dwm1000 init fail!\r\n");
      OLED_ShowString(0,0,"INIT FAIL");
      while (1)
      {
                                          //STM_EVAL_LEDOn(LED1);
                                        GPIO_SetBits(GPIOC,GPIO_Pin_13);
            deca_sleep(1000);
            //STM_EVAL_LEDOff(LED1);
                                        GPIO_ResetBits(GPIOC,GPIO_Pin_13);
            deca_sleep(1000);
                                       

      }
    }
    spi_set_rate_high();

    /* Configure DW1000. See NOTE 6 below. */
    dwt_configure(&amp;config);
    dwt_setleds(1);
               
    /* Apply default antenna delay value. See NOTE 1 below. */
    dwt_setrxantennadelay(RX_ANT_DLY);
    dwt_settxantennadelay(TX_ANT_DLY);
    OLED_ShowString(0,0,"INIT PASS");

    printf("init pass!\r\n");
                printf("AIT-BU01-DB V100 T2020-5-17\r\n");
               
               
    AnchorList.x =0.12;
    AnchorList.y =0.34;
    AnchorList.z =0;

    AnchorList.x =0.25;
    AnchorList.y =0;
    AnchorList.z =0;

    AnchorList.x =0;
    AnchorList.y =0;
    AnchorList.z =0;
    int rx_ant_delay =32880;
    int index = 0 ;
               
        extern UserSet UserSetNow;
        uint16_t buff={1,0,0xff};//ĬèÏÖμ
        FLASH_ReadMoreData(USER_FLASH_BASE,buff,3);
        if(buff==1)
        {
                UserSetNow.ANCHOR_TAG=1;
        }
        else if(buff==0)
        {
                UserSetNow.ANCHOR_TAG=0;
        }
        else
        {
                UserSetNow.ANCHOR_TAG=1;
        }
       
//#ifdef ANTHOR
       
if(UserSetNow.ANCHOR_TAG==1)
{
        if(buff&gt;=0 &amp;&amp; buff&lt;=255)
        {
                UserSetNow.ID=buff;
                ANCHOR_IND=UserSetNow.ID;
        }
        printf("device:anchor ID:%d\r\n",ANCHOR_IND);
       
                          Anchor_Array_Init();
    /* Loop forever initiating ranging exchanges. */
    OLED_ShowString(0,0,"DS TWR ANTHOR");
    //OLED_ShowString(0,2,"Distance:");

    //KalMan_PramInit();
                ANTHOR_MEASURE();

       
}

//#endif

//#ifdef TAG

if(UserSetNow.ANCHOR_TAG==0)
{
       
        if(buff&gt;=0 &amp;&amp; buff&lt;=255)
        {
                UserSetNow.ID=buff;
                TAG_ID=UserSetNow.ID;
                MASTER_TAG=TAG_ID;
        }
       
        printf("device:TAG ID:%d\r\n",UserSetNow.ID);
        if(TAG_ID == MASTER_TAG)
    {
      OLED_ShowString(0,0,"DS MASTER TAG:");
    }
    else
    {
      OLED_ShowString(0,0,"DS SLAVE TAG:");
    }
               
    /* Set expected response's delay and timeout. See NOTE 4 and 5 below.
   * As this example only handles one incoming frame with always the same delay and timeout, those values can be set here once for all. */
    dwt_setrxaftertxdelay(POLL_TX_TO_RESP_RX_DLY_UUS);
    dwt_setrxtimeout(RESP_RX_TIMEOUT_UUS);
   

    //OLED_ShowString(0,2,"Distance:"); chnage by johhn

    if(TAG_ID ==MASTER_TAG)
    {
      Semaphore_Enable = 1 ;
      Semaphore_Init();
      Waiting_TAG_Release_Semaphore = 0;
    }
    else
    {
      Semaphore_Enable = 0 ;
    }
    //Master TAG0
                       
                TAG_MEASURE();



}
               
//#endif
}</code></pre>

<p>&nbsp;</p>

<p>在基站模式下,程序中通过OLED在其显示&ldquo;DS TWR ANTHOR&rdquo;信息,通过调用ANTHOR_MEASURE函数来完成具体的功能;</p>

<p>在标签模式下,程序中根据当前TAG_ID的主从通过OLED在其显示&ldquo;DS MASTER TAG&rdquo;或者&ldquo;DS SLAVE TAG&rdquo;信息,通过调用TAG_MEASURE函数来写成具体的功能;</p>

<p>&nbsp;</p>

<p>而TAG_MEASURE和ANTHOR_MEASURE这两个函数在整个工程文件中,只在lib.h中进行了声明,也没有具体的实现&hellip;&hellip;所以这函数具体实现的代码是被封装了STM3210E-EVAL.lib这个库文件里了吗?那么我想把这个UWB功能移植到其它的MCU平台,该怎么来实现或者操作呢?感觉又被卡住了&hellip;&hellip;<img height="51" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/sweat.gif" width="50" /></p>

<p>&nbsp;</p>
</div><script>                                        var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;"   style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
                                       
                                        if(parseInt(discuz_uid)==0){
                                                                                                (function($){
                                                        var postHeight = getTextHeight(400);
                                                        $(".showpostmsg").html($(".showpostmsg").html());
                                                        $(".showpostmsg").after(loginstr);
                                                        $(".showpostmsg").css({height:postHeight,overflow:"hidden"});
                                                })(jQuery);
                                        }                </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script>

Jacktang 发表于 2022-2-28 08:33

<p>功能移植到其它的MCU平台需要考虑兼容性,因为不同平台包含与编译器兼容的类型说明与定义</p>

xld0932 发表于 2022-2-28 08:58

Jacktang 发表于 2022-2-28 08:33
功能移植到其它的MCU平台需要考虑兼容性,因为不同平台包含与编译器兼容的类型说明与定义

<p>说得是没错,但对于NodeMCU-BU01开发板来说,平台就是STM32呀,平台都确定了,干嘛还封装一个LIB呢,直接说这套代码仅是在STM32F103平台上适用就可以了呀&hellip;&hellip;封装代码就有点&hellip;&hellip;我本来是想用安信可的UWB应用到自己项目上,对比一下的,现在倒好,代码都移植不了&hellip;&hellip;之前用的研创物联的UWB,和安信可的内核一样都是DW1000,也没见<img height="50" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/wanwan57.gif" width="49" />人家封装源代码哈&hellip;&hellip;</p>

Ma_11 发表于 2022-7-20 10:31

<p>确实,搞那么多,我想自己画板子买bu01弄进去,看到这个代码真的劝退</p>
页: [1]
查看完整版本: 【安信可UWB室内定位模组NodeMCU-BU01】05.移植准备:测距功能代码分析