Skip to content

Instantly share code, notes, and snippets.

@jshaw
Forked from hsiboy/lightbar.ino
Created November 6, 2023 14:44
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jshaw/7fc0e370c7acd67add8b7c56ee55deb1 to your computer and use it in GitHub Desktop.
Save jshaw/7fc0e370c7acd67add8b7c56ee55deb1 to your computer and use it in GitHub Desktop.
WS2811 - lightbar - FastLED
// 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);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment