Benutzer-Werkzeuge

Webseiten-Werkzeuge


arduino:flackerndes_windlicht:programmversion_0.3

Flackerndes Windlicht - Programmversion 0.3

Der Nachteil der Programmversion 0.2 ist, dass die Flamme sich nur auf einer Kreisbahn bewegen kann. Das ist schon recht effektvoll, aber nur eine lausige Simulation der Bewegung einer echten Flamme im Windzug. Daher habe ich den Code in dieser Programmversion vollständig überarbeitet.

Ab dieser Programmversion kann sich die Flamme über die gesamte Kreisfläche bewegen, die der NeoPixel-Ring umschließt. Die Variable „deviance“ beschreibt die Ablenkung der Flamme aus der Mittelstellung, die Variable „angle“ den Winkel der Ablenkung und die Variable „flickerDepth“ die Stärke des Flackerns. Die Variable „FlickerDepth“ wirkt sich global auf die Helligkeit aller NeoPixel aus, da sie ein Multiplikator ist aber auf die helleren stärker als auf die dunkleren. Was mir sehr gut gefällt ist, dass der Algorithmus sehr kompakt ist.

// Flickering and fluttering candle
// This code emulates a candle using a ring of twelve NeoPixels
// Version 0.4.3
// by Frickelpiet

// Libraries
#include <Adafruit_NeoPixel.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_TSL2561_U.h>

// Define output pin
#define PIN 2
 
// Define the NeoPixel ring
int numPixels = 12;                                     // Number of NeoPixels 
Adafruit_NeoPixel ring = Adafruit_NeoPixel(numPixels, PIN, NEO_GRBW + NEO_KHZ800);

// Define the light seensor (TSL2561)
Adafruit_TSL2561_Unified tsl = Adafruit_TSL2561_Unified(TSL2561_ADDR_FLOAT, 12345);

// Variables
int mode = 0;                                           // Mode of the flame's flickering and fluttering

double deviation = 0;                                   // Value for the flame's deviation from the center of the candle (min: 0; max: 1)
double angle = 0;                                       // Angle of the flame's deviation from the center (min: 0; max: 359)
double flickering;                                      // Value for the flame's flickering (min: 0; max: 1000)
int brightness = 255;                                   // Value for the flame's brightness (min: 0; max: 255)

double pi = 3.14159265358979;                           // Pi
double angleArray[12];                                  // Array für die Winkelpositionen der NeoPixel
double deviationArray[12];                              // Array für die d-Werte für jedes einzelne NeoPixel
byte flameArray[12];

double flickerDepth;                                    // (min: 0; max: 1000)
double deviationAlteration;                             // (min: 0; max: 1000)
double deviationTreshold;                               // (min: 0; max: 1)
double angleAlteration;                                 // (min: 0; max: 1000)

float sensorValue;

unsigned long previousMillisProgram = 0;                // Program
unsigned long previousMillisCandle = 0;                 // Emulation
unsigned long previousMillisBrightness = 0;             // Brightness

unsigned long intervalProgram = 50;                     // Program
unsigned long intervalCandle = 20;                      // Emulation
unsigned long intervalBrightness = 200;                 // Brightness

void setup() {
  Serial.begin(115200);

  if(!tsl.begin())
  {
    /* There was a problem detecting the TSL2561 ... check your connections */
    Serial.print("Ooops, no TSL2561 detected ... Check your wiring or I2C ADDR!");
    while(1);
  }
    sensor_t sensor;
  tsl.getSensor(&sensor);
  Serial.println("------------------------------------");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println(" lux");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println(" lux");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println(" lux");  
  Serial.println("------------------------------------");
  Serial.println("");
  delay(500);
  
    /* You can also manually set the gain or enable auto-gain support */
  tsl.setGain(TSL2561_GAIN_1X);      /* No gain ... use in bright light to avoid sensor saturation */
  // tsl.setGain(TSL2561_GAIN_16X);     /* 16x gain ... use in low light to boost sensitivity */
  // tsl.enableAutoRange(true);            /* Auto-gain ... switches automatically between 1x and 16x */
  
  /* Changing the integration time gives you better sensor resolution (402ms = 16-bit data) */
  tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS);      /* fast but low resolution */
  // tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_101MS);  /* medium resolution and speed   */
  // tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_402MS);  /* 16-bit data but slowest conversions */

  /* Update these values depending on what you've set above! */  
  Serial.println("------------------------------------");
  Serial.print  ("Gain:         "); Serial.println("Auto");
  Serial.print  ("Timing:       "); Serial.println("13 ms");
  Serial.println("------------------------------------");

  randomSeed(analogRead(6));

  // Calculate the angle for each NeoPixel
  angleArray[0] = 0;
  for (int i = 0; i < numPixels - 1; i++) {
    angleArray[i + 1] = angleArray[i] + pi / (numPixels / 2);
  }
  for(int i = 0; i < numPixels; i++) {
      Serial.println(angleArray[i]);
    }
  
  ring.begin();
  ring.show();                                         // Initialize all pixels to 'off'

}


