OctoWS2811, Teensy 3.2, FastLED, and a button?

Status
Not open for further replies.

slurry bowl

Active member
Hello good people of the forum.

I was having poor results running over 300, WS2811 LEDs on my Teensy 3.2, turns out I needed a resistor on the data output pin.

I then tried a Teensy LC and it worked well as I knew pin 17 was 5V logic, but I couldnt see any difference when I used the other LC pins as outputs and again used a resistor. I used a 20 ohm resistor for 475 LEDs on both 17 and any other pin, with good results, running 2, 475 LED strips.

I then put my Teensy 3.2 on a OctoWS2811 board and was having a hard time getting my favorite code to run on it. I enjoy modifying the Juggle animation within
the FastLED demo reel. I solved this problem by bypassing the ethernet ports and just running data from the Octo's #1 and #22 pins. My code looks smoother then when I had the LC or just the Teensy 3.2

I now want to add a button to scroll through my different animations. Previously I used a library simply called Button but it does not work with Teensy.
I know I need to call for a pull-up resistor and wire up the button to one of the open pins on the OctoW2811. Any advice appreciated on how to do this. Apologies as my current shown code has the prior button library commented out and is kinda messy.

Code:
#include "FastLED.h"
#include <OctoWS2811.h>
//OctoWS2811 leds(ledsPerStrip, displayMemory, drawingMemory, config);

FASTLED_USING_NAMESPACE

#if FASTLED_VERSION < 3001000
#error "Requires FastLED 3.1 or later; check github for latest code."
#endif

//#define DATA_PIN    1
//#define CLK_PIN   4
#define LED_TYPE    WS2812B
#define COLOR_ORDER GRB
#define NUM_LEDS    475
CRGB leds[NUM_LEDS];  


CRGBPalette16 gPal;

bool gReverseDirection = false;

#define BRIGHTNESS          90
#define FRAMES_PER_SECOND  120

//#include "Button.h"    // Include Button library
//const int buttonPin = 3;  // Set digital pin used with debounced pushbutton8Button 
//myButton(buttonPin, true, true, 50);  // Declare the butto
void setup() {
  delay(3000); // 3 second delay for recovery
  
  // tell FastLED about the LED strip configuration
 // FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  FastLED.addLeds<NEOPIXEL, 1>(leds, NUM_LEDS);
  FastLED.addLeds<NEOPIXEL, 22>(leds, NUM_LEDS);

  // set master brightness control
  FastLED.setBrightness(BRIGHTNESS);

  gPal = CRGBPalette16( CRGB:: Purple, CRGB::Black, CRGB::Blue, CRGB::Green);
  //gPal = CRGBPalette16( CRGB:: Red, CRGB::Black, CRGB::Red, CRGB::Black);

}
//Fire2012WithPalette
// List of patterns to cycle through.  Each is defined as a separate function below.
typedef void (*SimplePatternList[])();

//SimplePatternList gPatterns = { rainbow, rainbowuniform, rainbowWEIRD, rainbowWithGlitter, confetti_GB, confetti, juggle, juggle_B, juggle_R, juggle_G, sinelon };
//SimplePatternList gPatterns = {  confetti_GB, confetti_PB,juggle_mag, juggle_lilblue, juggle_B_less,juggle_B_more,juggle_B_lots, juggle_perfblue, juggle_2lilgreen, juggle_4lilgreen,juggle_G, juggle_4lilred,juggle_R_less,
//juggle_R, sinelon, rainbowWithGlitter, };

//SimplePatternList gPatterns = {  juggle_test, juggle_perfblue  };
SimplePatternList gPatterns = {   juggle_perfblue, juggle_mag  };
//SimplePatternList gPatterns = {   juggle_mag  };
//SimplePatternList gPatterns = {   Fire2012WithPalette  };
//SimplePatternList gPatterns = {  confetti_GB };

uint8_t gCurrentPatternNumber = 0; // Index number of which pattern is current
uint8_t gHue = 0; // rotating "base color" used by many of the patterns
  
void loop()
{
  // Call the current pattern function once, updating the 'leds' array
  gPatterns[gCurrentPatternNumber]();

  // send the 'leds' array out to the actual LED strip
  FastLED.show();  
  // insert a delay to keep the framerate modest
  FastLED.delay(1000/FRAMES_PER_SECOND); 

  // do some periodic updates
  EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow
  //EVERY_N_SECONDS( 10 ) { nextPattern(); } // change patterns periodically
 // readbutton();  // check for button press
 
}

#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
void nextPattern()
{
  // add one to the current pattern number, and wrap around at the end
  gCurrentPatternNumber = (gCurrentPatternNumber + 1) % ARRAY_SIZE( gPatterns);
}

void rainbow() 
{
  // FastLED's built-in rainbow generator
  fill_rainbow( leds, NUM_LEDS, gHue, 7);
}


void rainbowuniform() 
{
  // FastLED's built-in rainbow generator
  fill_rainbow( leds, NUM_LEDS, gHue, 2);
}

void rainbowWEIRD() 
{
  // FastLED's built-in rainbow generator
  fill_rainbow( leds, NUM_LEDS, gHue, 30);
}
void sinelon()
{
  // a colored dot sweeping back and forth, with fading trails
  fadeToBlackBy( leds, NUM_LEDS, 20);
  int pos = beatsin16(13,0,NUM_LEDS);
  leds[pos] += CHSV( gHue, 255, 192);
}

void confetti() 
{
  // random colored speckles that blink in and fade smoothly
  fadeToBlackBy( leds, NUM_LEDS, 10);
  int pos = random16(NUM_LEDS);
  leds[pos] += CHSV( gHue + random8(64), 250, 250);
}

void rainbowWithGlitter() 
{
  // built-in FastLED rainbow, plus some random sparkly glitter
  rainbow();
  addGlitter(80);
}

void addGlitter( fract8 chanceOfGlitter) 
{
  if( random8() < chanceOfGlitter) {
    leds[ random16(NUM_LEDS) ] += CRGB::White;
  }
}
void juggle_test() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 60);
  byte dothue = 100;
  for( int i = 0; i < 4; i++) {
    leds[beatsin16(i+1,0,NUM_LEDS)] |= CHSV(dothue, 180, 200);
    //dothue += 32;
  }
}

void juggle_4lilgreen() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 300);
  byte dothue = 100;
  for( int i = 0; i < 4; i++) {
    leds[beatsin16(i+8,0,NUM_LEDS)] |= CHSV(dothue, 180, 200);
    dothue += 32;
  }
}

void juggle_4lilred() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 300);
  byte dothue = 1;
  for( int i = 0; i < 4; i++) {
    leds[beatsin16(i+5,50,NUM_LEDS)] |= CHSV(dothue, 220, 200);
    //dothue += 32;
  }
}

void juggle_2lilgreen() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 300);
  byte dothue = 100;
  for( int i = 0; i < 2; i++) {
    leds[beatsin16(i+1,0,NUM_LEDS)] |= CHSV(dothue, 250, 200);
    //dothue += 32;
  }
}

void juggle_perfblue() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 600);
  byte dothue = 180;
  for( int i = 0; i < 1; i++) {
    leds[beatsin16(i+1,0,NUM_LEDS)] |= CHSV(dothue, 250, 200);
    //dothue += 32;
  }
}

void juggle_lilblue() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 100);
  byte dothue = 180;
  for( int i = 0; i < 3; i++) {
    leds[beatsin16(i+1,0,NUM_LEDS)] |= CHSV(dothue, 250, 200);
    //dothue += 32;
  }
}

void juggle_mag() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 600);
  byte dothue = 225;
  for( int i = 0; i < 2; i++) {
    leds[beatsin16(i+1,0,NUM_LEDS)] |= CHSV(dothue, 250, 200);
    //dothue += 32;
  }
}

void juggle_R() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 20);
  byte dothue = 5;
  for( int i = 0; i < 8; i++) {
    leds[beatsin16(i+1,0,NUM_LEDS)] |= CHSV(dothue, 200, 180);
    //dothue += 32;
  }
}

void juggle_G() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 200);
  byte dothue = 96;
  for( int i = 0; i < 8; i++) {
    leds[beatsin16(i+1,0,NUM_LEDS)] |= CHSV(dothue, 200, 100);
    //dothue += 32;
  }
}
void juggle_B_less() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 240);
  byte dothue = 160;
  for( int i = 0; i < 8; i++) {
    leds[beatsin16(i+1,0,NUM_LEDS)] |= CHSV(dothue, 200, 100);
    //dothue += 32;
  }
}

void juggle_R_less() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 240);
  byte dothue = 5;
  for( int i = 0; i < 8; i++) {
    leds[beatsin16(i+1,0,NUM_LEDS)] |= CHSV(dothue, 200, 180);
    //dothue += 32;
  }
}

void juggle_B_more() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 100);
  byte dothue = 160;
  for( int i = 0; i < 8; i++) {
    leds[beatsin16(i+1,0,NUM_LEDS)] |= CHSV(dothue, 200, 100);
    //dothue += 32;
  }
}

void juggle_B_lots() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 10);
  byte dothue = 160;
  for( int i = 0; i < 8; i++) {
    leds[beatsin16(i+1,0,NUM_LEDS)] |= CHSV(dothue, 200, 100);
    //dothue += 32;
  }
}

void juggle_Bsteady() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 1);
  byte dothue = 160;
  for( int i = 0; i < 240; i++) {
    leds[beatsin16(i+200,0,NUM_LEDS)] |= CHSV(dothue, 200, 55);
    //dothue += 32;
  }
}

void juggle() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 20);
  byte dothue = 0;
  for( int i = 0; i < 8; i++) {
    leds[beatsin16(i+7,0,NUM_LEDS)] |= CHSV(dothue, 200, 100);
    dothue += 32;
  }
}

void confetti_GB()
{
//   random colored speckles, Green and Blue hues only
  // Green = 96, Blue = 160
  uint8_t p = 30;  // What percentage of the time to make speckles.  [Range 0-100]
 
  fadeToBlackBy( leds, NUM_LEDS, 10);
  if (random8(100) < p) {
    int pos = random16(NUM_LEDS);
    uint8_t hue = random8(2);  // randomly chooses a 0 or 1
    if (hue == 0) {
      hue = random8(92,111);  // pick a hue somewhere in the green zone
    } else {
      hue = random8(156,165);  // pick a hue somewhere in the blue zone
    }
    leds[pos] += CHSV( hue, random8(200,240), 100);
  }
}//end confetti_GB

void confetti_PB()
{
//   random colored speckles, Green and Blue hues only
  // Green = 96, Blue = 160
  uint8_t p = 70;  // What percentage of the time to make speckles.  [Range 0-100]
 
  fadeToBlackBy( leds, NUM_LEDS, 10);
  if (random8(100) < p) {
    int pos = random16(NUM_LEDS);
    uint8_t hue = random8(2);  // randomly chooses a 0 or 1
    if (hue == 0) {
      hue = random8(2,80);  // pick a hue somewhere in the green zone
    } else {
      hue = random8(156,165);  // pick a hue somewhere in the blue zone
    }
    leds[pos] += CHSV( hue, random8(200,240), 100);
  }
}//end confetti_GB





// Fire2012 by Mark Kriegsman, July 2012
// as part of "Five Elements" shown here: http://youtu.be/knWiGsmgycY
//// 
// This basic one-dimensional 'fire' simulation works roughly as follows:
// There's a underlying array of 'heat' cells, that model the temperature
// at each point along the line.  Every cycle through the simulation, 
// four steps are performed:
//  1) All cells cool down a little bit, losing heat to the air
//  2) The heat from each cell drifts 'up' and diffuses a little
//  3) Sometimes randomly new 'sparks' of heat are added at the bottom
//  4) The heat from each cell is rendered as a color into the leds array
//     The heat-to-color mapping uses a black-body radiation approximation.
//
// Temperature is in arbitrary units from 0 (cold black) to 255 (white hot).
//
// This simulation scales it self a bit depending on NUM_LEDS; it should look
// "OK" on anywhere from 20 to 100 LEDs without too much tweaking. 
//
// I recommend running this simulation at anywhere from 30-100 frames per second,
// meaning an interframe delay of about 10-35 milliseconds.
//
// Looks best on a high-density LED setup (60+ pixels/meter).
//
//
// There are two main parameters you can play with to control the look and
// feel of your fire: COOLING (used in step 1 above), and SPARKING (used
// in step 3 above).
//
// COOLING: How much does the air cool as it rises?
// Less cooling = taller flames.  More cooling = shorter flames.
// Default 55, suggested range 20-100 
#define COOLING  35

// SPARKING: What chance (out of 255) is there that a new spark will be lit?
// Higher chance = more roaring fire.  Lower chance = more flickery fire.
// Default 120, suggested range 50-200.
#define SPARKING 50


void Fire2012WithPalette()
{
// Array of temperature readings at each simulation cell
  static byte heat[NUM_LEDS];

  // Step 1.  Cool down every cell a little
    for( int i = 0; i < NUM_LEDS; i++) {
      heat[i] = qsub8( heat[i],  random8(0, ((COOLING * 10) / NUM_LEDS) + 2));
    }
  
    // Step 2.  Heat from each cell drifts 'up' and diffuses a little
    for( int k= NUM_LEDS - 1; k >= 2; k--) {
      heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
    }
    
    // Step 3.  Randomly ignite new 'sparks' of heat near the bottom
    if( random8() < SPARKING ) {
      int y = random8(7);
      heat[y] = qadd8( heat[y], random8(160,255) );
    }

    // Step 4.  Map from heat cells to LED colors
    for( int j = 0; j < NUM_LEDS; j++) {
      // Scale the heat value from 0-255 down to 0-240
      // for best results with color palettes.
      byte colorindex = scale8( heat[j], 240);
      CRGB color = ColorFromPalette( gPal, colorindex);
      int pixelnumber;
      if( gReverseDirection ) {
        pixelnumber = (NUM_LEDS-1) - j;
      } else {
        pixelnumber = j;
      }
      leds[pixelnumber] = color;
    }
}


