Code

This step includes a review of pixel mapping, combining both strips into an array, and setting up new functions.

If you are new to Arduino, check out this guide: Adafruit Arduino IDE Setup. Check out this guide for additional information about Arduino IDE Setup for the Gemma M0.

This sketch uses the FastLED library. See FastLED.io for more information, the FastLED github, or visit their community on Reddit. You can learn more about Arduino libraries by reading this guide from Adafruit.

Download the sketch & open it on your Arduino IDE. The complete file is needed to run the sketch.

Connect the Gemma M0 and select it as the board in the Arduino IDE. Choose the connected Gemma from the port dropdown and upload the code. 

The tabs of the sketch (DiscoBandCamp.ino, XYmap.h, utils.h, effects.h, & buttons.h) are all reviewed below. 

DiscoBandCamp.ino

On the first tab, review the pins where the strips are connected: 

Download: file
//  Pins on Adafruit Gemma M0
#define LEFT_PIN    1     // Visual Left (LEDs on the wearers right) connected to D1
#define NUM_LEFT    60    // number of LEDs connected on the Left
#define RIGHT_PIN   0     // Visual Right (LEDs on the wearers left) connected to D0
#define NUM_RIGHT   60    // number of LEDs connected on the Right

The strips are combined into an array so that they act as a single unit: 

Download: file
// Runs one time at the start of the program (power up or reset)
void setup() {

//Add the onboard Strip on the Right and Left to create a single array
  FastLED.addLeds<CHIPSET, LEFT_PIN, COLOR_ORDER>(leds, 0, NUM_LEFT);
  FastLED.addLeds<CHIPSET, RIGHT_PIN, COLOR_ORDER>(leds, NUM_LEFT, NUM_RIGHT);

  // set global brightness value
  FastLED.setBrightness( scale8(currentBrightness, MAXBRIGHTNESS) );

  // configure input buttons
  pinMode(MODEBUTTON, INPUT_PULLUP);
}

XYmap.h

Mark Kriegsman, co-author of the FastLED library, created a great XY mapping code which allows us to program our project as if it were a (24x8) matrix. The Macetech RGB LED shades and Charity Stolarz Bright Top use this approach; both served as a great model for this project.

Start by mapping out pixels in a spreadsheet based on their location. I left a couple spaces between the strip on the left and the one on the right because there is an opening between the sections.

Fill in open holes on the spreadsheet with numbers above 119. I've highlighted the additions. 

Add a comma at the end of every cell.

I used the concatenate function in my spreadsheet to add this quickly. 

The mapping above creates a matrix with a height of 8 pixels and a width of 24 pixels, which can be entered into the sketch:

Download: file
// Parameters for width and height
const uint8_t kMatrixWidth = 24;
const uint8_t kMatrixHeight = 8;
const uint8_t kBorderWidth = 0;

#define NUM_LEDS (kMatrixWidth * kMatrixHeight)
CRGB leds[ NUM_LEDS ];

Next, copy and paste the entire spreadsheet into the table, titled JacketTable:

Download: file
  const uint8_t JacketTable[] = {
10, 9,  8,  7,  6,  5,  4,  3,  2,  1,  0,  145,
153,60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 
120,11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 146,  
154,80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 182, 
121,127,21, 22, 23, 24, 25, 26, 27, 28, 29, 147, 
155,89, 88, 87, 86, 85, 84, 83, 82, 81, 176,183, 
122,128,133,30, 31, 32, 33, 34, 35, 36, 37, 148,  
156,97, 96, 95, 94, 93, 92, 91, 90, 171,177,184, 
123,129,134,135,38, 39, 40, 41, 42, 43, 44, 149,  
157,104,103,102,101,100,99, 98, 167,172,178,185, 
124,130,134,136,139,45, 46, 47, 48, 49, 50, 150,  
158,110,109,108,107,106,105,164,168,173,179,186, 
125,131,134,137,140,142,51, 52, 53, 54, 55, 151,  
159,115,114,113,112,111,162,165,169,174,180,187, 
126,132,134,138,141,143,144,56, 57, 58, 59, 152,  
160,119,118,117,116,161,163,166,170,175,181,188,
  };

buttons.h

This part of the sketch has button setup information. The RGB Shades sketch utilized two buttons but the Gemma only has space for one. The pin the button is connected to is named here:

Download: file
#define NUMBUTTONS 1
#define MODEBUTTON 2  //define the pin the button is connected to

Next, review how the buttons will work. When there's a short button press, a new mode will be selected, and when there's a longer button press, the brightness will increase (or wrap down to a lower brightness).

Download: file
void doButtons() {
  switch (buttonStatus(0)) {

    case BTNRELEASED: // short button press
      cycleMillis = currentMillis;
      if (++currentEffect >= numEffects) currentEffect = 0; // loop to start of effect list
      effectInit = false; // trigger effect initialization when new effect is selected
      break;

    case BTNLONGPRESS: // long button press
      currentBrightness += 51; // increase the brightness (wraps to lowest)
      FastLED.setBrightness(scale8(currentBrightness, MAXBRIGHTNESS));
      break;
  }
}

