Jusqu'à présent, notre lanterne fonctionne assez bien et peut déjà être utilisée à distance avec les fonctions de base. Cependant, et je l'avais laissé transparaître dans la partie précédente, aujourd'hui, nous allons «pimp» notre lanterne un peu dans la dernière partie de notre série de lanternes d'humeur et non seulement lui donner un programme de scintillement, mais un total de 5 programmes de simulation de feu différents, chacun aussi peut encore être sélectionné individuellement par télécommande!
Le code peut et doit! Bien sûr, vous pouvez également ajouter vos propres algorithmes de simulation, afin que le lecteur intéressé ait un nombre infini de possibilités pour laisser libre cours à sa propre créativité. Mais regardons d'abord les 5 algorithmes que j'ai construits qui sont dérivés les uns des autres.
- Programme 1: pas de scintillement, modification rapide des différentes températures de flamme.
- Programme 2: Pas de scintillement, température de flamme constante. Lumière debout.
- Programme 3: Scintillement fort et fréquent, modification rapide des différentes températures de flamme.
- Programme 4: forte, rare scintillement, même température de flamme.
- Programme 5: scintillement doux et fréquent, variation rapide des différentes températures de flamme.
- Programme 6: Fort, rare scintillement, changeant rapidement différentes températures de flamme.
Le programme 5 est le "programme standard" de la partie 2 de cette série de fabricant.
Le lecteur incliné aura probablement déjà reconnu que ces différents algorithmes de simulation sont appelés ou contrôlés via la structure "switch-case". Cela se produit en fonction du code de télécommande lu dans la section suivante:
commutateur (IRCode)
{
case -522182433: // Dans mon cas 1 sur mon téléviseur - Télécommande
{
FireON =! FireON;
FireSequence = 1;
}
casser;
case -522149793: // Dans mon cas 2 sur mon téléviseur - Télécommande
{
FireON =! FireON;
FireSequence = 2;
}
casser;
case -522166113: // Dans mon cas 3 sur mon téléviseur - Télécommande
{
FireON =! FireON;
FireSequence = 3;
}
casser;
case -522186513: // Dans mon cas 4 sur mon téléviseur - Télécommande
{
FireON =! FireON;
FireSequence = 4;
}
casser;
case -522153873: // Dans mon cas 5 sur mon téléviseur - Télécommande
{
FireON =! FireON;
FireSequence = 5;
}
casser;
case -522173873: // Dans mon cas 6 sur mon téléviseur - Télécommande
{
FireON =! FireON;
FireSequence = 5;
}
casser;
par défaut:
Serial.println (IRCode);
casser;
}
Pour que tout fonctionne avec notre propre télécommande, tout ce que nous avons à faire est de laisser les codes de télécommande de 5 boutons, que nous voulons utiliser pour contrôler la lanterne, être sortis en premier via l'interface série (fonctionne également avec le code de la partie 2) :
Nous téléchargeons le code suivant sur notre Arduino après avoir entré les chiffres dans l'instruction de cas en conséquence:
#include <Adafruit_NeoPixel.h> #include <IRrote.h> #define PIN 6 // Quelle broche de l'Arduino est connectée aux NeoPixels? #define RECV_PIN 11 // définir la broche d'entrée IR sur Arduino #define NUMPIXELS 12 // Combien de NeoPixels sont attachés à l'Arduino? // Taille de bague NeoPixel populaire Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); IRrecv irrecv(RECV_PIN); decode_results résultats; // La classe decode_results est définie dans IRremote.h longue FirelastTime = 0; longue IRlastTime = 0; longue TimerlastTime = 0; int intervalle; longue IRCode = 0; longue Code OLDIR = 0; bool FireON = faux; bool FireOFF = faux; octet FireSequence = 0; nul configuration() { Série.commencer(115200); tout (!Série); // attendre que Serial soit établi - requis sur certaines plateformes irrecv.enableIRIn(); // Démarrer le récepteur pixels.commencer(); // INITIALISEZ NeoPixels pixels.montrer(); // Initialise tous les pixels sur 'off' intervalle = 300; randomSeed(analogRead(0)); } nul SimulateFire (bool Sur, octet FireSq) { octet LightValue[NUMPIXELS * 3]; si (millis() - FirelastTime >= intervalle) { si (Sur) { FireOFF = faux; FirelastTime = millis(); intervalle = 200; si (FireSq == 1) { pour (int je = 0; je < NUMPIXELS; je++) { // Pour chaque pixel ... LightValue[je * 3] = Aléatoire(200, 255); // 250 LightValue[je * 3 + 1] = Aléatoire(30, 70); // 50 LightValue[je * 3 + 2] = 0; } pour (int je = 0; je < NUMPIXELS; je++) { // Pour chaque pixel ... pixels.setPixelColor(je, LightValue[je * 3], LightValue[je * 3 + 1], LightValue[je * 3 + 2]); } noInterrupts(); pixels.spectacle(); // Envoie les couleurs de pixels mises à jour au matériel. interrompt(); } si (FireSq == 2) { pour (int je = 0; je < NUMPIXELS; je++) { // Pour chaque pixel ... pixels.setPixelColor(je, 250, 50, 0); } noInterrupts(); pixels.spectacle(); // Envoie les couleurs de pixels mises à jour au matériel. interrompt(); } si (FireSq == 3) { intervalle = Aléatoire(50, 100); pour (int je = 0; je < NUMPIXELS; je++) { // Pour chaque pixel ... LightValue[je * 3] = Aléatoire(240, 255); // 250 LightValue[je * 3 + 1] = Aléatoire(30, 60); // 50 LightValue[je * 3 + 2] = 0; } // Éteignez certaines lumières octet Lumières éteintes = Aléatoire(0, 6); pour (int je = 0; je < Lumières éteintes; je++) { octet Choisi = Aléatoire(NUMPIXELS); LightValue[Choisi * 3] = 0; LightValue[Choisi * 3 + 1] = 0; LightValue[Choisi * 3 + 2] = 0; } pour (int je = 0; je < NUMPIXELS; je++) { // Pour chaque pixel ... pixels.setPixelColor(je, LightValue[je * 3], LightValue[je * 3 + 1], LightValue[je * 3 + 2]); } noInterrupts(); pixels.spectacle(); // Envoie les couleurs de pixels mises à jour au matériel. interrompt(); } si (FireSq == 4) { intervalle = Aléatoire(80); pour (int je = 0; je < NUMPIXELS; je++) { // Pour chaque pixel ... LightValue[je * 3] = 250; // aléatoire (240 255); // 250 LightValue[je * 3 + 1] = 50; // aléatoire (30,60); // 50 LightValue[je * 3 + 2] = 0; } // Éteignez certaines lumières si Chance Hit octet ChanceforLightsOff = Aléatoire(0, 40); si (ChanceforLightsOff > 35) { octet Lumières éteintes = Aléatoire(5); pour (int je = 0; je < Lumières éteintes; je++) { octet Choisi = Aléatoire(NUMPIXELS); LightValue[Choisi * 3] = 0; LightValue[Choisi * 3 + 1] = 0; LightValue[Choisi * 3 + 2] = 0; } } pour (int je = 0; je < NUMPIXELS; je++) { // Pour chaque pixel ... pixels.setPixelColor(je, LightValue[je * 3], LightValue[je * 3 + 1], LightValue[je * 3 + 2]); } noInterrupts(); pixels.spectacle(); // Envoie les couleurs de pixels mises à jour au matériel. interrompt(); } si (FireSq == 5) { intervalle = Aléatoire(150, 200); pour (int je = 0; je < NUMPIXELS; je++) { // Pour chaque pixel ... LightValue[je * 3] = Aléatoire(240, 255); // 250 LightValue[je * 3 + 1] = Aléatoire(30, 60); // 50 LightValue[je * 3 + 2] = 0; } // Allume certaines lumières plus sombres octet Lumières éteintes = Aléatoire(0, 4); pour (int je = 0; je < Lumières éteintes; je++) { octet Choisi = Aléatoire(NUMPIXELS); LightValue[Choisi * 3] = Aléatoire(50, 60); LightValue[Choisi * 3 + 1] = Aléatoire(5, 10); LightValue[Choisi * 3 + 2] = 0; } pour (int je = 0; je < NUMPIXELS; je++) { // Pour chaque pixel ... pixels.setPixelColor(je, LightValue[je * 3], LightValue[je * 3 + 1], LightValue[je * 3 + 2]); } noInterrupts(); pixels.spectacle(); // Envoie les couleurs de pixels mises à jour au matériel. interrompt(); } si (FireSq == 6) { intervalle = Aléatoire(80); pour (int je = 0; je < NUMPIXELS; je++) { // Pour chaque pixel ... LightValue[je * 3] = Aléatoire(240, 255); // 250 LightValue[je * 3 + 1] = Aléatoire(40, 60); // 50 LightValue[je * 3 + 2] = 0; } // Éteignez certaines lumières si Chance Hit octet ChanceforLightsOff = Aléatoire(0, 40); si (ChanceforLightsOff > 35) { octet Lumières éteintes = Aléatoire(5); pour (int je = 0; je < Lumières éteintes; je++) { octet Choisi = Aléatoire(NUMPIXELS); LightValue[Choisi * 3] = 0; LightValue[Choisi * 3 + 1] = 0; LightValue[Choisi * 3 + 2] = 0; } } pour (int je = 0; je < NUMPIXELS; je++) { // Pour chaque pixel ... pixels.setPixelColor(je, LightValue[je * 3], LightValue[je * 3 + 1], LightValue[je * 3 + 2]); } noInterrupts(); pixels.spectacle(); // Envoie les couleurs de pixels mises à jour au matériel. interrompt(); } } autre { si (!(FireOFF)) { pixels.clair(); noInterrupts(); pixels.spectacle(); // Envoie les couleurs de pixels mises à jour au matériel. interrompt(); FireOFF = vrai; } } } } longue ReceiveIrCommand () { longue résultat = 0; si (irrecv.décoder(&résultats)) { résultat = résultats.valeur; irrecv.reprendre(); // Recevez la valeur suivante revenir résultat; } revenir 0 ; } néant IRCommandProcessor (longue IrCommand) { si (IRCode == OLDIRCode) { TimerlastTime = millis(); // Quelques trucs sur le rebouncing IR Remote } si (millis() - TimerlastTime >= 300) { OLDIRCode = 0 ; // Quelques trucs sur le rebouncing IR Remote } si ((IRCode < -1) & (IRCode != OLDIRCode) & (IRCode > -600000000) & (IRCode < -500000000)) // Signal IR valide reçu { OLDIRCode = IRCode; // Quelques trucs sur le rebouncing IR Remote commutateur (IRCode) { Cas -522182433: // Dans mon cas 1 sur mon téléviseur - Télécommande { Tirer sur = !Tirer sur; FireSequence = 1; } Pause; Cas -522149793: // Dans mon cas 2 sur mon téléviseur - Télécommande { Tirer sur = !Tirer sur; FireSequence = 2; } Pause; Cas -522166113: // Dans mon cas 3 sur mon téléviseur - Télécommande { Tirer sur = !Tirer sur; FireSequence = 3; } Pause; Cas -522186513: // Dans mon cas 4 sur mon téléviseur - Télécommande { Tirer sur = !Tirer sur; FireSequence = 4; } Pause; Cas -522153873: // Dans mon cas 5 sur mon téléviseur - Télécommande { Tirer sur = !Tirer sur; FireSequence = 5; } Pause; Cas -522178353: // Dans mon cas 6 sur mon téléviseur - Télécommande { Tirer sur = !Tirer sur; FireSequence = 6; } Pause; défaut: En série.println(IRCode); Pause; } } } néant boucle() { IRCode = ReceiveIrCommand(); IRCommandProcessor(IRCode); SimulateFire(Tirer sur, FireSequence); }
Die Funktion der Tasten chapeau sich etwas verändert. Es gibt jetzt keine dedizierte Taste mehr zum Ein- und Ausschalten der Laterne. Vielmehr kann jetzt jede der 6 definierten Tasten die Laterne durch eine weitere (erneute) Betätigung die Laterne wieder ausschalten., Sofern zwischen den einzelnen Tastendrücken eine Pause von mindestens 1 Sekunde eingehalten wird (Taste loslassen.)
Ich wünsche euch viel Spaß beim Upgrade euer Laternenfirmware.
8 commentaires
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 ?