Skip to content

Instantly share code, notes, and snippets.

@jshaw
Forked from hsiboy/lightbar.ino
Created November 6, 2023 14:44
Show Gist options
  • Save jshaw/7fc0e370c7acd67add8b7c56ee55deb1 to your computer and use it in GitHub Desktop.
Save jshaw/7fc0e370c7acd67add8b7c56ee55deb1 to your computer and use it in GitHub Desktop.

Revisions

  1. @hsiboy hsiboy created this gist Jan 16, 2015.
    119 changes: 119 additions & 0 deletions lightbar.ino
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,119 @@
    // From Mark Kriegsman's Anti-aliased light bar example: http://pastebin.com/g8Bxi6zW

    #include <FastLED.h>

    #define LED_PIN 13 // hardware SPI pin SCK
    #define NUM_LEDS 250
    #define COLOR_ORDER RGB
    #define LED_TYPE WS2811
    #define MAX_BRIGHTNESS 255 // watch the power!

    struct CRGB leds[NUM_LEDS];

    int Width = 4; // width of each light bar, in whole pixels

    const int barCount = 8;
    int bars[barCount];

    int F16delta = 1; // how many 16ths of a pixel to move the Fractional Bar
    uint16_t Fhue16 = 0; // color for Fractional Bar

    int InterframeDelay = 40; //ms

    void setup()
    {
    LEDS.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
    FastLED.setBrightness(MAX_BRIGHTNESS);

    for (int i = 0; i < barCount; i++) {
    bars[i] = i * ((NUM_LEDS * 16) / barCount);
    }
    }

    // Draw a "Fractional Bar" of light starting at position 'pos16', which is counted in
    // sixteenths of a pixel from the start of the strip. Fractional positions are
    // rendered using 'anti-aliasing' of pixel brightness.
    // The bar width is specified in whole pixels.
    // Arguably, this is the interesting code.
    void drawFractionalBar(int pos16, int width, uint8_t hue, uint8_t sat)
    {
    int i = pos16 / 16; // convert from pos to raw pixel number
    uint8_t frac = pos16 & 0x0F; // extract the 'factional' part of the position

    // brightness of the first pixel in the bar is 1.0 - (fractional part of position)
    // e.g., if the light bar starts drawing at pixel "57.9", then
    // pixel #57 should only be lit at 10% brightness, because only 1/10th of it
    // is "in" the light bar:
    //
    // 57.9 . . . . . . . . . . . . . . . . . 61.9
    // v v
    // ---+---56----+---57----+---58----+---59----+---60----+---61----+---62---->
    // | | X|XXXXXXXXX|XXXXXXXXX|XXXXXXXXX|XXXXXXXX |
    // ---+---------+---------+---------+---------+---------+---------+--------->
    // 10% 100% 100% 100% 90%
    //
    // the fraction we get is in 16ths and needs to be converted to 256ths,
    // so we multiply by 16. We subtract from 255 because we want a high
    // fraction (e.g. 0.9) to turn into a low brightness (e.g. 0.1)
    uint8_t firstpixelbrightness = 255 - (frac * 16);

    // if the bar is of integer length, the last pixel's brightness is the
    // reverse of the first pixel's; see illustration above.
    uint8_t lastpixelbrightness = 255 - firstpixelbrightness;

    // For a bar of width "N", the code has to consider "N+1" pixel positions,
    // which is why the "<= width" below instead of "< width".

    uint8_t bright;
    for (int n = 0; n <= width; n++) {
    if (n == 0) {
    // first pixel in the bar
    bright = firstpixelbrightness;
    }
    else if (n == width) {
    // last pixel in the bar
    bright = lastpixelbrightness;
    }
    else {
    // middle pixels
    bright = 255;
    }

    leds[i] += CHSV(hue, sat, bright);
    i++;
    if (i == NUM_LEDS) i = 0; // wrap around
    }
    }

    void loop()
    {
    // Draw everything:
    // clear the pixel buffer
    memset8(leds, 0, NUM_LEDS * sizeof(CRGB));

    for (int i = 0; i < barCount; i++) {
    int bar = bars[i];

    // Update the "Fraction Bar" by 1/16th pixel every time
    if (i % 2 == 0)
    bar += F16delta;
    else
    bar -= F16delta;

    // wrap around at end
    // remember that F16pos contains position in "16ths of a pixel"
    // so the 'end of the strip' is (NUM_LEDS * 16)
    if (bar >= (NUM_LEDS * 16))
    bar -= NUM_LEDS * 16;
    else if (bar < 0)
    bar = (NUM_LEDS * 16) - 1;

    // draw the Fractional Bar, length=4px
    drawFractionalBar(bar, Width, 0, 0);

    bars[i] = bar;
    }

    FastLED.show();
    FastLED.delay(InterframeDelay);
    }