/ws2812_pico_sdk

a thin wrapper around ws2812 control for raspberry pi pico SDK in C

Primary LanguageCGNU General Public License v2.0GPL-2.0

Readme

This is a small WS2812 ‘object’ written in plain C. It controls a WS2812 led strip using the programmable IO feature of the RP2040.

Quickstart

  • Copy ws2812.c, ws2812.h and ws2812.pio into your project directory
  • Add pico_generate_pio_header(YourProject ${CMAKE_CURRENT_LIST_DIR}/WS2812.pio) to your CMakeLists.txt (Replacing YourProject with the name of your project, duh :D)
  • Add the ws2812.c to your add_executable instruction of your CMakeLists.txt
  • Make sure hardware_pio is included within the target_link_libraries instruction of your CMakeLists.txt

In your sources:

  • get a ws2812 ‘Object’ using ws2812_initialize() Depending on what LED strip you have (with a value for white or without) you need to pass is_rgbw as true or false.
  • Set LED colors using ws2812_set_LED() and ws2812_fill() These functions take a uint32_t to set the color. Use the provided functions (e.g. ws2812_urgb_grbu32()) to pack RGB (0-255) values into such an uint32_t. Most WS2812 strips take GRB values, so use ws2812_urgb_grbu32(), for strips that use RGB use ws2812_urgb_rgbu32() and for RGBW use ws2812_urgb_wrgbu32(). If you have a very special LED strip that takes a completely different format, you can also build your own uint32_t and pass that into ws2812_set_LED().

Usage

#include "pico/stdlib.h"
#include "bsp/board.h"
#include "WS2812.pio.h"
#include "ws2812.h"

#define LED_PIN 2
#define NUM_LEDS 3
#define STATE_MACHINE 0
#define IS_RGBW false

struct WS2812* led_strip;

int main(void) {
  board_init();
  stdio_init_all();

  // Create a WS2812 object
  led_strip = ws2812_initialize(pio0, STATE_MACHINE, LED_PIN, NUM_LEDS, IS_RGBW);

  // fill the whole LED strip with white
  ws2812_fill(led_strip, ws2812_urgb_grbu32(255, 255, 255));
  // write the data do the strip
  ws2812_show(led_strip);

  while (1) {
    // set first LED to red
    ws2812_set_led(led_strip, 0, ws2812_urgb_grbu32(255, 0, 0));
    // set second LED to green
    ws2812_set_led(led_strip, 1, ws2812_urgb_grbu32(0, 255, 0));
    // set third LED to blue
    ws2812_set_led(led_strip, 2, ws2812_urgb_grbu32(0, 0, 255));
    // write the data do the strip
    ws2812_show(led_strip);
    sleep_ms(1000);
  }
}

Building the example

This assumes you have a working arm-none-eabi-gcc for the Pico

Clone this repo:

git clone https://github.com/Schievel1/ws2812_pico_sdk.git
cd ws2812_pico_sdk

Update the pico-sdk submodule:

git submodule update --init --recursive

Build:

mkdir build
cd build
cmake ..
make ws2812-example

Alternatives

ForsakenNGS has two WS2812 libraries is C++ that are more sophisticated. The newer one is huge, can be adapted to other LED types and contains tons of functions like filling a strip with a gradient or rainbow colors. (https://github.com/ForsakenNGS/PicoLED)

The older one is more specific to the WS2812 and contains only the basic functions like this one I wrote (https://github.com/ForsakenNGS/Pico_WS2812)

However, I tend to refrain having C++ in my projects, because once you pull one C++ thing in it tends to spread.

For a more baremetal approach you can also use the bare functions provided by the Pico-SDK: https://github.com/raspberrypi/pico-examples/tree/master/pio/ws2812