Advertisement
kriegsman

Anti-aliased light bar example

Nov 29th, 2013
6,338
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.48 KB | None | 0 0
  1. #include <FastLED.h>
  2.  
  3. #define DATA_PIN 6
  4. #define NUM_LEDS 30
  5. CRGB leds[NUM_LEDS];
  6.  
  7.  
  8. // Anti-aliased light bar example
  9. //   v1 by Mark Kriegsman <kriegsman@tr.org>, November 29, 2013
  10. //
  11. // This example shows the basics of using variable pixel brightness
  12. // as a form of anti-aliasing to animate effects on a sub-pixel level,
  13. // which is useful for effects you want to be particularly "smooth".
  14. //
  15. // This animation shows two bars looping around an LED strip, one moving
  16. // in blocky whole-pixel "integer" steps, and the other one moving
  17. // by smoothly anti-aliased "fractional" (1/16th pixel) steps.
  18. // The use of "16ths" (vs, say, 10ths) is totally arbitrary, but 16ths are
  19. // a good balance of data size, expressive range, and code size and speed.
  20. //
  21. // Notionally, "I" is the Integer Bar, "F" is the Fractional Bar.
  22.  
  23. int     Ipos   = NUM_LEDS / 2; // position of the "integer-based bar"
  24. int     Idelta = 1; // how many pixels to move the Integer Bar
  25. uint8_t Ihue = 20; // color for Integer Bar
  26.  
  27. int     F16pos = 0; // position of the "fraction-based bar"
  28. int     F16delta = 1; // how many 16ths of a pixel to move the Fractional Bar
  29. uint8_t Fhue = 20; // color for Fractional Bar
  30.  
  31. int Width  = 4; // width of each light bar, in whole pixels
  32.  
  33. int InterframeDelay = 40; //ms
  34.  
  35.  
  36. void setup() {
  37.   delay(3000); // setup guard
  38.   FastLED.addLeds<WS2811, DATA_PIN, GRB>(leds, NUM_LEDS);
  39.   FastLED.setBrightness(128);
  40. }
  41.  
  42. // Draw an "Integer Bar" of light starting at pixel 'pos', with given
  43. // width (in whole pixels) and hue.
  44. // This is not the interesting code.
  45. void drawIntegerBar( int intpos, int width, uint8_t hue)
  46. {
  47.   int i = intpos; // start drawing at "I"
  48.   for( int n = 0; n < width; n++) {
  49.     leds[i] += CHSV( hue, 255, 255);
  50.     i++;
  51.     if( i == NUM_LEDS) i = 0; // wrap around
  52.   }
  53. }
  54.  
  55.  
  56. // Draw a "Fractional Bar" of light starting at position 'pos16', which is counted in
  57. // sixteenths of a pixel from the start of the strip.  Fractional positions are
  58. // rendered using 'anti-aliasing' of pixel brightness.
  59. // The bar width is specified in whole pixels.
  60. // Arguably, this is the interesting code.
  61. void drawFractionalBar( int pos16, int width, uint8_t hue)
  62. {
  63.   int i = pos16 / 16; // convert from pos to raw pixel number
  64.   uint8_t frac = pos16 & 0x0F; // extract the 'factional' part of the position
  65.  
  66.   // brightness of the first pixel in the bar is 1.0 - (fractional part of position)
  67.   // e.g., if the light bar starts drawing at pixel "57.9", then
  68.   // pixel #57 should only be lit at 10% brightness, because only 1/10th of it
  69.   // is "in" the light bar:
  70.   //
  71.   //                       57.9 . . . . . . . . . . . . . . . . . 61.9
  72.   //                        v                                      v
  73.   //  ---+---56----+---57----+---58----+---59----+---60----+---61----+---62---->
  74.   //     |         |        X|XXXXXXXXX|XXXXXXXXX|XXXXXXXXX|XXXXXXXX |  
  75.   //  ---+---------+---------+---------+---------+---------+---------+--------->
  76.   //                   10%       100%      100%      100%      90%        
  77.   //
  78.   // the fraction we get is in 16ths and needs to be converted to 256ths,
  79.   // so we multiply by 16.  We subtract from 255 because we want a high
  80.   // fraction (e.g. 0.9) to turn into a low brightness (e.g. 0.1)
  81.   uint8_t firstpixelbrightness = 255 - (frac * 16);
  82.  
  83.   // if the bar is of integer length, the last pixel's brightness is the
  84.   // reverse of the first pixel's; see illustration above.
  85.   uint8_t lastpixelbrightness  = 255 - firstpixelbrightness;
  86.  
  87.   // For a bar of width "N", the code has to consider "N+1" pixel positions,
  88.   // which is why the "<= width" below instead of "< width".
  89.  
  90.   uint8_t bright;
  91.   for( int n = 0; n <= width; n++) {
  92.     if( n == 0) {
  93.       // first pixel in the bar
  94.       bright = firstpixelbrightness;
  95.     } else if( n == width ) {
  96.       // last pixel in the bar
  97.       bright = lastpixelbrightness;
  98.     } else {
  99.       // middle pixels
  100.       bright = 255;
  101.     }
  102.    
  103.     leds[i] += CHSV( hue, 255, bright);
  104.     i++;
  105.     if( i == NUM_LEDS) i = 0; // wrap around
  106.   }
  107. }
  108.  
  109.  
  110. void loop()
  111. {
  112.   // Update the "Fraction Bar" by 1/16th pixel every time
  113.   F16pos += F16delta;
  114.  
  115.   // wrap around at end
  116.   // remember that F16pos contains position in "16ths of a pixel"
  117.   // so the 'end of the strip' is (NUM_LEDS * 16)
  118.   if( F16pos >= (NUM_LEDS * 16)) {
  119.     F16pos -= (NUM_LEDS * 16);
  120.   }
  121.    
  122.   // For this demo, we want the Integer Bar and the Fraciton Bar
  123.   // to move at the same speed down the strip.
  124.   // The Fraction Bar moves 1/16th of a pixel each time through the
  125.   // loop, so to get the same speed on the strip for the Integer Bar,
  126.   // we need to move it by 1 full pixel -- but only every 16 times
  127.   // through the loop.  'countdown' is used to tell when it's time
  128.   // to advance the Integer Bar position again.
  129.   static byte countdown = 0;
  130.   if( countdown == 0) {
  131.     countdown = 16; // reset countdown
  132.      
  133.     // advance Integer Bar one full pixel now
  134.     Ipos += 1;
  135.     // wrap around at end
  136.     if( Ipos >= NUM_LEDS) {
  137.       Ipos -= NUM_LEDS;  
  138.     }
  139.    }
  140.    // countdown is decremented every time through the loop
  141.    countdown -= 1;
  142.    
  143.    // Draw everything:
  144.    // clear the pixel buffer
  145.    memset8( leds, 0, NUM_LEDS * sizeof(CRGB));
  146.    // draw the Integer Bar, length=4px, hue=180
  147.    drawIntegerBar( Ipos, Width, Ihue);
  148.    // draw the Fractional Bar, length=4px, hue=180
  149.    drawFractionalBar( F16pos, Width, Fhue);
  150.    
  151.    FastLED.show();
  152.    delay(InterframeDelay);
  153. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement