atuline

kerosene.ino

Sep 17th, 2021
919
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.   File: kerosene.ino
  3.   By: Andrew Tuline
  4.   Date: Sept 2021
  5.  
  6.   YouTube: https://youtu.be/nujPXey2Elo
  7.  
  8.   To simimulate a kerosene lantern on an Arduino Nano with WS2812 LED's and three potentiometers.
  9.  
  10.   This routine creates a sinewave envelope that limits the brightness across the length of the LED strip and uses my twinkleup routine to animate each LED.
  11.  
  12.   This routine:
  13.   - Must support strands >255 leds.
  14.   - Uses floating point math for ease of development.
  15.  
  16.   It has:
  17.   - An adjustable location from 1 up to NUM_LED/2 for the maximum brightness.
  18.   - An adjustable gamma correction in the top half (after the maximum value).
  19.   - An adjustable minimum brightness.
  20.  
  21.   Bottom half of strand has:
  22.   - A portion of a sinewave going from 0 to 255.
  23.   - A slider to control the location of maximum brightness (up to NUM_LEDS/2).
  24.   - A slider to adjust the minimum brightness.
  25.  
  26.   Top half of strand has:
  27.   - A portion of a sinewave going from 255 to 0.
  28.   - The frequency of that wave extends from end of bottom half up to NUM_LEDS-1.
  29.   - An adjustable gamma correction. Think tapering the flame.
  30.   - Minimum brightness is not applied here.
  31.  
  32.   Controls:
  33.   A2 - Upper flame height/taper (aka gamma correction).
  34.   A3 - Max brightness location (aka adjustable frequency).
  35.   A4 - Minimum brightness for bottom half of animation.
  36.  
  37.   Optional Controls:
  38.  
  39.   ?? - Blur amount.
  40.   ?? - Speed.
  41.   ?? - Colours/palette selectability
  42.  
  43. */
  44.  
  45.  
  46. #include <FastLED.h>
  47.  
  48. #define LED_DT 12
  49. #define NUM_LEDS 64
  50.  
  51. uint8_t max_bright = 255;
  52. struct CRGB leds[NUM_LEDS];
  53. CRGBPalette16 currentPalette = LavaColors_p;
  54.  
  55.  
  56. #define PI 3.1415926535
  57.  
  58. // Global variables used by controls.
  59. uint16_t lowSin;        // Adjustable midpoint/maximum brightness location of the animation.
  60. float gamma;            // Used for tapering the top half of the flame.
  61. uint8_t minBri;         // Used to control minimum brightness for bottom half of flame.
  62.  
  63.  
  64.  
  65. void setup() {
  66.   Serial.begin(115200);
  67.   LEDS.addLeds<WS2812, LED_DT, GRB>(leds, NUM_LEDS);
  68.   FastLED.setBrightness(max_bright);
  69. } // setup()
  70.  
  71.  
  72.  
  73. void loop() {
  74.   getinputs();
  75.   kerosene();
  76.   FastLED.show();
  77. } // loop()
  78.  
  79.  
  80.  
  81. void getinputs() {
  82.   lowSin = analogRead(A3) / 32;                       // The location of the highest value of the sine wave is between 0 and 31. . .
  83.   if (lowSin > NUM_LEDS / 2) lowSin = NUM_LEDS / 2;   // But not higher than halfway.
  84.   gamma = (float)(1024 - analogRead(A2)) / 128. + 1.; // Tapering/gamma correction on the top half of the wave.
  85.   minBri =  analogRead(A4) / 4;                       // Minimum brightness for the bottom half of the wave.
  86. } // getinputs()
  87.  
  88.  
  89.  
  90. void kerosene() {
  91.  
  92.   random16_set_seed(535);                                                         // Pseudo-random number seed ensures the same random numbers for every frame. Requires no array space.
  93.   uint16_t sinOut;                                                                // Envelope of brightness.
  94.   uint16_t pixBri;                                                                // Resultant pixel brightness.
  95.  
  96.   for (int i = 0; i < NUM_LEDS; i++) {
  97.     if (i < lowSin) {                                                             // Low end of the kerosene lamp.
  98.       sinOut = (127 * cos( PI + i * PI / lowSin) + 127.);                         // Create a sinewave based brightness envelope.
  99.       pixBri = beatsin8(128 / 2 + random8() / 4, 128, 255, 0, random8());         // Every pixel gets a different timebase.
  100.       pixBri = pixBri * sinOut / 255;                                             // Apply the brightness envelope.
  101.       if (pixBri < minBri) pixBri = minBri;                                       // Oops, not bright enough.
  102.     } else {                                                                      // High end of the kerosene lamp.
  103.       float temp = (float)(i - lowSin) / (NUM_LEDS - lowSin - 1);                 // Tapering high end of the flame.
  104.       sinOut = cos( PI * temp) * 128. + 127;                                      // Create a sinewave based brightness envelope.
  105.       sinOut = (float)(pow((float)sinOut / (float)255, gamma) * 255. + 0.5);      // Gamma correction applied to the envelope.
  106.       pixBri = beatsin8(128 / 2 + random8() / 4, 128, 255, 0, random8());         // Every pixel gets a different timebase.
  107.       pixBri = pixBri * sinOut / 255;                                             // Apply the brightness envelope, but with no minBri value test.
  108.     }
  109.  
  110.     //    setPixelColor(i, color_blend(SEGCOLOR(1), color_from_palette(random8()+now/100, false, PALETTE_SOLID_WRAP, 0), pixBri));  // Used for WLED.
  111.     //    leds[i] = ColorFromPalette(currentPalette, i * 20 + millis() / 100, pixBri, LINEARBLEND);                                 // Palette compatible.
  112.     leds[i] = CHSV(64, 255, pixBri);                                                                                                // Basic CHSV support.
  113.   }
  114.  
  115.   blur1d( leds, NUM_LEDS, 128);                                                   // Need to blur so it looks more like a kerosene lamp. Could be adjustable.
  116.  
  117. } // kerosene()
RAW Paste Data