13. FastLED 示例3则

Best of FastLED Discussions

1. Fire2012: FastLED 火灾模拟器

// Fire2012: a basic fire simulation for a one-dimensional string of LEDs
// Mark Kriegsman, July 2012.
//
// Compiled size for Arduino/AVR is about 3,968 bytes.
 
#include <FastLED.h>
 
#define LED_PIN     5
#define COLOR_ORDER GRB
#define CHIPSET     WS2811
#define NUM_LEDS    50
 
#define BRIGHTNESS  200
#define FRAMES_PER_SECOND 60
 
CRGB leds[NUM_LEDS];
 
void setup() {
  delay(3000); // sanity delay
  FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS);
  FastLED.setBrightness( BRIGHTNESS );
}
 
void loop()
{
  // Add entropy to random number generator; we use a lot of it.
  random16_add_entropy( random());
  
  Fire2012(); // run simulation frame
  FastLED.show(); // display this frame
  
#if defined(FASTLED_VERSION) && (FASTLED_VERSION >= 2001000)
  FastLED.delay(1000 / FRAMES_PER_SECOND);
#else  
  delay(1000 / FRAMES_PER_SECOND);
#endif  
}
 
 
// Fire2012 by Mark Kriegsman, July 2012
// as part of "Five Elements" shown here: http://youtu.be/knWiGsmgycY
//
// This basic one-dimensional 'fire' simulation works roughly as follows:
// There's a underlying array of 'heat' cells, that model the temperature
// at each point along the line.  Every cycle through the simulation, 
// four steps are performed:
//  1) All cells cool down a little bit, losing heat to the air
//  2) The heat from each cell drifts 'up' and diffuses a little
//  3) Sometimes randomly new 'sparks' of heat are added at the bottom
//  4) The heat from each cell is rendered as a color into the leds array
//     The heat-to-color mapping uses a black-body radiation approximation.
//
// Temperature is in arbitrary units from 0 (cold black) to 255 (white hot).
//
// This simulation scales it self a bit depending on NUM_LEDS; it should look
// "OK" on anywhere from 20 to 100 LEDs without too much tweaking. 
//
// I recommend running this simulation at anywhere from 30-100 frames per second,
// meaning an interframe delay of about 10-35 milliseconds.
//
//
// There are two main parameters you can play with to control the look and
// feel of your fire: COOLING (used in step 1 above), and SPARKING (used
// in step 3 above).
//
// COOLING: How much does the air cool as it rises?
// Less cooling = taller flames.  More cooling = shorter flames.
// Default 55, suggested range 20-100 
#define COOLING  55
 
// SPARKING: What chance (out of 255) is there that a new spark will be lit?
// Higher chance = more roaring fire.  Lower chance = more flickery fire.
// Default 120, suggested range 50-200.
#define SPARKING 120
 
 
void Fire2012()
{
// Array of temperature readings at each simulation cell
  static byte heat[NUM_LEDS];
 
  // Step 1.  Cool down every cell a little
    for( int i = 0; i < NUM_LEDS; i++) {
      heat[i] = qsub8( heat[i],  random8(0, ((COOLING * 10) / NUM_LEDS) + 2));
    }
  
    // Step 2.  Heat from each cell drifts 'up' and diffuses a little
    for( int k= NUM_LEDS - 3; k > 0; k--) {
      heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
    }
    
    // Step 3.  Randomly ignite new 'sparks' of heat near the bottom
    if( random8() < SPARKING ) {
      int y = random8(7);
      heat[y] = qadd8( heat[y], random8(160,255) );
    }
 
    // Step 4.  Map from heat cells to LED colors
    for( int j = 0; j < NUM_LEDS; j++) {
        leds[j] = HeatColor( heat[j]);
    }
}
 
 
 
// CRGB HeatColor( uint8_t temperature)
// [to be included in the forthcoming FastLED v2.1]
//
// Approximates a 'black body radiation' spectrum for 
// a given 'heat' level.  This is useful for animations of 'fire'.
// Heat is specified as an arbitrary scale from 0 (cool) to 255 (hot).
// This is NOT a chromatically correct 'black body radiation' 
// spectrum, but it's surprisingly close, and it's extremely fast and small.
//
// On AVR/Arduino, this typically takes around 70 bytes of program memory, 
// versus 768 bytes for a full 256-entry RGB lookup table.
 
