Mahmood ul Hassan
Published © GPL3+

How to interface Nordic Thingy:53 with Neopixels (ws2812b)

Nordic thingy:53 has built-in a RGB led but addition of Neopixels in shape of array or strip can make any thingy:53 project eye catching.

BeginnerProtip30 minutes500
How to interface Nordic Thingy:53 with Neopixels (ws2812b)

Things used in this project

Hardware components

Nordic Thingy:53
Nordic Semiconductor Nordic Thingy:53
×1
J-Link EDU Mini
×1
Solderless Breadboard Half Size
Solderless Breadboard Half Size
×1
SparkFun Voltage-Level Translator Breakout - TXB0104
SparkFun Voltage-Level Translator Breakout - TXB0104
×1
LED Stick, NeoPixel Stick
LED Stick, NeoPixel Stick
×1
Jumper wires (generic)
Jumper wires (generic)
×1

Software apps and online services

nRF Connect SDK
Nordic Semiconductor nRF Connect SDK

Story

Read more

Schematics

NeoPixels circuit

Code

thingy53_nrf5340_cpuapp_ns.overlay

C/C++
// To get started, press Ctrl+Space to bring up the completion menu and view the available nodes.

// You can also use the buttons in the sidebar to perform actions on nodes.
// Actions currently available include:

// * Enabling / disabling the node
// * Adding the bus to a bus
// * Removing the node
// * Connecting ADC channels

// For more help, browse the DeviceTree documentation at https://docs.zephyrproject.org/latest/guides/dts/index.html
// You can also visit the nRF DeviceTree extension documentation at https://nrfconnect.github.io/vscode-nrf-connect/devicetree/nrfdevicetree.html
/{
	leds {
		compatible = "gpio-leds";
		neopixel: rgb_led  {
			gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>;
			label = "RGB LED";
		};
	};
};

main.c

C/C++
/*
 * Copyright (c) 2012-2014 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/zephyr.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>

#include <zephyr/drivers/sensor.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/adc.h>

#include <stdio.h>
#include <zephyr/sys/__assert.h>

#include <stdio.h>
#include <stdlib.h>

#include "neopixel.h"

#define HAL_delay(ms_delay) k_sleep(K_MSEC(ms_delay))

#define NEOPIXEL_SIZE	5

void main(void)
{
	int ret;
	if (IS_ENABLED(CONFIG_LOG_BACKEND_RTT)) {
		/* Give RTT log time to be flushed before executing tests */
		k_sleep(K_MSEC(500));
	}

	neopixel_init(5);
	neopixel_set_color(0, 255, 0, 0);
	neopixel_set_color(1, 0, 255, 0);
	neopixel_set_color(2, 0, 0, 255);
	neopixel_set_color(3, 0, 0, 0);
	neopixel_set_color(4, 255, 255, 255);
    HAL_delay(3000);

	neopixel_show();

	while(1){
		neopixel_set_color(0, 255, 0, 0);
		neopixel_set_color(1, 255, 0, 0);
		neopixel_set_color(2, 255, 0, 0);
		neopixel_set_color(3, 255, 0, 0);
		neopixel_set_color(4, 255, 0, 0);
		neopixel_show();
		HAL_delay(1000);

		neopixel_set_color(0, 0, 255, 0);
		neopixel_set_color(1, 0, 255, 0);
		neopixel_set_color(2, 0, 255, 0);
		neopixel_set_color(3, 0, 255, 0);
		neopixel_set_color(4, 0, 255, 0);
		neopixel_show();
		HAL_delay(1000);

		neopixel_set_color(0, 0, 0, 255);
		neopixel_set_color(1, 0, 0, 255);
		neopixel_set_color(2, 0, 0, 255);
		neopixel_set_color(3, 0, 0, 255);
		neopixel_set_color(4, 0, 0, 255);
		neopixel_show();
		HAL_delay(1000);

		neopixel_set_color(0, 255, 255, 255);
		neopixel_set_color(1, 0, 0, 0);
		neopixel_set_color(2, 0, 0, 0);
		neopixel_set_color(3, 0, 0, 0);
		neopixel_set_color(4, 0, 0, 0);
		neopixel_show();
		HAL_delay(200);

		neopixel_set_color(0, 0, 0, 0);
		neopixel_set_color(1, 255, 255, 255);
		neopixel_set_color(2, 0, 0, 0);
		neopixel_set_color(3, 0, 0, 0);
		neopixel_set_color(4, 0, 0, 0);
		neopixel_show();
		HAL_delay(200);

		neopixel_set_color(0, 0, 0, 0);
		neopixel_set_color(1, 0, 0, 0);
		neopixel_set_color(2, 255, 255, 255);
		neopixel_set_color(3, 0, 0, 0);
		neopixel_set_color(4, 0, 0, 0);
		neopixel_show();
		HAL_delay(200);

		neopixel_set_color(0, 0, 0, 0);
		neopixel_set_color(1, 0, 0, 0);
		neopixel_set_color(2, 0, 0, 0);
		neopixel_set_color(3, 255, 255, 255);
		neopixel_set_color(4, 0, 0, 0);
		neopixel_show();
		HAL_delay(200);

		neopixel_set_color(0, 0, 0, 0);
		neopixel_set_color(1, 0, 0, 0);
		neopixel_set_color(2, 0, 0, 0);
		neopixel_set_color(3, 0, 0, 0);
		neopixel_set_color(4, 255, 255, 255);
		neopixel_show();
		HAL_delay(200);

		neopixel_set_color(0, 255, 0, 0);
		neopixel_set_color(1, 0, 255, 0);
		neopixel_set_color(2, 0, 0, 255);
		neopixel_set_color(3, 128, 255, 0);
		neopixel_set_color(4, 255, 0, 255);
		neopixel_show();
		HAL_delay(2000);
	}
}

