NRF52840 BLE LED/Button Pairing

Hello. 

I am modifying the nRF52840DK NRF desktop firmware for a custom mouse application. Using the standard firmware, LED2 is used as the status LED for connectivity. What is the best way to reconfigure the status LED (LED3 or LED4)? I can't find any setting in the nRF Kconfig GUI. Also, is there any way to reconfigure other buttons as the peer control? 

Thank you.

  • Hi,

    I believe you have to do it in the .dts file for your project. The board or your project would have an LED2 section as "gpio-led" in the board's DTS file. You can still name it LED2 but change the pin assignment and re-build. Or you can add a new LED3/4 in your DTS file following the same conventions as LED2, configure LED3/4 instead of LED2 in your source, and rebuild.

    Example:

    board_device_tree.dts

    / { 
    	leds {
    	compatible = "gpio-leds";
    
    	led1: led_1{
    		gpios = < &gpio0 24 GPIO_ACTIVE_HIGH>;
    		label = "Green LED";
    	};
    
    	led2: led_2{
    		gpios = < &gpio1 16 GPIO_ACTIVE_HIGH>;
    		label = "Blue LED";
    	};
    }

    led.c:

    /* The devicetree node identifier for the leds. */
    #define LED_GREEN_NODE DT_NODELABEL(led1)
    #define LED_BLUE_NODE DT_NODELABEL(led2)
    
    static const struct gpio_dt_spec led_green = GPIO_DT_SPEC_GET(LED_GREEN_NODE, gpios);
    static const struct gpio_dt_spec led_blue = GPIO_DT_SPEC_GET(LED_BLUE_NODE, gpios);
    
    K_THREAD_DEFINE(green_blinky_tid, LED_STACKSIZE, green_blinky, NULL, NULL, NULL, 2, 0, 0);
    K_THREAD_DEFINE(blue_blinky_tid, LED_STACKSIZE, blue_blinky, NULL, NULL, NULL, 2, 0, 0);
    
    void green_blinky(void)
    {
    	int ret; 
    	
    	gpio_pin_configure_dt(&led_green, GPIO_OUTPUT_ACTIVE);
    
    	if (!gpio_is_ready_dt(&led_green))
    	{
    		return;
    	}
    
    	while (1)
    	{
    		ret = gpio_pin_toggle_dt(&led_green);
    		if (ret < 0) {
    			return;
    		}
    		k_msleep(SLEEP_TIME_MS);
    	}
    	return;
    
    }
    
    void blue_blinky(void)
    {
    	int ret;
    	
    	gpio_pin_configure_dt(&led_blue, GPIO_OUTPUT_ACTIVE);
    
    	if (!gpio_is_ready_dt(&led_blue))
    	{
    		return;
    	}
    
    	while (1)
    	{
    		ret = gpio_pin_toggle_dt(&led_blue);
    		if (ret < 0) {
    			return;
    		}
    		k_msleep(SLEEP_TIME_MS / 2);
    	}
    	return;
    }

    Something along those lines.

    Cheers,

    Alberto

  • Hi tsroga,

    Alberto's suggestions are right for most common usage of LEDs in the nRF Connect SDK. The DTS approach is still the same for the nRF Desktop application.

    As for .c files changes, it's a little different for the nRF Desktop application.

    First, I will try to explain what is going on.
    If you cannot afford to dive into the details, just skip to the conclusion after the horizontal divider line.

    1. nRF Desktop is a full application based on the Common Application Framework. Functionalities are implemented in different modules that communicate with each other by events, via the Application Event Manager.

    2. For LEDs in particular, these modules are involved:
      1. LED state module
      2. LED stream module
      3. LEDs module
      4. HID state module

    3. The mapping of LEDs "roles" to available LEDs defined on the DTS is done in the configuration of the LED state module and HID state module.
      1. In /configuration/common/led_state.h, two roles are defined, System State LED and Peer State LED (the one you referred to as Connectivity State).
      2. In /configuration/common/hid_keyboard_leds.h, five more roles for a keyboard build are defined, Caps Lock, Num Lock, Scroll Lock, etc.

    4. The actuation of the LEDs is handled in the LED stream module.
      All available LEDs in the DTS are fetched automatically, and ID are given in the order they are found.
      Note that here, the ID are given from 0, versus on the nRF52840 DK, where the LED are numbered from 1.

    5. In each board's configurations, the roles are mapped to the LEDs available on the DTS. For example:
      1. In /configuration/nrf52840dk_nrf52840/led_state_def.h, the System State LED is mapped to LED 0, and the Peer State LED is mapped to LED 1
      2. In /configuration/nrf52840dk_nrf52840/hid_keyboard_leds_def_keyboard.h, the Caps Lock LED and Num Lock LED (for keyboard build) are mapped to LED 2 and 3, respectively.
      3. For an example of when the LED is physically unavailable, see /configuration/nrf52kbd_nrf52832/led_state_def.h

    Based on the facts above, there will be a number of approaches to reconfigure the connectivity LED 2 to LED 3. Here are the two simplest ones:

    • Just swap the two LEDs on the board overlay file.
    • Reconfigure the LED ID in led_state_def.h and hid_keyboard_leds_def_keyboard.h.

    I hope the explanation makes sense. The nRF Desktop application was designed with an architecture, and giving a brief summary of an aspect has been quite challenging for me.

    Please don't hesitate to let me know if anything doesn't make sense.

    Hieu

  • Hello Hieu. 

    Thank you for the information you provided. It did help me understand more of what is going on. I should be a little more clear on what I'm trying to do. I created a 52840DK board/configuration based on 52840 gmouse project. While the project flashes onto my board, I do not see a "breathing" led, like I do with the nrf52840dk_nrf52840 sample project. Diving further into the sample project, each LED on the DK are assigned their own PWM timer. On my firmware, pwm0 and pwm1 are used for RGB lighting. I did assign channel 3 of pwm1 to one of the LEDs, but this had no effect. Do I have to configure an event for both the system and peer LEDs? 

  • Hi tsroga,

    Could you please share how you are setting up the new LED with channel 3 of PWM1?

  • Hello Hieu.

    I have figured out how to initialize the LEDs. I just copied the pin and PWM configurations from the sample DTS file and the app overlay. However, I am facing a new problem. My 52840DK board does not want to connect to my 52833DK board which is acting as the dongle. They should connect automatically, but the LED on both boards are "breathing". I tried to play around with the peer control in the .conf file, but I still can't get it to work. I made sure the vendor of the 52840 matches with the 52833. I also made sure the product ID of the 840 matches the ones listed in the ble_discovery_def file. The name of the 52840 also matches the PEER_TYPE_MOUSE peer name in ble_scan_def file. 

Related