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

ble mesh trasmission

hi guys, I'm looking for understand how to send a simple signal using ble mesh between two nrf52840 boards.

The  available example aren't so usefull in order to have the input signal to trasmitt but I need to have a pin interrupt on a gpio port that start trasmission in tx-board ,so in the rx one riceve only the pin-interrupt.

In which way can I set this using the given examples???

some advices?

Thanks a lot for your answers!!!!

I tried to do something like that..using the example on light switch,but obviusly it didn't work..moreover in no way does the board recognize the interrupt input on port 28!!!

 
  • #include <stdint.h>
    #include <string.h>
    
    /* HAL */
    #include "boards.h"
    #include "simple_hal.h"
    #include "app_timer.h"
    
    /* Core */
    #include "nrf_mesh_config_core.h"
    #include "nrf_mesh_gatt.h"
    #include "nrf_mesh_configure.h"
    #include "nrf_mesh.h"
    #include "mesh_stack.h"
    #include "device_state_manager.h"
    #include "access_config.h"
    
    /* Provisioning and configuration */
    #include "mesh_provisionee.h"
    #include "mesh_app_utils.h"
    
    /* Models */
    #include "generic_onoff_client.h"
    
    /* Logging and RTT */
    #include "log.h"
    #include "rtt_input.h"
    
    /* Example specific includes */
    #include "app_config.h"
    #include "nrf_mesh_config_examples.h"
    #include "light_switch_example_common.h"
    #include "example_common.h"
    #include "ble_softdevice_support.h"
    #include "nrf_drv_gpiote.h"
    #include "nrf_gpio.h"
    
    #define APP_STATE_OFF                (0)
    #define APP_STATE_ON                 (1)
    
    #define APP_UNACK_MSG_REPEAT_COUNT   (2)
    
    static generic_onoff_client_t m_clients[CLIENT_MODEL_INSTANCE_COUNT];
    static bool                   m_device_provisioned;
    
    /* Forward declaration */
    static void app_gen_onoff_client_publish_interval_cb(access_model_handle_t handle, void * p_self);
    static void app_generic_onoff_client_status_cb(const generic_onoff_client_t * p_self,
                                                   const access_message_rx_meta_t * p_meta,
                                                   const generic_onoff_status_params_t * p_in);
    static void app_gen_onoff_client_transaction_status_cb(access_model_handle_t model_handle,
                                                           void * p_args,
                                                           access_reliable_status_t status);
    
    const generic_onoff_client_callbacks_t client_cbs =
    {
        .onoff_status_cb = app_generic_onoff_client_status_cb,
        .ack_transaction_status_cb = app_gen_onoff_client_transaction_status_cb,
        .periodic_publish_cb = app_gen_onoff_client_publish_interval_cb
    };
    
    static void device_identification_start_cb(uint8_t attention_duration_s)
    {
        hal_led_mask_set(LEDS_MASK, false);
        hal_led_blink_ms(BSP_LED_2_MASK  | BSP_LED_3_MASK,
                         LED_BLINK_ATTENTION_INTERVAL_MS,
                         LED_BLINK_ATTENTION_COUNT(attention_duration_s));
    }
    
    static void provisioning_aborted_cb(void)
    {
        hal_led_blink_stop();
    }
    
    static void provisioning_complete_cb(void)
    {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Successfully provisioned\n");
    
    #if MESH_FEATURE_GATT_ENABLED
        /* Restores the application parameters after switching from the Provisioning
         * service to the Proxy  */
        gap_params_init();
        conn_params_init();
    #endif
    
        dsm_local_unicast_address_t node_address;
        dsm_local_unicast_addresses_get(&node_address);
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Node Address: 0x%04x \n", node_address.address_start);
    
        hal_led_blink_stop();
        hal_led_mask_set(LEDS_MASK, LED_MASK_STATE_OFF);
        hal_led_blink_ms(LEDS_MASK, LED_BLINK_INTERVAL_MS, LED_BLINK_CNT_PROV);
    }
    
    /* This callback is called periodically if model is configured for periodic publishing */
    static void app_gen_onoff_client_publish_interval_cb(access_model_handle_t handle, void * p_self)
    {
         __LOG(LOG_SRC_APP, LOG_LEVEL_WARN, "Publish desired message here.\n");
    }
    
    /* Acknowledged transaction status callback, if acknowledged transfer fails, application can
    * determine suitable course of action (e.g. re-initiate previous transaction) by using this
    * callback.
    */
    static void app_gen_onoff_client_transaction_status_cb(access_model_handle_t model_handle,
                                                           void * p_args,
                                                           access_reliable_status_t status)
    {
        switch(status)
        {
            case ACCESS_RELIABLE_TRANSFER_SUCCESS:
                __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Acknowledged transfer success.\n");
                break;
    
            case ACCESS_RELIABLE_TRANSFER_TIMEOUT:
                hal_led_blink_ms(LEDS_MASK, LED_BLINK_SHORT_INTERVAL_MS, LED_BLINK_CNT_NO_REPLY);
                __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Acknowledged transfer timeout.\n");
                break;
    
            case ACCESS_RELIABLE_TRANSFER_CANCELLED:
                __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Acknowledged transfer cancelled.\n");
                break;
    
            default:
                ERROR_CHECK(NRF_ERROR_INTERNAL);
                break;
        }
    }
    
    /* Generic OnOff client model interface: Process the received status message in this callback */
    static void app_generic_onoff_client_status_cb(const generic_onoff_client_t * p_self,
                                                   const access_message_rx_meta_t * p_meta,
                                                   const generic_onoff_status_params_t * p_in)
    {
        if (p_in->remaining_time_ms > 0)
        {
            __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "OnOff server: 0x%04x, Present OnOff: %d, Target OnOff: %d, Remaining Time: %d ms\n",
                  p_meta->src.value, p_in->present_on_off, p_in->target_on_off, p_in->remaining_time_ms);
        }
        else
        {
            __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "OnOff server: 0x%04x, Present OnOff: %d\n",
                  p_meta->src.value, p_in->present_on_off);
        }
    }
    
    static void node_reset(void)
    {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "----- Node reset  -----\n");
        hal_led_blink_ms(LEDS_MASK, LED_BLINK_INTERVAL_MS, LED_BLINK_CNT_RESET);
        /* This function may return if there are ongoing flash operations. */
        mesh_stack_device_reset();
    }
    
    static void config_server_evt_cb(const config_server_evt_t * p_evt)
    {
        if (p_evt->type == CONFIG_SERVER_EVT_NODE_RESET)
        {
            node_reset();
        }
    }
    
    void in_pin_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
    {
    nrf_gpio_pin_toggle(16);
    
    }
    
    static void gpio_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_drv_gpiote_init();
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_gpiote_out_config_t out_config = GPIOTE_CONFIG_OUT_SIMPLE(true);
    
        err_code = nrf_drv_gpiote_out_init(15, &out_config);
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_gpiote_in_config_t in_config =GPIOTE_CONFIG_IN_SENSE_HITOLO(true);
        in_config.hi_accuracy = true,                     \
        in_config.pull = NRF_GPIO_PIN_NOPULL,                \
        in_config.sense = NRF_GPIOTE_POLARITY_HITOLO,  
    
        err_code = nrf_drv_gpiote_in_init(28, &in_config, in_pin_handler);
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_gpiote_in_event_enable(28, true);
    }
    
    static void button_event_handler(uint32_t button_number)
    {
    
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Button %u pressed\n", button_number);
      
        ret_code_t err_code;
        uint32_t status = NRF_SUCCESS;
        generic_onoff_set_params_t set_params;
        model_transition_t transition_params;
        static uint8_t tid = 0;
    
        /* Button 1: On, Button 2: Off, Client[0]
         * Button 2: On, Button 3: Off, Client[1]
         */
    
        switch(button_number)
        {
           ret_code_t err_code;
            case 0:
            gpio_init();
     
            case 2:
                set_params.on_off = APP_STATE_ON;
                break;
    
            case 1:
            case 3:
                set_params.on_off = APP_STATE_OFF;
                break;
        }
    
        set_params.tid = tid++;
        transition_params.delay_ms = APP_CONFIG_ONOFF_DELAY_MS;
        transition_params.transition_time_ms = APP_CONFIG_ONOFF_TRANSITION_TIME_MS;
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Sending msg: ONOFF SET %d\n", set_params.on_off);
    
        switch (button_number)
        {
            case 0:
    
    
            case 1:
                /* Demonstrate acknowledged transaction, using 1st client model instance */
                /* In this examples, users will not be blocked if the model is busy */
                (void)access_model_reliable_cancel(m_clients[0].model_handle);
                status = generic_onoff_client_set(&m_clients[0], &set_params, &transition_params);
                hal_led_pin_set(BSP_LED_0, set_params.on_off);
                break;
    
            case 2:
            case 3:
                /* Demonstrate un-acknowledged transaction, using 2nd client model instance */
                status = generic_onoff_client_set_unack(&m_clients[1], &set_params,
                                                        &transition_params, APP_UNACK_MSG_REPEAT_COUNT);
                hal_led_pin_set(BSP_LED_1, set_params.on_off);
                break;
        }
    
        switch (status)
        {
            case NRF_SUCCESS:
                break;
    
            case NRF_ERROR_NO_MEM:
            case NRF_ERROR_BUSY:
            case NRF_ERROR_INVALID_STATE:
                __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Client %u cannot send\n", button_number);
                hal_led_blink_ms(LEDS_MASK, LED_BLINK_SHORT_INTERVAL_MS, LED_BLINK_CNT_NO_REPLY);
                break;
    
            case NRF_ERROR_INVALID_PARAM:
                /* Publication not enabled for this client. One (or more) of the following is wrong:
                 * - An application key is missing, or there is no application key bound to the model
                 * - The client does not have its publication state set
                 *
                 * It is the provisioner that adds an application key, binds it to the model and sets
                 * the model's publication state.
                 */
                __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Publication not configured for client %u\n", button_number);
                break;
    
            default:
                ERROR_CHECK(status);
                break;
        }
    }
    
    static void rtt_input_handler(int key)
    {
        if (key >= '0' && key <= '3')
        {
            uint32_t button_number = key - '0';
            button_event_handler(button_number);
        }
    }
    
    static void models_init_cb(void)
    {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Initializing and adding models\n");
    
        for (uint32_t i = 0; i < CLIENT_MODEL_INSTANCE_COUNT; ++i)
        {
            m_clients[i].settings.p_callbacks = &client_cbs;
            m_clients[i].settings.timeout = 0;
            m_clients[i].settings.force_segmented = APP_CONFIG_FORCE_SEGMENTATION;
            m_clients[i].settings.transmic_size = APP_CONFIG_MIC_SIZE;
    
            ERROR_CHECK(generic_onoff_client_init(&m_clients[i], i + 1));
        }
    }
    
    static void mesh_init(void)
    {
        mesh_stack_init_params_t init_params =
        {
            .core.irq_priority       = NRF_MESH_IRQ_PRIORITY_LOWEST,
            .core.lfclksrc           = DEV_BOARD_LF_CLK_CFG,
            .core.p_uuid             = NULL,
            .models.models_init_cb   = models_init_cb,
            .models.config_server_cb = config_server_evt_cb
        };
        ERROR_CHECK(mesh_stack_init(&init_params, &m_device_provisioned));
    }
    
    static void initialize(void)
    {
        __LOG_INIT(LOG_SRC_APP | LOG_SRC_ACCESS | LOG_SRC_BEARER, LOG_LEVEL_INFO, LOG_CALLBACK_DEFAULT);
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "----- BLE Mesh Light Switch Client Demo -----\n");
    
        ERROR_CHECK(app_timer_init());
        hal_leds_init();
    
    #if BUTTON_BOARD
        ERROR_CHECK(hal_buttons_init(button_event_handler));
    #endif
    
        ble_stack_init();
    
    #if MESH_FEATURE_GATT_ENABLED
        gap_params_init();
        conn_params_init();
    #endif
    
        mesh_init();
    }
    
    static void start(void)
    {
    
        rtt_input_enable(rtt_input_handler, RTT_INPUT_POLL_PERIOD_MS);
    
        if (!m_device_provisioned)
        {
            static const uint8_t static_auth_data[NRF_MESH_KEY_SIZE] = STATIC_AUTH_DATA;
            mesh_provisionee_start_params_t prov_start_params =
            {
                .p_static_data    = static_auth_data,
                .prov_complete_cb = provisioning_complete_cb,
                .prov_device_identification_start_cb = device_identification_start_cb,
                .prov_device_identification_stop_cb = NULL,
                .prov_abort_cb = provisioning_aborted_cb,
                .p_device_uri = EX_URI_LS_CLIENT
            };
            ERROR_CHECK(mesh_provisionee_prov_start(&prov_start_params));
        }
    
        mesh_app_uuid_print(nrf_mesh_configure_device_uuid_get());
    
        ERROR_CHECK(mesh_stack_start());
    
        hal_led_mask_set(LEDS_MASK, LED_MASK_STATE_OFF);
        hal_led_blink_ms(LEDS_MASK, LED_BLINK_INTERVAL_MS, LED_BLINK_CNT_START);
    }
    
    int main(void)
    {
        initialize();
        start();
        for (;;)
        {
            (void)sd_app_evt_wait();
        }
    }
    

  • Hi. 

     

    The  available example aren't so usefull in order to have the input signal to trasmitt but I need to have a pin interrupt on a gpio port that start trasmission in tx-board ,so in the rx one riceve only the pin-interrupt.

     Not sure what you want to do exactly. 

    The examples in the nRF5 SDK for Mesh (Light switch examples) will be in RX-mode for the most of the time, as you might already know. This is because the nodes will be listening for packets from the other mesh nodes. 

    The light swtich example wil, on button press, send an on/off command to turn on/off the light on the server. Is this something that you can re-use for your application?

    If not, I suggest that you take a look at the GPIO and GPIOTE chapter in the product specification. 
    We also have a GPIOTE example in our SDK that you can use as guidance. 

    Best regards, 
    Joakim Jakobsen

  • HI Joakim ,thanks a lot for your answer....but, the problem isn't about the gpio...i used it in other wifi protocol and it was fine. The problem concern the sending of a message with ble mesh. Reading the examples about ble mesh i didin't find the line code i have to use in orther to do : ''ok,now send a message to the other node''!!

    For example , In the case  of light switch example i tried and if i press the button 0 the led 0 turn on...but in case 0 in the code there is a white space..so which is the code that make that possible????

    static void button_event_handler(uint32_t button_number)
    {
    
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Button %u pressed\n", button_number);
      
        ret_code_t err_code;
        uint32_t status = NRF_SUCCESS;
        generic_onoff_set_params_t set_params;
        model_transition_t transition_params;
        static uint8_t tid = 0;
    
        /* Button 1: On, Button 2: Off, Client[0]
         * Button 2: On, Button 3: Off, Client[1]
         */
    
        switch(button_number)
        {
           ret_code_t err_code;
            case 0:
     
            case 2:
                set_params.on_off = APP_STATE_ON;
                break;
    
            case 1:
            case 3:
                set_params.on_off = APP_STATE_OFF;
                break;
        }
    
        set_params.tid = tid++;
        transition_params.delay_ms = APP_CONFIG_ONOFF_DELAY_MS;
        transition_params.transition_time_ms = APP_CONFIG_ONOFF_TRANSITION_TIME_MS;
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Sending msg: ONOFF SET %d\n", set_params.on_off);
    
        switch (button_number)
        {
            case 0:
    
    
            case 1:
                /* Demonstrate acknowledged transaction, using 1st client model instance */
                /* In this examples, users will not be blocked if the model is busy */
                (void)access_model_reliable_cancel(m_clients[0].model_handle);
                status = generic_onoff_client_set(&m_clients[0], &set_params, &transition_params);
                hal_led_pin_set(BSP_LED_0, set_params.on_off);
                break;
    
            case 2:
            case 3:
                /* Demonstrate un-acknowledged transaction, using 2nd client model instance */
                status = generic_onoff_client_set_unack(&m_clients[1], &set_params,
                                                        &transition_params, APP_UNACK_MSG_REPEAT_COUNT);
                hal_led_pin_set(BSP_LED_1, set_params.on_off);
                break;
        }
    
        switch (status)
        {
            case NRF_SUCCESS:
                break;
    
            case NRF_ERROR_NO_MEM:
            case NRF_ERROR_BUSY:
            case NRF_ERROR_INVALID_STATE:
                __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Client %u cannot send\n", button_number);
                hal_led_blink_ms(LEDS_MASK, LED_BLINK_SHORT_INTERVAL_MS, LED_BLINK_CNT_NO_REPLY);
                break;
    
            case NRF_ERROR_INVALID_PARAM:
                /* Publication not enabled for this client. One (or more) of the following is wrong:
                 * - An application key is missing, or there is no application key bound to the model
                 * - The client does not have its publication state set
                 *
                 * It is the provisioner that adds an application key, binds it to the model and sets
                 * the model's publication state.
                 */
                __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Publication not configured for client %u\n", button_number);
                break;
    
            default:
                ERROR_CHECK(status);
                break;
        }
    }

  • hi Joakim,are there any other suggestions about my problem? i can't find the way in orther to trasmit a pin interrupt beetwen two boards using ble mesh.

    Thanks . Best Regards!.

Related