Teensy 3.2, a button, and 2 WS2812 strips on separate pins.

Status
Not open for further replies.

slurry bowl

Active member
Greetings forum dwellers.

I have been enjoying FastLED for awhile but always have challenges incorporating a button w/Teensy.
Some of the other button libraries for Arduino benefit from default pull-up resistors on that board and when applied
to Teensy, they dont work, at least that is what I think has been my problem. Cree (another forum member) did post some code that worked w/ Teensy and a button.

So......

I want to cycle through a list of patterns when the button is pushed, simple button cycler sorta thing.
Except I have 2 data pins on my Teensy LC, 10 and 17. So when the button is pushed it changes the data on both strips.

Here is my code w/o the button and it works great.

Code:
#include <FastLED.h>

#define BUTTON_PIN   3   
#define NUM_LEDS_core 60
#define NUM_LEDS_arm 54

CRGB coreLeds[NUM_LEDS_core];
CRGB armLeds[NUM_LEDS_arm];
CRGBPalette16 gPal;

void setup() {
  FastLED.addLeds<NEOPIXEL, 10>(coreLeds, NUM_LEDS_core);
  FastLED.addLeds<NEOPIXEL, 17>(armLeds, NUM_LEDS_arm);
}

void loop() {
            
        //CORE    
            for(int led = 0; led < NUM_LEDS_core; led++) { 
            coreLeds[led] = CRGB::Green;        
            }
              FastLED.show();
        
        //ARMS
          fadeToBlackBy( armLeds, NUM_LEDS_arm, 8);
          byte dothue = 10;
          for( int i = 0; i < 8; i++) {
          armLeds[beatsin16( i+0, 0, NUM_LEDS_arm )] |= CHSV(dothue, 250, 80);
          dothue += 22;
          
              FastLED.show();
             }
       }

Here is my attempt at incorporating a button. Unfortunately its not working. I am trying to declare my functions below the void loop.

Code:
#include <FastLED.h>

#define BUTTON_PIN   3    // Digital IO pin connected to the button.  This will be
                          // driven with a pull-up resistor so the switch should
                          // pull the pin to ground momentarily.  On a high -> low
                          // transition the button press logic will execute.
#define NUM_LEDS_core 60
#define NUM_LEDS_arm 54

CRGB coreLeds[NUM_LEDS_core];
CRGB armLeds[NUM_LEDS_arm];
CRGBPalette16 gPal;

bool oldState = HIGH;
int showType = 0;

void setup() {
  pinMode(BUTTON_PIN, INPUT_PULLUP);
 

  FastLED.addLeds<NEOPIXEL, 10>(coreLeds, NUM_LEDS_core);
  FastLED.addLeds<NEOPIXEL, 17>(armLeds, NUM_LEDS_arm);
}

void loop() {
  // Get current button state.
  bool newState = digitalRead(BUTTON_PIN);

  // Check if state changed from high to low (button press).
  if (newState == LOW && oldState == HIGH) {
    // Short delay to debounce button.
    delay(20);
    // Check if button is still low after debounce.
    newState = digitalRead(BUTTON_PIN);
    if (newState == LOW) {
      showType++;
      if (showType > 9)
        showType=0;
      startShow(showType);
    }
  }

  // Set the last button state to the old state.
  oldState = newState;

}

void startShow(int i) {
  switch(i){
    case 0: R1;    // Black/off
            break;
    
    case 1: R2;
            break;
  }
}


void R1 ()
{
   
        
        //ARMS
          fadeToBlackBy( armLeds, NUM_LEDS_arm, 8);
          byte dothue = 10;
          for( int i = 0; i < 8; i++) {
          armLeds[beatsin16( i+0, 0, NUM_LEDS_arm )] |= CHSV(dothue, 250, 80);
          dothue += 22;
          
             }

             //CORE    
            for(int led = 0; led < NUM_LEDS_core; led++) { 
            coreLeds[led] = CRGB::Green;        
            }
              FastLED.show();
}

