Teensy 4.0 Freezes with button presses, and more consistently when not plugged into PC

alasor31

New member
This is my first project with an IC, so I'm sure I am doing something obviously wrong.

I am using a Teensy 4.0 to control 3 WS2812 Addressable LEDs with arcade style buttons as inputs. I am using the integrated pulldown resistor to tell when the buttons are pressed. When a button is pressed, it's corresponding LED should toggle on. I intend to power this with a USB battery bank (current one is an AnkerCore Slim 10000).

My current issue is the circuit will occasionally freeze. I find that it constantly freezes when powered from a source other than my PC's USB port, but will occasionally freeze with enough rapid button presses. Sometimes it almost seems to "reset itself" and begins to work correctly again, while other times it just stays stuck.

Here are some videos of the device. Additionally, I've attached a wire diagram I made of the circuit, as well as a photo of my poor soldering job.
Working as intended while plugged into PC
Freezing while plugged into battery bank.
Freezing while plugged into battery bank.

//edit - I am using FastLED version 3.10.3

Code:
#include "FastLED.h"

#define NUM_LEDS 3
#define DATA_PIN 10

CRGB leds[NUM_LEDS];

int pushButton1 = 1;
int pushButton2 = 3;
int pushButton3 = 5;

int button1State;
int button2State;
int button3State;

int lastButton1State = LOW;
int lastButton2State = LOW;
int lastButton3State = LOW;

int ledRState = LOW;
int ledGState = LOW;
int ledBState = LOW;

// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

void setup() {
  // put your setup code here, to run once:
FastLED.addLeds<WS2812, DATA_PIN, RGB>(leds, NUM_LEDS);
  pinMode(pushButton1,INPUT_PULLDOWN);
  pinMode(pushButton2,INPUT_PULLDOWN);
  pinMode(pushButton3,INPUT_PULLDOWN);

}

void loop() {

  // read the state of switch1 into a local variable:
  int readingButton1 = digitalRead(pushButton1);
  int readingButton2 = digitalRead(pushButton2);
  int readingButton3 = digitalRead(pushButton3);

  // check to see if you just pressed the button
  // (i.e. the input went from LOW to HIGH), and you've waited long enough
  // since the last press to ignore any noise:

  // If the switch changed, due to noise or pressing:
  if (readingButton1 != lastButton1State) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer than the debounce
    // delay, so take it as the actual current state:

    // if the button state has changed:
    if (readingButton1 != button1State) {
      button1State = readingButton1;

      // only toggle the LED if the new button state is HIGH
      if (button1State == HIGH) {
        ledRState = !ledRState;
      }
    }
  }

 
  // If the switch changed, due to noise or pressing:
  if (readingButton2 != lastButton2State) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer than the debounce
    // delay, so take it as the actual current state:

    // if the button state has changed:
    if (readingButton2 != button2State) {
      button2State = readingButton2;

      // only toggle the LED if the new button state is HIGH
      if (button2State == HIGH) {
        ledGState = !ledGState;
      }
    }
  }
  // If the switch changed, due to noise or pressing:
  if (readingButton3 != lastButton3State) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer than the debounce
    // delay, so take it as the actual current state:

    // if the button state has changed:
    if (readingButton3 != button3State) {
      button3State = readingButton3;

      // only toggle the LED if the new button state is HIGH
      if (button3State == HIGH) {
        ledBState = !ledBState;
      }
    }
  }



 
if (ledRState == HIGH){
  leds[0] = CRGB(255,0,0);
}else{
  leds[0] = CRGB(0,0,0);
}

if (ledGState == HIGH){
  leds[1] = CRGB(0,255,0);
}else{
  leds[1] = CRGB(0,0,0);
}

if (ledBState == HIGH){
  leds[2] = CRGB(0,0,255);
}else{
  leds[2] = CRGB(0,0,0);
}

  FastLED.show();

  lastButton1State = readingButton1;
  lastButton2State = readingButton2;
  lastButton3State = readingButton3;
}
 

Attachments

  • Screenshot 2025-12-13 150727.png
    Screenshot 2025-12-13 150727.png
    11.5 KB · Views: 25
  • Circuit picture.jpg
    Circuit picture.jpg
    191.3 KB · Views: 27
Last edited:
@alasor31: Welcome to the world of "you can make this processor do anything you want !!" For your particular application, I would recommend taking a look at using the BOUNCE library, as it will efficiently take care of handling any switch/button bounce for you. This should make managing your buttons much simpler, allowing you to fucus more on what happens when a button is actually pressed. <Here's> a previous post in which @PaulStoffregen discusses one example of its usage.

Hope that helps . . .

Mark J Culross
KD5RXT
 
Teensy 4.x pins are not 5v tolerant - your diagram shows that's what you've wired on the high side of the switches, which will fry your Teensy. You should stop using this circuit immediately to prevent permanently damaging it.
 
@kd5rxt-mark Thanks! That dramatically reduced the size of code, made it much more readable, and the problem of rapid button presses causing a freeze has been eliminated.

However, I still freeze while plugged into any other power source besides my computer.

Here is the update code:

Code:
#include "FastLED.h"
#include <Bounce.h>

#define NUM_LEDS 3
#define DATA_PIN 10

CRGB leds[NUM_LEDS];

int pushButtonR = 1;
int pushButtonG = 3;
int pushButtonB = 5;

Bounce buttonR = Bounce(pushButtonR, 10);
Bounce buttonG = Bounce(pushButtonG, 10);
Bounce buttonB = Bounce(pushButtonB, 10);

int ledRState = LOW;
int ledGState = LOW;
int ledBState = LOW;

void setup() {
  // put your setup code here, to run once:
FastLED.addLeds<WS2812, DATA_PIN, RGB>(leds, NUM_LEDS);
  pinMode(pushButtonR,INPUT_PULLDOWN);
  pinMode(pushButtonG,INPUT_PULLDOWN);
  pinMode(pushButtonB,INPUT_PULLDOWN);

}

void loop() {

buttonR.update();
buttonG.update();
buttonB.update();

if(buttonR.risingEdge()){
  ledRState = !ledRState;
}
if(buttonG.risingEdge()){
  ledGState = !ledGState;
}
if(buttonB.risingEdge()){
  ledBState = !ledBState;
}

if (ledRState == HIGH){
  leds[0] = CRGB(255,0,0);
}else{
  leds[0] = CRGB(0,0,0);
}

if (ledGState == HIGH){
  leds[1] = CRGB(0,255,0);
}else{
  leds[1] = CRGB(0,0,0);
}

if (ledBState == HIGH){
  leds[2] = CRGB(0,0,255);
}else{
  leds[2] = CRGB(0,0,0);
}

FastLED.show();
}
 
Yikes, DO NOT wire the pushbuttons to +5V power!! Serious risk of damage to Teensy this way!

You should wire the pushbuttons to GND. The pins should use pinMode INPUT_PULLUP.
 
Back
Top