This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

ANT+ sd_ant_channel_close reseting

Hi,

We are using nrf52832 for ANT and BLE for which we use SDK_17.0.2 and s332_nrf52_7.0.1

Our objective is to pair and un-pair ANT sensors. So far pairing multiple ANT sensors and snding the data via BLE works fine. But when we do try to un-pair sensors by closing the channel, the device does restarts.

For that we did try to use sd_ant_channel_close() function. We did use it in our event and in main while loop with a dalay as well. We did try with sd_ant_channel_unassign() function after closing the channel as well.

Is there some sequence that we are missing? Below is our channel init code. Thank you.

static void ANT_profile_HRM_setup(uint8_t ant_channel_no, uint32_t ant_device_no)
{
/** @snippet [ANT HRM RX Profile Setup] */
       
    uint32_t err_code = sd_ant_lib_config_set(ANT_LIB_CONFIG_MESG_OUT_INC_DEVICE_ID);
    APP_ERROR_CHECK(err_code);

        ant_channel_config_t channel_config =
    {
        .channel_number     = ant_channel_no,
        .channel_type       = CHANNEL_TYPE_SLAVE,
        .ext_assign         = HRM_EXT_ASSIGN,
        .rf_freq            = HRM_ANTPLUS_RF_FREQ,
        .transmission_type  = CHAN_ID_TRANS_TYPE,
        .device_type        = HRM_DEVICE_TYPE,
        .device_number      = ant_device_no,
        .channel_period     = HRM_MSG_PERIOD_1Hz,
        .network_number     = ANTPLUS_NETWORK_NUM,
    };

    const ant_search_config_t ant_search_config =
    {
        .channel_number        = ant_channel_no,
        .low_priority_timeout  = ANT_LOW_PRIORITY_TIMEOUT_DISABLE,
        .high_priority_timeout = ANT_HIGH_PRIORITY_SEARCH_DISABLE,
        .search_sharing_cycles = ANT_SEARCH_SHARING_CYCLES_DISABLE,
        .search_priority       = ANT_SEARCH_PRIORITY_DEFAULT,
        .waveform              = ANT_WAVEFORM_DEFAULT,
    };


    err_code = ant_hrm_disp_init(&m_ant_hrm, &channel_config, ant_tmp_evt_handler);
    APP_ERROR_CHECK(err_code);

        // Set search timeout
        err_code = ant_search_init(&ant_search_config);
        APP_ERROR_CHECK(err_code);

    err_code = sd_ant_channel_open(ant_channel_no);
    APP_ERROR_CHECK(err_code);


    err_code = ant_state_indicator_channel_opened();
    APP_ERROR_CHECK(err_code);

/** @snippet [ANT HRM RX Profile Setup] */
}

