NAV Navbar

WICED CYW920819EVB-02 BLE_MESH_Dimmer

The demo app BLE_Mesh_Dimmer shows a simple light dimmer on the CYW920819EVB-02 kit or CYBT-213043 MESH EVAL kit. A dimmer has two buttons to turn the light ON and OFF. This application performs dimming using a single button available on the EVK. On a short push, the level is toggled between 0% and 100%. When a button is kept pushed, the level is changed every 0.5 seconds from 0 to 100 in 8 steps 12.5% each. The button can be released before the level reaches 100%; in this case, a consecutive push or long push will continue increasing the level. If the level reaches 100%, the next button control will decrease the level.

Initialization

Code Snippet (dimmer.c):

void mesh_app_init(wiced_bool_t is_provisioned)
{
    button_control_init();
    wiced_bt_mesh_model_level_client_init(MESH_LEVEL_CLIENT_ELEMENT_INDEX,    
    mesh_app_message_handler, is_provisioned);
}

This function initializes the Mesh functionality, which eventually calls the button functionality (button_control_init()). wiced_bt_mesh_model_level_client_init is the function where the device element is initialized. Mesh Models library will execute the application callback function mesh_app_message_handler, or send a reply to the application request.

Button Functionality

Code Snippet (button_control.c):

void button_control_init(void)
{
    wiced_init_timer(&button_timer, &button_timer_callback, 0, 
    WICED_MILLI_SECONDS_TIMER);
    button_previous_value = platform_button[WICED_PLATFORM_BUTTON_1].default_state;
}

void button_hardware_init(void)
{
    /* Configure buttons available on the platform */
    wiced_platform_register_button_callback(WICED_PLATFORM_BUTTON_1, 
    button_interrupt_handler, NULL, GPIO_EN_INT_BOTH_EDGE);
}

A timer (wiced_init_timer) is initialized to track the button functionalities. In the button_hardware_init() function, the button callback is registered and button_interrupt_handler is called.

Button Timer Callback

Code Snippet (button_control.c):

void button_timer_callback(uint32_t arg)
{
    if (!button_level_moving)
    {
        if (button_step == 0)
        {
            button_direction = WICED_TRUE;
            button_step++;
        }
        else if (button_step == NUM_STEPS - 1)
        {
            button_direction = WICED_FALSE;
            button_step--;
        }
        else
        {
            if (button_direction)
            {
                if (button_step != NUM_STEPS - 1)
                    button_step++;
            }
            else
            {
                if (button_step != 0)
                    button_step--;
            }
        }
    }
    else
    {
        if (button_direction)
        {
            if (button_step != NUM_STEPS - 1)
                button_step++;
        }
        else
        {
            if (button_step != 0)
                button_step--;
        }
    }
    if ((button_step != NUM_STEPS - 1) && (button_step != 0))
    {
        button_level_moving = WICED_TRUE;
        wiced_start_timer(&button_timer, 500);
        button_set_level(WICED_FALSE, WICED_FALSE);
    }
    else
    {
        button_level_moving = WICED_FALSE;
        button_set_level(WICED_FALSE, WICED_TRUE);
    }
}

This function controls dimming level sensing. The button step is defined in nine steps using button_level_step[NUM_STEPS]. When the dimming level is stable, the button step is increased or decreased depending on the level increase-decrease direction. When the button step is moving, button_set_level() is called and a level is set.

Code snippet:

void button_set_level(wiced_bool_t is_instant, wiced_bool_t is_final)
{
    wiced_bt_mesh_level_set_level_t set_data;

    set_data.level = button_level_step[button_step];
    set_data.transition_time = is_instant ? 100 : 500;
    set_data.delay = 0;

    WICED_BT_TRACE("Set level:%d transition time:%d final:%d\n", set_data.level, 
    set_data.transition_time, is_final);

    wiced_bt_mesh_model_level_client_set(0, is_final, &set_data);
}

This function tells the peer to set the level. In an Instant transition, the button is pushed and released; otherwise the button is being pushed. The transition time is set to 500 ms, which is the duration between two consecutive commands. i.e., a command to proceed to next level for every 500 ms and with a duration of 500 ms, to make the transition smooth. The final parameter indicates that the transition is complete, and peer sends the acknowledgment.

Button Interrupt Handler Callback

Code Snippet (button_control.c):

    void button_interrupt_handler(void* user_data, uint8_t pin)
{
    uint32_t value = wiced_hal_gpio_get_pin_input_status(pin);
    uint32_t current_time = wiced_bt_mesh_core_get_tick_count();
    uint32_t button_pushed_duration;

    if (value == button_previous_value)
    {
        WICED_BT_TRACE("interrupt_handler: duplicate pin:%d value:%d current_time:%d\n", pin, value, current_time);
        return;
    }
    button_previous_value = value;

    if (value == platform_button[WICED_PLATFORM_BUTTON_1].button_pressed_value)
    {
        button_pushed_time = current_time;

        // if button is not released within 500ms, we will start sending move events
        wiced_start_timer(&button_timer, 500);
        return;
    }
    wiced_stop_timer(&button_timer);

    // button is released
    button_pushed_duration = current_time - button_pushed_time;
    if (button_pushed_duration < 500)
    {
        button_level_moving = WICED_FALSE;

        if (button_step == 0)
            button_step = NUM_STEPS - 1;
        else if (button_step == NUM_STEPS - 1)
            button_step = 0;
        else
            button_step = (button_direction ? NUM_STEPS - 1 : 0);
        button_set_level(WICED_TRUE, WICED_TRUE);
        return;
    }
    else if (button_pushed_duration < 15000)
    {
        // we were moving the level and button is released.mset message with ack
        if ((button_step != NUM_STEPS - 1) && (button_step != 0))
            button_set_level(WICED_FALSE, WICED_TRUE);
        return;
    }
    // More than 15 seconds means factory reset
    mesh_application_factory_reset();
}

The Interrupt Handler handles operations after button press. The irst button pushed time is calculated after starting the timer. When the button is released and if the button push duration is less than 500 ms, button_set_level is called depending on button steps calculated. If the button is pressed for more than 15 seconds, a Mesh factory reset function is called.

Message Handler Callback

Code snippet (dimmer.c):


void mesh_app_message_handler(uint16_t event, wiced_bt_mesh_event_t *p_event, wiced_bt_mesh_level_status_data_t *p_data)
{
    WICED_BT_TRACE("level clt msg:%d\n", event);

    switch (event)
    {
    case WICED_BT_MESH_TX_COMPLETE:
        WICED_BT_TRACE("tx complete status:%d\n", p_event->tx_status);
        break;

    case WICED_BT_MESH_LEVEL_STATUS:
        WICED_BT_TRACE("level present:%d target:%d remaining time:%d\n", p_data-
        >present_level, p_data->target_level, p_data->remaining_time);
        break;

    default:
        WICED_BT_TRACE("unknown\n");
        break;
    }
    wiced_bt_mesh_release_event(p_event);
}

The function mesh_app_message_handler() is called after the Mesh client is initialized to respond to the events WICED_BT_MESH_TX_COMPLETE and WICED_BT_MESH_LEVEL_STATUS. WICED_BT_MESH_TX_COMPLETE is called when the transmission is complete and WICED_BT_MESH_LEVEL_STATUS is called when the level state is changed.