====== Flackerndes Windlicht - Programmversion 0.3 ====== Der Nachteil der [[arduino:flackerndes_windlicht:programmversion_0.2|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 #include #include #include // 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