//BUTTON STUFF
//---------Function to read the button and do something----------
//void readbutton() {
//  myButton.read();
 // if(myButton.wasPressed()) {
 //   nextPattern();  // Change to the next pattern

    
//end_readbutton
 
Last edited by a moderator:
I've in essence just done something very similar for my christmas tree lights project. I have 150 WS2812 LEDs being controlled by a Teensy 3.5, using the FastLED library. I have one button used to cycle through the modes, including a special mode that is triggered if the button is held down and then released for longer than a given period.

It's my first project, it works well, and I'm more than happy to share what I learnt if it helps! I've used the Bounce library as suggested above.

Relevant code snippets for the button:

Include the Bounce library and setup global constants, variables and button input pin -
Code:
#'include Bounce.h
// Button setup
const int buttonPin = 25;
Bounce pushbutton = Bounce(buttonPin, 10); // 10 ms debounce. Don't know if this is needed
byte previousState = HIGH;
int mode = -1;
int cols = 0;
// Timer setup for button hold reading
unsigned long startMillis;
unsigned long currentMillis;
const unsigned long period = 3000; // 3 seconds hold

Within the Setup loop, just setup the pullup resistor for the button -
Code:
  pinMode(buttonPin, INPUT_PULLUP);

My main loop is then very simple:
Code:
// Main loop - polls to see if a button has been pressed and sets the appropriate mode
void loop() {
 // Serial.println(mode);
 // Serial.println(cols);
  buttonPush();
  switch (mode) {
    case 0:
      mode0();
      break;
    case 1:
      mode1();
      break;
    case 2:
      mode2();
      break;
    case 3:
      mode3();
      break;
    case 4:
      mode4();
      break;
    case 5:
      mode5();
      break;
    case 6:
      mode6();
      break;
    case 7:
      mode7();
      break;
    case 8:
      mode8();
      break;
    default:
      Serial.println("All gone wrong");
  }
}
The commented out lines were used for de-bugging. You can see I have 8 standard operating modes. Each of this is a function, which then calls any number of light effect functions.

The other relevant function defined you need is the buttonPush function, which is defined as follows -
Code:
// Polling for if button has been pressed
void buttonPush() {
  if (pushbutton.update()) {
    if (pushbutton.fallingEdge()) {
      startMillis = millis();
    }
    if (pushbutton.risingEdge()) {
      currentMillis = millis();
      if (currentMillis - startMillis > period) {
        modespecial();
        }
        else {
          int startmode = mode;
          mode = mode +1;
          if (mode >= 9) {
            mode = 0;
            fadeall();
            cols = cols +1;
            if (cols >=7) {
              cols = 0;
            }
          }
          if (mode == 1) {
            if (mode != startmode) {
              InitPixelStates();
            } 
          }
        }
    }  
  }
}

You can see this is where it calls the special mode (modespecial()) if the button has been pressed and held down, otherwise it updates the global mode variable to the next value (or back to the beginning if it loops round) so that when the function finishes and returns to the main loop it moves into the next operating mode. The cols global variable is used so that each time the operating modes cycle back to the start it increases the hue value used within the FastLED functions, meaning that it uses a different colour.

Hope this makes sense and helps with your project.
 
Last edited:
I've in essence just done something very similar for my christmas tree lights project. I have 150 WS2812 LEDs being controlled by a Teensy 3.5, using the FastLED library. I have one button used to cycle through the modes, including a special mode that is triggered if the button is held down and then released for longer than a given period.

Incredible. Thanks so much. I modified your code with my various animation functions and I KNOW IM CLOSE, but I get errors when compiling at

fadeall(); was not declared in this scope
and
InitPixelStates(); was not declared in this scope

I am using Button2 library as that is the latest. I am also using the newest FastLED...

any ideas on what may be happening???

Code:
#include <Bounce2.h>

#include "FastLED.h"

FASTLED_USING_NAMESPACE

#define LED_TYPE    WS2811
#define COLOR_ORDER GRB
#define NUM_LEDS    475
CRGB leds[NUM_LEDS];  

CRGBPalette16 gPal;

bool gReverseDirection = false;

#define BRIGHTNESS          90
#define FRAMES_PER_SECOND  320

// Button setup
const int buttonPin = 17;
Bounce pushbutton = Bounce(buttonPin, 10); // 10 ms debounce. Don't know if this is needed
byte previousState = HIGH;
int mode = -1;
int cols = 0;
// Timer setup for button hold reading
unsigned long startMillis;
unsigned long currentMillis;
const unsigned long period = 3000; // 3 seconds hold

uint8_t gHue = 0;

void setup() {
  delay(3000); // 3 second delay for recovery
  
  // tell FastLED about the LED strip configuration
 // FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  FastLED.addLeds<NEOPIXEL, 1>(leds, NUM_LEDS);
  FastLED.addLeds<NEOPIXEL, 22>(leds, NUM_LEDS);

  // set master brightness control
  FastLED.setBrightness(BRIGHTNESS);

  gPal = CRGBPalette16( CRGB:: Purple, CRGB::Black, CRGB::Blue, CRGB::Green);
  //gPal = CRGBPalette16( CRGB:: Red, CRGB::Black, CRGB::Red, CRGB::Black);

pinMode(17, INPUT_PULLUP);
uint8_t gHue = 0; // rotating "base color" used by many of the patterns
}
void loop()  {
 // Serial.println(mode);
 // Serial.println(cols);
  buttonPush();
  switch (mode) {
     case 0:
      mode0();
      break;
    case 1:
      mode1();
      break;
    case 2:
      mode2();
      break;
    case 3:
      mode3();
      break;
    case 4:
      mode4();
      break;
    case 5:
      mode5();
      break;
    case 6:
      mode6();
      break;
    
    
  }
}
//rainbow
void mode0() 
{
  // FastLED's built-in rainbow generator
  fill_rainbow( leds, NUM_LEDS, gHue, 7);
}
//juggle_perfblue
void mode1() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 600);
  byte dothue = 180;
  for( int i = 0; i < 1; i++) {
    leds[beatsin16(i+1,0,NUM_LEDS)] |= CHSV(dothue, 250, 250);
    //dothue += 32;
  }
}
//juggle_mag
void mode2() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 600);
  byte dothue = 225;
  for( int i = 0; i < 1; i++) {
    leds[beatsin16(i+1,0,NUM_LEDS)] |= CHSV(dothue, 250, 250);
    //dothue += 32;
  }
}
//confetti_PB
void mode3()
{
//   random colored speckles, Green and Blue hues only
  // Green = 96, Blue = 160
  uint8_t p = 70;  // What percentage of the time to make speckles.  [Range 0-100]
 
  fadeToBlackBy( leds, NUM_LEDS, 10);
  if (random8(100) < p) {
    int pos = random16(NUM_LEDS);
    uint8_t hue = random8(2);  // randomly chooses a 0 or 1
    if (hue == 0) {
      hue = random8(2,80);  // pick a hue somewhere in the green zone
    } else {
      hue = random8(156,165);  // pick a hue somewhere in the blue zone
    }
    leds[pos] += CHSV( hue, random8(200,240), 100);
  }
}//end confetti_GB
//sinelong
void mode4()
{
  // a colored dot sweeping back and forth, with fading trails
  fadeToBlackBy( leds, NUM_LEDS, 20);
  int pos = beatsin16(13,0,NUM_LEDS);
  leds[pos] += CHSV( gHue, 255, 192);
}
//rainbowWEIRD
void mode5() 
{
  // FastLED's built-in rainbow generator
  fill_rainbow( leds, NUM_LEDS, gHue, 30);
}

//jugglespecial
void modespecial() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 600);
  byte dothue = 25;
  for( int i = 0; i < 1; i++) {
    leds[beatsin16(i+1,0,NUM_LEDS)] |= CHSV(dothue, 250, 250);
    //dothue += 32;
  }
}



#define COOLING  35

#define SPARKING 50

//FIRE
void mode6()
{
// Array of temperature readings at each simulation cell
  static byte heat[NUM_LEDS];

  // Step 1.  Cool down every cell a little
    for( int i = 0; i < NUM_LEDS; i++) {
      heat[i] = qsub8( heat[i],  random8(0, ((COOLING * 10) / NUM_LEDS) + 2));
    }
  
    // Step 2.  Heat from each cell drifts 'up' and diffuses a little
    for( int k= NUM_LEDS - 1; k >= 2; k--) {
      heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
    }
    
    // Step 3.  Randomly ignite new 'sparks' of heat near the bottom
    if( random8() < SPARKING ) {
      int y = random8(7);
      heat[y] = qadd8( heat[y], random8(160,255) );
    }

    // Step 4.  Map from heat cells to LED colors
    for( int j = 0; j < NUM_LEDS; j++) {
      // Scale the heat value from 0-255 down to 0-240
      // for best results with color palettes.
      byte colorindex = scale8( heat[j], 240);
      CRGB color = ColorFromPalette( gPal, colorindex);
      int pixelnumber;
      if( gReverseDirection ) {
        pixelnumber = (NUM_LEDS-1) - j;
      } else {
        pixelnumber = j;
      }
      leds[pixelnumber] = color;
    }
}

void buttonPush() {
  if (pushbutton.update()) {
    if (pushbutton.fallingEdge()) {
      startMillis = millis();
    }
    if (pushbutton.risingEdge()) {
      currentMillis = millis();
      if (currentMillis - startMillis > period) {
        modespecial();
        }
        else {
          int startmode = mode;
          mode = mode +1;
          if (mode >= 9) {
            mode = 0;
        //    fadeall();
            cols = cols +1;
            if (cols >=7) {
              cols = 0;
            }
          }
          if (mode == 1) {
            if (mode != startmode) {
              InitPixelStates();
            } 
          }
        }
    }  
  }
}
 
Last edited by a moderator:
Fadeall and initpixelfunctions are calls to functions that are defined elsewhere in my code. Sorry I hadn't noticed that.

You can delete them from your code and it should compile and run. Fingers crossed!
 
Other quick notes:
- you've got modes 0 to 6 and a special mode. Look at the logic in the else loop in buttonPush, with respect to what it does to the mode variable. What value should you go for in the If statement regarding if mode >= value?
- your code isn't using the cols variable that I can see. You could remove this from your code. Or you could modify your modes code so that it uses cols to set the hue used; then each time you cycle through the modes the colour will change. Think that would get rid of one of your operating modes too but it all depends on how you want to access/order the modes
 
Code:
 you've got modes 0 to 6 and a special mode. Look at the logic in the else loop in buttonPush, with respect to what it does to the mode variable. What value should you go for in the If statement regarding if mode >= value?
I tried 5, 6, and 7 to reflect the reduced # of modes, but still no luck.

I also commented out the two lines I mentioned above fadeall(): and InitPixelStates(); but still I dont get any light.

I think that init pixel states is important, I tried replacing it with strip.show(); but that didnt work.

I really appreciate the help thus far. I can run other code cleanly on my setup so I know there are no power/data line issues. Its all code.
Would you be willing to post your whole code or have any suggestions for fixing my situation. thanks.
 
I also commented out the two lines I mentioned above fadeall(): and InitPixelStates(); but still I dont get any light.

I don't think anywhere in your code it tells the leds to "show?

I think you need FastLED.show(); in there at the points when you want the leds to show a colour/visibly update.

Depending on the function you're calling you either want this statement at the end of the function loop, somewhere within it, or in the main loop inbetween calling each of the mode functions and the break statement.

Then with light it will make it easier to see what value you need in the mode logic ;-)

Not near my machine at the moment but pretty sure initpixelstates came from a github example (FastLED palettes?) So you maybe able to find that elsewhere if it won't work without. I think it will be ok though.
 
I did a project almost exactly what your trying to do. Uses two buttons one for effects and the other for brightness control. If using the 8x8 tiles it will do a cool matrix effect.

See video on Matrix effect. This project was used on a burning mac costume running from a Powerbank.

https://youtu.be/bYAEZZFxPL0


Code:
// Matrix effect by Jeremy Williams
// Designed for Game Frame
// http://www.ledseq.com
// Modified for use in costume by crees



#include <FastLED.h>
#include <Button.h>

Button button1(22); // Connect your button between pin 2 and GND
Button button2(23); // Connect your button between pin 3 and GND


// LED setup
#define kMatrixWidth  16
#define kMatrixHeight 32
#define DATA_PIN 2
#define DATA_PIN2 14
//#define CLOCK_PIN 4
#define NUM_LEDS 512
#define LED_TYPE WS2812
#define COLOR_ORDER GBR
#define FRAMES_PER_SECOND  120
uint8_t ledBrightness = 50;


CRGB leds[NUM_LEDS];

void setup()
{

  button1.begin();
  button2.begin();
  delay(3000); // 3 second delay for recovery  

  // LED Init
  FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, 0, NUM_LEDS/2).setDither(0);
  FastLED.addLeds<LED_TYPE, DATA_PIN2, COLOR_ORDER>(leds, NUM_LEDS/2, NUM_LEDS/2).setDither(0);

  FastLED.setBrightness(ledBrightness);
  FastLED.show();

  Serial.begin(115200);
}



#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))

// convert x/y cordinates to LED index on zig-zag grid
uint16_t getIndex(uint16_t x, uint16_t y)
{
  uint16_t index;
  if (y == 0)
  {
    index = x;
  }
  else if (y % 2 == 0)
  {
    index = y * kMatrixWidth + x;
  }
  else
  {
    index = ((y * kMatrixWidth) + (kMatrixWidth-1)) - x;
  }
  return index;
}

