LuMini Ring Hookup Guide

Pages
Contributors: Englandsaurus
Favorited Favorite 1

Light It Up

SparkFun has also written some example code specific to the rings to get you started. These example sketches can be found in the LuMini 3-Inch GitHub Repo under Firmware. To download, click on the button below.

Make sure to adjust the pin definition depending on how you connected the LEDs to your microcontroller.

Example 1 --- Ring Test

Glen Larson invented the Larson Scanner as an LED effect for the TV series Knight Rider. In this example, we'll reproduce it, only we'll add in some color for good measure. The Larson Scanner is a great and colorful way to test all of your LEDs on your ring. We'll first begin by creating an object for our ring. Simply uncomment the proper number of LED's for your ring of choice. For these examples, we'll be using the 3 inch ring.

language:c
#include <FastLED.h>

// How many leds in your strip? Uncomment the corresponding line
#define NUM_LEDS 60 //3 Inch
//#define NUM_LEDS 40 //2 Inch
//#define NUM_LEDS 20 //1 Inch

// The LuMini rings need two data pins connected
#define DATA_PIN 16
#define CLOCK_PIN 17

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

We'll then initialize a ring using the .addLeds function below. Notice the BGR in this statement, this is the color order, sometimes, the manufacturer will change the order in which the received data is put into the PWM registers, so you'll have to change your color order to match. The particular chipset we're using is BGR, but this could change in the future. We'll also set the global brightness to 32.

language:c
void setup() {
  LEDS.addLeds<APA102, DATA_PIN, CLOCK_PIN, BGR>(ring, NUM_LEDS);
  LEDS.setBrightness(32);
}

Our animation is then contained in the fadeAll() function, which loops through every LED and fades it to a percentage of it's previous brightness. Our loop() then set's an LED to a hue, increments the hue, and then shows our LEDs. After this, we use the fadeAll() function to fade our LED's down so they don't all end up being on.

lanuage:c
void fadeAll() {
  for (int i = 0; i < NUM_LEDS; i++)
  {
    ring[i].nscale8(250);
  }
}

void loop() {
  static uint8_t hue = 0;
  //Rotate around the circle
  for (int i = 0; i < NUM_LEDS; i++) {
    // Set the i'th led to the current hue
    ring[i] = CHSV(hue++, 150, 255); //display the current hue, then increment it.
    // Show the leds
    FastLED.show();
    fadeAll();//Reduce the brightness of all LEDs so our LED's fade off with every frame.
    // Wait a little bit before we loop around and do it again
    delay(5);
  }
}

Your code should look like the GIF below if you've hooked everything up right. If thing's aren't quite what you'd expect, double check your wiring.

Example 1 Output

Example 1 Output

Example 2 --- RGB Color Picker

In this second example, we'll use the serial terminal to control the color displayed by the ring. We initialize everything in the same way. We then listen for data on the serial port, parsing integers that are sent from the serial terminal on your desktop and putting them in the corresponding color (red, green or blue). The code to accomplish this is shown below.

language:c
#include <FastLED.h>

// How many leds in your strip?
#define NUM_LEDS 60 //3 Inch
//#define NUM_LEDS 40 //2 Inch
//#define NUM_LEDS 20 //1 Inch

//Data and Clock Pins
#define DATA_PIN 16
#define CLOCK_PIN 17

CRGB color;
char colorToEdit;

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

void setup() {
  Serial.begin(115200);
  Serial.println("resetting");
  LEDS.addLeds<APA102, DATA_PIN, CLOCK_PIN, BGR>(ring, NUM_LEDS);
  LEDS.setBrightness(32);

  //Display our current color data
  Serial.print("Red Value: ");
  Serial.println(color[0]);
  Serial.print("Green Value: ");
  Serial.println(color[1]);
  Serial.print("Blue Value: ");
  Serial.println(color[2]);
  Serial.println();      
}

void loop()
{
  if (Serial.available()) //Check to see if we have new Serial data.
  {
    colorToEdit = Serial.read();
    switch (colorToEdit)
    {
      case 'R':
      case 'r':
        color[0] = Serial.parseInt();
        break;
      case 'G':
      case 'g':
        color[1] = Serial.parseInt();
        break;
      case 'B':
      case 'b':
        color[2] = Serial.parseInt();
        break;
    }
    //Display our current color data
    Serial.print("Red Value: ");
    Serial.println(color[0]);
    Serial.print("Green Value: ");
    Serial.println(color[1]);
    Serial.print("Blue Value: ");
    Serial.println(color[2]);
    Serial.println();
    for (int i = 0; i < NUM_LEDS; i++)
    {
      ring[i] = color;
      FastLED.show();
      delay(10);
    }
  }
}

Go ahead and upload this code, then open your serial monitor to 115200. It should be displaying the current color value (R:0, G:0, B:0), if not.

RGB Color Picker

Changing the value of a color is done be sending the letter of the color (R, G, or B) followed by a value between 0 and 255. For instance, turning red to half brightness would be achieved by sending R127. Play around and look for your favorite color.

Example 3 --- HSV Color Picker

The third example is very similar to the first in that we are picking colors using the serial terminal. However, in this example, we are working with an HSV color space. This sketch works mostly the same as the previous one, only we send h, s or v instead of r, g or b. Upload the below code and play around in search of your favorite color.

language:c
#include <FastLED.h>

// How many leds in your strip?
#define NUM_LEDS 60 //3 Inch
//#define NUM_LEDS 40 //2 Inch
//#define NUM_LEDS 20 //1 Inch

//Data and Clock Pins
#define DATA_PIN 16
#define CLOCK_PIN 17

CHSV color = CHSV(0, 255, 255);
char colorToEdit;

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

void setup() {
  Serial.begin(115200);
  Serial.println("resetting");
  LEDS.addLeds<APA102, DATA_PIN, CLOCK_PIN, BGR>(ring, NUM_LEDS);
  LEDS.setBrightness(32);

  //Display our current color data
  Serial.print("Hue: ");
  Serial.println(color.hue);
  Serial.print("Saturation: ");
  Serial.println(color.sat);
  Serial.print("Value: ");
  Serial.println(color.val);
  Serial.println();
}

void loop()
{
  if (Serial.available()) //Check to see if we have new Serial data.
  {
    colorToEdit = Serial.read();
    switch (colorToEdit)
    {
      case 'H':
      case 'h':
        color.hue = Serial.parseInt();
        break;
      case 'S':
      case 's':
        color.sat = Serial.parseInt();
        break;
      case 'V':
      case 'v':
        color.val = Serial.parseInt();
        break;
    }
    //Display our current color data
    Serial.print("Hue: ");
    Serial.println(color.hue);
    Serial.print("Saturation: ");
    Serial.println(color.sat);
    Serial.print("Value: ");
    Serial.println(color.val);
    Serial.println();

    for (int i = 0; i < NUM_LEDS; i++)
    {
      ring[i] = color;
      FastLED.show();
      delay(10);
    }
  }
}

Once again, play around to try and find your favorite color. I find that HSV is a much more intuitive space to work in than RGB space.

Example 4 --- Angle Assignment

In this example, we'll assign the LED's in our circle to the angles of the unit circle so we won't have to think about which LED corresponds to which angle. We're also going to use 0-255 instead of 0-360, as this makes more sense from a computer standpoint. For example, the LED's at 90° would be accessed by calling ringMap[64]. This is accomplished using the populateMap() function, which populates the uint8_t ringMap[255] object. The populateMap() function is shown below and gets called in our setup() loop.

language:c
#include <FastLED.h>

// How many leds in your strip?
#define NUM_LEDS 60 //3 Inch
//#define NUM_LEDS 40 //2 Inch
//#define NUM_LEDS 20 //1 Inch

//Data and Clock Pins
#define DATA_PIN 16
#define CLOCK_PIN 17

// Define the array of leds
CRGB ring[NUM_LEDS];
uint8_t ringMap[255];
uint8_t rotation = 0;

float angleRangePerLED = 256.0 / NUM_LEDS; //A single LED will take up a space this many degrees wide.

void populateMap () //we map LED's to a 360 degree circle where 360 == 255
{
  for (int ledNum = 0; ledNum < NUM_LEDS; ledNum++) //Loops through each LED and assigns it to it's range of angles
  {
    for (int j = round(ledNum * angleRangePerLED); j < round((ledNum + 1) * angleRangePerLED); j++)
    {
      ringMap[j] = ledNum;
    }
  }
}

void fadeAll(uint8_t scale = 250)
{
  for (int i = 0; i < NUM_LEDS; i++)
  {
    ring[i].nscale8(scale);
  }
}

void setup()
{
  Serial.begin(115200);
  FastLED.addLeds<APA102, DATA_PIN, CLOCK_PIN, BGR>(ring, NUM_LEDS);
  FastLED.setBrightness(32);
  populateMap();
}

In our loop, we'll map each angle of the circle to a hue, then we'll light up 3 pixels, each separated by 120° We do this by lighting an LED at a starting angle 0, then add 120° which corresponds to 85.333 ((120/360)*255 = 85.333) and light the LED at this angle. We repeat the same process to light the final LED. Each angle is matched to a hue, so we should see the same colors in each position.

language:c
void loop()
{
  for (int i = 0; i < 3; i++)
  {
    uint8_t angle = round(i * 85.3333) + rotation;
    ring[ringMap[angle]] = CHSV(angle, 127, 255);
  }
  FastLED.show();
  rotation++;
  fadeAll(248);
  delay(5);
}

Notice how ringMap[angle] is called within ring, as it will return the LED number at that angle. Uploading this code should look similar to the below GIF

Example 4 Output

Example 4 Output

Example 5 --- Using Gradients

In this final example, we'll leverage FastLED's palette object (CRGBPalette16) to create and visualize a color palette on our ring. We have much the same initialization as our previous examples, only this time we also initialize a CRGBPalette16 object which will be full of colors along with a TBlendType which will tell us whether or not to blend the colors together or not. This can be either LINEARBLEND or NOBLEND. To populate this gradient, we use examples 2 and 3 to find the colors we want to put into our gradient. The gradient included is a bunch of colors created in HSV space, but you can easily change to RGB space if you prefer. You can also use any of the preset palettes by uncommenting the line that sets it equal to currentPalette.

language:c
TBlendType    currentBlending = LINEARBLEND;
CRGBPalette16 currentPalette = {
  CHSV(5, 190, 255),
  CHSV(0, 190, 255),
  CHSV(245, 255, 255),
  CHSV(235, 235, 255),
  CHSV(225, 235, 255),
  CHSV(225, 150, 255),
  CHSV(16, 150, 255),
  CHSV(16, 200, 255),
  CHSV(16, 225, 255),
  CHSV(0, 255, 255),
  CHSV(72, 200, 255),
  CHSV(115, 225, 255),
  CHSV(40, 255, 255),
  CHSV(35, 255, 255),
  CHSV(10, 235, 255),
  CHSV(5, 235, 255)
};

//currentPalette = RainbowColors_p;
//currentPalette = RainbowStripeColors_p;
//currentPalette = OceanColors_p;
//currentPalette = CloudColors_p;
//currentPalette = LavaColors_p;
//currentPalette = ForestColors_;
//currentPalette = PartyColors_p;

We then use the ColorFromPalette function to put the colors from our gradient onto our LED ring. Notice how we use the angle functions once again to map each part of the gradient to an angle.

language:c
void loop() {
  for (uint8_t i = 0; i < 255; i++)
  {
    uint8_t gradientIndex = i + rotation;
    ring[ringMap[i]] = ColorFromPalette(currentPalette, gradientIndex, brightness, currentBlending);
  }
  FastLED.show();
  rotation++;
  delay(20);
}

Play around with the colors in your palette until you're satisfied. If all is hooked up correctly your ring should look something like the below GIF.

Example 5 Output

Example 5 Output

Additional Examples

There are quite a few additional examples contained in the FastLED library. While they aren't made specifically for the rings, they can still show you some useful features in the FastLED library, and may give you some ideas for some animations of your own.

If the FastLED library is installed, they can be found from the Arduino IDE menu by opening up File -> Examples -> Examples From Custom Libraries -> FastLED .