Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

23 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

LuxLib

Team 71881M Mutex logo

Object-oriented addressable LED control for VEX V5 robots.
Built on PROS Β· Non-blocking tasks Β· Zone system Β· Frame-based playback

Built and maintained by Team 71881M "Mutex" (Capital Cougars) for VEX V5RC.

PROS License Hardware Team GitHub downloads

πŸ“– Full Docs Β· 🎨 Animation Designer


Features

Feature Details
🎨 14 Procedural Animations Rainbow, Meteor, Fire, Scanner, Bounce, Pulse, Breathe, Strobe, Theater Chase, Wipe, Sparkle, Confetti, Cycle
🎞️ Frame-Based Animation C-array pixel sequences with loop, cycle, and timed playback
πŸ—ΊοΈ Named Zone System Independent named sub-ranges per strip β€” overlap detection included
⚑ Non-Blocking Every animation runs in a dedicated PROS background task
🌈 HSV + RGB Math Conversion, interpolation, scaling, blending
πŸ’‘ Brightness Pipeline Global per-strip brightness applied at write time
πŸ”Œ ADI Expander Support First-class V5 expander support

Installation

Method 1 β€” PROS Template (Recommended)

Download the latest luxlib@X.X.X.zip from the Releases page, then:

pros c fetch luxlib@1.0.0.zip
pros c apply luxlib

Done. #include "luxlib/luxlib.hpp" is now available.

Method 2 β€” Manual

  1. Copy luxlib.hpp β†’ include/ and led_control.cpp β†’ src/
  2. Create include/luxlib/designs/ with an empty designs.h inside
  3. Add #include "luxlib/luxlib.hpp" wherever needed

Note: If using the ADI Expander, ensure main.h includes expander headers before luxlib.hpp.


Quick Start

#include "luxlib/luxlib.hpp"
using namespace luxlib;

// Expander port 1, ADI port 'A', 60 LEDs
LedStrip drive(1, 'A', 60, "DriveLEDs");

void initialize() {
    drive.set_all(LED_BLUE);
}

void autonomous() {
    drive.animate_fire();           // Runs in background
}

void opcontrol() {
    drive.animate_rainbow();        // Loops forever, non-blocking

    while (true) {
        // Robot code here
        pros::delay(20);
    }
}

Direct brain wiring? Pass 0 as the expander port: LedStrip strip(0, 'A', 30);


Core Concepts

The LedStrip Object

// LedStrip(expander_port, adi_port, num_leds, name = "LedStrip")
LedStrip intake(0, 'B', 20, "Intake");      // Brain port B, 20 LEDs
LedStrip drive(1, 'A', 60, "Drive");        // Expander port 1, ADI A, 60 LEDs

Multiple strips operate fully independently β€” tasks, zones, and brightness do not interact.

Color Constants

All 14 constants are uint32_t in 0xRRGGBB format:

LED_OFF  LED_RED  LED_GREEN  LED_BLUE  LED_WHITE  LED_YELLOW
LED_ORANGE  LED_PURPLE  LED_CYAN  LED_PINK  LED_WARM  LED_TEAL  LED_LIME  LED_INDIGO

You can also use any hex literal or the color utilities:

strip.set_all(0xFF4500);                  // Orange-red
strip.set_all(rgb_to_hex(100, 200, 50));  // From components

Zone System

// add_zone(name, start, end) β€” inclusive on both ends
strip.add_zone("Drive",   0,  39);
strip.add_zone("Intake",  40, 49);
strip.add_zone("Shooter", 50, 59);

// Pass zone name to any animate_* or fill call. "" = full strip.
strip.fill_zone("Intake", LED_GREEN);
strip.animate_breathe(LED_CYAN, 15, "Drive");

Overlapping zones are rejected with a terminal error.

Brightness & Buffer

strip.set_brightness(0.3f);   // 30% β€” applied at write time, buffer unchanged
strip.turn_off();             // Save buffer, cut hardware output
strip.turn_on();              // Restore buffer, re-enable output

strip.save_buffer();          // Snapshot state
strip.load_buffer();          // Restore snapshot

// In-place manipulation
strip.rotate(3);              // Rotate right 3 positions
strip.gradient(0, 59, LED_RED, LED_BLUE, true);  // HSV gradient
strip.pulse(LED_WHITE, 15, 6);                    // Soft pulse at pos 15

Procedural Animations

Calling any animate_* stops the current animation and starts the new one immediately.

