Controlling more LEDs from a blinky

Hello,

From the blinky example, how would I go about blinking LED0 to LED1 or LED0 to LED2 like a knight rider circuit?

This is what I have done so far that works for LED0 and LED1:

/*
 * Copyright (c) 2016 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr.h>
#include <drivers/gpio.h>

/* 1000 msec = 1 sec */
#define SLEEP_TIME_MS   500

/* The devicetree node identifier for the "led0" alias. */
#define LED0_NODE DT_ALIAS(led0)
#define LED1_NODE DT_ALIAS(led1)
/*
 * A build error on this line means your board is unsupported.
 * See the sample documentation for information on how to fix this.
 */
static const struct gpio_dt_spec led_0 = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
static const struct gpio_dt_spec led_1 = GPIO_DT_SPEC_GET(LED1_NODE, gpios);
void main(void)
{
	int ret0;
	int ret1;
	if (!device_is_ready(led_0.port)) {
		return;
	}
	if (!device_is_ready(led_1.port)) {
		return;
	}
	ret0 = gpio_pin_configure_dt(&led_0, GPIO_OUTPUT_ACTIVE);
	if (ret0 < 0) {
		return;
	}
	ret1 = gpio_pin_configure_dt(&led_1, GPIO_OUTPUT_ACTIVE);
	if (ret1 < 0) {
		return;
	}

	while (1) {
		ret0 = gpio_pin_toggle_dt(&led_0);
		if (ret0 < 0) {
			return;
		}
		k_msleep(SLEEP_TIME_MS);
		ret0 = gpio_pin_toggle_dt(&led_0);
		ret1 = gpio_pin_toggle_dt(&led_1);
		if (ret1 < 0) {
			return;
		}
		k_msleep(SLEEP_TIME_MS);
		ret1 = gpio_pin_toggle_dt(&led_1);
		// ret0 = gpio_pin_toggle_dt(&led_0);
		// if (ret0 < 0) {
		// 	return;
		// }
		// k_msleep(SLEEP_TIME_MS);
		// ret1 = gpio_pin_toggle_dt(&led_1);
		// if (ret1 < 0) {
		// 	return;
		// }
		// k_msleep(SLEEP_TIME_MS);
	}
}

and code below is for LED0 to LED3

/*
 * Copyright (c) 2016 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr.h>
#include <drivers/gpio.h>

/* 1000 msec = 1 sec */
#define SLEEP_TIME_MS   80

/* The devicetree node identifier for the "led0" alias. */
#define LED0_NODE DT_ALIAS(led0)
#define LED1_NODE DT_ALIAS(led1)
#define LED2_NODE DT_ALIAS(led2)
#define LED3_NODE DT_ALIAS(led3)
/*
 * A build error on this line means your board is unsupported.
 * See the sample documentation for information on how to fix this.
 */
static const struct gpio_dt_spec led_0 = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
static const struct gpio_dt_spec led_1 = GPIO_DT_SPEC_GET(LED1_NODE, gpios);
static const struct gpio_dt_spec led_2 = GPIO_DT_SPEC_GET(LED2_NODE, gpios);
static const struct gpio_dt_spec led_3 = GPIO_DT_SPEC_GET(LED3_NODE, gpios);
void main(void)
{
	int ret0;
	int ret1;
	int ret2;
	int ret3;
	if (!device_is_ready(led_0.port)) {
		return;
	}
	if (!device_is_ready(led_1.port)) {
		return;
	}
	if (!device_is_ready(led_2.port)) {
		return;
	}
	if (!device_is_ready(led_3.port)) {
		return;
	}
	/* Sets all the LEDs to OFF state */
	ret0 = gpio_pin_configure_dt(&led_0, GPIO_OUTPUT_INACTIVE);
	if (ret0 < 0) {
		return;
	}
	ret1 = gpio_pin_configure_dt(&led_1, GPIO_OUTPUT_INACTIVE);
	if (ret1 < 0) {
		return;
	}
	ret2 = gpio_pin_configure_dt(&led_2, GPIO_OUTPUT_INACTIVE);
	if (ret2 < 0) {
		return;
	}
	ret3 = gpio_pin_configure_dt(&led_3, GPIO_OUTPUT_INACTIVE);
	if (ret3 < 0) {
		return;
	}

	while (1) {
		/* Turns on LED0 */
		ret0 = gpio_pin_toggle_dt(&led_0);
		if (ret0 < 0) {
			return;
		}
		k_msleep(SLEEP_TIME_MS);

		/* Turns off LED0 and turns on LED1*/
		ret0 = gpio_pin_toggle_dt(&led_0);
		ret1 = gpio_pin_toggle_dt(&led_1);
		if (ret1 < 0) {
			return;
		}
		k_msleep(SLEEP_TIME_MS);

		/* Turns off LED1 and turns on LED3*/
		ret1 = gpio_pin_toggle_dt(&led_1);
		ret3 = gpio_pin_toggle_dt(&led_3);
		if (ret3 < 0) {
			return;
		}
		k_msleep(SLEEP_TIME_MS);

		/* Turns off LED3 and turns on LED2*/
		ret3 = gpio_pin_toggle_dt(&led_3);
		ret2 = gpio_pin_toggle_dt(&led_2);
		if (ret2 < 0) {
			return;
		}
		k_msleep(SLEEP_TIME_MS);

		/* Turns off LED2*/
		ret2 = gpio_pin_toggle_dt(&led_2);

		// ret0 = gpio_pin_toggle_dt(&led_0);
		// if (ret0 < 0) {
		// 	return;
		// }
		// k_msleep(SLEEP_TIME_MS);
		// ret1 = gpio_pin_toggle_dt(&led_1);
		// if (ret1 < 0) {
		// 	return;
		// }
		// k_msleep(SLEEP_TIME_MS);
	}
}

I'd like to also ask any way to improve my code? optimize? that would be appreciated.

board: nrf52840dk

Parents
  • Hello,

    Here is a slightly more condensed version of your code:

    /* 1000 msec = 1 sec */
    #define SLEEP_TIME_MS 80
    
    /* The devicetree node identifier for the "led0" alias. */
    #define LED0_NODE DT_ALIAS(led0)
    #define LED1_NODE DT_ALIAS(led1)
    #define LED2_NODE DT_ALIAS(led2)
    #define LED3_NODE DT_ALIAS(led3)
    
    
    static const struct gpio_dt_spec led[] = {
    	GPIO_DT_SPEC_GET(LED0_NODE, gpios),
    	GPIO_DT_SPEC_GET(LED1_NODE, gpios),
    	GPIO_DT_SPEC_GET(LED2_NODE, gpios),
    	GPIO_DT_SPEC_GET(LED3_NODE, gpios)
    };
    
    void main(void)
    {
    	int ret;
    	int led_num = ARRAY_SIZE(led);
    
    	/* No need to check all pins if they are all on the same Port/device */
    	if (!gpio_is_ready_dt(&led[0])) {
    		printk("GPIO port is not ready.\n");
    		return;
    	}
    
    	/* Initialize LED pins as outputs */
    	for (int i=0; i < led_num; i++) {
    		ret = gpio_pin_configure_dt(&led[i], GPIO_OUTPUT_INACTIVE);
    		if (ret < 0) {
    			printk("gpio_pin_configure_dt() failed for pin %d(err %d)\n", led[i].pin, ret);
    		};
    	}
    
    	while(1) {
    		for (int i = 0; i < led_num; i++) {
    			(void)gpio_pin_set_dt(&led[i], 1);
    			k_msleep(SLEEP_TIME_MS);
    			(void)gpio_pin_set_dt(&led[i], 0);
    		}
    
    		for (int k = led_num - 2; k > 0; k--) {
    			(void)gpio_pin_set_dt(&led[k], 1);
    			k_msleep(SLEEP_TIME_MS);
    			(void)gpio_pin_set_dt(&led[k], 0);
    		}
    	}
    }

    Best regards,

    Vidar

  • If I wanted to do a random order of the leds like example a "c" blink patter, do I simply make a new array like below and call it? or is there better way of doing this?

    static const struct gpio_dt_spec cpattern[] = {
    	GPIO_DT_SPEC_GET(LED0_NODE, gpios),
    	GPIO_DT_SPEC_GET(LED1_NODE, gpios),
    	GPIO_DT_SPEC_GET(LED3_NODE, gpios),
    	GPIO_DT_SPEC_GET(LED2_NODE, gpios)
    };

  • I don’t see any reason to create a new array. You can already reference each LED by its array index. That is, led[<led index>], so led[0] points to LED_0, led[1] to LED_1, and so on.

    Led array:

    static const struct gpio_dt_spec led[] = {
      GPIO_DT_SPEC_GET(LED0_NODE, gpios),
      GPIO_DT_SPEC_GET(LED1_NODE, gpios),
      GPIO_DT_SPEC_GET(LED2_NODE, gpios),
      GPIO_DT_SPEC_GET(LED3_NODE, gpios)
    };Code

