WS2812 LED not displaying correct colors with I2S driver

Hi,

I'm using WS2812B as a status LED. I don't have any free SPI ports. So my only option is to use I2S. It is displaying just white. I cannot change colors or turn it off. It displays a shade of the color I want with a a lot of white. It's difficult to view the correct color. I have used up all 4 possible serial peripherals so I2S is my only choice. Please let me know if this can be fixed or if there is any other way to control this LED. I have verified the LED with the SPI driver it is working properly. I'm using v2.7.0 toolchain & v2.6.1 SDK.
Here is the overlay and program.

#include <zephyr/dt-bindings/led/led.h>

&pinctrl {
	i2s0_default_alt: i2s0_default_alt {
		group1 {
			psels = <NRF_PSEL(I2S_SCK_M, 0, 20)>,
				<NRF_PSEL(I2S_LRCK_M, 0, 19)>,
				<NRF_PSEL(I2S_SDOUT, 0, 0)>,
				<NRF_PSEL(I2S_SDIN, 0, 21)>;
		};
	};
};

i2s_led: &i2s0 {
	status = "okay";
	pinctrl-0 = <&i2s0_default_alt>;
	pinctrl-names = "default";
};

/ {
	led_strip: ws2812 {
		compatible = "worldsemi,ws2812-i2s";

		i2s-dev = < &i2s_led >;
		chain-length = <1>; /* arbitrary; change at will */
		color-mapping = <LED_COLOR_ID_GREEN
					LED_COLOR_ID_RED
					LED_COLOR_ID_BLUE>;
		out-active-low;
		reset-delay = <120>;
	};

	aliases {
		led-strip = &led_strip;
	};
};

/*
 * Copyright (c) 2017 Linaro Limited
 * Copyright (c) 2018 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <errno.h>
#include <string.h>

#define LOG_LEVEL 4
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(main);

#include <zephyr/kernel.h>
#include <zephyr/drivers/led_strip.h>
#include <zephyr/device.h>
#include <zephyr/drivers/spi.h>
#include <zephyr/sys/util.h>

#define STRIP_NODE DT_ALIAS(led_strip)
#define STRIP_NUM_PIXELS DT_PROP(DT_ALIAS(led_strip), chain_length)

#define DELAY_TIME K_MSEC(500)

#define RGB(_r, _g, _b) {.r = (_r), .g = (_g), .b = (_b)}

static const struct led_rgb colors[] = {
	RGB(0x0f, 0x00, 0x00), /* red */
	RGB(0x00, 0x0f, 0x00), /* green */
	RGB(0x00, 0x00, 0x0f), /* blue */
};

struct led_rgb pixels[STRIP_NUM_PIXELS];

static const struct device *const strip = DEVICE_DT_GET(STRIP_NODE);

int main(void)
{
	size_t cursor = 0, color = 0;
	int rc;

	if (device_is_ready(strip))
	{
		LOG_INF("Found LED strip device %s", strip->name);
	}
	else
	{
		LOG_ERR("LED strip device %s is not ready", strip->name);
		return 0;
	}

	LOG_INF("Displaying pattern on strip");
	while (1)
	{
		memset(&pixels, 0x00, sizeof(pixels));
		memcpy(&pixels[cursor], &colors[color], sizeof(struct led_rgb));
		rc = led_strip_update_rgb(strip, pixels, STRIP_NUM_PIXELS);

		if (rc)
		{
			LOG_ERR("couldn't update strip: %d", rc);
		}

		cursor++;
		if (cursor >= STRIP_NUM_PIXELS)
		{
			cursor = 0;
			color++;
			if (color == ARRAY_SIZE(colors))
			{
				color = 0;
			}
		}

		k_sleep(DELAY_TIME);
	}
	return 0;
}

Thanks.

Parents Reply Children
  • Yes or no. In theory it should be possible since GPIO is for general usage and the driver is writen by C langauge, but it would very chanllege since nRF Connect SDK(Zephy) and nRF5 SDK has so many difference from building concepts to supported chips espcially supported ARM architecture. Seen RF Connect SDK and nRF5 SDK statement. nRF91 chips(ARM cortex-M33) are only supported on nRF Connect SDK(Zephyr), afterwards all recent Nordics chips SDK shift from nRF5 SDK to nRF Connect SDK, so nRF5 SDK is not suggested for new projects. If you have to develop your project based on nRF5 SDK, this is nor easier than writing new drivers for nRF91.

    Best regards,

    Charlie

Related