Benvenuti alla terza Parte del Bluetooth con Display Serie. Oggi il nostro Display, oltre obbligatoria di altre Bedienermenüpunkt un piccolo Ampliamento dell'Hardware donato! Su questa nuova Hardwareerweiterung la Sfondo Luminosità del nostro Display tramite Software controllato e configurato!
Utilizziamo la Porta 5 del nostro Onu s Pulse-Ampio Modulationsausgang. Questa Uscita controlla poi un IRF520 modulo del driver. Questo Modulo, per Esempio, per il Pilotaggio di Motori usato, utilizzate per il Collegamento dei Led incorporato dello Schermo per controllare. (Il IRF520 si accende contro di Massa)
In questo Modo, in modo che la Luminosità del nostro Display a 255 Livelli di controllo. Per di più, anche più conveniente del nostro Bluetooth Terminale.
Ma ora la Costruzione effettiva e per la realizzazione dell'Ampliamento. Nella prima Fase, stiamo espandendo la nostra Hardware, come nel seguente Schema mostrato, per il IRF520 MOS Driver Modulo.
Nel Circuito colpisce il positivo Ingresso e Morsetti di Uscita del IRF520 MOS Driver Modulos non sono occupati. Questo non è un Schaltungsfehler, perché questi Terminali / Connettori del Modulo per il corretto funzionamento del nostro Circuito non è necessaria, in quanto la Tensione di esercizio Positivo per la Retroilluminazione del Display tramite il Vorwiederstand direttamente sui 5 Volt Guida di riferimento.
(Anche nel Modulo stesso sono i Morsetti Vin e V+ solo ponte e non hanno attiva o passiva, i Componenti tra i due Terminali!)
Lasciatevi quindi di qualcosa di diverso da quello Predefinito, Beschaltungsweise del Modulo non irrita.
Successivamente, invitiamo per questa Estensione sul nostro Arduino uno seguente Codice personalizzato in alto:
#include <SPI.h> #include <Wire.h> #include <SoftwareSerial.h> #include <EEPROM.h> #include <LiquidCrystal.h> #include <avr/sleep.h> #define MaxInputBufferSize 20 // fino a 255 Caratteri per personalizzare al vlcdr #define EEpromSize 990 #define rLcdChr 20 #define LcdRows 4 #define interval 1000 #define BackgroundLight 5 // Porta 5 Retroilluminazione LED #define DelayTOPWROFF 500 // EEprom SpeicherzellenAdressen per la Configurazione #define EEFadeSeconds 993 #define EEPINA 996 #define EEPINC 997 #define EEPINDD 998 SoftwareSerial mySerial(7, 6); // RX, TX LiquidCrystal lcd(8, 13, 12, 11, 10, 9); //variabile di byte DisplayBankContent = 0; //Serial Input Handling char TBuffer; char Cbuffer[MaxInputBufferSize + 1]; //Codice USB Buffer di Input String Sbuffer = ""; /USB/String Buffer di Input int value; /USB/Nummeric Input Buffer di byte Ccount = 0; //Number received Chars byte Inptype = 0; boolean StrInput = false; boolean NumberInput = false; boolean DataInput = false; boolean EnterInput = false; byte MenueSelection = 0; byte SelectedMsg = 0; //EEPROM int eeaddress; //EEPROM Indirizzo Pointer byte EEPromBanks = 0; //Used for Calculating the EEPROM Banks //SerMnueControl byte MnuState = 0; // Massimo Menuetiefe 255 icl Sub byte Selectedbank = 0; //Real Time Clock long previousMillis = 0; // will store last time was measured long previousMillisB = 0; // will store last time was measured //Display Management boolean DisplayLock = false; boolean Directprint = false; boolean EchoMode = true; byte DirectprintROW = 0; byte DirectprintLine = 0; boolean RefreshDisplay = false; byte FRMCheck = 0; // Used fpr Writing Operations to eeprom per save Ospiti cycles // PWM di controllo della luce byte Currentbrightness = 0; byte Targetbrightness = 0; byte FadeSeconds = 0; // Standard = 3 void setup() { EEPromBanks = EEpromSize / ((rLcdChr) * LcdRows); lcd.begin(rLcdChr, LcdRows); lcd.clear(); lcd.setCursor(0, 0); lcd.print(" Bluetooth"); lcd.setCursor(0, 1); lcd.print(" Display"); mySerial.begin(9600); pinMode(BackgroundLight, OUTPUT); // Retroilluminazione / Display /DA digitalWrite(BackgroundLight, LOW); // read Config FadeSeconds = 0; Currentbrightness = 0; Targetbrightness = 0; lcd.setCursor(0, 4); if (DisplayLock) { lcd.di stampa(" Sistema gesperrt"); } // Ulteriori procedure di Installazione / initalizing lcd.setCursor(0, 0); Targetbrightness = 255; mySerial.filo(); } // ###################################################################################################### // void loop() { SerialcommandProcessor(); runrealTimeClock(); Displayprocessor(); //Fine ciclo Principale } // ###################################################################################################### // void TextHeader(byte rowm) { mySerial.println("Testo per la Banca " + Stringa( Selectedbank) + " RIGA " + Stringa (rowm) + ":"); } void SerialcommandProcessor() { int un; Inptype = 0; Inptype = SerInputHandler(); // 0 keine Rückgabe // 1 Nummer // 2 Stringa // 3 i Dati se ((Inptype > 0) & (!Directprint)) { MenueSelection = 0; se ((MnuState < 2) && (Inptype == 2)) { Sbuffer.toUpperCase(); // Per una Facile Immissione dei Comandi } se ((Sbuffer == "S") && (MnuState == 0) && (Inptype == 2)) { MenueSelection = 3; } // Cancellazione di TUTTO il Contenuto della EEprom se ((Sbuffer == "E") && (MnuState == 0) && (Inptype == 2)) { MenueSelection = 4; } se ((Sbuffer == "SÌ") && (MnuState == 1) && (Inptype == 2)) { MenueSelection = 5; } se ((Sbuffer != "SÌ") && (MnuState == 1) && (Inptype == 2)) { MenueSelection = 6; } //Modificare il Contenuto Selezionato se ((Sbuffer == "W") && (MnuState == 0) && (Inptype == 2)) { MenueSelection = 7; } se ((MnuState == 2) && (valore < EEPromBanks) && (Inptype == 1)) { MenueSelection = 8; } se (MnuState == 3) { MenueSelection = 9; } se (MnuState == 4) { MenueSelection = 10; } //Visualizza il Contenuto Selezionato se ((Sbuffer == "P") && (MnuState == 0) && (Inptype == 2)) { MenueSelection = 11; } se ((MnuState == 5) && (Inptype == 1)) { MenueSelection = 12; } se ((Sbuffer == "R") && (MnuState == 0) && (Inptype == 2)) { MenueSelection = 13; } se ((MnuState == 6) && (Inptype == 1)) { MenueSelection = 14; } se ((Sbuffer == "D") && (MnuState == 0) && (Inptype == 2)) { MenueSelection = 15; } se ((Sbuffer == "Z") && (MnuState == 0) && (Inptype == 2)) { MenueSelection = 16; } se ((Sbuffer == "B") && (MnuState == 0) && (Inptype == 2)) { MenueSelection = 17; } se ((MnuState == 7) && (Inptype == 1)) { MenueSelection = 18; } se ((Sbuffer == "FADE") && (MnuState == 0) && (Inptype == 2)) { MenueSelection = 19; } se (MnuState == 9) { MenueSelection = 20; } se (MnuState == 10) { MenueSelection = 21; } se (MnuState == 12) { MenueSelection = 25; } se (MnuState == 13) { MenueSelection = 27; } se (MnuState == 14) { MenueSelection = 29; } interruttore (MenueSelection) { caso 3: { mySerial.println("Leggi EEEPROM Contenuto:" ); mySerial.a filo(); per (int a = 0; un < EEPromBanks; un++) { mySerial.println("Memoria EEPROM Banca: " + Stringa di(un) ); mySerial.a filo(); per (int b = 1; b <= LcdRows; b++) { mySerial.stampa("Riga " + Stringa(b) + ": "); mySerial.a filo(); per (int c = 0; c < rLcdChr; c++) { eeaddress = 0; eeaddress = (un * (rLcdChr) * LcdRows) + ((rLcdChr) * b) + c; valore = EEPROM.lettura(eeaddress); mySerial.stampa(char(valore)); mySerial.filo(); } mySerial.println(" "); mySerial.filo(); } } Sbuffer = ""; mySerial.println("Non più EEPROM Banche disponibili."); mySerial.filo(); pausa; } caso 4: { il valore = 0; mySerial.stampa("Cancellare EEPROM "); mySerial.println("SÌ/NO:"); mySerial.filo(); MnuState = 1; Sbuffer = ""; pausa; } caso 5: { il valore = 0; mySerial.stampa("Cancellare EEPROM "); mySerial.println("Stand by".); mySerial.a filo(); per (int a = 0; un < EEPromBanks; un++) { //Banca di Memoria di un mySerial.println("Clear Banca: " + Stringa(una)); per (int b = 1; b <= LcdRows; b++) { per (int c = 0; c < rLcdChr; c++) { eeaddress = 0; eeaddress = (un * (rLcdChr) * LcdRows) + ((rLcdChr ) * b) + c; FRMCheck = EEPROM.lettura(eeaddress); se (FRMCheck > 0) { EEPROM.scrivere(eeaddress, 00); // Formatierung mySerial.stampa("."); il valore++; di ritardo(30); mySerial.filo(); } } } mySerial.println(""); mySerial.filo(); } mySerial.println(""); mySerial.println("Finito. " + Stringa di(valore) + " Byte cancellato"); mySerial.println(""); mySerial.filo(); Sbuffer = ""; MnuState = 0; pausa; } caso 6: { il valore = 0; Sbuffer = ""; MnuState = 0; mySerial.println("OP abort".); mySerial.filo(); pausa; } caso 7: { mySerial.println("EEPPROM Banca Numero (0-" + Stringa(EEPromBanks - 1) + "):"); mySerial.filo(); MnuState = 2; valore = 0; Sbuffer = ""; pausa; } caso 8: { Selectedbank = valore; TextHeader(1); MnuState = 3; Sbuffer = ""; valore = 0; pausa; } caso 9: { WriteEEPROM(Selectedbank, 1); TextHeader(2); valore = 0; MnuState = 4; Sbuffer = ""; pausa; } caso 10: { WriteEEPROM(Selectedbank, 2); valore = 0; MnuState = 0; Sbuffer = ""; TextHeader(3); mySerial.flush(); valore = 0; MnuState = 9; Sbuffer = ""; pausa; } caso 11: { il valore = 0; mySerial.println("EEPPROM Banca Numero (0-" + Stringa(EEPromBanks - 1) + "):"); MnuState = 5; Sbuffer = ""; mySerial.filo(); pausa; } caso 12: { SelectedMsg = valore di; DisplayBank(valore); pausa; } caso 13: { il valore = 0; mySerial.println("EEPPROM Banca Numero (0-" + Stringa(EEPromBanks - 1) + "):"); MnuState = 6; Sbuffer = ""; mySerial.filo(); pausa; } caso 14: { di un = valore; , se ( un < EEPromBanks) { mySerial.println("Banca della Memoria: " + Stringa di(un) ); mySerial.a filo(); per (int b = 1; b <= LcdRows; b++) { mySerial.stampa("Riga " + Stringa(b) + ": "); mySerial.a filo(); per (int c = 0; c < rLcdChr; c++) { eeaddress = 0; eeaddress = (un * (rLcdChr) * LcdRows) + ((rLcdChr) * b) + c; valore = EEPROM.lettura(eeaddress); mySerial.stampa(char(valore)); mySerial.filo(); } mySerial.println(" "); mySerial.flush(); } } altro { mySerial.println("Valore di Intervallo."); } valore = 0; Sbuffer = ""; MnuState = 0; pausa; } caso 15: { // Diretta pPrint per Visualizzare Directprint = vero; mySerial.println ("Directprint SU."); se (Directprint) { DirectprintROW = 0; DirectprintLine = 0; lcd.clear(); lcd.cursore(); lcd.lampeggia(); } il valore = 0; Sbuffer = ""; MnuState = 0; pausa; } caso 16: { il valore = 0; Sbuffer = ""; MnuState = 0; pausa; } caso 17: { mySerial.println("la Luminosità del Display: (max 255)"); MnuState = 7; valore = 0; Sbuffer = ""; pausa; } caso 18: { se ((il valore < 256)) { Targetbrightness = valore; mySerial.println("Luminosità: " + Stringa (Targetbrightness) + " Set"); } altro { mySerial.println("Valore di Intervallo."); } MnuState = 0; valore = 0; Sbuffer = ""; pausa; } caso 19: { mySerial.println("Fade Ritardo: (max 255 Sec)"); MnuState = 12; valore = 0; Sbuffer = ""; pausa; } caso 20: { WriteEEPROM(Selectedbank, 3); valore = 0; MnuState = 0; Sbuffer = ""; TextHeader(4); mySerial.flush(); valore = 0; MnuState = 10; Sbuffer = ""; pausa; } caso 21: { WriteEEPROM(Selectedbank, 4); valore = 0; MnuState = 0; Sbuffer = ""; pausa; } caso 25: { se ((di valore > 0) & (valore di < 251)) { FadeSeconds = valore; EEPROM.scrivere(EEFadeSeconds, FadeSeconds); mySerial.println("Valore " + Stringa di (valore) + " set".); } altro { valore = 0; Sbuffer = ""; mySerial.println("Valore di Intervallo."); } valore = 0; MnuState = 0; Sbuffer = ""; pausa; } di default: { mySerial.println("-------Smart Bluetooth con Display 1.1------"); mySerial.println("S - Leggi TUTTE le EEPROM Banche"); mySerial.println("E - Cancellare TUTTI i EEPROM Banche"); mySerial.println("Scrittura di W sel. EEPROM Banca"); mySerial.println("R - Leggi di sel. EEPROM Banca"); mySerial.println(("P - Stampa EEPROM Banca sul Display"); mySerial.println("----------------------------------------"); mySerial.println("D - la Stampa Diretta"); mySerial.println("B - Luminosità del Display il Valore della Corrente di: " + Stringa (Currentbrightness)); mySerial.println("----------------------------------------"); mySerial.println("Digitare Cmd e premere Invio"); mySerial.filo(); MnuState = 0; valore = 0; Sbuffer = ""; } } } // Eingabe erkannt } void WriteEEPROM(byte FBank, byte FRow) { byte Writecounter; Writecounter = 0; mySerial.stampa("Risparmio "); per (int c = 0; c < rLcdChr; c++) { eeaddress = 0; eeaddress = (FBank * (rLcdChr) * LcdRows) + ((rLcdChr) * FRow) + c; valore = EEPROM.lettura(eeaddress); se (Sbuffer[c] != valore) { EEPROM.scrivere(eeaddress, Sbuffer[c]); mySerial.stampa("."); Writecounter++; } } mySerial.println(" " + Stringa (Writecounter) + " Byte scritti."); } void ClearCBuffer () { per (byte un = 0; MaxInputBufferSize - 1; un++) Cbuffer[un] = 0; } byte SerInputHandler() { byte risultato = 0; int c,; int d,; int a; int b; risultato = 0; se (CheckforserialEvent()) { se ((NumberInput) e non (DataInput) e non (StrInput)) //solo i Numeri { Sbuffer = ""; valore = 0; StrInput = false; NumberInput = false; DataInput = false; EnterInput = false; a = 0; b = 0; c = 0; d = 0; Sbuffer = Cbuffer; // Zahl wird AUCH ! in SBUFFER übernommen, cade benötigt. se (il conteggio == 1) { valore = Cbuffer[0] - 48 ; } se (Ccount == 2) { un = Cbuffer[0] - 48 ; un = un * 10; b = Cbuffer[1] - 48 ; valore di = un + b; } se (Ccount == 3) { un = Cbuffer[0] - 48 ; un = un * 100; b = Cbuffer[1] - 48 ; b = b * 10; c = Cbuffer[2] - 48 ; valore = a + b + c; } se (Ccount == 4) { un = Cbuffer[0] - 48 ; un = un * 1000; b = Cbuffer[1] - 48 ; b = b * 100; c = Cbuffer[2] - 48 ; c = c * 10; d = Cbuffer[3] - 48 ; valore di = un + b + c + d; } se (Ccount >= 5) { Sbuffer = ""; valore = 0; Sbuffer = Cbuffer; ClearCBuffer; risultato = 2; } altro { ClearCBuffer; Ccount = 0; risultato = 1; //Numero di Codice di ritorno NumberInput = false; StrInput = false; DataInput = false; EnterInput = false; Ccount = 0; di ritorno risultato; } } se ((StrInput) e non (DataInput)) //La stringa di Input solo { Sbuffer = ""; Sbuffer = Cbuffer; valore = 0; StrInput = false; NumberInput = false; DataInput = false; EnterInput = false; Ccount = 0; ClearCBuffer; risultato = 2; //Numero di Codice di ritorno } , se (DataInput) { Sbuffer = ""; Sbuffer = Cbuffer; valore = 0; StrInput = false; NumberInput = false; DataInput = false; EnterInput = false; Ccount = 0; ClearCBuffer; risultato = 3; //Numero di Codice di ritorno } , se ((EnterInput) e non (StrInput) e non (NumberInput) e non (DataInput)) { Sbuffer = ""; valore = 0; Ccount = 0; ClearCBuffer; risultato = 4; //Numero di Codice di ritorno } NumberInput = false; StrInput = false; DataInput = false; EnterInput = false; Ccount = 0; di ritorno risultato; } di ritorno risultato; //Fine CheckforSerialEvent } // Eingabebuffer boolean CheckforserialEvent() { mentre (mySerial.disponibile()) { // ottiene il nuovo byte: TBuffer = mySerial.leggere(); se (TBuffer > 9 && TBuffer < 14) { Cbuffer[Ccount] = 0; TBuffer = 0; se (EchoMode) { mySerial.stampa(char(13)); mySerial.filo(); } se (Directprint) { mySerial.println(""); DirectprintLine = 0; DirectprintROW = DirectprintROW + 1; se ( DirectprintROW > 3) { Directprint = false; lcd.noCursor(); lcd.noBlink(); Sbuffer = ""; valore = 0; } altro { lcd.cursore(); lcd.lampeggia(); lcd.setCursor(0, DirectprintROW); } } EnterInput = true; return true; } else if (TBuffer > 47 && TBuffer < 58 ) { se ( Ccount < MaxInputBufferSize) { Cbuffer[Ccount] = TBuffer; Ccount++; se ((Directprint)) { lcd.di stampa(char(TBuffer)); DirectprintLine = DirectprintLine + 1; se ( Ccount > MaxInputBufferSize - 1) { lcd.noCursor(); lcd.noBlink(); } altro { lcd.cursore(); lcd.lampeggia(); } } se (EchoMode) { mySerial.stampa(char(TBuffer)); mySerial.flush(); } } altro { mySerial.stampa("#"); } //Numero di Input rilevati NumberInput = vero; } altro se (TBuffer > 64 && TBuffer < 123 ) { se ( Ccount < MaxInputBufferSize) { Cbuffer[Ccount] = TBuffer; Ccount++; se ((Directprint)) { lcd.di stampa(char(TBuffer)); DirectprintLine = DirectprintLine + 1; se ( Ccount > MaxInputBufferSize - 1) { lcd.noCursor(); lcd.noBlink(); } altro { lcd.cursore(); lcd.lampeggia(); } } se (EchoMode) { mySerial.stampa(char(TBuffer)); mySerial.flush(); } } altro { mySerial.stampa("#"); } StrInput = vero; } altro se ( (TBuffer == 127 ) | (TBuffer == 8 ) ) { se ( DirectprintLine > 0 ) { DirectprintLine = DirectprintLine - 1; lcd.setCursor(DirectprintLine, DirectprintROW); lcd.di stampa(" "); lcd.setCursor(DirectprintLine, DirectprintROW); } se (( DirectprintLine == 0 ) & ( DirectprintROW > 0 )) { DirectprintROW = DirectprintROW - 1; DirectprintLine = rLcdChr - 1; lcd.setCursor(DirectprintLine, DirectprintROW); } se ( Ccount > 0) { Ccount--; Cbuffer[Ccount] = 0; se ((Directprint)) { se ( Ccount > MaxInputBufferSize - 1) { lcd.noCursor(); lcd.noBlink(); } altro { lcd.cursore(); lcd.lampeggia(); } } se (EchoMode) { mySerial.stampa("-"); mySerial.a filo(); } } } il resto { se ( Ccount < MaxInputBufferSize) { Cbuffer[Ccount] = TBuffer; Ccount++; se ((Directprint)) { DirectprintLine = DirectprintLine + 1; se (TBuffer < 128) { lcd.di stampa(char(TBuffer)); } altro { lcd.di stampa(Stringa(TBuffer)); } se ( Ccount > MaxInputBufferSize - 1) { lcd.noCursor(); lcd.noBlink(); } altro { lcd.cursore(); lcd.lampeggia(); } } se (EchoMode) { mySerial.stampa(char(TBuffer)); mySerial.flush(); } } altro { mySerial.stampa("#"); } //Immissione Dati rilevati DataInput = true; } return false; } return false; } void Displayprocessor() // Bei Blauem Display wird auf Scrollfunktion verzichtet, da das nur "schmiert" { se (RefreshDisplay) { lcd.chiaro(); RefreshDisplay = false; per (int b = 1; b <= LcdRows; b++) { lcd.setCursor(0, b - 1); per (int c = 0; c < rLcdChr; c++) { eeaddress = 0; eeaddress = (DisplayBankContent * (rLcdChr) * LcdRows) + ((rLcdChr) * b) + c; valore = 0; valore = EEPROM.lettura(eeaddress); se (il valore > 31) // Sonderzeichen nicht anzeigen { mySerial.stampa(char(value)); lcd.di stampa(char(valore)); } altro { lcd.di stampa(char(32)); } } mySerial.println(); } } } void runrealTimeClock() //TIMEBASE { // Real Time Clock & Countdown // lungo previousMillis = 0; // memorizza l'ultima volta è stato misurato // byte SecDivider = 0; unsigned long currentMillis = millis(); int StepValue = 0; // PWM Display Steuerung StepValue = 4 * FadeSeconds; se (currentMillis - previousMillis > StepValue) { previousMillis = currentMillis; se (Currentbrightness < Targetbrightness ) { Currentbrightness = Currentbrightness + 1; analogWrite (BackgroundLight, Currentbrightness); } altro se (Currentbrightness > Targetbrightness) { Currentbrightness = Currentbrightness - 1; analogWrite (BackgroundLight, Currentbrightness); } } se (currentMillis - previousMillisB > 1000) { // sekundentakt previousMillisB = currentMillis; } } void DisplayBank ( byte cobank) { se (cobank < EEPromBanks ) { RefreshDisplay = true; // Inizializzare l'Uscita del Display DisplayBankContent = cobank; mySerial.println("Banca " + Stringa(cobank) + " viene visualizzato sul display LCD"); MnuState = 0; Sbuffer = ""; valore = 0; mySerial.flush(); } altro { mySerial.println("la Banca non disponibile".); valore = 0; MnuState = 0; Sbuffer = ""; mySerial.filo(); } }
Fertig ! Mehr ist nicht mehr notwendig.
Nach dieser kleinen Erweiterung bzw. Anpassung der Hardware steht uns nun der weitere Befehl "B" für Luminosità in dem Bluetooth Menü zur Verfügung.
-
B – Luminosità del Display Corrente Valore: 255
Morire dahinter angegebene Zahl beschreibt morire aktuell eingestellte Displayhelligkeit in einem Wertebereich von 0 (Hintergrundbeleuchtung Aus) bis massima di 255 (Luminosità di picco)
in Modo wir sehen immer auf einem Blick, welche Luminosità auf gerade unserem Display eingestellt ist.
Möchten wir nun die Luminosità der Hintergrundbeleuchtung ändern, così wählen wir den Punkt "B" (Luminosità) aus und drücken Invio. Wir werden kurz und dann knapp gefragt: la Luminosità del Display: (max 255) und geben dahinter unseren gewünschten Wert ein.
Wir geben In diesem Beispiel 20 als gewünschten Helligkeitswert ein)
Muore wird mit der Ausgabe: Luminosità: 20 Set quittiert.Wir sehen suora, wie das Display sich auf den gewünschten Wert verdunkelt.
Für alle Interessierten, die das Segnale PWM, das unser Codice zur Steuerung der Luminosità generiert, sehen möchten habe ich von meinem Oszilloskop einmal bei dem Wert 20 und bei dem Wert 200 Screenshot angefertigt:
Wert: 20
Wert:200
Wie zu erkennen ist, unterscheidet sich das Puls-Pausen Verhältnis des Signales, während die Frequenz gleich bleibt. Unser Auge mittelt dieses Verhältnis wieder zu einer gleichmäßigen Luminosità.
Ich wünsche viel Spaß beim Nachbauen und wie immer bis zum nächsten Mal.