Simulation of fire

Zápisník experimentátora

Hierarchy: WS2812

This article describes an algorithm that simulates a burning fire. This is my first attempt to simulate fire. The simulation was run on NeoPixel Ring with 24 LEDs. The simulator is not designed for direct viewing. Place it next to the white wall on which it produces flickering like a real fire in the fireplace.

The simulation results, I would like to use with the LED strip 5 meters long. One effect should be this fire.

Components

We will need the following components:

  • Arduino Uno or Mini. {linkArduino}
  • Breadboard. {linkBreadboard}
  • NeoPixel Ring with 24 diodes. I bought mine from Banggood. It can also be bought on Ebay (under name led ring 24bit) and average price at the time of purchase was $ 5.6 apiece. {linkNeopixel}
  • Protective resistor 470R. {linkR}
  • Protective condensator 1000 uF. {linkC}

Protective components are necessary in order to not damage NeoPixel Ring. Details of protection are in article on powering these diodes.

The picture shows a ring with 12 diodes. Ring with 24 diodes is not very different from it and it is therefore possible to use a smaller ring after minor changes in the sketch.

Algorithm

Fire simulation is simple. We need to know the RGB value of the fire. 156,42,0 and 255,153,0 values represent shades of orange color, from which we will build our color. WS2812 LED green color is a little bit more intensive, so little of it we take, that we had more resulting color the red than green. Because these LEDs glow strong enough, we detract a little from the intensity and color brightness to get the smaller bonfire that burns instead of fire that melts the metal.

The algorithm consists of two steps:

  • Setting up all the points on the maximum value of the color of fire.
  • A random number for each diode. This value is subtracted from the maximum value of the fire. Random numbers are chosen so that we create a wider range of darker shades of the original color.
  • After all LEDs are set, follows a short period of random length, slowing down effect on the rate at which it burned around a real fire.

Programming

The significant parts of the program are given in the following lines. I relied on my previous code to control NeoPixel Ring Clock. I added a function for substraction of values by which I am darkening color of each diode.

The definition of a class that simulates a burning fire. Important functions are Draw and Subtract, which creates a darker points in fire.

// led count
#define CNT 24

uint32_t fire_color   = strip.Color ( 80,  35,  00);
uint32_t off_color    = strip.Color (  0,  0,  0);

///
/// Set all colors
///
void NeoFire::Draw()
{
Clear();

for(int i=0;i<CNT;i++)
  {
  AddColor(i, fire_color);
  int r = random(80);
  uint32_t diff_color = strip.Color ( r, r/2, r/2);
  SubstractColor(i, diff_color);
  }
  
strip.show();
}

///
/// Set color of LED
///
void NeoFire::AddColor(uint8_t position, uint32_t color)
{
uint32_t blended_color = Blend(strip.getPixelColor(position), color);
strip.setPixelColor(position, blended_color);
}

///
/// Set color of LED
///
void NeoFire::SubstractColor(uint8_t position, uint32_t color)
{
uint32_t blended_color = Substract(strip.getPixelColor(position), color);
strip.setPixelColor(position, blended_color);
}

///
/// Color blending
///
uint32_t NeoFire::Blend(uint32_t color1, uint32_t color2)
{
uint8_t r1,g1,b1;
uint8_t r2,g2,b2;
uint8_t r3,g3,b3;

r1 = (uint8_t)(color1 >> 16),
g1 = (uint8_t)(color1 >>  8),
b1 = (uint8_t)(color1 >>  0);

r2 = (uint8_t)(color2 >> 16),
g2 = (uint8_t)(color2 >>  8),
b2 = (uint8_t)(color2 >>  0);

return strip.Color(constrain(r1+r2, 0, 255), constrain(g1+g2, 0, 255), constrain(b1+b2, 0, 255));
}

///
/// Color blending
///
uint32_t NeoFire::Substract(uint32_t color1, uint32_t color2)
{
uint8_t r1,g1,b1;
uint8_t r2,g2,b2;
uint8_t r3,g3,b3;
int16_t r,g,b;

r1 = (uint8_t)(color1 >> 16),
g1 = (uint8_t)(color1 >>  8),
b1 = (uint8_t)(color1 >>  0);

r2 = (uint8_t)(color2 >> 16),
g2 = (uint8_t)(color2 >>  8),
b2 = (uint8_t)(color2 >>  0);

r=(int16_t)r1-(int16_t)r2;
g=(int16_t)g1-(int16_t)g2;
b=(int16_t)b1-(int16_t)b2;
if(r<0) r=0;
if(g<0) g=0;
if(b<0) b=0;

return strip.Color(r, g, b);
}

Object of fire simulation.

NeoFire fire(strip);

///
/// Setup
///
void setup()
{
strip.begin();
strip.show(); // Initialize all pixels to 'off'
}

///
/// Main loop
///
void loop()
{
fire.Draw();
delay(random(50,150));
}

Video

No one has such a good imagination, so you can see the resulting video on Youtube.



Video




Download

18.06.2019


Menu