Reply
  • I don’t see any reason to create a new array. You can already reference each LED by its array index. That is, led[<led index>], so led[0] points to LED_0, led[1] to LED_1, and so on.

    Led array:

    static const struct gpio_dt_spec led[] = {
      GPIO_DT_SPEC_GET(LED0_NODE, gpios),
      GPIO_DT_SPEC_GET(LED1_NODE, gpios),
      GPIO_DT_SPEC_GET(LED2_NODE, gpios),
      GPIO_DT_SPEC_GET(LED3_NODE, gpios)
    };Code

Children
  • Hi Vidar,

    Like this one?

    /*
     * Copyright (c) 2016 Intel Corporation
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr.h>
    #include <drivers/gpio.h>
    
    /* 1000 msec = 1 sec */
    #define SLEEP_TIME_MS   200
    
    /* The devicetree node identifier for the "led0" alias. */
    #define LED0_NODE DT_ALIAS(led0)
    #define LED1_NODE DT_ALIAS(led1)
    #define LED2_NODE DT_ALIAS(led2)
    #define LED3_NODE DT_ALIAS(led3)
    /*
     * A build error on this line means your board is unsupported.
     * See the sample documentation for information on how to fix this.
     */
    
    static const struct gpio_dt_spec led[] = {
    	GPIO_DT_SPEC_GET(LED0_NODE, gpios),
    	GPIO_DT_SPEC_GET(LED1_NODE, gpios),
    	GPIO_DT_SPEC_GET(LED2_NODE, gpios),
    	GPIO_DT_SPEC_GET(LED3_NODE, gpios)
    };
    
    
    void main(void)
    {
    	int ret;
    	int led_num = ARRAY_SIZE(led);
    
    	int ordinal_pattern[] = {0,1,2,3};
    
    
    	if (!device_is_ready(led[0].port)) {
    		printk("GPIO port is not ready.\n");
    		return;
    	}
    	
    	for (int i=0; i < led_num; i++) {
    		ret = gpio_pin_configure_dt(&led[i], GPIO_OUTPUT_INACTIVE);
    		if (ret < 0) {
    			printk("gpio_pin_configure_dt() failed for pin %d(err %d)\n", led[i].pin, ret);
    		};
    	}
    
    	while (1) {
    		blink_pattern(ordinal_pattern, led_num);
    	}
    	
    }
    
    void blink_pattern(int pattern[], int led_total){
        /* Blink pattern in first direction*/
    	for (int i = 0; i < led_total; i++) {
    			(void)gpio_pin_set_dt(&led[pattern[i]], 1);
    			k_msleep(SLEEP_TIME_MS);
    			(void)gpio_pin_set_dt(&led[pattern[i]], 0);
    		}
        /* Blink pattern in reversed direction*/
    	for (int k = led_total - 2; k > 0; k--) {
    			(void)gpio_pin_set_dt(&led[pattern[k]], 1);
    			k_msleep(SLEEP_TIME_MS);
    			(void)gpio_pin_set_dt(&led[pattern[k]], 0);
    		}
    }

Related