Basic Setup - AlbertGBarber/PixelSpork GitHub Wiki

Overview:

Note that this page is intended to be paired with the library's "Basic_Setup" code example, and provides a more detailed explanation of the example.

This example displays the bare minimum amount of code needed to use Pixel Spork. It assumes that you already have an LED strip and micro-controller setup, connected, and ready to go. For help with connecting LEDs, see here.

For the code we need:

  1. The basic FastLED setup needed for controlling the LEDs.
  2. A Segment Set.
  3. An effect to draw.
Example Output for a Strip of 60 LEDs
Streamer effect on 2D disk

Note: when compiling using the Arduino IDE, if you have your "compiler warnings" (found in "preferences") set to "More" or "All" you may get a few warnings when you first compile a sketch. These should mainly concern the possible non-usage of various static variables, and are expected. They will not prevent the code from running!

1. A Basic FastLED Setup:

Pixel Spork uses the FastLED library to handle writing color data to the LEDs and various other behind-the-scenes interfacing tasks. So, to use Pixel Spork, we have to configure our LEDs using FastLED. Note that while an understanding of FastLED is useful, it is not required to use Pixel Spork; the basic FastLED setup shown below should be sufficient for almost all Pixel Spork programs.

We setup FastLED using the code below:

//How many LEDs in your strip?
#define NUM_LEDS 60

//Define the data pin for your LEDs
#define DATA_PIN 4

//Define the array of leds
CRGB leds[NUM_LEDS];

//--------Some other, unrelated code-----------------

//FastLED setup in the Arduino Setup function
void setup() {

    //Setup your LED strip using FastLED
    //This setup assumes you're using WS2812 LEDs
    //For other LED type setups, see the FastLED Blink example
    FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);  // GRB ordering is assumed

    //Set a strip brightness
    FastLED.setBrightness(40);
}

The first few lines are fairly simple, defining how many LEDs there are in your strip (NUM_LEDs), and what micro-controller pin they are connected to (DATA_PIN) (Note that some types of LEDs may require a second data pin, see FastLED's Blink example for more). Adjust the pin and LED count to match your strip.

The next line, CRGB leds[NUM_LEDS] needs some explanation. When the code writes colors out to your strip, it needs to re-send color data to all the LEDs, even if you only changed the color for a single one. In order to write the data out, FastLED needs to store the color data somewhere. That somewhere is a big array of CRGB color objects, with one entry for each LED's color. You can name the array anything you like, but its length should be the same as the number of LEDs in your strip.

Note that for larger sets of LEDs, Pixel Spork supports FastLED's parallel output implementation, but only the "the one array, many strips" method. You can read more about parallel outputs here.

Next, we move to the Arduino Setup() function where we add our LEDs to FastLED using FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS). This line tells FastLED (and Pixel Spork) that there is a strip of Neopixel (WS2812) LEDs of length 60 (NUM_LEDS) attached to pin 4 (DATA_PIN) of your micro-controller. If you're using a different type of LED, you'll need to adjust this line to match, you can read more about that here.

Finally, we set the strip's brightness using FastLED.setBrightness(40) (max 255).

That's all for the FastLED setup! Now we need a segment set to draw on.

2. A Segment Set:

Segment Sets allow you to virtually arrange your LEDs, grouping sets of LEDs that are in different parts of the strip. This allows you to wire your LEDs in whatever way is most convenient, and then adjust their connections in code using Segment Sets. Segment Sets are a fundamental part of Pixel Spork; every effect requires a Segment Set to draw on. For this example, we'll create a very basic Segment Set that directly matches your physical strip.

You can read more about segment sets here.

The Segment Set Code:

//The code below sets up a segment set that replicates your LED strip as it is connected IRL.
const PROGMEM segmentSecCont mainSec[] = { {0, NUM_LEDS} }; //Create a segment section

SegmentPS mainSegment = { mainSec, SIZE(mainSec), true }; //Create a segment using the section above

//Create a segment set using the segment above
SegmentPS *main_arr[] = { &mainSegment };
SegmentSetPS mainSegments(leds, NUM_LEDS, main_arr, SIZE(main_arr));

Before we go over the code above, lets talk about how Segment Sets are structured.

Segment Sets have three layers:

  1. Segment Sections -- An individual line of LEDs, containing their physical addresses.
  2. Segments -- A group of Segment Sections, forming a continuous line of LEDs.
  3. The Segment Set itself -- A group of Segments.

Segment Sections:

For this example, Segment Sections are continuous lengths of LEDs. For example, I could have a section that is the first 10 LEDs, and another that runs from LED 15 to 20, but not one that only contains LEDs 3, 15, and 20, because they are not a continuous line. Segment Sections require a starting LED and a length.

In the example code above, we want to represent the strip as a single line, the same as it is physically connected. For this, we only need one section, starting at 0, and running NUM_LEDs in length. We create the Section using the line const PROGMEM segmentSecCont mainSec[] = { {0, NUM_LEDS} };. Note that this is actually an array of Segment Sections (of type segmentSecCont and named "mainSec") with a single entry for our single Section. We use an array because we'll later form our Section into a Segment, which requires an array of Sections as an input. Likewise, it makes it easier to add more Sections to our Segment if needed. Finally, note the const PROGMEM. Segment Sections are stored in program memory, which helps free up RAM, but makes the Sections read-only. You cannot modify Segment Sections while the program is running.

Segments:

Segments are groups of Sections that are treated as continuous lines of LEDs. For example, if we placed two Sections, one containing the first 10 LEDs, and another with LEDs 15 to 20, in a Segment, the combined 20 LEDs would be treated as a single line, connecting the 10th LED directly to the 15th. You can use multiple Segments to form 2D shapes, which is covered in the 2D Segment Sets for 2D Effects example. For our single strip example, we only have one Section, so we only need one Segment.

We create the Segment, named "mainSegment", with type SegmentPS, using the line, SegmentPS mainSegment = { mainSec, SIZE(mainSec), true };, which takes our Section array, the array's length, and a direction as arguments. Note that we use SIZE() to automatically fill in the array's length, which is discussed here. The Segment's direction sets the Segment to either start at the first or last LED in the Segment. In our case, we set the direction to "true" because we want our Segment to match our strip, so we want to start at the first LED and move positively along the strip. Note that Segments are stored in RAM as normal, so you can modify a Segment while the program is running.

Segment Sets:

Segment Sets are the final step in organizing LEDs; grouping multiple segments together into a 1 or 2D shape. In our case, we only have a single Segment, so our Segment Set will be 1D (just a line). 2D Segment Sets are covered in the 2D Segment Sets for 2D Effects example.

To create our Segment Set, we need to create an array of Segments, just as we created an array of Sections earlier. We create the array with SegmentPS *main_arr[] = { &mainSegment };. It only has one entry; our "mainSegment" Segment. Note the * and &, these indicate that we are using Segment pointers in the array rather than copying the Segments themselves. While understanding pointers is not strictly required (you should be able to mostly copy-paste lines from these examples), it is helpful in understanding and using Pixel Spork, particularly when working with complex Segment Set and effect setups. I have written a guide to pointers and how you may need to use them in Pixel Spork here.

With the Segment array created, we can create the Segment Set, named "mainSegments", using SegmentSetPS mainSegments(leds, NUM_LEDS, main_arr, SIZE(main_arr));. To create the Segment Set, we input the FastLED CRGB color array from above, the color array's length, our Segment array, and its length (calculated using SIZE()). This creates a neat package that lets effects know where to draw, and what LEDs to draw on.

With our Segment Set created, we can use it in effects. For more on Segments Sets, Segments, and Sections, see Segment Basics, Advanced Segment Usage, the 2D Segment Sets for 2D Effects example, and all the wiki entries under the "Segments" section in the right-hand sidebar.

3. An Effect to Draw:

In Pixel Spork, all effects are class-based, so to use an effect, you create an instance of it using the effect's constructor. You can then modify and update the effect's instance freely while the program is running. Effects are all entirely self-contained; they track their own states, timing, drawing, etc. Once an effect is created, to draw it you simply need to update() it. Note that Pixel Spork uses object-oriented programming (OOP) frequently, so if you are unfamiliar with C++ classes and/or (OOP), it would be helpful to seek out some tutorials.

In this example we'll use the simple, but classic, RainbowCyclePS effect. This effect moves a fixed length rainbow along the strip (repeating if the rainbow is shorted than the strip). Note that this is the 1D version of the effect, for a 2D version, see the 2D Segment Sets for 2D Effects example.

To create the effect, we do:

//<<Placed before the Arduino setup() function>>
RainbowCyclePS rainbowCycle(mainSegments, true, 80);
//Creates an instance of the RainbowCyclePS effect, named "rainbowCycle"
//The effect will be drawn on mainSegments, move in the forward direction, and update at an 80ms rate.

The code above creates an instance of the RainbowCyclePS effect, naming the instance "rainbowCycle". The inputs to create the effect include a Segment Set (mainSegments from above), a direction for the rainbow (true), and an update rate in milliseconds (80), which sets how fast the rainbow moves.

In general, most effects include a Segment Set and update rate as inputs, but beyond that, the options can vary widely. Many effects even have multiple possible constructors with different sets of input options. For example, RainbowCyclePS has an additional constructor that adds the rainbow's length as an input option. To read more about effects, see the Effect Basics wiki page, and all the topics under the "Effects" heading in the right-hand sidebar. In addition, each effect has its own wiki page, which can be found under the "Effect List" drop-down in the sidebar. Each page is a complete guide to the effect, and includes example constructors to help get you up and running quickly. Here is the page for RainbowCyclePS.

With our effect created, to use it, we just need to update it in the Arduino's loop() function:

rainbowCycle.update(); //that's it!

This will draw and display the effect at its update rate.

Outro:

This example gave you an intro to the basic parts of Pixel Spork: Segment Sets and Effects. Hopefully it was enough to get you up and running! Keep in mind that each of the parts have a lot more details, which you can explore on their respective wiki pages.

In our next example, we'll move on to 2D Segment Sets and 2D Effects, which is where Pixel Spork really starts to shine!

⚠️ **GitHub.com Fallback** ⚠️