strip.animate_rainbow();
strip.timeout(5000);     // Auto-stop after 5s (non-blocking)
strip.set_cycles(3);     // Auto-stop after 3 cycles
strip.stop();            // Stop and clear immediately
Animation Defaults Description
animate_pulse (color, width=8, step_ms=30, zone="", reverse=false, bg=OFF) Band sweeps, wrapping
animate_bounce (color, width=6, step_ms=20, zone="", bg=OFF) Band bounces end to end
animate_scanner (color, width=8, step_ms=20, zone="") KITT-style with fade tail
animate_breathe (color, step_ms=10, zone="") Quadratic in/out fade loop
animate_rainbow (step_ms=20, reverse=false, speed=1.0f, zone="") Full-spectrum scroll
animate_cycle (colors[], count, step_ms=30, reverse=false, zone="") Scroll a custom palette
animate_strobe (color, on_ms=50, off_ms=50, bg=OFF, zone="") Timed flash
animate_theater_chase (color, bg=OFF, step_ms=50, spacing=3, reverse=false, zone="") Marquee scroll
animate_meteor (color, size=6, tail_fade=0.7f, step_ms=20, reverse=false, zone="") Comet with fading tail
animate_wipe (color, step_ms=20, reverse=false, bg=OFF, zone="") Fill one LED at a time
animate_sparkle (color, density=3, step_ms=30, bg=OFF, zone="") Random flashing pixels
animate_confetti (colors[], count, density=3, step_ms=30, zone="") Sparkle from palette
animate_fire (intensity=0.8f, step_ms=30, reverse=false, zone="") Cellular automaton fire

Frame-Based Animations

Define exact pixel layouts as C arrays and play them at runtime β€” ideal for logo reveals, alliance intros, and match sequences.

static const uint32_t frame0[60] = { 0xFF0000, 0xFF0000, /* ... */ };
static const uint32_t frame1[60] = { /* ... */ };

static const LedFrame frames[] = {
    { frame0, 200 },
    { frame1, 200 },
};
const LedAnimation my_anim = { frames, 2, true };  // loop = true

strip.show(frame);                // Hold forever
strip.show(frame, 2000);          // Hold 2s then clear
strip.play(my_anim, 5000);        // Play for 5s
strip.play_cycles(my_anim, 3);    // Play 3 loops

LED Animation Designer

LuxLib ships a browser-based pixel editor. Paint frames on a 60-LED model, build a timeline, and export ready-to-compile C code β€” no server required.

β–Ά Open the Animation Designer

Workflow:

  1. Open led_designer.html in any browser
  2. Paint LEDs β†’ Save Frame β†’ repeat
  3. Export Animation (.c) β†’ drop into project
  4. #include it in designs.h
// designs.h
#include "my_reveal.c"
// usage
extern const LedAnimation my_reveal;
strip.play_cycles(my_reveal, 1);  // Play once at match start

Examples

Zone-Based State Feedback

strip.add_zone("Drive",   0,  39);
strip.add_zone("Intake",  40, 49);
strip.add_zone("Shooter", 50, 59);

void opcontrol() {
    strip.animate_breathe(LED_BLUE, 15, "Drive");
}
void on_intake_active()   { strip.fill_zone("Intake", LED_GREEN); }
void on_shooter_spinup()  { strip.animate_strobe(LED_YELLOW, 80, 80, LED_OFF, "Shooter"); }
void on_shooter_ready()   { strip.fill_zone("Shooter", LED_GREEN); }

Multi-Strip Setup

LedStrip left(1, 'A', 30, "Left");
LedStrip right(1, 'B', 30, "Right");
LedStrip intake(0, 'C', 15, "Intake");

void opcontrol() {
    left.animate_rainbow();
    right.animate_rainbow(20, true);   // Mirrored
    intake.animate_breathe(LED_GREEN);
    // All three run simultaneously
}

FAQ

My LEDs flicker or show wrong colors.
WS2812B requires a 5V data line. If the V5 brain outputs 3.3V on ADI, use a level shifter. Also check strip data direction β€” WS2812Bs are unidirectional.

Can I run two animations on two zones simultaneously?
Not with one LedStrip object β€” it has one task slot. Use two LedStrip instances, or write a custom PROS task that calls fill_zone for each zone in a loop.

Does stop() block?
No. It removes the task and clears the strip synchronously and returns in microseconds.

What if I call animate_* while another animation is running?
The new call invokes stop() internally, kills the running task, and starts immediately.


Contributing

PRs and issues are welcome. When adding a new animation, also add an entry to the LuxAnimType enum in luxlib.hpp and a wrapper in led_control.cpp following the existing pattern.


LuxLib is developed by Team 71881M "Mutex" (Capital Cougars). Not affiliated with VEX Robotics or PROS. WS2812B is a trademark of Worldsemi.

About

VEX V5 Object-oriented addressable WS2812B LED control library built on PROS. Non-blocking animations, named zones, frame playback. Built by Team 71881M Mutex.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages