Mehrere „Feuer-Programme“ für unsere Stimmungslaterne - AZ-Delivery

Finora la nostra lanterna funziona abbastanza bene e può già essere utilizzata in remoto con le funzioni di base. Tuttavia, e l'avevo lasciato trasparire nella parte precedente, oggi "papperemo" un po 'la nostra lanterna nell'ultima parte della nostra serie di lanterne umore e non solo le daremo un programma tremolante, ma per un totale di 5 diversi programmi di simulazione del fuoco, ognuno anche può ancora essere selezionato individualmente tramite telecomando!


Il codice può e dovrebbe! Naturalmente, puoi anche aggiungere i tuoi algoritmi di simulazione, in modo che il lettore interessato abbia un numero infinito di possibilità per liberare la propria creatività. Ma prima diamo un'occhiata ai 5 algoritmi che ho incorporato che sono derivati ​​l'uno dall'altro.

  • Programma 1: nessuno sfarfallio, che cambia rapidamente diverse temperature di fiamma.
  • Programma 2: Nessun tremolio, temperatura della fiamma costante. Luce stazionaria.
  • Programma 3: sfarfallio intenso e frequente, che cambia rapidamente diverse temperature di fiamma.
  • Programma 4: forte, raro sfarfallio, stessa temperatura di fiamma.
  • Programma 5: lieve, frequente sfarfallio, variazione rapida di diverse temperature di fiamma.
  • Programma 6: forte, raro sfarfallio, che cambia rapidamente diverse temperature di fiamma.

Il programma 5 è il "programma standard" della parte 2 di questa serie di produttori. 
Probabilmente il lettore incline avrà già riconosciuto che questi diversi algoritmi di simulazione vengono richiamati o controllati tramite la struttura "switch-case". Ciò accade in base al codice del telecomando letto nella sezione seguente:

 

switch (IRCode)
{
case -522182433: // Nel mio caso 1 sulla mia TV - Telecomando
{
 FireON =! FireON;
 FireSequence = 1;
}
 break;
case -522149793: // Nel mio caso 2 sulla mia TV - Telecomando
{
 FireON =! FireON;
 FireSequence = 2;
}
 break;
case -522166113: // Nel mio caso 3 sulla mia TV - Telecomando
{
 FireON =! FireON;
 FireSequence = 3;
}
 break;
case -522186513: // Nel mio caso 4 sulla mia TV - Telecomando
{
 FireON =! FireON;
 FireSequence = 4;
}
 break;
case -522153873: // Nel mio caso 5 sulla mia TV - Telecomando
{
 FireON =! FireON;
 FireSequence = 5;
}
 break;
case -522173873: // Nel mio caso 6 sulla mia TV - Telecomando
{
 FireON =! FireON;
 FireSequence = 5;
}
 break;

DEFAULT:
 Serial.println (IRCode);
 break;
}

 

Per far funzionare tutto con il nostro telecomando, tutto ciò che dobbiamo fare è lasciare che i codici di telecomando di 5 pulsanti, che vogliamo usare per controllare la lanterna, vengano emessi prima tramite l'interfaccia seriale (funziona anche con il codice della parte 2) :

Parte 3 - Uscita seriale

Carichiamo il seguente codice sul nostro Arduino dopo aver inserito i numeri nelle istruzioni del caso di conseguenza:

 

 

#include <Adafruit_NeoPixel.B>
#include <irRemote.B>

#define PIN        6  // Quale pin di Arduino è collegato ai NeoPixels?
#define RECV_PIN 11  // definisce il pin di ingresso IR su Arduino 
#define numPixels 12 // Quanti NeoPixels sono collegati ad Arduino? // Dimensione popolare dell'anello NeoPixel

Adafruit_NeoPixel pixel(numPixels, PIN, NEO_GRB + NEO_KHZ800);
IRrecv irrecv(RECV_PIN);
decode_results risultati; // la classe decode_results è definita in IRremote.h

lungo Fuoco Last Time = 0;
lungo IRlastTime = 0;
lungo Timer Last Time = 0;
int intervallo;
lungo IRCode = 0;
lungo Codice OLDIR = 0;
bool fireon = falso;
bool FireOFF = falso;
byte FireSequence = 0;

