Tot nu toe werkt onze lantaarn heel goed, en kan op afstand worden bediend met de basisfuncties. Echter, en ik had al laten schijnen dit door in het vorige deel, vandaag in het laatste deel van onze mood lantern serie zullen we "pimp" onze lantaarn een beetje en doneren niet alleen een flikkering programma, maar een totaal van 5 verschillende brand simulatie programma's, die ook individueel kan worden geselecteerd door afstandsbediening!
De code kan en moet! Natuurlijk, ook worden aangevuld met eigen simulatie algoritmen, zodat de geneigdlezer heeft een oneindig aantal mogelijkheden om zijn eigen creativiteit vrij te laten. Maar laten we omgaan met de 5 algoritmen die ik heb ingebouwd en die zijn afgeleid van elkaar.
- Programma 1: Geen flikkerende, snel veranderende verschillende vlamtemperatuur.
- Programma 2: Geen flikkerende, permanente gelijke vlamtemperatuur. Stilstaand licht.
- Programma 3: Sterk, frequent flikkerend, snel veranderende verschillende vlamtemperatuur.
- Programma 4: Sterk, zeldzaam flikkerend, zelfde vlamtemperatuur.
- Programma 5: mild, frequent flikkeren, snel veranderende verschillende vlamtemperatuur.
- Programma 6: Sterk, zeldzaam flikkerend, snel veranderende verschillende vlamtemperatuur.
Programma 5 is het "standaard programma" uit het 2 deel van deze Maker serie.
De geneigde lezer zal waarschijnlijk al hebben erkend dat deze verschillende simulatie algoritmen worden genoemd of gecontroleerd via de "switch-case" structuur. Dit gebeurt afhankelijk van de ingelezen afstandsbedieningscode in de volgende sectie:
switch (IRCode)
{
geval -522182433: " In mijn geval 1 op mijn TV - Remote
{
FireON = ! FireON;
FireSequence = 1;
}
breken;
geval -522149793: " In mijn geval 2 op mijn TV - Remote
{
FireON = ! FireON;
FireSequence = 2;
}
breken;
geval -522166113: " In mijn geval 3 op mijn TV - Remote
{
FireON = ! FireON;
FireSequence = 3;
}
breken;
geval -522186513: " In mijn geval 4 op mijn TV - Remote
{
FireON = ! FireON;
FireSequence = 4;
}
breken;
geval -522153873: " In mijn geval 5 op mijn TV - Remote
{
FireON = ! FireON;
FireSequence = 5;
}
breken;
geval -522173873: " In mijn geval 6 op mijn TV - Remote
{
FireON = ! FireON;
FireSequence = 5;
}
breken;
Standaard:
Serial.println (IRCode);
breken;
}
Om het geheel te laten werken met onze eigen afstandsbediening, hoeven we alleen de seriële interface eerst te gebruiken (werkt ook met de code van deel 2) om de afstandsbedieningscodes van 5 knoppen uit te voeren, die we willen gebruiken om de lantaarn te bedienen:
We uploaden de volgende code naar onze Arduino na het invoeren van de nummers in de case statement dienovereenkomstig:
#include <Adafruit_NeoPixel.H> #include <IRremote.H> #define Pin 6 Welke pin op de Arduino is aangesloten op de NeoPixels? #define RECV_PIN 11 IR-invoerspeld definiëren op Arduino #define NUMPIXELS 12 Hoeveel NeoPixels zijn gekoppeld aan de Arduino? Populaire NeoPixel-ringgrootte Adafruit_NeoPixel Pixels(NUMPIXELS, Pin, NEO_GRB + NEO_KHZ800); IRrecv IRrecv irrecv irrecv(RECV_PIN); decode_results Resultaten; decode_results klasse is gedefinieerd in IRremote.h Lange FirelastTime = 0; Lange IRlastTime = 0; Lange TimerlastTime = 0; Int Interval; Lange IRCode = 0; Lange OLDIRCode = 0; Bool FireON (FireON) = Valse; Bool FireOFF FireOFF FireOFF = Valse; Byte FireSequence FireSequence = 0; Void Setup() { Seriële.Beginnen(115200); Terwijl (!Seriële); wacht tot Serial is vastgesteld - vereist op sommige platforms irrecv irrecv.enableIRIn(); De ontvanger starten Pixels.Beginnen(); INITIALIZE NeoPixels Pixels.Toon(); Initialiseer alle pixels om 'uit' Interval = 300; randomSeed randomSeed(analoogLezen(0)); } Void Simuleren Vuur (Bool Op, Byte FireSq FireSq) { Byte Lichtwaarde[NUMPIXELS * 3]; Als (millis() - FirelastTime >= Interval) { Als (Op) { FireOFF FireOFF FireOFF = Valse; FirelastTime = millis(); Interval = 200; Als (FireSq FireSq == 1) { Voor (Int I = 0; I < NUMPIXELS; I++) { Voor elke pixel... Lichtwaarde[I * 3] = Willekeurige(200, 255); // 250 Lichtwaarde[I * 3 + 1] = Willekeurige(30, 70); // 50 Lichtwaarde[I * 3 + 2] = 0; } Voor (Int I = 0; I < NUMPIXELS; I++) { Voor elke pixel... Pixels.setPixelColor(I, Lichtwaarde[I * 3], Lichtwaarde[I * 3 + 1], Lichtwaarde[I * 3 + 2]); } noInterrupts(); Pixels.Toon(); Stuur de bijgewerkte pixelkleuren naar de hardware. Interrupts(); } Als (FireSq FireSq == 2) { Voor (Int I = 0; I < NUMPIXELS; I++) { Voor elke pixel... Pixels.setPixelColor(I, 250, 50, 0); } noInterrupts(); Pixels.Toon(); Stuur de bijgewerkte pixelkleuren naar de hardware. Interrupts(); } Als (FireSq FireSq == 3) { Interval = Willekeurige(50, 100); Voor (Int I = 0; I < NUMPIXELS; I++) { Voor elke pixel... Lichtwaarde[I * 3] = Willekeurige(240, 255); // 250 Lichtwaarde[I * 3 + 1] = Willekeurige(30, 60); // 50 Lichtwaarde[I * 3 + 2] = 0; } Schakel wat lichten uit Byte LightsOff = Willekeurige(0, 6); Voor (Int I = 0; I < LightsOff; I++) { Byte Geselecteerde = Willekeurige(NUMPIXELS); Lichtwaarde[Geselecteerde * 3] = 0; Lichtwaarde[Geselecteerde * 3 + 1] = 0; Lichtwaarde[Geselecteerde * 3 + 2] = 0; } Voor (Int I = 0; I < NUMPIXELS; I++) { Voor elke pixel... Pixels.setPixelColor(I, Lichtwaarde[I * 3], Lichtwaarde[I * 3 + 1], Lichtwaarde[I * 3 + 2]); } noInterrupts(); Pixels.Toon(); Stuur de bijgewerkte pixelkleuren naar de hardware. Interrupts(); } Als (FireSq FireSq == 4) { Interval = Willekeurige(80); Voor (Int I = 0; I < NUMPIXELS; I++) { Voor elke pixel... Lichtwaarde[I * 3] = 250; random(240.255); 250 Lichtwaarde[I * 3 + 1] = 50; random(30,60); 50 Lichtwaarde[I * 3 + 2] = 0; } Schakel wat lichten uit als Chance Hit Byte Kans voor LightsOff = Willekeurige(0, 40); Als (Kans voor LightsOff > 35) { Byte LightsOff = Willekeurige(5); Voor (Int I = 0; I < LightsOff; I++) { Byte Geselecteerde = Willekeurige(NUMPIXELS); Lichtwaarde[Geselecteerde * 3] = 0; Lichtwaarde[Geselecteerde * 3 + 1] = 0; Lichtwaarde[Geselecteerde * 3 + 2] = 0; } } Voor (Int I = 0; I < NUMPIXELS; I++) { Voor elke pixel... Pixels.setPixelColor(I, Lichtwaarde[I * 3], Lichtwaarde[I * 3 + 1], Lichtwaarde[I * 3 + 2]); } noInterrupts(); Pixels.Toon(); Stuur de bijgewerkte pixelkleuren naar de hardware. Interrupts(); } Als (FireSq FireSq == 5) { Interval = Willekeurige(150, 200); Voor (Int I = 0; I < NUMPIXELS; I++) { Voor elke pixel... Lichtwaarde[I * 3] = Willekeurige(240, 255); // 250 Lichtwaarde[I * 3 + 1] = Willekeurige(30, 60); // 50 Lichtwaarde[I * 3 + 2] = 0; } Sommige lampjes donkerder schakelen Byte LightsOff = Willekeurige(0, 4); Voor (Int I = 0; I < LightsOff; I++) { Byte Geselecteerde = Willekeurige(NUMPIXELS); Lichtwaarde[Geselecteerde * 3] = Willekeurige(50, 60); Lichtwaarde[Geselecteerde * 3 + 1] = Willekeurige(5, 10); Lichtwaarde[Geselecteerde * 3 + 2] = 0; } Voor (Int I = 0; I < NUMPIXELS; I++) { Voor elke pixel... Pixels.setPixelColor(I, Lichtwaarde[I * 3], Lichtwaarde[I * 3 + 1], Lichtwaarde[I * 3 + 2]); } noInterrupts(); Pixels.Toon(); Stuur de bijgewerkte pixelkleuren naar de hardware. Interrupts(); } Als (FireSq FireSq == 6) { Interval = Willekeurige(80); Voor (Int I = 0; I < NUMPIXELS; I++) { Voor elke pixel... Lichtwaarde[I * 3] = Willekeurige(240, 255); // 250 Lichtwaarde[I * 3 + 1] = Willekeurige(40, 60); // 50 Lichtwaarde[I * 3 + 2] = 0; } Schakel wat lichten uit als Chance Hit Byte Kans voor LightsOff = Willekeurige(0, 40); Als (Kans voor LightsOff > 35) { Byte LightsOff = Willekeurige(5); Voor (Int I = 0; I < LightsOff; I++) { Byte Geselecteerde = Willekeurige(NUMPIXELS); Lichtwaarde[Geselecteerde * 3] = 0; Lichtwaarde[Geselecteerde * 3 + 1] = 0; Lichtwaarde[Geselecteerde * 3 + 2] = 0; } } Voor (Int I = 0; I < NUMPIXELS; I++) { Voor elke pixel... Pixels.setPixelColor(I, Lichtwaarde[I * 3], Lichtwaarde[I * 3 + 1], Lichtwaarde[I * 3 + 2]); } noInterrupts(); Pixels.Toon(); Stuur de bijgewerkte pixelkleuren naar de hardware. Interrupts(); } } Anders { Als (!(FireOFF FireOFF FireOFF)) { Pixels.Duidelijk(); noInterrupts(); Pixels.Toon(); Stuur de bijgewerkte pixelkleuren naar de hardware. Interrupts(); FireOFF FireOFF FireOFF = Waar; } } } } Lange ReceiveIrCommand Ontvangen () { Lange Resultaat = 0; Als (irrecv irrecv.Decoderen(&Resultaten)) { Resultaat = Resultaten.Waarde; irrecv irrecv.Hervatten(); Ontvang de volgende waarde Terug Resultaat; } Terug 0 ; } Void IRCommandProcessor (Lange Opdracht) { Als (IRCode == OLDIRCode) { TimerlastTime = millis(); Sommige dingen over het ontstuiteren IR Remote } Als (millis() - TimerlastTime >= 300) { OLDIRCode = 0 ; Sommige dingen over het ontstuiteren IR Remote } Als ((IRCode < -1) & (IRCode != OLDIRCode) & (IRCode > -600000000) & (IRCode < -500000000)) Geldig IR-signaal ontvangen { OLDIRCode = IRCode; Sommige dingen over het ontstuiteren IR Remote Schakelen (IRCode) { Geval -522182433: In mijn geval 1 op mijn TV - Remote { FireON (FireON) = !FireON (FireON); FireSequence FireSequence = 1; } Breken; Geval -522149793: In mijn geval 2 op mijn TV - Remote { FireON (FireON) = !FireON (FireON); FireSequence FireSequence = 2; } Breken; Geval -522166113: In mijn geval 3 op mijn TV - Remote { FireON (FireON) = !FireON (FireON); FireSequence FireSequence = 3; } Breken; Geval -522186513: In mijn geval 4 op mijn TV - Remote { FireON (FireON) = !FireON (FireON); FireSequence FireSequence = 4; } Breken; Geval -522153873: In mijn geval 5 op mijn TV - Remote { FireON (FireON) = !FireON (FireON); FireSequence FireSequence = 5; } Breken; Geval -522178353: In mijn geval 6 op mijn TV - Remote { FireON (FireON) = !FireON (FireON); FireSequence FireSequence = 6; } Breken; Standaard: Seriële.println(IRCode); Breken; } } } Void Lus() { IRCode = ReceiveIrCommand Ontvangen(); IRCommandProcessor(IRCode); Simuleren Vuur(FireON (FireON), FireSequence FireSequence); }
De functie van de knoppen is enigszins veranderd. Er is niet langer een speciale knop om de lantaarn aan en uit te zetten. In plaats daarvan kan elk van de 6 gedefinieerde knoppen de lantaarn nu weer uitschakelen door een verdere (vernieuwde) actuator, op voorwaarde dat een pauze van ten minste 1 seconde wordt waargenomen tussen de afzonderlijke toetsaanslagen (laat de knop los).
Ik wens u veel plezier upgraden van uw lantaarn firmware.
8 Reacties
Joachim
Hallo, mich würde interessieren, was ich an der Programmierung ändern muss, damit der LED bereits mit z.B. Programm 1 startet sobald der Arduino gestartet wird? Habe schon einiges probiert, aber nichts gescheites hinbekommen, außer dauer an….
Ake
Hallo, was müsste ich am Code ändern, um z.B. immer mit FireSequenz 1 zu starten. Das quasi beim starten des Arduino Programm 1 läuft, ohne das die Fernbedienung benutzt wird…
Bert
Hallo Tobias,
vielen Dank für Deine Mühe.
Durch den Nachtrag funktioniert es nun PERFEKT &
“Oma’s Windlicht” erstrahlt (buchstäblich) in neuem Glanz :-)
Tobias
Hallo bert,
Für Fernbedienungen aus dem Einsteiger KIT verwende bitte im Code statt:
if ((IRCode < -1) & (IRCode != OLDIRCode) ….
den Code:
if ((IRCode > 0) & (IRCode != OLDIRCode)
Die Einsteiger-KIT Fernbedienungen haben ein komplett anderen Codebereich als die “normalen” Fernbedienungen"
Bert
Hallo Tobias,
Danke für den Tipp UND die tolle Projektidee.
Das mit den Strays hatte ich (Dank Google) herausgefunden, den Hinweis mit den Codes befolgt. Wie befürchtet hat es aber nicht geholfen – denn die Fernbedienung ist keine TV Fernbedienung (damit habe ich es übrigens auch probiert Fabr. LG), sondern eine aus den Einsteigerkits (aus da ist auch der LED Empfänger her) .
Ich kenn mich jetzt (noch) nicht mir der Arduino Programmiersprache aus, aber es sein,
dass da die Auswahlroutine “zu” gründlich ist ?
Anyway – “zum Laufen” habe ich den Aufbau ja bekommen, nur das mit den verschiedenen Lichtstimmungen bekomme ich nicht hin :-(
Da gibt es doch Funktions-/Routine Aufrufe ( void ?) – kannst Du da evtl. einzelne
Code Teile – wie “Programm 1: Kein Flackern, schnell wechselnde unterschiedliche Flammentemperatur” als >> Flacker(); << zum Download einstellen, die dann je nach Ereignis (IR Code) ausgeführt werden ?
Hoffe ich hab mich verständlich ausgedrückt – wie gesagt – was Arduino Programmierung angeht bin ich ein absoluter Neuling :-)
Tobias Kuch
Noch ein Nachtrag: Falls die u.g Änderungen keinen Erfolg bringen, kann es auch helfen die Zeile:
if ((IRCode < -1) & (IRCode != OLDIRCode) & (IRCode > -600000000) & (IRCode < -500000000)) // Valid IR Signal Received
{
in
if ((IRCode < -1) & (IRCode != OLDIRCode) ) // Valid IR Signal Received
zu ändern, um hier das Filtern der IR Codes auf einen Bereich zu unterdrücken, und “alle” Codebereiche damit freizugeben. Dies kann insbesondere bei NICHT-Samsung Fernbedienungen sinnvoll sein.
Tobias
Hallo Bert,
Der “Stray”-Fehler ist ein Klassiker. Er wird nicht durch den Code selbst oder ein evtl. Fehler erzeugt, sondern durch Sonderzeichen, die durch den Kopiervorgang in die Arduino IDE eingefügt werden. Umgehen lässt er sich, wenn die Sonderzeichen vor Einfügen in die IDE gelöscht werden. Das kleine Ausgabe der IR Codes erfolgt liegt evtl. daran, das eine ähnliche Fernbedienung genutzt wird, die ich zum Testen des Codes verwendet habe. (Samsung TV). Bei belegten Codes erfolgt keine Ausgabe mehr auf der seriellen Schnittstelle. Bitte ersetzte alle genannten Fernbedienungscodes im Code erst mal durch einen Dummy (Bsp: 111) und teste dann mit einer Schnittstellengeschwindigkeit von 115200 Baud. Gruß
Bert
Eigentlich ein klasse Projekt, aber bei Code kopieren “Stray” Fehler.
Beim copy & paste vom Quelltext hier auf der Seite kein Fehler.
Dafür wird aber auch im Seriellen Monitor kein IR Code angezeigt
und auch sonst “tut sich nix” .
Mit (angepassten) Programmen wie hier
=> https://funduino.de/nr-11-fernbedienung
wird wenigstens der / die Codes ausgegeben & LED Ring angeschaltet.
Hardware, Aufbau, etc. sollten also OK sein – wo ist der Haken ?