CRGB HeatColor( uint8_t temperature)
{
  CRGB heatcolor;
  
  // Scale 'heat' down from 0-255 to 0-191,
  // which can then be easily divided into three
  // equal 'thirds' of 64 units each.
  uint8_t t192 = scale8_video( temperature, 192);
 
  // calculate a value that ramps up from
  // zero to 255 in each 'third' of the scale.
  uint8_t heatramp = t192 & 0x3F; // 0..63
  heatramp <<= 2; // scale up to 0..252
 
  // now figure out which third of the spectrum we're in:
  if( t192 & 0x80) {
    // we're in the hottest third
    heatcolor.r = 255; // full red
    heatcolor.g = 255; // full green
    heatcolor.b = heatramp; // ramp up blue
    
  } else if( t192 & 0x40 ) {
    // we're in the middle third
    heatcolor.r = 255; // full red
    heatcolor.g = heatramp; // ramp up green
    heatcolor.b = 0; // no blue
    
  } else {
    // we're in the coolest third
    heatcolor.r = heatramp; // ramp up red
    heatcolor.g = 0; // no green
    heatcolor.b = 0; // no blue
  }
  
  return heatcolor;
}

2. 二维 XY 矩阵示例

#include <FastLED.h>

#define LED_PIN 5
#define COLOR_ORDER GRB
#define CHIPSET WS2811

#define BRIGHTNESS 32

const uint8_t kMatrixWidth = 16;
const uint8_t kMatrixHeight = 16;
const bool kMatrixSerpentineLayout = true;

#define NUM_LEDS (kMatrixWidth * kMatrixHeight)
CRGB leds[NUM_LEDS];

void setup() {
  FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS);
  FastLED.setBrightness(BRIGHTNESS);
}

void loop() {
  uint32_t ms = millis();
  int32_t yHueDelta32 = ((int32_t)cos16(ms * 27) * (350 / kMatrixWidth));
  int32_t xHueDelta32 = ((int32_t)cos16(ms * 39) * (310 / kMatrixHeight));
  DrawOneFrame(ms / 65536, yHueDelta32 / 32768, xHueDelta32 / 32768);
  FastLED.show();
}

void DrawOneFrame(byte startHue8, int8_t yHueDelta8, int8_t xHueDelta8) {
  byte lineStartHue = startHue8;
  for (byte y = 0; y < kMatrixHeight; y++) {
    lineStartHue += yHueDelta8;
    byte pixelHue = lineStartHue;
    for (byte x = 0; x < kMatrixWidth; x++) {
      pixelHue += xHueDelta8;
      leds[XY(x, y)] = CHSV(pixelHue, 255, 255);
    }
  }
}

// Helper function that translates from x, y into an index into the LED array
// Handles both 'row order' and 'serpentine' pixel layouts.
uint16_t XY(uint8_t x, uint8_t y) {
  uint16_t i;

  if (kMatrixSerpentineLayout == false) {
    i = (y * kMatrixWidth) + x;
  } else {
    if (y & 0x01) {
      // Odd rows run backwards
      uint8_t reverseX = (kMatrixWidth - 1) - x;
      i = (y * kMatrixWidth) + reverseX;
    } else {
      // Even rows run forwards
      i = (y * kMatrixWidth) + x;
    }
  }

  return i;
}

3. 小数像素渲染

#include <FastLED.h>
 
#define DATA_PIN 6
#define NUM_LEDS 30
CRGB leds[NUM_LEDS];
 
 
// Anti-aliased light bar example
//   v1 by Mark Kriegsman <kriegsman@tr.org>, November 29, 2013
//
// This example shows the basics of using variable pixel brightness
// as a form of anti-aliasing to animate effects on a sub-pixel level, 
// which is useful for effects you want to be particularly "smooth".
//
// This animation shows two bars looping around an LED strip, one moving
// in blocky whole-pixel "integer" steps, and the other one moving 
// by smoothly anti-aliased "fractional" (1/16th pixel) steps.
// The use of "16ths" (vs, say, 10ths) is totally arbitrary, but 16ths are
// a good balance of data size, expressive range, and code size and speed.
//
// Notionally, "I" is the Integer Bar, "F" is the Fractional Bar.
 
int     Ipos   = NUM_LEDS / 2; // position of the "integer-based bar"
int     Idelta = 1; // how many pixels to move the Integer Bar
uint8_t Ihue = 20; // color for Integer Bar
 
int     F16pos = 0; // position of the "fraction-based bar"
int     F16delta = 1; // how many 16ths of a pixel to move the Fractional Bar
uint8_t Fhue = 20; // color for Fractional Bar
 
int Width  = 4; // width of each light bar, in whole pixels
 
int InterframeDelay = 40; //ms
 
 
void setup() {
  delay(3000); // setup guard
  FastLED.addLeds<WS2811, DATA_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(128);
}
 
// Draw an "Integer Bar" of light starting at pixel 'pos', with given 
// width (in whole pixels) and hue.
// This is not the interesting code.
void drawIntegerBar( int intpos, int width, uint8_t hue)
{
  int i = intpos; // start drawing at "I"
  for( int n = 0; n < width; n++) {
    leds[i] += CHSV( hue, 255, 255);
    i++; 
    if( i == NUM_LEDS) i = 0; // wrap around
  }
}
 
 
// 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)
{
  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, 255, bright);
    i++; 
    if( i == NUM_LEDS) i = 0; // wrap around
  }
}
 
 
void loop()
{
  // Update the "Fraction Bar" by 1/16th pixel every time
  F16pos += 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( F16pos >= (NUM_LEDS * 16)) {
    F16pos -= (NUM_LEDS * 16);
  }
    
  // For this demo, we want the Integer Bar and the Fraciton Bar
  // to move at the same speed down the strip.
  // The Fraction Bar moves 1/16th of a pixel each time through the 
  // loop, so to get the same speed on the strip for the Integer Bar, 
  // we need to move it by 1 full pixel -- but only every 16 times
  // through the loop.  'countdown' is used to tell when it's time
  // to advance the Integer Bar position again.
  static byte countdown = 0;
  if( countdown == 0) {
    countdown = 16; // reset countdown
     
    // advance Integer Bar one full pixel now
    Ipos += 1;
    // wrap around at end
    if( Ipos >= NUM_LEDS) {
      Ipos -= NUM_LEDS;   
    } 
   }
   // countdown is decremented every time through the loop
   countdown -= 1;
   
   // Draw everything:
   // clear the pixel buffer
   memset8( leds, 0, NUM_LEDS * sizeof(CRGB));
   // draw the Integer Bar, length=4px, hue=180
   drawIntegerBar( Ipos, Width, Ihue);
   // draw the Fractional Bar, length=4px, hue=180
   drawFractionalBar( F16pos, Width, Fhue);
   
   FastLED.show();
   delay(InterframeDelay);
}
相关推荐
tundra381 天前
esp8266外控LED灯颜色调节亮度
arduino
ice小游2 天前
使用ATmega328p芯片制作Arduino Uno R3开发板
嵌入式硬件·arduino·开发板·芯片·atmega328p
e调布鲁斯11 天前
esp32cam+Arduino IDE在编译时提示找不到 esp_camera.h 的解决办法
esp32·arduino
ourkix17 天前
arduino uno R3更换328pb-au芯片,烧录bootloader
嵌入式硬件·arduino
IT永勇19 天前
基于Arduino的LED亮灭按键控制
单片机·嵌入式硬件·arduino·电子设计·按键检测
_后知后觉_21 天前
竹壳天气时钟(四)UTF8转GB2312后使用HZK16字库在TFT屏幕上显示中文
开发语言·arduino·esp8266·nodemcu·st7735s·tft_espi
_后知后觉_1 个月前
基于esp8266的nodemcu实现网页配置wifi功能
arduino·esp8266·nodemcu
深海大都督1 个月前
【深海王国】初中生也能画的电路板?目录合集
单片机·嵌入式硬件·青少年编程·硬件工程·arduino·pcb工艺
IT永勇1 个月前
基于Arduino的L298N电机驱动模块使用
驱动开发·单片机·嵌入式硬件·arduino·电子设计
_后知后觉_2 个月前
使用arduino编程在基于esp8266的nodemcu开发板上实现开机自动连接wifi
arduino·esp8266·nodemcu