void R2 ()
{
   
        
        //ARMS
          fadeToBlackBy( armLeds, NUM_LEDS_arm, 8);
          byte dothue = 100;
          for( int i = 0; i < 8; i++) {
          armLeds[beatsin16( i+0, 0, NUM_LEDS_arm )] |= CHSV(dothue, 250, 80);
          dothue += 22;
          
             }

         //CORE    
            for(int led = 0; led < NUM_LEDS_core; led++) { 
            coreLeds[led] = CRGB::Red;        
            }
              FastLED.show();
}

any help most appreciated.
 
... default pull-up resistors on that board and when applied to Teensy, they dont work, at least that is what I think has been my problem.

No, the problem is a simple mistake in your code. pinMode INPUT_PULLUP works fine on Teensy.

The issue is here:

Code:
void startShow(int i) {
  switch(i){
    case 0: R1;    // Black/off
            break;
    
    case 1: R2;
            break;
  }
}

Using just the function name "R1" does nothing. You need to write "R1()" to actually call the function. Without the parentheses, it's just the address of the function which has no effect.

When writing this sort of code, I highly recommend using Serial.println() in many places. Then as your program runs, you can watch what prints in the Arduino Serial Monitor to get a much clearer idea of what's really happening.

For example, in loop(), you might add these 2 lines:

Code:
      showType++;
      if (showType > 9)
        showType = 0;
      Serial.print("button press, showType=");
      [B]Serial.println(showType);
      startShow(showType);[/B]
    }

In startShow(), maybe add these:

Code:
  switch (i) {
    case 0: R1();    // Black/off
      [B]Serial.println("case R1");[/B]
      break;
    case 1: R2();
      [B]Serial.println("case R2");[/B]
      break;
  }

Seeing the lines printed in the serial monitor gives you far more insight than just watching what happens on the LEDs.

Two other quick suggestions...

1: Using the Bounce library is *much* better than digitalRead(). It does the state change detection for you, without delays, so it's easy to use more than 1 button. Many of the Teensyduino examples use Bounce. For example, File > Examples > Teensy > USB_Keyboard > Bounce. I recommend copying code from those examples. It will really help.

2: Occasionally using Tools > Auto Format will help keep your code indented well. It can help you see problems more easily, and when posting to a forum, well indented code has a much better chance of someone quickly noticing a problem.
 
Thanks for the replies. This stuff can be demoralizing for me....alas onward.

I did not realize that you are the same author until now. The code example I shared works with teensy great.

Crees, I am the same author as before. This situation is different in that I am using multiple arrays. One array has 60 leds and is called CORE and another array has 54 LEDs and is called ARM. When I call a function I need it to write to these two separate arrays. I tried my best to modify your code to work for my needs and currently get an error when I compile.

Here is that code:
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(3); // Connect your button between pin 2 and GND
Button button2(4); // Connect your button between pin 3 and GND

// LED setup
#define kMatrixWidth  16
#define kMatrixHeight 32

#define NUM_LEDS_core 60
#define NUM_LEDS_arm 54

#define LED_TYPE WS2812
#define COLOR_ORDER GBR
#define FRAMES_PER_SECOND  120
uint8_t ledBrightness = 50;

CRGB coreleds[NUM_LEDS_core];
CRGB armleds[NUM_LEDS_arm];


void setup()
{

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

  // LED Init
  FastLED.addLeds<NEOPIXEL, 10>(coreLeds, NUM_LEDS_core);
  FastLED.addLeds<NEOPIXEL, 17>(armLeds, NUM_LEDS_arm);

  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 R1() {

  //CORE
  for (int led = 0; led < NUM_LEDS_core; led++) {
    coreLeds[led] = CRGB::Red;
  }

  //ARMS
  fadeToBlackBy( armLeds, NUM_LEDS_arm, 8);
  byte dothue = 100;
  for ( int i = 0; i < 8; i++) {
    armLeds[beatsin16( i + 0, 0, NUM_LEDS_arm )] |= CHSV(dothue, 250, 80);
    dothue += 22;

  }
}

void R2() {

  //CORE
  for (int led = 0; led < NUM_LEDS_core; led++) {
    coreLeds[led] = CRGB::Green;
  }

  //ARMS
  fadeToBlackBy( armLeds, NUM_LEDS_arm, 8);
  byte dothue = 10;
  for ( int i = 0; i < 8; i++) {
    armLeds[beatsin16( i + 0, 0, NUM_LEDS_arm )] |= CHSV(dothue, 250, 80);
    dothue += 22;

  }
}

// List of patterns to cycle through.  Each is defined as a separate function below.
typedef void (*SimplePatternList[])();
SimplePatternList gPatterns = {R1, R2, };

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.

}