void thematrix()
{
    EVERY_N_MILLIS(70) // falling speed
  {
    // move code downward
    // start with lowest row to allow proper overlapping on each column
    for (int8_t row=kMatrixHeight-1; row>=0; row--)
    {
      for (int8_t col=0; col<kMatrixWidth; col++)
      {
        if (leds[getIndex(col, row)] == CRGB(175,255,175))
        {
          leds[getIndex(col, row)] = CRGB(27,130,39); // create trail
          if (row < kMatrixHeight-1) leds[getIndex(col, row+1)] = CRGB(175,255,175);
        }
      }
    }

    // fade all leds
    for(int i = 0; i < NUM_LEDS; i++) {
      if (leds[i].g != 255) leds[i].nscale8(192); // only fade trail
    }

    // check for empty screen to ensure code spawn
    bool emptyScreen = true;
    for(int i = 0; i < NUM_LEDS; i++) {
      if (leds[i])
      {
        emptyScreen = false;
        break;
      }
    }

    // spawn new falling code
    if (random8(3) == 0 || emptyScreen) // lower number == more frequent spawns
    {
      int8_t spawnX = random8(kMatrixWidth);
      leds[getIndex(spawnX, 0)] = CRGB(175,255,175 );
    }

    //FastLED.show();
  }
}

uint8_t gCurrentPatternNumber = 0; // Index number of which pattern is current
uint8_t gHue = 0; // rotating "base color" used by many of the patterns

void rainbow() 
{
  // FastLED's built-in rainbow generator
  fill_rainbow( leds, NUM_LEDS, gHue, 7);
}
void addGlitter( fract8 chanceOfGlitter) 
{
  if( random8() < chanceOfGlitter) {
    leds[ random16(NUM_LEDS) ] += CRGB::White;
  }
}

void rainbowWithGlitter() 
{
  // built-in FastLED rainbow, plus some random sparkly glitter
  rainbow();
  addGlitter(80);
}



void confetti() 
{
  // random colored speckles that blink in and fade smoothly
  fadeToBlackBy( leds, NUM_LEDS, 10);
  int pos = random16(NUM_LEDS);
  leds[pos] += CHSV( gHue + random8(64), 200, 255);
}

void sinelon()
{
  // a colored dot sweeping back and forth, with fading trails
  fadeToBlackBy( leds, NUM_LEDS, 20);
  int pos = beatsin16(13,0,NUM_LEDS);
  leds[pos] += CHSV( gHue, 255, 192);
}

void bpm()
{
  // colored stripes pulsing at a defined Beats-Per-Minute (BPM)
  uint8_t BeatsPerMinute = 62;
  CRGBPalette16 palette = PartyColors_p;
  uint8_t beat = beatsin8( BeatsPerMinute, 64, 255);
  for( int i = 0; i < NUM_LEDS; i++) { //9948
    leds[i] = ColorFromPalette(palette, gHue+(i*2), beat-gHue+(i*10));
  }
}

void juggle() {
  // eight colored dots, weaving in and out of sync with each other
  fadeToBlackBy( leds, NUM_LEDS, 20);
  byte dothue = 0;
  for( int i = 0; i < 8; i++) {
    leds[beatsin16(i+7,0,NUM_LEDS-1)] |= CHSV(dothue, 200, 255);
    dothue += 32;
  }
}

// List of patterns to cycle through.  Each is defined as a separate function below.
typedef void (*SimplePatternList[])();
SimplePatternList gPatterns = {thematrix, rainbow, rainbowWithGlitter, confetti, sinelon, juggle, bpm };

void nextPattern()
{
  // add one to the current pattern number, and wrap around at the end
  gCurrentPatternNumber = (gCurrentPatternNumber + 1) % ARRAY_SIZE( gPatterns);
}

void readbutton() {                                           // Read the button and increase the mode
    if (button1.released()){
    Serial.println("Button 1 released");
    nextPattern();
    }
    if (button2.released()){
    Serial.println("Button 2 released");
    ledBrightness = ledBrightness + 10;
    if (ledBrightness > 50){
      ledBrightness = 10;
    }
    }
    FastLED.setBrightness(ledBrightness);
  }
 // readbutton()

void loop()
{
  // Call the current pattern function once, updating the 'leds' array
  gPatterns[gCurrentPatternNumber]();

  // send the 'leds' array out to the actual LED strip
  FastLED.show();  
  // insert a delay to keep the framerate modest
  FastLED.delay(1000/FRAMES_PER_SECOND); 

  // do some periodic updates
  EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow
//  EVERY_N_SECONDS( 10 ) { nextPattern(); } // change patterns periodically

    readbutton();                                               // Button press increases the ledMode up to last contiguous mode and then starts over at 0.

}
 
I did a project almost exactly what your trying to do. Uses two buttons one for effects and the other for brightness control. If using the 8x8 tiles it will do a cool matrix effect.
/QUOTE]

Thanks for sharing your code and your expertise. I was able to get it running on my project. I appreciate the button for controlling brightness!
On certain modes, the pixel count seems off.

With both the Fire2012WithPallette and juggle animations, I have to set the pixel count higher then it actually is. The animations seem to start prior to the LEDs, as in LED 0 seems to be about LED 200. Its weird.
Perhaps that has to do with the code being designed for tiles?

Im working on voltage drop issues and I am running the whole project on 1 data pin. Total LED count is around 1500. Im considering using two pins and was curious maximum LED count the signal can reliably send with 1 data out pin??
 
Thanks for sharing your code and your expertise. I was able to get it running on my project. I appreciate the button for controlling brightness!
On certain modes, the pixel count seems off.

With both the Fire2012WithPallette and juggle animations, I have to set the pixel count higher then it actually is. The animations seem to start prior to the LEDs, as in LED 0 seems to be about LED 200. Its weird.
Perhaps that has to do with the code being designed for tiles?

Im working on voltage drop issues and I am running the whole project on 1 data pin. Total LED count is around 1500. Im considering using two pins and was curious maximum LED count the signal can reliably send with 1 data out pin??

The longer your runs the shorter the frame rate will be. If your ok with sub par frame rates of over 1000 pixels then your good to keep adding knowing the more you add the slower it will frame. However the signal will continue to regenerate after each pixel so there is no issue there (unless your distance between pixels is too much).

The advantage of using another pin is to divide the pixels up. This way you can keep your Frames per second decent. 680 pixels per port will get you around 40 FPS while 1000 will get you around 25. Power injection every 100-150 pixels is a good start.
 
The advantage of using another pin is to divide the pixels up. This way you can keep your Frames per second decent. 680 pixels per port will get you around 40 FPS while 1000 will get you around 25. Power injection every 100-150 pixels is a good start.

Thats really helpful information. I was confused as to why when I increased pixel count, my animations would be stretched and not as smooth. I had also thought it could be a dithering problem or a math problem. For my modified juggle animation to look smooth, I find that about 200 pixel count is when it starts to deteriorate. So if I understand you correctly, I need to have separate data lines for each 200 leds to maintain the desired effect.
 
Thats really helpful information. I was confused as to why when I increased pixel count, my animations would be stretched and not as smooth. I had also thought it could be a dithering problem or a math problem. For my modified juggle animation to look smooth, I find that about 200 pixel count is when it starts to deteriorate. So if I understand you correctly, I need to have separate data lines for each 200 leds to maintain the desired effect.

Using the octows2811 and or Fastled method will allow very efficient frame rates over the 8 pins. So if you can divide your pixels over those 8 pins you should see smooth results
 
Using the octows2811 and or Fastled method will allow very efficient frame rates over the 8 pins. So if you can divide your pixels over those 8 pins you should see smooth results

I managed to rip off the USB input on my Teensy 3.2 which is heavily soldered to my OCTO board. I tried a solder wick to remove the existing 3.2 off the headers as I have a second 3.2 to put on the OCTO board but to no avail. Too much solder.

So I am messing around with an UNO and I successfully got the FAST LED > MULTIPLES > MultipleStripsInOneArray
to work with my setup which could lead itself towards 1 large array with multiple data pins to keep animation frame rate high.

How would I modify the code to have strips of different size?

I am wrapping a Japanese maple tree and the base has 120 LEDs, then the branch sections have 200 LEDs.

Ive tried adjusting different variable to no avail and my dimmer function seems to also not work.

For certain it has to be in this part of the code, just not using the multiplier, but actually calling out LED #s.:
#define NUM_STRIPS 2
#define NUM_LEDS_PER_STRIP 20
#define NUM_LEDS NUM_LEDS_PER_STRIP * NUM_STRIPS

CRGB leds[NUM_STRIPS * NUM_LEDS_PER_STRIP];

// For mirroring strips, all the "special" stuff happens just in setup. We
// just addLeds multiple times, once for each strip
void setup() {
// tell FastLED there's 60 NEOPIXEL leds on pin 10, starting at index 0 in the led array
FastLED.addLeds<NEOPIXEL, 3>(leds, 0, NUM_LEDS_PER_STRIP);

// tell FastLED there's 60 NEOPIXEL leds on pin 11, starting at index 60 in the led array
FastLED.addLeds<NEOPIXEL, 8>(leds, NUM_LEDS_PER_STRIP, NUM_LEDS_PER_STRIP);

Any help very appreciated.

Thanks
 
Status
Not open for further replies.
Back
Top