cookbook/troubleshooting/debugging.md
Difficulty Level: ⭐⭐ Beginner to Intermediate Time to Complete: 40-50 minutes Prerequisites:
You'll Learn:
Techniques and code examples for diagnosing and debugging FastLED projects.
Use Serial output to monitor your LED system's status and performance.
void setup() {
Serial.begin(115200);
while (!Serial) { } // Wait for serial (Leonardo/Micro only)
Serial.println("FastLED Starting...");
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
Serial.println("LEDs initialized");
}
void loop() {
// Print diagnostic info
EVERY_N_SECONDS(5) {
Serial.print("FPS: ");
Serial.println(FastLED.getFPS());
}
}
Tips:
while (!Serial) for non-USB boards (it will hang)Use this comprehensive test pattern to verify your hardware and wiring:
void testPattern() {
// Test RED
fill_solid(leds, NUM_LEDS, CRGB::Red);
FastLED.show();
delay(1000);
// Test GREEN
fill_solid(leds, NUM_LEDS, CRGB::Green);
FastLED.show();
delay(1000);
// Test BLUE
fill_solid(leds, NUM_LEDS, CRGB::Blue);
FastLED.show();
delay(1000);
// Test individual LEDs
FastLED.clear();
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB::White;
FastLED.show();
Serial.print("LED ");
Serial.println(i);
delay(100);
}
}
What this tests:
Usage: Call testPattern() from setup() or by pressing a button
Monitor RAM usage to prevent out-of-memory issues, especially on AVR boards.
void setup() {
Serial.begin(115200);
// Calculate memory usage
int ledMemory = NUM_LEDS * sizeof(CRGB);
Serial.print("LED array uses: ");
Serial.print(ledMemory);
Serial.println(" bytes");
// Check available RAM (AVR only)
#ifdef __AVR__
extern int __heap_start, *__brkval;
int freeMemory;
if ((int)__brkval == 0) {
freeMemory = ((int)&freeMemory) - ((int)&__heap_start);
} else {
freeMemory = ((int)&freeMemory) - ((int)__brkval);
}
Serial.print("Free RAM: ");
Serial.print(freeMemory);
Serial.println(" bytes");
#endif
}
Memory guidelines:
Verify color order and values are correct:
void debugColors() {
// Test if colors are correct
leds[0] = CRGB(255, 0, 0); // Should be RED
leds[1] = CRGB(0, 255, 0); // Should be GREEN
leds[2] = CRGB(0, 0, 255); // Should be BLUE
FastLED.show();
// If colors are wrong, try different COLOR_ORDER:
// RGB, RBG, GRB, GBR, BRG, BGR
}
Advanced color debugging:
void printColorValues() {
for (int i = 0; i < min(10, NUM_LEDS); i++) {
Serial.print("LED ");
Serial.print(i);
Serial.print(": R=");
Serial.print(leds[i].r);
Serial.print(" G=");
Serial.print(leds[i].g);
Serial.print(" B=");
Serial.println(leds[i].b);
}
}
Track performance and identify slowdowns:
void loop() {
updatePattern();
FastLED.show();
EVERY_N_SECONDS(1) {
uint16_t fps = FastLED.getFPS();
Serial.print("FPS: ");
Serial.println(fps);
if (fps < 30) {
Serial.println("WARNING: Low frame rate!");
}
}
}
Interpreting results:
Common causes of low FPS:
Verify LED data array hasn't been corrupted:
void validateLEDData() {
bool hasError = false;
for (int i = 0; i < NUM_LEDS; i++) {
// Check for impossible values
if (leds[i].r > 255 || leds[i].g > 255 || leds[i].b > 255) {
Serial.print("ERROR at LED ");
Serial.println(i);
hasError = true;
}
}
if (!hasError) {
Serial.println("LED data OK");
}
}
When to use:
Complete diagnostic test for hardware verification:
// Comprehensive hardware test
void hardwareTest() {
Serial.begin(115200);
delay(1000);
Serial.println("=== FastLED Hardware Test ===");
// Test 1: Single LED
Serial.println("Test 1: First LED RED");
FastLED.clear();
leds[0] = CRGB::Red;
FastLED.show();
delay(2000);
// Test 2: All RED
Serial.println("Test 2: All LEDs RED");
fill_solid(leds, NUM_LEDS, CRGB::Red);
FastLED.show();
delay(2000);
// Test 3: Color test
Serial.println("Test 3: Color sequence");
CRGB colors[] = {CRGB::Red, CRGB::Green, CRGB::Blue, CRGB::White};
for (int c = 0; c < 4; c++) {
fill_solid(leds, NUM_LEDS, colors[c]);
FastLED.show();
delay(1000);
}
// Test 4: Individual LEDs
Serial.println("Test 4: Individual LED scan");
FastLED.clear();
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB::White;
FastLED.show();
delay(50);
leds[i] = CRGB::Black;
}
Serial.println("=== Test Complete ===");
}
To use: Call hardwareTest() from setup() or create a test sketch
What it tests:
Check for timing problems with animations:
unsigned long lastFrameTime = 0;
unsigned long frameCount = 0;
void loop() {
unsigned long now = millis();
unsigned long frameTime = now - lastFrameTime;
lastFrameTime = now;
EVERY_N_SECONDS(5) {
Serial.print("Average frame time: ");
Serial.print(frameTime);
Serial.println("ms");
Serial.print("Frames in 5 sec: ");
Serial.println(frameCount);
frameCount = 0;
}
updateLEDs();
FastLED.show();
frameCount++;
}
Test components individually:
If LEDs work up to a certain point:
void findBadLED() {
int testPoint = NUM_LEDS / 2;
fill_solid(leds, testPoint, CRGB::Red);
fill_solid(&leds[testPoint], NUM_LEDS - testPoint, CRGB::Green);
FastLED.show();
// Adjust testPoint up or down based on which lights up
// Repeat until you find the exact failing LED
}
Create simplest possible sketch to isolate issues:
#include <FastLED.h>
#define LED_PIN 5
#define NUM_LEDS 10 // Start with just 10
CRGB leds[NUM_LEDS];
void setup() {
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
fill_solid(leds, NUM_LEDS, CRGB::Red);
FastLED.show();
}
void loop() {
// Empty - just show red
}