Best regards, Ram

  • Hi Kenneth,

    yes of course. I am attaching(it is in HRM RX example):

    - complete SDK with example

    (nRF5_SDK_17.0.2_d674dde\examples\ant\ant_plus\ant_hrm\hrm_rx\pca10040\s212\ses)

    - ony main.c, ant_hrm.c, ant_hrm.h

    (\examples\ant\ant_plus\ant_hrm\hrm_rx          \components\ant\ant_profiles\ant_hrm)

    /**
     * This software is subject to the ANT+ Shared Source License
     * www.thisisant.com/swlicenses
     * Copyright (c) Garmin Canada Inc. 2012
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or
     * without modification, are permitted provided that the following
     * conditions are met:
     *
     *    1) Redistributions of source code must retain the above
     *       copyright notice, this list of conditions and the following
     *       disclaimer.
     *
     *    2) Redistributions in binary form must reproduce the above
     *       copyright notice, this list of conditions and the following
     *       disclaimer in the documentation and/or other materials
     *       provided with the distribution.
     *
     *    3) Neither the name of Garmin nor the names of its
     *       contributors may be used to endorse or promote products
     *       derived from this software without specific prior
     *       written permission.
     *
     * The following actions are prohibited:
     *
     *    1) Redistribution of source code containing the ANT+ Network
     *       Key. The ANT+ Network Key is available to ANT+ Adopters.
     *       Please refer to http://thisisant.com to become an ANT+
     *       Adopter and access the key. 
     *
     *    2) Reverse engineering, decompilation, and/or disassembly of
     *       software provided in binary form under this license.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
     * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
     * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE HEREBY
     * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, 
     * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
     * SERVICES; DAMAGE TO ANY DEVICE, LOSS OF USE, DATA, OR 
     * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
     * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
     * OF THE POSSIBILITY OF SUCH DAMAGE. SOME STATES DO NOT ALLOW 
     * THE EXCLUSION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THE
     * ABOVE LIMITATIONS MAY NOT APPLY TO YOU.
     *
     */
    /**@file
     * @defgroup ant_hrm_rx_example ANT HRM RX example
     * @{
     * @ingroup nrf_ant_hrm
     *
     * @brief Example of ANT HRM RX profile.
     *
     * Before compiling this example for NRF52, complete the following steps:
     * - Download the S212 SoftDevice from <a href="https://www.thisisant.com/developer/components/nrf52832" target="_blank">thisisant.com</a>.
     * - Extract the downloaded zip file and copy the S212 SoftDevice headers to <tt>\<InstallFolder\>/components/softdevice/s212/headers</tt>.
     * If you are using Keil packs, copy the files into a @c headers folder in your example folder.
     * - Make sure that @ref ANT_LICENSE_KEY in @c nrf_sdm.h is uncommented.
     */
    
    #include <stdio.h>
    #include "nrf.h"
    #include "bsp.h"
    #include "hardfault.h"
    #include "app_error.h"
    #include "app_timer.h"
    #include "nrf_pwr_mgmt.h"
    #include "nrf_sdh.h"
    #include "nrf_sdh_ant.h"
    #include "ant_key_manager.h"
    #include "ant_hrm.h"
    #include "bsp_btn_ant.h"
    #include "ant_state_indicator.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    
    // There are 7 lines added or commented out, in main.c #1-#5, in ant_hrm.c #6 and ant_hrm.h #7 they are all marked with #x 
    
    //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    
    //#include "nrf_delay.h"
    //#include "ant_hrm.h"
    //#include "ant_interface.h"
    uint32_t counter_1 = 0;     //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #1
    char channel_flag_1 = 0;    //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #2
    
    /** @snippet [ANT HRM RX Instance] */
    HRM_DISP_CHANNEL_CONFIG_DEF(m_ant_hrm,
                                HRM_CHANNEL_NUM,
                                CHAN_ID_TRANS_TYPE,
                                CHAN_ID_DEV_NUM,
                                ANTPLUS_NETWORK_NUM,
                                HRM_MSG_PERIOD_4Hz);
    
    static ant_hrm_profile_t m_ant_hrm;
    /** @snippet [ANT HRM RX Instance] */
    
    
    NRF_SDH_ANT_OBSERVER(m_ant_observer, ANT_HRM_ANT_OBSERVER_PRIO,
                         ant_hrm_disp_evt_handler, &m_ant_hrm);
    
    static void ant_hrm_evt_handler(ant_hrm_profile_t * p_profile, ant_hrm_evt_t event)
    {
        nrf_pwr_mgmt_feed();
    
        switch (event)
        {
            case ANT_HRM_PAGE_0_UPDATED:
                /* fall through */
            case ANT_HRM_PAGE_1_UPDATED:
                /* fall through */
            case ANT_HRM_PAGE_2_UPDATED:
                /* fall through */
            case ANT_HRM_PAGE_3_UPDATED:
                /* fall through */
            case ANT_HRM_PAGE_4_UPDATED:
                NRF_LOG_INFO("Page was updated");
                break;
    
            default:
                break;
        }
    }
    
    /**@brief Function for handling events from the BSP module.
     *
     * @param[in]   event   Event generated by BSP.
     */
    void bsp_event_handler(bsp_event_t event)
    {
        switch (event)
        {
            case BSP_EVENT_SLEEP:
                nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF);
                break;
    
            default:
                break;
        }
    }
    
    /**
     * @brief Function for shutdown events.
     *
     * @param[in]   event       Shutdown type.
     */
    static bool shutdown_handler(nrf_pwr_mgmt_evt_t event)
    {
        ret_code_t err_code;
    
        switch (event)
        {
            case NRF_PWR_MGMT_EVT_PREPARE_WAKEUP:
                err_code = bsp_btn_ant_sleep_mode_prepare();
                APP_ERROR_CHECK(err_code);
                break;
    
            default:
                break;
        }
    
        return true;
    }
    
    NRF_PWR_MGMT_HANDLER_REGISTER(shutdown_handler, APP_SHUTDOWN_HANDLER_PRIORITY);
    
    /**@brief Function for the Timer and BSP initialization.
     */
    static void utils_setup(void)
    {
        ret_code_t err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
    
        err_code = bsp_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS,
                            bsp_event_handler);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_pwr_mgmt_init();
        APP_ERROR_CHECK(err_code);
    
        err_code = bsp_btn_ant_init(m_ant_hrm.channel_number, HRM_DISP_CHANNEL_TYPE);
        APP_ERROR_CHECK(err_code);
    
        err_code = ant_state_indicator_init(m_ant_hrm.channel_number, HRM_DISP_CHANNEL_TYPE);
        APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for ANT stack initialization.
     *
     * @details Initializes the SoftDevice and the ANT event interrupt.
     */
    static void softdevice_setup(void)
    {
        ret_code_t err_code = nrf_sdh_enable_request();
        APP_ERROR_CHECK(err_code);
    
        ASSERT(nrf_sdh_is_enabled());
    
        err_code = nrf_sdh_ant_enable();
        APP_ERROR_CHECK(err_code);
    
        err_code = ant_plus_key_set(ANTPLUS_NETWORK_NUM);
        APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for HRM profile initialization.
     *
     * @details Initializes the HRM profile and open ANT channel.
     */
    static void profile_setup(void)
    {
    /** @snippet [ANT HRM RX Profile Setup] */
        ret_code_t err_code =
            ant_hrm_disp_init(&m_ant_hrm, HRM_DISP_CHANNEL_CONFIG(m_ant_hrm), ant_hrm_evt_handler);
        APP_ERROR_CHECK(err_code);
    
        err_code = ant_hrm_disp_open(&m_ant_hrm);
        APP_ERROR_CHECK(err_code);
    
        err_code = ant_state_indicator_channel_opened();
        APP_ERROR_CHECK(err_code);
    /** @snippet [ANT HRM RX Profile Setup] */
    }
    
    /**
     *@brief Function for initializing logging.
     */
    static void log_init(void)
    {
        ret_code_t err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    }
    
    /**@brief Function for application main entry, does not return.
     */
    int main(void)
    {
        log_init();
        utils_setup();
        softdevice_setup();
        profile_setup();
    
        NRF_LOG_INFO("ANT+ Heart Rate RX example started.");
    
        for (;;)
        {
    
            if ( channel_flag_1 == 0)       //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #3
            {
                ant_close_channel();
    //            sd_ant_channel_close(HRM_CHANNEL_NUM);
                channel_flag_1 = 1;
            }
    
            counter_1++;                  //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #4
    
    //        NRF_LOG_FLUSH();            //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #5 (commented out)
    //        nrf_pwr_mgmt_run();
        }
    }
    
    
    /**
     *@}
     **/
    
    /**
     * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA
     *
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     *
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     *
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     *
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     *
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    #include "sdk_config.h"
    #if ANT_HRM_ENABLED
    
    #include "nrf_assert.h"
    #include "app_error.h"
    #include "ant_interface.h"
    #include "app_util.h"
    #include "ant_hrm.h"
    #include "ant_hrm_utils.h"
    #include "app_error.h"
    
    #define NRF_LOG_MODULE_NAME ant_hrm
    #if ANT_HRM_LOG_ENABLED
    #define NRF_LOG_LEVEL       ANT_HRM_LOG_LEVEL
    #define NRF_LOG_INFO_COLOR  ANT_HRM_INFO_COLOR
    #else // ANT_HRM_LOG_ENABLED
    #define NRF_LOG_LEVEL       0
    #endif // ANT_HRM_LOG_ENABLED
    #include "nrf_log.h"
    NRF_LOG_MODULE_REGISTER();
    
    #define BACKGROUND_DATA_INTERVAL 64 /**< The number of main data pages sent between background data page.
                                             Background data page is sent every 65th message. */
    #define TX_TOGGLE_DIVISOR        4  /**< The number of messages between changing state of toggle bit. */
    
    /**@brief HRM message data layout structure. */
    typedef struct
    {
        ant_hrm_page_t page_number         : 7;
        uint8_t        toggle_bit          : 1;
        uint8_t        page_payload[7];
    } ant_hrm_message_layout_t;
    
    /**@brief Function for initializing the ANT HRM profile instance.
     *
     * @param[in]  p_profile        Pointer to the profile instance.
     * @param[in]  p_channel_config Pointer to the ANT channel configuration structure.
     *
     * @retval     NRF_SUCCESS      If initialization was successful. Otherwise, an error code is returned.
     */
    static ret_code_t ant_hrm_init(ant_hrm_profile_t          * p_profile,
                                 ant_channel_config_t const * p_channel_config)
    {
        p_profile->channel_number = p_channel_config->channel_number;
    
        p_profile->page_0 = DEFAULT_ANT_HRM_PAGE0();
        p_profile->page_1 = DEFAULT_ANT_HRM_PAGE1();
        p_profile->page_2 = DEFAULT_ANT_HRM_PAGE2();
        p_profile->page_3 = DEFAULT_ANT_HRM_PAGE3();
        p_profile->page_4 = DEFAULT_ANT_HRM_PAGE4();
    
        NRF_LOG_INFO("ANT HRM channel %u init", p_profile->channel_number);
        return ant_channel_init(p_channel_config);
    }
    
    
    ret_code_t ant_hrm_disp_init(ant_hrm_profile_t          * p_profile,
                               ant_channel_config_t const * p_channel_config,
                               ant_hrm_evt_handler_t        evt_handler)
    {
        ASSERT(p_profile != NULL);
        ASSERT(p_channel_config != NULL);
        ASSERT(evt_handler != NULL);
    
        p_profile->evt_handler = evt_handler;
    
        return ant_hrm_init(p_profile, p_channel_config);
    }
    
    
    ret_code_t ant_hrm_sens_init(ant_hrm_profile_t           * p_profile,
                               ant_channel_config_t const  * p_channel_config,
                               ant_hrm_sens_config_t const * p_sens_config)
    {
        ASSERT(p_profile != NULL);
        ASSERT(p_channel_config != NULL);
        ASSERT(p_sens_config != NULL);
        ASSERT(p_sens_config->p_cb != NULL);
        ASSERT(p_sens_config->evt_handler != NULL);
    
        ASSERT((p_sens_config->main_page_number == ANT_HRM_PAGE_0)
               || (p_sens_config->main_page_number == ANT_HRM_PAGE_4));
    
        p_profile->evt_handler       = p_sens_config->evt_handler;
        p_profile->_cb.p_sens_cb     = p_sens_config->p_cb;
    
        ant_hrm_sens_cb_t * p_hrm_cb = p_profile->_cb.p_sens_cb;
        p_hrm_cb->page_1_present     = p_sens_config->page_1_present;
        p_hrm_cb->main_page_number   = p_sens_config->main_page_number;
        p_hrm_cb->ext_page_number    = p_hrm_cb->page_1_present ? ANT_HRM_PAGE_1 : ANT_HRM_PAGE_2;
        p_hrm_cb->message_counter    = 0;
        p_hrm_cb->toggle_bit         = true;
    
        return ant_hrm_init(p_profile, p_channel_config);
    }
    
    
    /**@brief Function for getting next page number to send.
     *
     * @param[in]  p_profile        Pointer to the profile instance.
     *
     * @return     Next page number.
     */
    static ant_hrm_page_t next_page_number_get(ant_hrm_profile_t * p_profile)
    {
        ant_hrm_sens_cb_t * p_hrm_cb = p_profile->_cb.p_sens_cb;
        ant_hrm_page_t      page_number;
    
        if (p_hrm_cb->message_counter == (BACKGROUND_DATA_INTERVAL))
        {
            page_number = p_hrm_cb->ext_page_number;
    
            p_hrm_cb->message_counter = 0;
    
            p_hrm_cb->ext_page_number++;
    
            if (p_hrm_cb->ext_page_number > ANT_HRM_PAGE_3)
            {
                p_hrm_cb->ext_page_number = p_hrm_cb->page_1_present ? ANT_HRM_PAGE_1 : ANT_HRM_PAGE_2;
            }
        }
        else
        {
            page_number = p_hrm_cb->main_page_number;
        }
    
        if (p_hrm_cb->message_counter % TX_TOGGLE_DIVISOR == 0)
        {
            p_hrm_cb->toggle_bit ^= 1;
        }
    
        p_hrm_cb->message_counter++;
    
        return page_number;
    }
    
    
    /**@brief Function for encoding HRM message.
     *
     * @note Assume to be call each time when Tx window will occur.
     */
    static void sens_message_encode(ant_hrm_profile_t * p_profile, uint8_t * p_message_payload)
    {
        ant_hrm_message_layout_t * p_hrm_message_payload =
            (ant_hrm_message_layout_t *)p_message_payload;
        ant_hrm_sens_cb_t * p_hrm_cb = p_profile->_cb.p_sens_cb;
    
        p_hrm_message_payload->page_number = next_page_number_get(p_profile);
        p_hrm_message_payload->toggle_bit  = p_hrm_cb->toggle_bit;
    
        NRF_LOG_INFO("HRM TX Page number: %u", p_hrm_message_payload->page_number);
    
        ant_hrm_page_0_encode(p_hrm_message_payload->page_payload, &(p_profile->page_0)); // Page 0 is present in each message
    
        switch (p_hrm_message_payload->page_number)
        {
            case ANT_HRM_PAGE_0:
                // No implementation needed
                break;
    
            case ANT_HRM_PAGE_1:
                ant_hrm_page_1_encode(p_hrm_message_payload->page_payload, &(p_profile->page_1));
                break;
    
            case ANT_HRM_PAGE_2:
                ant_hrm_page_2_encode(p_hrm_message_payload->page_payload, &(p_profile->page_2));
                break;
    
            case ANT_HRM_PAGE_3:
                ant_hrm_page_3_encode(p_hrm_message_payload->page_payload, &(p_profile->page_3));
                break;
    
            case ANT_HRM_PAGE_4:
                ant_hrm_page_4_encode(p_hrm_message_payload->page_payload, &(p_profile->page_4));
                break;
    
            default:
                return;
        }
    
        p_profile->evt_handler(p_profile, (ant_hrm_evt_t)p_hrm_message_payload->page_number);
    }
    
    
    /**@brief Function for setting payload for ANT message and sending it.
     *
     * @param[in]  p_profile        Pointer to the profile instance.
     */
    static void ant_message_send(ant_hrm_profile_t * p_profile)
    {
        uint32_t err_code;
        uint8_t  p_message_payload[ANT_STANDARD_DATA_PAYLOAD_SIZE];
    
        sens_message_encode(p_profile, p_message_payload);
        err_code =
            sd_ant_broadcast_message_tx(p_profile->channel_number,
                                        sizeof (p_message_payload),
                                        p_message_payload);
        APP_ERROR_CHECK(err_code);
    }
    
    
    void ant_hrm_sens_evt_handler(ant_evt_t * p_ant_evt, void * p_context)
    {
        ant_hrm_profile_t * p_profile = (ant_hrm_profile_t *)p_context;
        if (p_ant_evt->channel == p_profile->channel_number)
        {
            switch (p_ant_evt->event)
            {
                case EVENT_TX:
                    ant_message_send(p_profile);
                    break;
    
                default:
                    break;
            }
        }
    }
    
    
    ret_code_t ant_hrm_disp_open(ant_hrm_profile_t * p_profile)
    {
        ASSERT(p_profile != NULL);
    
        NRF_LOG_INFO("ANT HRM channel %u open", p_profile->channel_number);
        return sd_ant_channel_open(p_profile->channel_number);
    }
    
    
    ret_code_t ant_hrm_sens_open(ant_hrm_profile_t * p_profile)
    {
        ASSERT(p_profile != NULL);
    
        // Fill tx buffer for the first frame
        ant_message_send(p_profile);
    
        NRF_LOG_INFO("ANT HRM channel %u open", p_profile->channel_number);
        return sd_ant_channel_open(p_profile->channel_number);
    }
    
    
    /**@brief Function for decoding HRM message.
     *
     * @note Assume to be call each time when Rx window will occur.
     */
    static void disp_message_decode(ant_hrm_profile_t * p_profile, uint8_t * p_message_payload)
    {
        const ant_hrm_message_layout_t * p_hrm_message_payload =
            (ant_hrm_message_layout_t *)p_message_payload;
    
        NRF_LOG_INFO("HRM RX Page Number: %u", p_hrm_message_payload->page_number);
    
        ant_hrm_page_0_decode(p_hrm_message_payload->page_payload, &(p_profile->page_0)); // Page 0 is present in each message
    
        switch (p_hrm_message_payload->page_number)
        {
            case ANT_HRM_PAGE_0:
                // No implementation needed
                break;
    
            case ANT_HRM_PAGE_1:
                ant_hrm_page_1_decode(p_hrm_message_payload->page_payload, &(p_profile->page_1));
                break;
    
            case ANT_HRM_PAGE_2:
                ant_hrm_page_2_decode(p_hrm_message_payload->page_payload, &(p_profile->page_2));
                break;
    
            case ANT_HRM_PAGE_3:
                ant_hrm_page_3_decode(p_hrm_message_payload->page_payload, &(p_profile->page_3));
                break;
    
            case ANT_HRM_PAGE_4:
                ant_hrm_page_4_decode(p_hrm_message_payload->page_payload, &(p_profile->page_4));
                break;
    
            default:
                return;
        }
    
        p_profile->evt_handler(p_profile, (ant_hrm_evt_t)p_hrm_message_payload->page_number);
    }
    
    
    void ant_hrm_disp_evt_handler(ant_evt_t * p_ant_evt, void * p_context)
    {
        ant_hrm_profile_t * p_profile = ( ant_hrm_profile_t *)p_context;
        if (p_ant_evt->channel == p_profile->channel_number)
        {
            switch (p_ant_evt->event)
            {
                case EVENT_RX:
                    if (p_ant_evt->message.ANT_MESSAGE_ucMesgID == MESG_BROADCAST_DATA_ID
                     || p_ant_evt->message.ANT_MESSAGE_ucMesgID == MESG_ACKNOWLEDGED_DATA_ID
                     || p_ant_evt->message.ANT_MESSAGE_ucMesgID == MESG_BURST_DATA_ID)
                    {
                        disp_message_decode(p_profile, p_ant_evt->message.ANT_MESSAGE_aucPayload);
                    }
                    break;
    
                default:
                    break;
            }
        }
    }
    
    void ant_close_channel(void)        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! #6
    {
        sd_ant_channel_close(HRM_CHANNEL_NUM);
    }
    
    
    #endif // ANT_HRM_ENABLED
    
    ant_hrm.h

  • It seems to run fine here, what do you expect should happen if I run the HRM RX example project with your additional ant_close_channel()?

  • In a debug mode.

    It does stop because of some error. Please have a look at the video, 1. with ant_channel_close() counter stops and in video 2. when comentig out that function it counts normaly.

  • I believe this is because when the channel is closed it will go to system OFF mode, see ant_evt_handler() in ant_state_indicator.c where the switch case EVENT_CHANNEL_CLOSED will call nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF);

    Edit: Please comment out this line if you don't want to go to system OFF.

    Kenneth

Related