effects.h

This tab contains a selection of effects from the FastLED library, Macetech's RGB Shades, and Charity Stolarz's Bright Top. This is a review of the easiest modes to personalize.

Create a single color mode with whatever you'd like using any of the six ways to set an RGB LEDs color with FastLED:

Download: file
void SolidRed() //for startup, good for saving battery
{
    fill_solid( leds, NUM_LEDS, CRGB::Red);
}

There are two confetti modes in the sketch. One selects a random built-in FastLED palette (from utils.h) and the other will always use the palette I've created. 

Create your own confetti modes using the built in Palettes (see utils.h) or create your own. Use with the fadeAll function (see .ino) to allow old pixels to decay.

Update the palette below to see what different colors look like. If creating a new confetti function, generate a new palette, new confetti name, and update the ColorFromPalette selection. 

Download: file
//Palette for myConfetti
const TProgmemPalette16 MyColors_p PROGMEM =
{
  CRGB:: Crimson,
  CRGB:: Maroon,
  CRGB:: Red,
  CRGB:: OrangeRed,
 
  CRGB:: Crimson,
  CRGB:: Maroon,
  CRGB:: Red,
  CRGB:: OrangeRed,
 
  CRGB:: Crimson,
  CRGB:: Maroon,
  CRGB:: Red,
  CRGB:: OrangeRed,
 
  CRGB:: Crimson,
  CRGB:: Maroon,
  CRGB:: Red,
  CRGB:: OrangeRed,
};

void myConfetti() {
  // startup tasks
  if (effectInit == false) {
    effectInit = true;
    effectDelay = 15;
  }


//  scatter random colored pixels at several random coordinates
  for (byte i = 0; i < 4; i++) {
    leds[XY(random16(kMatrixWidth), random16(kMatrixHeight))] = ColorFromPalette(MyColors_p, random16(255), 255); //CHSV(random16(255), 255, 255);
    random16_add_entropy(1);
  }

}

Incorporate some other example code

I really like the NoisePlusPalette FastLED example sketch, so I pulled it in here. The main functions are in utils.h:

Download: file
void NoisePlusPalette() {
  
  fillnoise8();
  
  mapNoiseToLEDsUsingPalette();

}

I really like the swirly example sketch used in Charity's Bright Top, so I pulled it in here, too:

Download: file
void swirly()
{
  // startup tasks
  if (effectInit == false) {
    effectInit = true;
    effectDelay = 15;
  }

  // Apply some blurring to whatever's already on the matrix
  // Note that we never actually clear the matrix, we just constantly
  // blur it repeatedly.  Since the blurring is 'lossy', there's
  // an automatic trend toward black -- by design.
  uint8_t blurAmount = beatsin8(2,10,255);
  blur2d( leds, kMatrixWidth, kMatrixHeight, blurAmount);

  // Use two out-of-sync sine waves
  uint8_t  i = beatsin8( 27, kBorderWidth, kMatrixHeight-kBorderWidth);
  uint8_t  j = beatsin8( 41, kBorderWidth, kMatrixWidth-kBorderWidth);
  // Also calculate some reflections
  uint8_t ni = (kMatrixWidth-1)-i;
  uint8_t nj = (kMatrixWidth-1)-j;
  
  // The color of each point shifts over time, each at a different speed.
  uint16_t ms = millis();  
  leds[XY( i, j)] += CHSV( ms / 11, 200, 255);
  leds[XY( j, i)] += CHSV( ms / 13, 200, 255);
  leds[XY(ni,nj)] += CHSV( ms / 17, 200, 255);
  leds[XY(nj,ni)] += CHSV( ms / 29, 200, 255);
  leds[XY( i,nj)] += CHSV( ms / 37, 200, 255);
  leds[XY(ni, j)] += CHSV( ms / 41, 200, 255);
  
  FastLED.show();
}

utils.h

This page contains bits and pieces that are helpful, including pulling from a random built-in FastLED palette:

Download: file
// Pick a random palette from a list
void selectRandomPalette() {

  switch(random8(8)) {
    case 0:
    currentPalette = CloudColors_p;
    break;
    
    case 1:
    currentPalette = LavaColors_p;
    break;
    
    case 2:
    currentPalette = OceanColors_p;
    break;
    
    case 4:
    currentPalette = ForestColors_p;
    break;
    
    case 5:
    currentPalette = RainbowColors_p;
    break;
    
    case 6:
    currentPalette = PartyColors_p;
    break;
    
    case 7:
    currentPalette = HeatColors_p;
    break;
  }

}
This guide was first published on Aug 07, 2019. It was last updated on Aug 07, 2019. This page (Code) was last updated on Sep 22, 2019.