void loop() {
  // Get current time in microseconds
  unsigned long currentMillis = millis(); 

// Program modes
  if ((unsigned long)(currentMillis - previousMillisProgram) >= intervalProgram) {

    mode = random(0, 4);
    //mode = 4;
    
    // Calm burning
    if (mode == 0) {
      intervalCandle = random(80, 100);
      flickerDepth = 940;
      deviationAlteration = 50;
      deviationTreshold = 0.5;
      angleAlteration = 30;
      intervalProgram = random(1000, 30000);
      Serial.print("Calm burning: "); Serial.print(intervalCandle); Serial.print(", "); Serial.println(intervalProgram);
    }
    
    // Gentle flickering
    if (mode == 1) {
      intervalCandle = random(60, 80);
      flickerDepth = 900;
      deviationAlteration = 100;
      deviationTreshold = 0.6;
      angleAlteration = 60;
      intervalProgram = random(1000, 20000);
      Serial.print("Gentle flickering: "); Serial.print(intervalCandle); Serial.print(", "); Serial.println(intervalProgram);
    }

    // Moderate flickering
    if (mode == 2) {
      intervalCandle = random(50, 60);
      flickerDepth = 850;
      deviationAlteration = 150;
      deviationTreshold = 0.7;
      angleAlteration = 90;
      intervalProgram = random(1000, 10000);
      Serial.print("Moderatemoderat flickering: "); Serial.print(intervalCandle); Serial.print(", "); Serial.println(intervalProgram);
    }

    // Noticeabal flickering
    if (mode == 3) {
      intervalCandle = random(40, 50);
      flickerDepth = 800;
      deviationAlteration = 200;
      deviationTreshold = 0.8;
      angleAlteration = 120;
      intervalProgram = random(1000, 8000);
      Serial.print("Noticeable flickering: "); Serial.print(intervalCandle); Serial.print(", "); Serial.println(intervalProgram);
    }

    // Strong flickering
    if (mode == 4) {
      intervalCandle = random(30, 50);
      flickerDepth = 750;
      deviationAlteration = 250;
      deviationTreshold = 1.0;
      angleAlteration = 240;
      intervalProgram = random(1000, 5000);
      Serial.print("Strong flickering: "); Serial.print(intervalCandle); Serial.print(", "); Serial.println(intervalProgram);
    }

  previousMillisProgram = currentMillis;
  }  

  
  // Emulation of the flame's flickering and fluttering
  if ((unsigned long)(currentMillis - previousMillisCandle) >= intervalCandle) {


    // Calculation of the flame's deviation from the center
    deviation = deviation + double(random(-deviationAlteration, deviationAlteration)) / 1000;
    if (deviation < 0) {
      deviation = 0;
    }
    if (deviation > deviationTreshold) {
      deviation = deviationTreshold;
    }
    
   
    // Calculation of the angle of the flame's deviation
    angle = angle + double(random(-angleAlteration, angleAlteration)) / 1000 * pi;
    if (angle < 0) {
      angle = angle + 2 * pi;
    }
    if (angle > 2 * pi) {
      angle = angle - 2 * pi;
    }


    // Calculation of the flame's flickering
    flickering = double(random(flickerDepth, 1000)) / 1000;

    Serial.print("m:"); Serial.print(mode);
    Serial.print(" d:"); Serial.print(deviation);
    Serial.print(" w:"); Serial.print(angle);
    Serial.print(" f:"); Serial.print(flickering);
    Serial.print(" s:"); Serial.print(sensorValue);
    Serial.print(" b:"); Serial.print(brightness);
    Serial.print("   "); 
    
    
    // Calculation of the d values for the twelve NeoPixel
    for (int i = 0; i < numPixels; i++) {
      deviationArray[i] = (((cos(angleArray[i] - angle) / (2 / deviation)) + 0.5));
    }

    // Calculation of the flickering and brithness fpr the twelve NeoPixel
    for (int i = 0; i < numPixels; i++) {
      flameArray[i] = byte(deviationArray[i] * flickering * brightness);
    }

    // Calculation of the colors for the twelve NeoPixel
    for (int i = 0; i < numPixels; i++) {
      ring.setPixelColor(i, flameArray[i], flameArray[i] / 3.2, flameArray[i] / 25, flameArray[i] / 15);
      //ring.setPixelColor(i, flameArray[i], flameArray[i] / 3.2, flameArray[i] / 25, 0);
    }
    
    ring.show();



    for(int i = 0; i < numPixels; i++) {
      Serial.print(deviationArray[i]); Serial.print(" ");
    }
    for(int i = 0; i < numPixels; i++) {
      Serial.print(byte(flameArray[i] * 255)); Serial.print(" ");
    }
    
    Serial.println();

   previousMillisCandle = currentMillis;
  }


  // Brightness control
  if ((unsigned long)(currentMillis - previousMillisBrightness) >= intervalBrightness) {

    /* Get a new sensor event */ 
    sensors_event_t event;
    tsl.getEvent(&event);
    sensorValue = event.light;

    brightness = int(sqrt(sensorValue * 100) * 2);

    if (brightness < 192) {
      brightness = 128;
    }
    if (brightness > 255) {
      brightness = 255;
    }
   
    previousMillisBrightness = currentMillis;
  }
  
}

Tags: #Arduino #NeoPixel #Windlicht

arduino/flackerndes_windlicht/programmversion_0.3.txt · Zuletzt geändert: 18.05.2023 12:34 von 127.0.0.1