Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 4 of 4

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

  1. #1

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

    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.

  2. #2
    Senior Member crees's Avatar
    Join Date
    Dec 2016
    Location
    Utah
    Posts
    138
    I recalled that this topic was recently discussed and looked it up so I can share the code here, This is the thread

    https://forum.pjrc.com/threads/54549...+button+ws2812

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

  3. #3
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    19,734
    Quote Originally Posted by slurry bowl View Post
    ... 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=");
          Serial.println(showType);
          startShow(showType);
        }
    In startShow(), maybe add these:

    Code:
      switch (i) {
        case 0: R1();    // Black/off
          Serial.println("case R1");
          break;
        case 1: R2();
          Serial.println("case R2");
          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.

  4. #4
    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!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •