====== Neopixel-Feuereffekt für das SilentBase 802 - Programmversion 1 ====== Diesem Programm liegt der Fire2012-Effekt von Mark Kriegsman aus der FastLED-Bibliothek zugrunde, der allerdings so umgeschrieben wurde, dass er mit der Adafruit NeoPixel-Bibliothek funktioniert. // Beleuchtung BeQuiet SilentBase 802 // Arduino Nano (Every) //------------------------- Eingebundene Bibliotheken ---------------------// #include // Bibliothek für die Kommunikation über OneWire #include // Bibliothek für die digitalen Temperatursensoren DS18B20 #include // Bibliothek für die NeoPixel // Debug-Level #define DEBUG_EFFECT // Ausgabe sehr vieler Daten an die serielle Schnittstelle //#define DEBUG_SENSOR // Ausgabe der Sensordaten und Betriebszustände an die serielle Schnittstelle //------------------------- Definition der Inputs und Outputs ---------------------// #define NEOPIN1 2 // NeoPixel-Strip rechte Seite #define NEOPIN2 4 // NeoPixel-Strip linke Seite #define POWERPIN 3 // Schaltet über den MOSFET die NeoPixel-Streifen ein #define LEDPIN1 6 // LED 1 #define LEDPIN2 8 // LED 2 #define ONE_WIRE_BUS 11 // Datenleitung für die Temperatursensoren DS18B20 //-------------------------- Definition der Auflösung der Temperatursensoren ----// // 9 bit resolution: 0,5°C increments, takes 94 ms for A/D conversion // 10 bit resolution: 0,25°C increments, takes 188 ms for A/D conversion // 11 bit resolution: 0,125°C increments, takes 375 ms for A/D conversion // 12 bit resolution: 0,0625°C increments, takes 750 ms for A/D conversion #define TEMPERATURE_PRECISION 11 // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs) OneWire oneWire(ONE_WIRE_BUS); // Pass our oneWire reference to Dallas Temperature. DallasTemperature sensors(&oneWire); // arrays to hold device addresses DeviceAddress sensor0, sensor1, sensor2; // Definiert die Variablen int numPixels = 71; // Anzahl der NeoPixel float temperature; // Die höchste an den drei Sensoren gemessene Temperatur int load; // Variable repäsentiert später die Differenz zwischen minimaler und maximaler Netzteillast in Prozent float temperature_min = 20; // Konfiguriert den unteren Grenzwert der Gehäusetemperatur float temperature_max = 40; // Konfiguriert den oberen Grenzwert der Gehäusetemperatur boolean LEDstate; boolean POWERstate = 0; // Wird "1" sobald der Loop aufgerufen wird int cooling; // Variable für Beleuchtungseffekt Flammen int sparkling; // Variable für Beleuchtungseffekt Flammen int cooldown; static byte heat[71]; // Ein Array für die Temperaturwerte byte t192; // Variable für Beleuchtungseffekt Flammen // Definiert die NeoPixel-Strips Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(numPixels, NEOPIN1, NEO_GRB + NEO_KHZ800); Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(numPixels, NEOPIN2, NEO_GRB + NEO_KHZ800); // Definiert die globalen RGBW-Werte byte r = 0; byte g = 0; byte b = 0; byte w = 0; // Definiert die Tracking-Variablen für die IF-Abfragen unsigned long previousMillisSensors = 0; unsigned long previousMillisLED = 0; unsigned long previousMillisEffect = 0; unsigned long previousMillisSerialPrint = 0; // Definiert die Intervalle für die IF-Abfragen int intervalSensors = 1000; // Delay für Auslesen der Temperatursensoren int intervalLED = 500; // Delay für die Ausgabe der Temperatur als Blinkfrequenz der LED2 int intervalEffect = 5; // Delay für Effekte int intervalSerialPrint = 1000; // Delay für serielle Ausgabe void setup() { digitalWrite(POWERPIN, LOW); // Schaltet den MOSFET aus Serial.begin(115200); // Initialisiere die NeoPixel-Pins pinMode(NEOPIN1, OUTPUT); pinMode(NEOPIN2, OUTPUT); pinMode(POWERPIN, OUTPUT); pinMode(LEDPIN1, OUTPUT); pinMode(LEDPIN2, OUTPUT); // Initialisiere die NeoPixel-Strips digitalWrite(POWERPIN, HIGH); strip1.begin(); // Initialisiert das Neopixel //strip1.show(); // Macht das NeoPixel sichtbar strip1.clear(); // Macht das NeoPixel aus strip2.begin(); // Initialisiert das Neopixel //strip2.show(); // Macht das NeoPixel sichtbar strip2.clear(); // Macht das NeoPixel aus // Start up the library sensors.begin(); // locate devices on the bus Serial.print("Locating devices..."); Serial.print("Found "); Serial.print(sensors.getDeviceCount(), DEC); Serial.println(" devices."); // Search for devices on the bus and assign based on an index. Ideally, // you would do this to initially discover addresses on the bus and then // use those addresses and manually assign them (see above) once you know // the devices on your bus (and assuming they don't change). // // method 1: by index if (!sensors.getAddress(sensor0, 0)) Serial.println("Unable to find address for Device 0"); if (!sensors.getAddress(sensor1, 1)) Serial.println("Unable to find address for Device 1"); if (!sensors.getAddress(sensor2, 2)) Serial.println("Unable to find address for Device 2"); // show the addresses we found on the bus Serial.print("Device 0 Address: "); printAddress(sensor0); Serial.println(); Serial.print("Device 1 Address: "); printAddress(sensor1); Serial.println(); Serial.print("Device 2 Address: "); printAddress(sensor2); Serial.println(); // set the resolution to 11 bit per device sensors.setResolution(sensor0, TEMPERATURE_PRECISION); sensors.setResolution(sensor1, TEMPERATURE_PRECISION); sensors.setResolution(sensor2, TEMPERATURE_PRECISION); Serial.print("Device 0 Resolution: "); Serial.println(sensors.getResolution(sensor0), DEC); Serial.print("Device 1 Resolution: "); Serial.println(sensors.getResolution(sensor1), DEC); Serial.print("Device 2 Resolution: "); Serial.println(sensors.getResolution(sensor2), DEC); delay (2000); } void loop() { // Aktuelle Zeit abfragen unsigned long currentMillis = millis(); // Schaltet die NeoPixel ein und initialisiert die NeoPixel if(POWERstate == 0) { POWERstate = 1; digitalWrite(LEDPIN1, HIGH); // Schaltet LED1 ein /* digitalWrite(POWERPIN, HIGH); // Schaltet den MOSFET durch strip1.begin(); // Initialisiert das Neopixel strip1.show(); // Macht das NeoPixel sichtbar //strip1.clear(); // Macht das NeoPixel aus strip2.begin(); // Initialisiert das Neopixel strip2.show(); // Macht das NeoPixel sichtbar //strip2.clear(); // Macht das NeoPixel aus */ } // Auslesen der Temperatursensoren und Berechnen einiger Variablen zur Beeinflussung des Effekts if ((unsigned long)(currentMillis - previousMillisSensors) >= intervalSensors) { // Request to all devices on the bus //temperature conversion - non-blocking / async unsigned long start = micros(); sensors.setWaitForConversion(false); // makes it async sensors.requestTemperatures(); sensors.setWaitForConversion(true); unsigned long stop = micros(); #ifdef DEBUG_SENSOR Serial.print("Time used: "); Serial.print(stop - start); Serial.println(" microseconds"); // print the device information printData(sensor0); printData(sensor1); printData(sensor2); #endif // Berechnen der höchsten Temperatur an den verfügbaren Sensoren float tempSensor0 = sensors.getTempC(sensor0); float tempSensor1 = sensors.getTempC(sensor1); float tempSensor2 = sensors.getTempC(sensor2); temperature = 0; temperature = tempSensor0; if(tempSensor1 > temperature) { temperature = tempSensor1; } if(tempSensor2 > temperature) { temperature = tempSensor2; } #ifdef DEBUG_SENSOR Serial.print("Temperature: "); Serial.print(temperature); Serial.println(" °C"); #endif // Berechenen der Blinkfrequenz von LED2 if(temperature < temperature_min) { temperature = temperature_min; } if(temperature > temperature_max) { temperature = temperature_max; } intervalLED = map(temperature, temperature_min, temperature_max, 1000, 250); #ifdef DEBUG_SENSOR Serial.print("Blink frequency LED2: "); Serial.println(intervalLED); Serial.print(" ms"); #endif // Berechnung der Netzteillast in Prozent: Bei ruhendem Desktop soll der Wert 0 sein, bei maximaler Auslastung 100 load = map(temperature, temperature_min, temperature_max, 0, 100); // Berechnung von Cooling für den Effekt Fire 2012: Legt fest, wie stark die aufsteigenden Flammen abkühlen // Werte zwischen 20 und 100 sollen am hübschesten sein, ein guter Standard ist 50 cooling = map(temperature, temperature_min, temperature_max, 100, 20); // Berechnung von Sparkling für den Effekt Fire2012: Legt fest, wie oft ein Funke auflohdert //Werte zwischen 50 und 200 sollen am hübschesten sein, ein guter Standard ist 120 sparkling = map(temperature, temperature_min, temperature_max, 30, 200); #ifdef DEBUG_EFFECT //Serial.print("load: "); Serial.print(load); Serial.print("\t"); //Serial.print("cooling: "); Serial.print(cooling); Serial.print("\t"); //Serial.print("sparkling: "); Serial.println(sparkling); #endif //Speichere die aktuelle Zeit in die zughörige Variable previousMillisSensors = currentMillis; } // Ausgabe der Temperatur als Blinkfrequenz der LED1 if ((unsigned long)(currentMillis - previousMillisLED) >= intervalLED) { if(LEDstate == 0) { digitalWrite(LEDPIN2, HIGH); //Serial.println("LED an"); LEDstate = 1; } else if(LEDstate == 1) { digitalWrite(LEDPIN2, LOW); //Serial.println("LED aus"); LEDstate = 0; } //Speichere die aktuelle Zeit in die zughörige Variable previousMillisLED = currentMillis; } // Feuer-Effekt if ((unsigned long)(currentMillis - previousMillisEffect) >= intervalEffect) { // Step 1. Cool down every cell a little for(int i = 0; i < numPixels; i++) { cooldown = random(0, ((cooling * 10) / numPixels) + 2); if(cooldown > heat[i]) { heat[i] = 0; } else { heat[i] = heat[i] - cooldown; } } // Step 2. Heat from each cell drifts 'up' and diffuses a little if( t192 > 0x80) { // hottest for(int k = numPixels - 1; k >= 2; k--) { heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2]) / 3; // muss noch angepasst werden } } else if( t192 > 0x40 ) { // middle for(int k = numPixels - 1; k >= 2; k--) { heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2]) / 3; // muss noch angepasst werden } } else { // coolest for(int k = numPixels - 1; k >= 2; k--) { heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2]) / 3; // muss noch angepasst werden } } // Step 3. Randomly ignite new 'sparks' near the bottom if(random(255) < sparkling) { int l = random(7); heat[l] = heat[l] + random(160,255); //heat[l] = random(160,255); } // Step 4. Convert heat to LED colors for(int j = numPixels -1; j >= 0; j--) { // Scale 'heat' down from 0-255 to 0-191 t192 = round((heat[j] /255.0) * 191); // calculate ramp up from byte heatramp = t192 & 0x3F; // 0..63 heatramp <<= 2; // scale up to 0..252 // figure out which third of the spectrum we're in: if( t192 > 0x80) { // hottest strip1.setPixelColor(map(j, 0, numPixels, numPixels, 0), 255, 255, heatramp); strip2.setPixelColor(map(j, 0, numPixels, numPixels, 0), 255, 255, heatramp); } else if( t192 > 0x40 ) { // middle strip1.setPixelColor(map(j, 0, numPixels, numPixels, 0), 255, heatramp, 0); strip2.setPixelColor(map(j, 0, numPixels, numPixels, 0), 255, heatramp, 0); } else { // coolest strip1.setPixelColor(map(j, 0, numPixels, numPixels, 0), heatramp, 0, 0); strip2.setPixelColor(map(j, 0, numPixels, numPixels, 0), heatramp, 0, 0); } } strip1.show(); strip2.show(); //Speichere die aktuelle Zeit in die zughörige Variable previousMillisEffect = currentMillis; } } // function to print a device address void printAddress(DeviceAddress deviceAddress) { for (uint8_t i = 0; i < 8; i++) { // zero pad the address if necessary if (deviceAddress[i] < 16) Serial.print("0"); Serial.print(deviceAddress[i], HEX); } } // function to print the temperature for a device void printTemperature(DeviceAddress deviceAddress) { float tempC = sensors.getTempC(deviceAddress); Serial.print("Temp C: "); Serial.print(tempC); } // function to print a device's resolution void printResolution(DeviceAddress deviceAddress) { Serial.print("Resolution: "); Serial.print(sensors.getResolution(deviceAddress)); Serial.println(); } // main function to print information about a device void printData(DeviceAddress deviceAddress) { Serial.print("Device Address: "); printAddress(deviceAddress); Serial.print(" "); printTemperature(deviceAddress); Serial.println(); } {{tag>Arduino Neopixel PC}}