neopixel.c

C/C++
#include "neopixel.h"

#include <zephyr/zephyr.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>

#include <zephyr/drivers/gpio.h>

#include <stdlib.h>


static uint8_t mPIXEL_DATA_PIN;
static neopixel_strip_t m_strip;

#define NEOPIXEL_NODE DT_NODELABEL(neopixel)
static const struct gpio_dt_spec led_neopixel = GPIO_DT_SPEC_GET(NEOPIXEL_NODE, gpios);

#define HAL_nsDelay(nano_sec) k_sleep(K_NSEC(nano_sec))
#define HAL_usDelay(micro_sec) k_sleep(K_USEC(micro_sec))
#define HAL_msDelay(mili_sec) k_sleep(K_MSEC(mili_sec))



#define NEOPIXEL_SEND_ONE gpio_port_set_bits_raw(led_neopixel.port, (gpio_port_pins_t)BIT(led_neopixel.pin)); \
__ASM ( \
" NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t" \
" NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t" \
" NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t" \
" NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t" \
" NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t" \
" NOP\n\t" \
); \
gpio_port_clear_bits_raw(led_neopixel.port, (gpio_port_pins_t)BIT(led_neopixel.pin)); \
__ASM ( \
" NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t" \
" NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t" \
" NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t" \
); //Logic "1" 52x1 + 50x0 * 15.625ns = 812.5ns H + 781.25ns L

#define NEOPIXEL_SEND_ZERO gpio_port_set_bits_raw(led_neopixel.port, (gpio_port_pins_t)BIT(led_neopixel.pin)); \
__ASM ( \
" NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t" \
" NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t" \
); \
gpio_port_clear_bits_raw(led_neopixel.port, (gpio_port_pins_t)BIT(led_neopixel.pin)); \
__ASM ( \
" NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t" \
" NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t" \
" NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t" \
" NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t" \
" NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t NOP\n\t" \
); //Logic "0" 2x1 + 40x0 * 15.625ns = 30.25+overhead ns H + 781.25ns L

/*
#define NEOPIXEL_SEND_ONE 	gpio_port_set_bits_raw(led_neopixel.port, (gpio_port_pins_t)BIT(led_neopixel.pin)); \
							HAL_nsDelay(400); \
							gpio_port_clear_bits_raw(led_neopixel.port, (gpio_port_pins_t)BIT(led_neopixel.pin)); \
							HAL_nsDelay(850);

#define NEOPIXEL_SEND_ZERO 	gpio_port_set_bits_raw(led_neopixel.port, (gpio_port_pins_t)BIT(led_neopixel.pin)); \
							HAL_nsDelay(800); \
							gpio_port_clear_bits_raw(led_neopixel.port, (gpio_port_pins_t)BIT(led_neopixel.pin)); \
							HAL_nsDelay(450);
*/
#define NEOPIXEL_SET_ONE(void)		gpio_port_set_bits_raw(led_neopixel.port, (gpio_port_pins_t)BIT(led_neopixel.pin))

#define NEOPIXEL_SET_ZERO(void) 	gpio_port_clear_bits_raw(led_neopixel.port, (gpio_port_pins_t)BIT(led_neopixel.pin))


void neopixel_init(uint16_t num_leds)
{
	if (!device_is_ready(led_neopixel.port)) {
		printk("RGB LED port ERROR\n");
	}else{
		printk("RGB LED port OK\n");
	}

	if (!gpio_pin_configure_dt(&led_neopixel, GPIO_OUTPUT_INACTIVE)) {
		printk("RGB LED config LOW: OK\n");
	}else{
		printk("RGB LED config ERROR\n");
	}
	if (!gpio_pin_configure_dt(&led_neopixel, GPIO_OUTPUT_ACTIVE)) {
		printk("RGB LED config HIGH: OK\n");
	}else{
		printk("RGB LED config ERROR\n");
	}

//	gpio_pin_set_dt(&led_neopixel, 1);
/*
	nrf_gpio_cfg_output(mPIXEL_DATA_PIN);
	NRF_GPIO->OUTCLR = (1UL << mPIXEL_DATA_PIN);
	nrf_gpio_pin_clear(mPIXEL_DATA_PIN);
	nrf_gpio_cfg_output(mPIXEL_DATA_PIN);
	NRF_GPIO->OUTCLR = (1UL << mPIXEL_DATA_PIN);
	nrf_gpio_pin_set(mPIXEL_DATA_PIN);
*/

	mPIXEL_DATA_PIN=led_neopixel.pin;
	m_strip.leds = (color_t*) malloc(sizeof(color_t) * num_leds);
	m_strip.pin_num = mPIXEL_DATA_PIN;
	m_strip.num_leds = num_leds;

	for (int i = 0; i < num_leds; i++)
	{	
		m_strip.leds[i].simple.g = 0;
		m_strip.leds[i].simple.r = 0;
		m_strip.leds[i].simple.b = 0;
	}

}