vuoto configurazione()
{   serial.iniziare(115200);   mentre (!serial);   // attendi fino a quando non viene stabilito il numero seriale - richiesto su alcune piattaforme   irrecv.enableIRIn(); // Avvia il ricevitore   pixel.iniziare(); // INIZIALIZZA NeoPixels   pixel.spettacolo(); // Inizializza tutti i pixel su "off"   intervallo = 300;   randomSeed(Leggi analogico(0));
}

vuoto SimulateFire (bool su, byte FireSq)
{   byte LightValue[numPixels * 3];   Se (millis() - FirelastTime >= intervallo)   {     Se (Su)     {       FireOFF = falso;       FirelastTime = millis();       intervallo = 200;       Se (FireSq == 1)       {         per (int io = 0; io < numPixels; io++)         { // Per ogni pixel ...           LightValue[io * 3] = casuale(200, 255); // 250           LightValue[io * 3 + 1] = casuale(30, 70); // 50           LightValue[io * 3 + 2] = 0;         }         per (int io = 0; io < numPixels; io++)         { // Per ogni pixel ...           pixel.setPixelColor(io, LightValue[io * 3], LightValue[io * 3 + 1], LightValue[io * 3 + 2]);         }         noInterrupts();         pixel.mostrare();   // Invia i colori dei pixel aggiornati all'hardware.         interrupt();       }       Se (FireSq == 2)       {         per (int io = 0; io < numPixels; io++)         { // Per ogni pixel ...           pixel.setPixelColor(io, 250, 50, 0);         }         noInterrupts();         pixel.mostrare();   // Invia i colori dei pixel aggiornati all'hardware.         interrupt();       }       Se (FireSq == 3)       {         intervallo = casuale(50, 100);         per (int io = 0; io < numPixels; io++)         { // Per ogni pixel ...           LightValue[io * 3] = casuale(240, 255); // 250           LightValue[io * 3 + 1] = casuale(30, 60); // 50           LightValue[io * 3 + 2] = 0;         }         // Spegni alcune luci         byte Luci spente  = casuale(0, 6);         per (int io = 0; io < Luci spente; io++)         {           byte Selezionato = casuale(numPixels);           LightValue[Selezionato * 3] = 0;           LightValue[Selezionato * 3 + 1] = 0;           LightValue[Selezionato * 3 + 2] = 0;         }         per (int io = 0; io < numPixels; io++)         { // Per ogni pixel ...           pixel.setPixelColor(io, LightValue[io * 3], LightValue[io * 3 + 1], LightValue[io * 3 + 2]);         }         noInterrupts();         pixel.mostrare();   // Invia i colori dei pixel aggiornati all'hardware.         interrupt();       }       Se (FireSq == 4)       {         intervallo = casuale(80);         per (int io = 0; io < numPixels; io++)         { // Per ogni pixel ...           LightValue[io * 3] = 250; // casuale (240.255); // 250           LightValue[io * 3 + 1] =  50; // casuale (30,60); // 50           LightValue[io * 3 + 2] = 0;         }         // Spegni alcune luci se Chance Hit         byte ChanceforLightsOff  = casuale(0, 40);         Se (ChanceforLightsOff > 35)         {           byte Luci spente  = casuale(5);           per (int io = 0; io < Luci spente; io++)           {             byte Selezionato = casuale(numPixels);             LightValue[Selezionato * 3] = 0;             LightValue[Selezionato * 3 + 1] = 0;             LightValue[Selezionato * 3 + 2] = 0;           }         }         per (int io = 0; io < numPixels; io++)         { // Per ogni pixel ...           pixel.setPixelColor(io, LightValue[io * 3], LightValue[io * 3 + 1], LightValue[io * 3 + 2]);         }         noInterrupts();         pixel.mostrare();   // Invia i colori dei pixel aggiornati all'hardware.         interrupt();       }       Se (FireSq == 5)       {         intervallo = casuale(150, 200);         per (int io = 0; io < numPixels; io++)         { // Per ogni pixel ...           LightValue[io * 3] = casuale(240, 255); // 250           LightValue[io * 3 + 1] = casuale(30, 60); // 50           LightValue[io * 3 + 2] = 0;         }         // Cambia alcune luci più scure         byte Luci spente  = casuale(0, 4);         per (int io = 0; io < Luci spente; io++)         {           byte Selezionato = casuale(numPixels);           LightValue[Selezionato * 3] = casuale(50, 60);           LightValue[Selezionato * 3 + 1] = casuale(5, 10);           LightValue[Selezionato * 3 + 2] = 0;         }         per (int io = 0; io < numPixels; io++)         { // Per ogni pixel ...           pixel.setPixelColor(io, LightValue[io * 3], LightValue[io * 3 + 1], LightValue[io * 3 + 2]);         }         noInterrupts();         pixel.mostrare();   // Invia i colori dei pixel aggiornati all'hardware.         interrupt();       }       Se (FireSq == 6)       {         intervallo = casuale(80);         per (int io = 0; io < numPixels; io++)         { // Per ogni pixel ...           LightValue[io * 3] = casuale(240, 255); // 250           LightValue[io * 3 + 1] = casuale(40, 60); // 50           LightValue[io * 3 + 2] = 0;         }         // Spegni alcune luci se Chance Hit         byte ChanceforLightsOff  = casuale(0, 40);         Se (ChanceforLightsOff > 35)         {           byte Luci spente  = casuale(5);           per (int io = 0; io < Luci spente; io++)           {             byte Selezionato = casuale(numPixels);             LightValue[Selezionato * 3] = 0;             LightValue[Selezionato * 3 + 1] = 0;             LightValue[Selezionato * 3 + 2] = 0;           }         }         per (int io = 0; io < numPixels; io++)         { // Per ogni pixel ...           pixel.setPixelColor(io, LightValue[io * 3], LightValue[io * 3 + 1], LightValue[io * 3 + 2]);         }         noInterrupts();         pixel.mostrare();   // Invia i colori dei pixel aggiornati all'hardware.         interrupt();       }     }     altro     {       Se (!(FireOFF))       {         pixel.chiaro();         noInterrupts();         pixel.mostrare();   // Invia i colori dei pixel aggiornati all'hardware.         interrupt();         FireOFF = vero;       }     }   }
}

lungo ReceiveIrCommand ()
{   lungo risultato = 0;   Se (irrecv.decodificare(&risultati))   {     risultato = risultati.valore;     irrecv.curriculum vitae(); // Ricevi il valore successivo     ritorno risultato;   }   ritorno 0 ;
}

vuoto IRCommandProcessor (lungo IrCommand)
{   Se (IRCode == OLDIRCode) {     TimerlastTime = millis(); // Alcune cose sul debouncing IR Remote   }   Se (millis() - TimerlastTime >= 300) {     OLDIRCode = 0 ; // Alcune cose sul debouncing IR Remote   }   Se ((IRCode < -1) & (IRCode != OLDIRCode) & (IRCode > -600000000) & (IRCode < -500000000))  // Ricevuto segnale IR valido   {     OLDIRCode = IRCode;                                           // Alcune cose sul debouncing IR Remote     interruttore (IRCode)     {       Astuccio -522182433:        // Nel mio caso 1 sulla mia TV - Telecomando         {           FireON = !FireON;           FireSequence = 1;         }         rompere;       Astuccio -522149793:        // Nel mio caso 2 sulla mia TV - Telecomando         {           FireON = !FireON;           FireSequence = 2;         }         rompere;       Astuccio -522166113:        // Nel mio caso 3 sulla mia TV - Telecomando         {           FireON = !FireON;           FireSequence = 3;         }         rompere;       Astuccio -522186513:        // Nel mio caso 4 sulla mia TV - Telecomando         {           FireON = !FireON;           FireSequence = 4;         }         rompere;       Astuccio -522153873:        // Nel mio caso 5 sulla mia TV - Telecomando         {           FireON = !FireON;           FireSequence = 5;         }         rompere;       Astuccio -522178353:        // Nel mio caso 6 sulla mia TV - Telecomando         {           FireON = !FireON;           FireSequence = 6;         }         rompere;       predefinito:         Seriale.println(IRCode);         rompere;     }   }
}

vuoto ciclo continuo()
{   IRCode = ReceiveIrCommand();   IRCommandProcessor(IRCode);   SimulateFire(FireON, FireSequence);
}

 

Die Funktion der Tasten hat sich etwas verändert. Es gibt jetzt keine dedizierte Taste mehr zum Ein- e 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.

 

Für arduinoProjekte für fortgeschrittene

8 commenti

Joachim

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

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

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

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

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

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

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

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 ?

Lascia un commento

Tutti i commenti vengono moderati prima della pubblicazione