Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

BLE app Blinky - How do I assign the initial LED characteristic value as it is not initially defined (default is 0 / LED disabled)

I have modified the BLE app Blinky example so that the LED is enabled (state 1) on power up. However, this is not being reflected on the BLE side because when I connect with the device and read the LED characteristic this still indicates that the LED is disabled (state 0).

I am now trying to work out how to make the correct mods to the code.

I started with main.c but I didn't find anything within this file that sets (or writes) the initial BLE LED characteristic value.

Searching further I see there is a folder "nRF_BLE_Services", which contains the "ble_lbs" library. It looks like this is probably the place to make the changes, as this defines the custom service using the function "ble_lbs_init". I see that this function is then called by the services_init(void) function within main.c.

But then it gets confusing as to what to do as I thought that the parameter to change would be init which is defined as ble_lbs_init_t typedef. However, this only includes a led_write_handler.

So what's the cleanest way to do this. How do I add a "add_char_params" parameter (assume it's p_init_value) for the LED state.

Any advice is greatly appreciated.

Thanks

Parents
  • Hello,

    I have modified the BLE app Blinky example so that the LED is enabled (state 1) on power up.

    What did you do here? Did you just toggle the LED, or did you set the actual state of the characteristic?

    My guess is that you only set the LED, but try to add:

    add_char_params.p_init_value = &my_value;
    add_char_params.init_len     = my_len;

    inside ble_lbs_init().

    Another thing that comes is that when you connect, do you actively read the LED status?

    Best regards,

    Edvin

  • My guess is that you only set the LED, but try to add:

    Yes your guess is correct. I indeed wanted to change the code as you've suggested but as the example was developed by someone else, I wanted to understand how best to implement before I created a mess hacking.

    Another thing that comes is that when you connect, do you actively read the LED status?

    Yes I actively read the status when I need to. The important part I need is determining the initial LED status. If you do first write to the LED characteristic it will always be undefined or 0.

    Anyhow, it is amazing how the brain works. Start by taking time to explain the problem (as I did above), then sleep on it, and the next day the problem becomes so much clearer... and a solution appears.

    So I have just come up with an implementation, which seems clean enough but it does involve modifying 3 files.

    1. I modifed the typedef struct "ble_lbs_init_t" as found in ble_lbs.h

    /** @brief LED Button Service init structure. This structure contains all options and data needed for
     *        initialization of the service.*/
    typedef struct
    {
        ble_lbs_led_write_handler_t led_write_handler; /**< Event handler to be called when the LED Characteristic is written. */
        uint8_t initial_LED_state[1];
    } ble_lbs_init_t;

    2. Then I added an initial LED state within main.c via the services_init function

    /**@brief Function for initializing services that will be used by the application.
     */
    static void services_init(void)
    {
        ret_code_t         err_code;
        ble_lbs_init_t     init     = {0};
        nrf_ble_qwr_init_t qwr_init = {0};
    
        // Initialize Queued Write Module.
        qwr_init.error_handler = nrf_qwr_error_handler;
    
        err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
        APP_ERROR_CHECK(err_code);
    
        // Initialize LBS.
        init.led_write_handler = led_write_handler;
        init.initial_LED_state[0] = 1;        // Set to match the LED state set on board power up
    
        err_code = ble_lbs_init(&m_lbs, &init);
        APP_ERROR_CHECK(err_code);
    }

    3. Finally I added the additional "add_char_params.p_init_value" within ble_lbs_init function found in ble_lbs.c

    uint32_t ble_lbs_init(ble_lbs_t * p_lbs, const ble_lbs_init_t * p_lbs_init)
    {
    
    .....
    
        // Add LED characteristic.
        memset(&add_char_params, 0, sizeof(add_char_params));
    
        add_char_params.uuid             = LBS_UUID_LED_CHAR;
        add_char_params.uuid_type        = p_lbs->uuid_type;
        add_char_params.init_len         = sizeof(uint8_t);
        add_char_params.max_len          = sizeof(uint8_t);
        add_char_params.p_init_value     = p_lbs_init->initial_LED_state;
        add_char_params.char_props.read  = 1;
        add_char_params.char_props.write = 1;
        
    .....
    }

Reply
  • My guess is that you only set the LED, but try to add:

    Yes your guess is correct. I indeed wanted to change the code as you've suggested but as the example was developed by someone else, I wanted to understand how best to implement before I created a mess hacking.

    Another thing that comes is that when you connect, do you actively read the LED status?

    Yes I actively read the status when I need to. The important part I need is determining the initial LED status. If you do first write to the LED characteristic it will always be undefined or 0.

    Anyhow, it is amazing how the brain works. Start by taking time to explain the problem (as I did above), then sleep on it, and the next day the problem becomes so much clearer... and a solution appears.

    So I have just come up with an implementation, which seems clean enough but it does involve modifying 3 files.

    1. I modifed the typedef struct "ble_lbs_init_t" as found in ble_lbs.h

    /** @brief LED Button Service init structure. This structure contains all options and data needed for
     *        initialization of the service.*/
    typedef struct
    {
        ble_lbs_led_write_handler_t led_write_handler; /**< Event handler to be called when the LED Characteristic is written. */
        uint8_t initial_LED_state[1];
    } ble_lbs_init_t;

    2. Then I added an initial LED state within main.c via the services_init function

    /**@brief Function for initializing services that will be used by the application.
     */
    static void services_init(void)
    {
        ret_code_t         err_code;
        ble_lbs_init_t     init     = {0};
        nrf_ble_qwr_init_t qwr_init = {0};
    
        // Initialize Queued Write Module.
        qwr_init.error_handler = nrf_qwr_error_handler;
    
        err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
        APP_ERROR_CHECK(err_code);
    
        // Initialize LBS.
        init.led_write_handler = led_write_handler;
        init.initial_LED_state[0] = 1;        // Set to match the LED state set on board power up
    
        err_code = ble_lbs_init(&m_lbs, &init);
        APP_ERROR_CHECK(err_code);
    }

    3. Finally I added the additional "add_char_params.p_init_value" within ble_lbs_init function found in ble_lbs.c

    uint32_t ble_lbs_init(ble_lbs_t * p_lbs, const ble_lbs_init_t * p_lbs_init)
    {
    
    .....
    
        // Add LED characteristic.
        memset(&add_char_params, 0, sizeof(add_char_params));
    
        add_char_params.uuid             = LBS_UUID_LED_CHAR;
        add_char_params.uuid_type        = p_lbs->uuid_type;
        add_char_params.init_len         = sizeof(uint8_t);
        add_char_params.max_len          = sizeof(uint8_t);
        add_char_params.p_init_value     = p_lbs_init->initial_LED_state;
        add_char_params.char_props.read  = 1;
        add_char_params.char_props.write = 1;
        
    .....
    }

Children
No Data
Related