void neopixel_clear()
{
	for (int i = 0; i < m_strip.num_leds; i++)
	{
		m_strip.leds[i].simple.g = 0;
		m_strip.leds[i].simple.r = 0;
		m_strip.leds[i].simple.b = 0;
	}
	neopixel_show();
}

void neopixel_show()
{
	//	const uint8_t PIN =  m_strip.pin_num;

	//	NRF_GPIO->OUTCLR = (1UL << PIN);
	//	nrf_gpio_pin_clear(PIN);
	//	nrf_gpio_pin_set(PIN);

	NEOPIXEL_SET_ZERO();
	HAL_usDelay(50);
	__disable_irq();
	for (int i = 0; i < m_strip.num_leds; i++)
	{
		//Serial.print(" Red: ");Serial.print(m_strip.leds[i].grb[0]);Serial.print(" Green: ");Serial.print(m_strip.leds[i].grb[1]);Serial.print(" Blue: ");Serial.println(m_strip.leds[i].grb[2]);
		for (int j = 0; j < 3; j++)
		{
			if ((m_strip.leds[i].grb[j] & 128) > 0)	{NEOPIXEL_SEND_ONE}
			else	{NEOPIXEL_SEND_ZERO}
			
			if ((m_strip.leds[i].grb[j] & 64) > 0)	{NEOPIXEL_SEND_ONE}
			else	{NEOPIXEL_SEND_ZERO}
			
			if ((m_strip.leds[i].grb[j] & 32) > 0)	{NEOPIXEL_SEND_ONE}
			else	{NEOPIXEL_SEND_ZERO}
			
			if ((m_strip.leds[i].grb[j] & 16) > 0)	{NEOPIXEL_SEND_ONE}
			else	{NEOPIXEL_SEND_ZERO}
			
			if ((m_strip.leds[i].grb[j] & 8) > 0)	{NEOPIXEL_SEND_ONE}
			else	{NEOPIXEL_SEND_ZERO}
			
			if ((m_strip.leds[i].grb[j] & 4) > 0)	{NEOPIXEL_SEND_ONE}
			else	{NEOPIXEL_SEND_ZERO}
			
			if ((m_strip.leds[i].grb[j] & 2) > 0)	{NEOPIXEL_SEND_ONE}
			else	{NEOPIXEL_SEND_ZERO}
			
			if ((m_strip.leds[i].grb[j] & 1) > 0)	{NEOPIXEL_SEND_ONE}
			else	{NEOPIXEL_SEND_ZERO}
		}
	}

	HAL_usDelay(50);
	//	nrf_gpio_pin_set(PIN);
	__enable_irq();
}

void neopixel_set_color(uint16_t index, uint8_t red, uint8_t green, uint8_t blue )
{
	m_strip.leds[index].simple.r = red;
	m_strip.leds[index].simple.g = green;
	m_strip.leds[index].simple.b = blue;
}

void neopixel_set_color_and_show(uint16_t index, uint8_t red, uint8_t green, uint8_t blue)
{
	m_strip.leds[index].simple.r = red;
	m_strip.leds[index].simple.g = green;
	m_strip.leds[index].simple.b = blue;
	neopixel_show();
}

void neopixel_destroy()
{
	free(m_strip.leds);
	m_strip.num_leds = 0;
	m_strip.pin_num = 0;
}

neopixel.h

C/C++
#ifndef NEOPIXEL_H
 #define NEOPIXEL_H


#include <stdbool.h>
#include <stdint.h>

typedef union {
		struct {
			uint8_t g, r, b;
		}simple;
	uint8_t grb[3];
} color_t;
typedef struct {
	uint8_t pin_num;
	uint16_t num_leds;
	color_t *leds;
} neopixel_strip_t;

void neopixel_init(uint16_t num_leds);
void neopixel_clear();
void neopixel_show();
void neopixel_set_color(uint16_t index, uint8_t red, uint8_t green, uint8_t blue );
void neopixel_set_color_and_show(uint16_t index, uint8_t red, uint8_t green, uint8_t blue);
void neopixel_destroy();

#endif

Credits

Mahmood ul Hassan

Mahmood ul Hassan

13 projects • 18 followers
Electronics Engineer with more than 13 years of experience in reverse engineering and test & measurement equipment designing

Comments