Paul, thanks for your help as always. I added the parentheses and now I do get some light, but no animations. I also added your serial prints to help me see what is going wrong. Currently when I try to open the serial monitor, it says my board is not available.

Here is that code:
Code:
// This is a demonstration on how to use an input device to trigger changes on your neo pixels.
// You should wire a momentary push button to connect from ground to a digital IO pin.  When you
// press the button it will change to a new pixel animation.  Note that you need to press the
// button once to start the first animation!

#include <FastLED.h>

#define BUTTON_PIN   3    // Digital IO pin connected to the button.  This will be
// driven with a pull-up resistor so the switch should
// pull the pin to ground momentarily.  On a high -> low
// transition the button press logic will execute.
#define NUM_LEDS_core 60
#define NUM_LEDS_arm 54

CRGB coreLeds[NUM_LEDS_core];
CRGB armLeds[NUM_LEDS_arm];
CRGBPalette16 gPal;

bool oldState = HIGH;
int showType = 0;

void setup() {
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  FastLED.addLeds<NEOPIXEL, 10>(coreLeds, NUM_LEDS_core);
  FastLED.addLeds<NEOPIXEL, 17>(armLeds, NUM_LEDS_arm);
  Serial.begin(9600);

}

void loop() {
  // Get current button state.
  bool newState = digitalRead(BUTTON_PIN);

  // Check if state changed from high to low (button press).
  if (newState == LOW && oldState == HIGH) {
    // Short delay to debounce button.
    delay(20);
    // Check if button is still low after debounce.
    newState = digitalRead(BUTTON_PIN);
    if (newState == LOW) {
      showType++;
      if (showType > 9)
        showType = 0;
      startShow(showType);
      Serial.print("button press, showType=");
      Serial.println(showType);
      startShow(showType);
    }
  }

  // Set the last button state to the old state.
  oldState = newState;

}

void startShow(int i) {
  switch (i) {
    case 0: R1();
      Serial.println("case R1");
      break;

    case 1: R2();
      Serial.println("case R2");
      break;
  }
}


void R1 ()
{
  //CORE
  for (int led = 0; led < NUM_LEDS_core; led++) {
    coreLeds[led] = CRGB::Green;
  }

  //ARMS
  fadeToBlackBy( armLeds, NUM_LEDS_arm, 8);
  byte dothue = 10;
  for ( int i = 0; i < 8; i++) {
    armLeds[beatsin16( i + 0, 0, NUM_LEDS_arm )] |= CHSV(dothue, 250, 80);
    dothue += 22;
    FastLED.show();
  }
}

void R2 ()
{
  //CORE
  for (int led = 0; led < NUM_LEDS_core; led++) {
    coreLeds[led] = CRGB::Red;
  }
  //ARMS
  fadeToBlackBy( armLeds, NUM_LEDS_arm, 8);
  byte dothue = 100;
  for ( int i = 0; i < 8; i++) {
    armLeds[beatsin16( i + 0, 0, NUM_LEDS_arm )] |= CHSV(dothue, 250, 80);
    dothue += 22;
    FastLED.show();
  }
}

Overall, I desperately want my syntax to be better in my code and I want to make it as easy to get help as possible. I will use auto format and take any advice.
In essence (for my own benefit to write it) I want to have a button that cycles through different modes. These modes write to 2 separate arrays. One array is just a static color and the other array is a modified Juggle pattern from FastLED.

I BELIEVE!:cool:
 
Status
Not open for further replies.
Back
Top