Diskussion:Arduino: Unterschied zwischen den Versionen

Aus BS-Wiki: Wissen teilen
Wechseln zu: Navigation, Suche
(Die Seite wurde neu angelegt: „// ********************************************************************** // interaktives Periodensystem der Elemente // schaltet gewünschte LED an // Detlef…“)
 
 
(7 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
 +
<source lang="c">
 
// **********************************************************************
 
// **********************************************************************
 
// interaktives Periodensystem der Elemente
 
// interaktives Periodensystem der Elemente
Zeile 4: Zeile 5:
 
// Detlef Giesler
 
// Detlef Giesler
 
// BBS Winsen (Luhe)
 
// BBS Winsen (Luhe)
// 29.04.2015
 
 
// **********************************************************************
 
// **********************************************************************
 
// letzte Änderungen:
 
// letzte Änderungen:
// 29.04.2015: Arduino als HTTP-Client
+
// 2017: to do / Idee Uhrenfunktion, Std. gemäß OZ 1-24, Minuten OZ 1-59 als Herzblinker, z.B. 7:45 als N:Rh, volle Stunden mit 1 und 59, bei h = m Herzblinker links und rechts von h
 +
// - DeT-Pause
 +
// 15.07. www-Schaltaufruf mittels Port Forwarding
 +
// 14.07. Code säubern
 +
// 13.07. Bewegungsmelder, Standby neu
 +
// 12.07. Modi schaltbar
 +
// 11.07. Patchmodus gefixt
 +
// 10.07. const Variablenumbennung
 +
// 08.07. serieller Input in Unterprogramm, www gekürzt
 +
// 07.07. Fernbedienung mit Interrupt
 +
// 05.07. Fernbedienung, Serial.begin(115200);
 +
// 23.06. Reset nach Standby
 +
// 21.06. Weiterleitung i. O.
 +
// 18.06. Weiterleitung kaputt? Abgleich mit 08.06., dort funzts
 +
// 08.05.2015: Patch Panel fix
 +
// 06.05.2015: Patch Panel aktiviert aber irgendwie verschoben
 +
// 05.05.2015: Anpassung an Mega 2560 wg. Speicherproblemen beim Uno
 +
// 04.05.2015: rudimentäre Dimmfunktion
 +
// 03.05.2015: Ausbaustufe = 32, LED #0 gibt es nicht mehr, automatisches Abschalten nach 500 Leerzyklen
 +
// 02.05.2015: Aufruf auch von bs-wiki möglich
 +
// 01.05.2015: Schalten über HTTP GET
 +
// 29.04.2015: Arduino als HTTP Client
 
// 28.04.2015: Abfrage der seriellen Schnittstelle
 
// 28.04.2015: Abfrage der seriellen Schnittstelle
 
// **********************************************************************
 
// **********************************************************************
 +
// TO DOs:
 +
// Layout La & Ac
 +
// **********************************************************************
 +
// verwendete Bibliotheken:
 
#include <SPI.h>
 
#include <SPI.h>
 
#include <Ethernet.h>
 
#include <Ethernet.h>
byte mac[6] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
+
// ----------------------------------------------------------------------
byte ip[4] = { 192, 168, 178, 104 }; // ip in lan (that's what you need to use in your browser. ("192.168.178.104")
+
// globale Variablen:
byte gateway[4] = { 192, 168, 1, 1 }; // internet access via router
+
// KONSTANTEN
byte subnet[4] = { 255, 255, 255, 0 }; //subnet mask
+
// Pinning Arduino:
EthernetServer server(80); //server port
+
// Arduino-Pin 2 mit IR-Sensor verbunden:
 +
const byte IR_PIN = 2;
 +
// Arduino-Pin 3 als "Dimmer" verbunden mit OE des 74HC595 (dort Pin 13, Output Enable):
 +
const byte OUTPUT_ENABLE_PIN = 3;
 +
// Arduino-Pin 7 mit Bewegungsmelder verbunden (dort Pin 2, Out):
 +
const byte BEWEGUNGSMELDER_PIN = 7;
 +
// Arduino-Pin 8 als SHIFT_PIN verbunden mit SH_CP des 74HC595 (dort Pin 11, shift register clock input):
 +
const byte SHIFT_PIN = 8;
 +
// Arduino-Pin 9 verbunden mit ST_CP des 74HC595 (dort Pin 12, storage register clock input = latch pin):
 +
const byte STORE_PIN = 9;
 +
// Arduino-Pin 10 verbunden mit DS des 74HC595 (dort Pin 14, serial data input):
 +
const byte DATA_PIN = 10;
 +
// ----------------------------------------------------------------------
 +
// Internet:
 +
byte mac[6] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // physikalische mac-Adresse
 +
// TO DO: vor Ort anzupassen:
 +
byte ip[4] = { 192, 168, 178, 104 }; // IP im **lokalen** Netzwerk
 +
// Aufruf dann im Browser z. B. über http://192.168.178.104/?z=4
 +
// "Arduino an IP 192..., schalte Led Nr. 4 an!"
 +
//  Falls ein "echter", also **globaler** www-Aufruf ermöglicht werden soll, muss im Router eine Portweiterleitung eingerichtet werden.
 +
//  Bei meiner Fritzbox 7270 (Router-IP ist 31.19.122.16) über Internet:Freigaben:Portfreigabe mit den Einstellungen:
 +
//  andere Anwendungen, TCP, Port 80, an IP-Adresse 192.168.178.104. Die lokale IP hier im Sketch bleibt unverändert,
 +
//  allerdings kann dann der Schaltaufruf ebenso mit "http://31.19.122.16/?z=4" erfolgen.
 +
byte gateway[4] = { 192, 168, 1, 1 }; // Internetaccess via Router
 +
byte subnet[4] = { 255, 255, 255, 0 }; // subnet mask
 +
EthernetServer server(80); // Server port
 
String readString;
 
String readString;
 
+
// String URL = "http://www.bs-wiki.de/mediawiki/index.php?title=";
// globale Variablen:
+
// ----------------------------------------------------------------------
// Arduino-Pin verbunden mit SH_CP des 74HC595
+
// LED-Wand:
byte shiftPin = 8;
+
// Hardware-Info: 12m²-PSE aus 6 Teildisplays, 144/6 = 24 LEDs/Teildisplay,
// Arduino-Pin verbunden mit ST_CP des 74HC595
+
// ... jedes Teildisplay angesteuert durch 3x8 Datenleitungen (3 Spalten, 8 Zeilen),
byte storePin = 9;
+
// ... pro Spalte ein 8-bit-Schieberegister = 18 SR insgesamt
// Arduino-Pin verbunden mit DS des 74HC595
+
// Pinning Schieberegister:
byte dataPin = 10;
 
 
 
 
// Elemente und LEDs:
 
// Elemente und LEDs:
// 24 ist die derzeitige Ausbaustufe, am Ende 120 LEDs
+
// Ausbaustufe 144 LEDs
byte Ausbaustufe = 24;
+
const byte Ausbaustufe = 144;  // 144
 
+
byte Anzahl_Legenden_LEDs = 0;
// Auswahl
+
byte Legende_anfang = 121;
 +
byte Legende_ende = 140;
 +
boolean Patchmodus;
 +
// Compilerfehler erforderdert Vergrößerung der Arrays um ein Feld, andernfalls Überlauf in andere Variablen
 +
boolean led[Ausbaustufe + 1] = {0};
 +
unsigned int led_aus[Ausbaustufe + 1];
 +
// virtuelles Patchpanel: Zuordnung Ordungszahl/Pin, z. B. Natrium mit OZ 11 an *Pin 3*:
 +
byte Pin_von_Element[Ausbaustufe + 1] = { 0, 1, 137
 +
                                          , 2, 9, 97, 105, 113, 121, 129, 138
 +
                                          , 3, 10, 98, 106, 114, 122, 130, 139
 +
                                          , 4, 11, 19, 27, 35, 43, 51, 59, 67, 75, 83, 91, 99, 107, 115, 123, 131, 140
 +
                                          , 5, 12, 20, 28, 36, 44, 52, 60, 68, 76, 84, 92, 100, 108, 116, 124, 132, 141
 +
                                          , 6, 13, 23, 31, 39, 47, 55, 63, 71, 79, 87, 95, 103, 111, 119, 127, 21, 29, 37, 45, 53, 61, 69, 77, 85, 93, 101, 109, 117, 125, 133, 142
 +
                                          , 7, 14, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128, 22, 30, 38, 46, 54, 62, 70, 78, 86, 94, 102, 110, 118, 126, 134, 143, 15, 16, 17, 18, 25, 26, 33, 34, 41, 42, 49, 50, 57, 58, 65, 66, 73, 74, 81, 82, 89, 90, 135, 136, 144
 +
                                          , 8
 +
                                        };
 +
// Pinning ohne eine "Led #0"
 +
//                                          p1 p2 p3  p4  p5  p6
 +
byte Element_an_Pin[Ausbaustufe + 1] = { 0, 1, 3, 11, 19, 37, 55
 +
                                        //
 +
                                        //p7  p8 - p9 p10 p11 p12 p13 p14 p15  p16 -p17  p18  p19 p20 p21 p22  p23 p24-
 +
                                        , 87, 144, 4, 12, 20, 38, 56, 88, 119, 120, 121, 122, 21, 39, 71, 103, 57, 89
 +
                                        //
 +
                                        // p25 p26  p27 p28 p29 p30  p31 p32-p33  p34  p35 p36 p37 p38  p39 p40-p41  p42  p43 p44 p45 p46  p47 p48
 +
                                        , 123, 124, 22, 40, 72, 104, 58, 90, 125, 126, 23, 41, 73, 105, 59, 91, 127, 128, 24, 42, 74, 106, 60, 92
 +
                                        //
 +
                                        // p49 p50  p51 p52 p53 p54  p55 p56-p57  p58  p59 p60 p61 p62  p63 p64-p65  p66  p67 p68 p69 p70  p71 p72
 +
                                        , 129, 130, 25, 43, 75, 107, 61, 93, 131, 132, 26, 44, 76, 108, 62, 94, 133, 134, 27, 45, 77, 109, 63, 95
 +
                                        //
 +
                                        // p73 p74  p75 p76 p77 p78  p79 p80-p81  p82  p83 p84 p85 p86  p87 p88-p89  p90  p91 p92 p93 p94  p95 p96
 +
                                        , 135, 136, 28, 46, 78, 110, 64, 96, 137, 138, 29, 47, 79, 111, 65, 97, 139, 140, 30, 48, 80, 112, 66, 98
 +
                                        //
 +
                                        // p97p98 p99 p100p101p102 p103p104-p105p106p107p108p109p110p111p112-p113p114p115p116p117p118p119p120
 +
                                        ,  5, 13, 31, 49, 81, 113, 67, 99, 6, 14, 32, 50, 82, 114, 68, 100, 7, 15, 33, 51, 83, 115, 69, 101
 +
                                        //
 +
                                        //p121p122p123p124p125p126p127p128-p129p130p131p132p133p134p135 p136-p137p138p139p140p141p142p143p144
 +
                                        , 8, 16, 34, 52, 84, 116, 70, 102, 9, 17, 35, 53, 85, 117, 141, 142, 2, 10, 18, 36, 54, 86, 118, 143
 +
                                      };
 +
// ----------------------------------------------------------------------
 +
// Auswahl im laufenden Programm:
 +
String Input; // IR, Seriell oder www
 
// Ordnungszahl definiert Element 1...118
 
// Ordnungszahl definiert Element 1...118
byte Auswahl = 0;
+
int Auswahl = 0;   // 254
// 0 = Legende,
+
boolean neue_Auswahl;
// 1 = Wasserstoff, 2 = Helium ...
+
boolean Bewegungsstatus = HIGH; // bei Systemstart Bewegung simulieren
// 131...137 = 1. - 7. Periode
 
// 141...148 = 1. - 8. Hauptgruppe
 
// 160 = Metalle
 
// 170 = Halbmetalle
 
// 180 = Nichtmetalle
 
// 190 = fest
 
// 191 = flüssig
 
// 192 = gasförmig
 
// 193 = radioaktiv
 
// 194 = biatomar
 
// 200 = Bingo
 
// 201 = Programm_x
 
// 202 = Programm_y
 
// 203 = Programm_z
 
// 254 = alles_aus
 
// 255 = alles_an
 
 
 
boolean led[145];
 
unsigned int led_aus[145];
 
// virtuelles Patchpanel: Zuordnung Ordungszahl/Pin, z. B. Natrium mit OZ 11 an *Pin 3*:
 
// Pinning        -          p1 p2*p3* p4  p5  p6  p7  p8-p9 p10 p11 p12 p13 p14 p15  p16 -p17  p18  p19 p20 p21 p22  p23 p24-p25  p26  p27 p28 p29 p30  p31 p32-p33  p34  p35 p36 p37 p38  p39 p40-p41  p42  p43 p44 p45 p46  p47 p48-p49  p50  p51 p52 p53 p54  p55 p56-p57  p58  p59 p60 p61 p62  p63 p64-p65  p66  p67 p68 p69 p70  p71 p72-p73  p74  p75 p76 p77 p78  p79 p80-p81  p82  p83 p84 p85 p86  p87 p88-p89  p90  p91 p92 p93 p94  p95 p96-p97p98 p99 p100p101p102 p103p104-p105p106p107p108p109p110p111p112-p113p114p115p116p117p118p119p120-p121p122p123p124p125p126p127p128-p129p130p131p132p133p134p135p136-p137p138p139p140p141p142p143p144
 
const byte Element_an_Pin[145] = {0, 1, 3, 11, 19, 37, 55, 87, 0, 4, 12, 20, 38, 56, 88, 119, 120, 121, 122, 21, 39, 71, 103, 57, 89, 123, 124, 22, 40, 72, 104, 58, 90, 125, 126, 23, 41, 73, 105, 59, 91, 127, 128, 24, 42, 74, 106, 60, 92, 129, 130, 25, 43, 75, 107, 61, 93, 131, 132, 26, 44, 76, 108, 62, 94, 133, 134, 27, 45, 77, 109, 63, 95, 135, 136, 28, 46, 78, 110, 64, 96, 137, 138, 29, 47, 79, 111, 65, 97, 139, 140, 30, 48, 80, 112, 66, 98, 5, 13, 31, 49, 81, 113, 67, 99, 6, 14, 32, 50, 82, 114, 68, 100, 7, 15, 33, 51, 83, 115, 69, 101, 8, 16, 34, 52, 84, 116, 70, 102, 9, 17, 35, 53, 85, 117, 141, 142, 2, 10, 18, 36, 54, 86, 118, 143};
 
// Element_an_Pin[] nach steigender Ordungszahl notieren:
 
// TO DO wg. Speicherproblemen vorerst aus:
 
// byte patch[145];
 
 
 
 
byte Anzahl_angeschaltete_LEDs = 0;
 
byte Anzahl_angeschaltete_LEDs = 0;
unsigned int t_gesamt_in_sek = millis() / 1000;
+
// TO DO: über Poti einstellen und von Pin einlesen oder über Auswahl (180)
// TO DO: über Poti einstellen
+
const unsigned int LED_Eieruhr_normal = 30;  // Vorgabe der Einschaltdauer einer LED in Sekunden
byte Eieruhr = 20;  // Vorgabe der Einschaltdauer einer LED in Sekunden
+
unsigned int LED_Eieruhr = LED_Eieruhr_normal;  // gewählte Einschaltdauer einer LED in Sekunden
 
+
unsigned int Standby_Timer = 180;  // Zeit in Sekunden bis zum Standby
 +
const byte Standardhelligkeit = 127;
 +
byte Helligkeit = Standardhelligkeit; // beliebiger Wert für Dimmer
 +
byte Wunschhelligkeit = Standardhelligkeit; // durch Menüauswahl bestimmt
 +
byte last_Element = 0;
 +
int zyklus = 0; // loop-Zyklen
 +
unsigned int last_call = Laufzeit_in_sek();
 +
int serial_a = 0;
 +
int serial_nr = 0;
 +
// ----------------------------------------------------------------------
 +
// Debugging
 +
boolean Debug_Modus = 1; // mit Zusatzinfos über seriellen Monitor, kann über 208 umgeschaltet werden
 +
int bremse = 0;  // 1 ... 60000 Standardwert für Entschleunigung in ms zwischen einigen Befehlen zwecks Debugging
 +
// ----------------------------------------------------------------------
 +
// IR - Fernbedienung
 +
// Arduino IR Remote Sniffer
 +
// Portions © Andrew Ippoliti - acipo.com
 +
// const byte IR_PIN = 2;
 +
// volatile damit es auch in INT funktioniert
 +
volatile boolean bounced = 0;
 +
const byte CODE_LEN = 40;
 +
volatile unsigned long durations[CODE_LEN];
 +
int letzte_IR_Auswahl;
 +
int IR_Auswahl;
 +
boolean mehrstellig;
 
// **********************************************************************
 
// **********************************************************************
 
void setup() {
 
void setup() {
   Serial.begin(9600); // Kontrollausgabe über seriellen Monitor
+
   Serial.begin(115200); // Kontrollausgabe über seriellen Monitor
   // Pin 5 abfragen (analog, EMK) für Zufallszahl
+
   Serial.flush(); // löscht den Inhalt des seriellen Puffers
   randomSeed(analogRead(5));
+
  // CHECK Fenster: es kommt Müll, wenn nicht 'kein Zeilenende' eingestellt ist!
   // Pins 8,9,10 auf Ausgabe
+
  // Ausgabe-Pins: 3, 8, 9, 10:
   pinMode(storePin, OUTPUT);
+
  pinMode(OUTPUT_ENABLE_PIN, OUTPUT); // Dimmer
   pinMode(shiftPin, OUTPUT);
+
  analogWrite(OUTPUT_ENABLE_PIN, 255); // entspricht 5 Volt an OE und damit LEDs aus
   pinMode(dataPin, OUTPUT);
+
  pinMode(STORE_PIN, OUTPUT);
 +
   pinMode(SHIFT_PIN, OUTPUT);
 +
  pinMode(DATA_PIN, OUTPUT);
 +
   // Eingabe-Pins: 2, 7:
 +
   pinMode(BEWEGUNGSMELDER_PIN, INPUT);
 +
  // IR-Fernbedienung
 +
   pinMode(IR_PIN, INPUT);
 +
   attachInterrupt(0, decodeIR, FALLING);
 +
  //FALLING for when the Digitalpin 2 goes from high to low.
 +
  Serial.println("PSE");
 +
  Serial.println("--------------------------------");
 
   // start the Ethernet connection and the server:
 
   // start the Ethernet connection and the server:
 
   Ethernet.begin(mac, ip, gateway, subnet);
 
   Ethernet.begin(mac, ip, gateway, subnet);
 +
  // give the Ethernet shield 3 seconds to initialize:
 +
  delay(3000);
 
   server.begin();
 
   server.begin();
   Serial.print("server is at ");
+
   Serial.print("Server ist an IP ");
 
   Serial.println(Ethernet.localIP());
 
   Serial.println(Ethernet.localIP());
 
+
  Anzahl_Legenden_LEDs = 1 + Legende_ende - Legende_anfang;
   resetPins(); // alle Pins auf LOW
+
  Serial.print("Anzahl Legenden-LEDs: ");
 +
  Serial.println(Anzahl_Legenden_LEDs);
 +
   Serial.println();
 +
  // TO DO: löschen:
 +
  // Element_an_Pin[] nach steigender Ordungszahl notieren:
 
   // Switchen, Element_an_Pin[] nach steigender Ordungszahl merken:
 
   // Switchen, Element_an_Pin[] nach steigender Ordungszahl merken:
  // TO DO wg. Speicherproblemen vorerst aus:
+
   //  for (byte z = 1; z < 144 + 1; z++) {
   //  for (byte z = 0; z < 144; z++) {
 
 
   //    patch[Element_an_Pin[z]] = z;
 
   //    patch[Element_an_Pin[z]] = z;
   //    // Ordnungszahl
+
   //    //  //    // Ordnungszahl
 
   //  }
 
   //  }
 +
  //  for (byte z = 1; z < 144 + 1; z++) {
 +
  //    //    Serial.print("Pin: ");
 +
  //    //    Serial.print(z);
 +
  //    //    Serial.print(" = OZ: ");
 +
  //    //    Serial.print(Element_an_Pin[z]);
 +
  //    //    Serial.print(" = Patch(OZ): ");
 +
  //    Serial.print(patch[z]);
 +
  //    //    Serial.println();
 +
  //    Serial.print(", ");
 +
  //  }
 +
  //  Serial.println();
 
   // ***********************
 
   // ***********************
 
   // Kontrolle
 
   // Kontrolle
Zeile 100: Zeile 212:
 
   //      Serial.println(". Zeile");
 
   //      Serial.println(". Zeile");
 
   //      byte z = zeile + 8 * (spalte - 1);
 
   //      byte z = zeile + 8 * (spalte - 1);
  //      delay(1000);
+
   //      Serial.print("OZ ");
   //      Serial.print("Pin ");
 
 
   //      Serial.print(z);
 
   //      Serial.print(z);
   //      Serial.print(" - OZ ");
+
   //      Serial.print(" - Pin ");
   //      Serial.println(Element_an_Pin[z]);
+
   //      Serial.println(Pin_von_Element[z]);
  //      Serial.print("Patch = ");
 
  //      Serial.println(patch[z]);
 
 
   //    }
 
   //    }
 
   //  }
 
   //  }
  //  delay(10000);
+
   // für Testphase LED von Element = 7 im Setup einschalten:
  // ***********************
 
  // LED Nr. 0 (Legende) immer an, ist gleichzeitig Kontrollleuchte für aktives Board:
 
  Led_an(0, 1);
 
  delay(1000);
 
 
 
   // für Testphase LEDs im setup einschalten, später in loop:
 
  //  Element = 7;  // blau
 
 
   Led_an(7, 1);
 
   Led_an(7, 1);
   delay(1000);
+
   Patchmodus_umschalten(); // kann über 207 umgeschaltet werden
  Serial.println("alle_Elemente_an");
+
   debugging();  // kann über 208 umgeschaltet werden
  Auswahl_alles_an();
+
   Serial.println("Setup fertig, jetzt startet die Loop-Schleife ......");
  Serial.println("alle_Elemente sind an");
+
   Serial.println("----------------------------------------------------");
  delay(3000);
 
  Serial.println("alle_Elemente_aus");
 
   Auswahl_alles_aus();
 
  Serial.println("alle_Elemente sind aus");
 
  delay(1000);
 
  // Serial.println("alle_Elemente Bingo");
 
  // Auswahl_Bingo();
 
   Serial.println("jetzt startet die loop-Schleife ......");
 
   Serial.println("--------------------------------------");
 
  delay(3000);
 
 
}
 
}
 
// **********************************************************************
 
// **********************************************************************
 
void loop () {
 
void loop () {
   Serial.println("loop");
+
   zyklus = zyklus + 1;
  Auswahl = 0;
+
  //  Serial.print(zyklus);
   // horche an der seriellen Schnittstelle und
+
  //  Serial.println(". Loop");
   // erfrage Element; später mal durch Webserver nach Ordnungszahl o. ä. auswählen:
+
   // horche an IR-FB (Interrupt), der seriellen Schnittstelle und über Ethernet-Shield an www
   // z.B. Nr. 1 - Wasserstoff:
+
   // erfrage Element; nach Ordnungszahl o. ä. auswählen:
   //  while (Serial.available() == 0)
+
   // z. B. OZ 1 - Wasserstoff:
   // {
+
  serielle_Schnittstelle_abfragen();
   //
+
  www_abfragen();
 +
  Bewegungsmelder_abfragen();
 +
  if (neue_Auswahl) {
 +
    Auswahl_auswerten();
 +
  }
 +
  if (Anzahl_angeschaltete_LEDs > Anzahl_Legenden_LEDs) {
 +
    Treppenlicht();
 +
  }
 +
   //  if (zyklus > 9999) {        // 999
 +
  //    // 1000-mal is nichts passiert, daher:
 +
  //    reset();
 +
   //   Serial.println("-----ALLE LEDS AUS -------------------------------");
 +
   //   delay(3000);
 
   //  }
 
   //  }
  www();
+
}
   while (Serial.available() > 0)
+
// **********************************************************************
   {
+
// ############### Funktionen nach ABC ##############################
    byte a = 0;
+
// **********************************************************************
    {
+
void Auswahl_auswerten()
      Auswahl = Auswahl * 10;
+
{
      a = Serial.read() - '0';
+
  Bewegungsstatus = HIGH;
      Auswahl = Auswahl + a;
+
   zyklus = 0; // Schlafmodus beenden
      delay(1);
+
   neue_Auswahl = 0;
    }
+
  last_call = Laufzeit_in_sek();
     Serial.write(Auswahl);
+
  if (Debug_Modus) {
 +
    Serial.print("neue Auswahl von ");
 +
    Serial.println(Input);
 +
    Serial.println(Auswahl);
 +
     Serial.println();
 
   }
 
   }
  delay(100);
 
 
   switch (Auswahl) {
 
   switch (Auswahl) {
 +
    // 0 = existiert nicht
 +
    case 1 ... 118: Led_an(Auswahl, 1); break; // 1 = Wasserstoff, 2 = Helium ... 118 = Uuo
 +
    case 131 ... 139: Auswahl_Periode(); break;      // = 1. - 7. Periode, Lanthanoide, A.
 +
    case 141 ... 148: Auswahl_Hauptgruppe(); break;  // = 1. - 8. Hauptgruppe
 
     case 160: Auswahl_Metalle(); break;
 
     case 160: Auswahl_Metalle(); break;
     case 170: Auswahl_Halbmetalle(); break;
+
     case 161: Auswahl_Halbmetalle(); break;
     case 180: Auswahl_Nichtmetalle(); break;
+
    case 162: Auswahl_Nichtmetalle(); break;
 +
     case 180: LED_Eieruhr_switchen(); break; //  auf 180 Sekunden oder LED_Eieruhr_normal
 
     case 190: Auswahl_fest(); break;
 
     case 190: Auswahl_fest(); break;
 
     case 191: Auswahl_liquid(); break;
 
     case 191: Auswahl_liquid(); break;
Zeile 170: Zeile 282:
 
     case 202: Auswahl_Programm_y(); break;
 
     case 202: Auswahl_Programm_y(); break;
 
     case 203: Auswahl_Programm_z(); break;
 
     case 203: Auswahl_Programm_z(); break;
 +
    case 207: Patchmodus_umschalten(); break;
 +
    case 208: debugging(); break;    // Debugging-Modus
 +
    case 209: reset(); break;
 +
    case 210 ... 215: Auswahl_Helligkeit(); break;
 +
    // 222 = Browserfenster umschalten auf Arduino-Auswahlmenü
 +
    //    case 222: www_abfragen(); break;
 
     case 254: Auswahl_alles_aus(); break;
 
     case 254: Auswahl_alles_aus(); break;
 
     case 255: Auswahl_alles_an(); break;
 
     case 255: Auswahl_alles_an(); break;
     case 131: Auswahl_Periode(1, 2); break;
+
     default:  // unbelegte Zahlen sind unsinnig und werden genullt:
     default:
+
      Serial.println("keine neue Auswahl");
       Led_an(Auswahl, 1);
+
  }
 +
  // vergesse die bisherige Auswahl, LED nicht erneut anschalten:
 +
  Auswahl = 0;
 +
}
 +
// **********************************************************************
 +
void Auswahl_alles_an() {            // 255
 +
  Serial.println("alle_Elemente_an");
 +
  for (byte z = 1; z < Ausbaustufe + 1; z++) {
 +
    Led_an(z, 1);
 +
  }
 +
  Serial.println("alle_Elemente sind an");
 +
}
 +
// **********************************************************************
 +
void Auswahl_alles_aus() {
 +
  Helligkeit = 0;
 +
  Dimmer();
 +
  // schaltet alle LEDs außer die für die Legende aus
 +
  Serial.println("alle_Elemente_aus");
 +
  for (byte z = 1; z < Ausbaustufe + 1; z++) {
 +
    Led_an(z, 0);
 +
  }
 +
  Serial.println("alle_Elemente sind aus");
 +
  Legende_an();
 +
  Helligkeit = Standardhelligkeit;
 +
  Dimmer();
 +
}
 +
// **********************************************************************
 +
void Auswahl_biatomar() {
 +
  Serial.println("Auswahl_biatomar");
 +
  for (byte z = 1; z < Ausbaustufe + 1; z++) {
 +
     if ((z == 1) || (z == 7) || (z == 8) || (z == 9) || (z == 17) || (z == 35) || (z == 53) || (z == 138) ) {
 +
       Led_an(z, 1);
 +
    }
 
   }
 
   }
   // vergesse die bisherige Auswahl, also nicht erneut schalten:
+
}
   // Auswahl = 0;
+
// **********************************************************************
   // for (int z = 1; z < Ausbaustufe; z++) {
+
void Auswahl_Bingo() {
  //   delay(1000);
+
  Serial.println("Elemente-Bingo");
  //   Led_an(z, 1);
+
  byte zufall = random(1, Ausbaustufe);
  //   delay(100);
+
   // setzt 'zufall' mit einer Zufallszahl
  //   //   Led_an(z, 0);
+
  // zwischen 1 und Ausbaustufe gleich
  if (Anzahl_angeschaltete_LEDs > 1) {
+
  Serial.print("Zufalls-Element: ");
     Treppenlicht();
+
  Serial.println(zufall);
 +
   Led_an(zufall, 1);
 +
}
 +
// **********************************************************************
 +
void Auswahl_Hauptgruppe() {
 +
  byte Hauptgruppe = Auswahl - 140;
 +
  Serial.print(Hauptgruppe);
 +
  Serial.println(". Hauptgruppe");
 +
   switch (Hauptgruppe) {
 +
    case 1: // 1. Hauptgruppe
 +
      Led_an(1, 1); Led_an(3, 1); Led_an(11, 1); Led_an(19, 1); Led_an(37, 1); Led_an(55, 1); Led_an(87, 1); break;
 +
    case 2: // 2. Hauptgruppe
 +
      Led_an(4, 1); Led_an(12, 1); Led_an(20, 1); Led_an(38, 1); Led_an(56, 1); Led_an(88, 1); break;
 +
    case 3: // 3. Hauptgruppe
 +
      Led_an(5, 1); Led_an(13, 1); Led_an(31, 1); Led_an(49, 1); Led_an(81, 1); Led_an(113, 1); break;
 +
    case 4: // 4. Hauptgruppe
 +
      Led_an(6, 1); Led_an(14, 1); Led_an(32, 1); Led_an(50, 1); Led_an(82, 1); Led_an(114, 1); break;
 +
    case 5: // 5. Hauptgruppe
 +
      Led_an(7, 1); Led_an(15, 1); Led_an(33, 1); Led_an(51, 1); Led_an(83, 1); Led_an(115, 1); break;
 +
    case 6: // 6. Hauptgruppe
 +
      Led_an(8, 1); Led_an(16, 1); Led_an(34, 1); Led_an(52, 1); Led_an(84, 1); Led_an(116, 1); break;
 +
    case 7: // 7. Hauptgruppe
 +
      Led_an(9, 1); Led_an(17, 1); Led_an(35, 1); Led_an(53, 1); Led_an(85, 1); Led_an(117, 1); break;
 +
     case 8: // 8. Hauptgruppe
 +
      Led_an(2, 1); Led_an(10, 1); Led_an(18, 1); Led_an(36, 1); Led_an(54, 1); Led_an(86, 1); Led_an(118, 1); break;
 
   }
 
   }
  Serial.println("--------------------");
 
  delay(1000);
 
 
}
 
}
 
// **********************************************************************
 
// **********************************************************************
// ############### Unterprogramme nach ABC ##############################
+
void Auswahl_Helligkeit() {
 +
  // 210 ... 215
 +
  Wunschhelligkeit = 5 + 50 * (Auswahl - 210);
 +
  // 210 -> 5, 211 -> 55, ... 215 -> 255
 +
  Helligkeit = Wunschhelligkeit;
 +
  Dimmer();
 +
}
 
// **********************************************************************
 
// **********************************************************************
void Auswahl_Metalle() {
+
void Auswahl_Metalle() { // 160
   for (byte z = 1; z < Ausbaustufe; z++) {
+
  Serial.println("Metalle");
     if ((z == 3) || (z == 4) || (z == 11) || (z == 12) || (z == 13) || ((z >= 19) && (z <= 31)) || ((z >= 37) && (z <= 50)) || ((z >= 55) && (z <= 84)) || ((z >= 87) && (z <= 118)) || (z == 133)) {
+
   for (byte z = 1; z < Ausbaustufe + 1; z++) {
 +
     if ((z == 3) || (z == 4) || (z == 11) || (z == 12) || (z == 13) || ((z >= 19) && (z <= 31))
 +
        || ((z >= 37) && (z <= 50))
 +
        || ((z >= 55) && (z <= 84)) || ((z >= 87) && (z <= 118)) || (z == 133)) {
 
       Led_an(z, 1);
 
       Led_an(z, 1);
 
     }
 
     }
Zeile 201: Zeile 382:
 
// **********************************************************************
 
// **********************************************************************
 
void Auswahl_Halbmetalle() {
 
void Auswahl_Halbmetalle() {
   for (byte z = 1; z < Ausbaustufe; z++) {
+
  Serial.println("Halbmetalle");
     if ((z == 5) || (z == 14) || (z == 32) || (z == 33) || (z == 34) || (z == 51) || (z == 52) || (z == 85) || (z == 135)) {
+
   for (byte z = 1; z < Ausbaustufe + 1; z++) {
 +
     if ((z == 5) || (z == 14) || (z == 32) || (z == 33) || (z == 34) || (z == 51) || (z == 52) || (z == 85)
 +
        || (z == 135)) {
 
       Led_an(z, 1);
 
       Led_an(z, 1);
 
     }
 
     }
Zeile 209: Zeile 392:
 
// **********************************************************************
 
// **********************************************************************
 
void Auswahl_Nichtmetalle() {
 
void Auswahl_Nichtmetalle() {
   for (byte z = 1; z < Ausbaustufe; z++) {
+
  Serial.println("Nichtmetalle");
     if ((z == 1) || (z == 2) || ((z >= 6) && (z <= 10)) || ((z >= 15) && (z <= 18)) || ((z >= 35) && (z <= 36)) || ((z >= 53) && (z <= 54)) || (z == 86) || (z == 137)) {
+
   for (byte z = 1; z < Ausbaustufe + 1; z++) {
 +
     if ((z == 1) || (z == 2) || ((z >= 6) && (z <= 10)) || ((z >= 15) && (z <= 18)) || ((z >= 35) && (z <= 36))
 +
        || ((z >= 53) && (z <= 54)) || (z == 86) || (z == 137)) {
 
       Led_an(z, 1);
 
       Led_an(z, 1);
 
     }
 
     }
Zeile 217: Zeile 402:
 
// **********************************************************************
 
// **********************************************************************
 
void Auswahl_fest() {
 
void Auswahl_fest() {
   for (byte z = 1; z < Ausbaustufe; z++) {
+
  Serial.println("190 = fest");
     if (((z >= 3) && (z <= 6)) || ((z >= 11) && (z <= 16)) || ((z >= 19) && (z <= 34)) || ((z >= 37) && (z <= 53)) || ((z >= 55) && (z <= 85)) || ((z >= 87) && (z <= 118))) {
+
   for (byte z = 1; z < Ausbaustufe + 1; z++) {
 +
     if (((z >= 3) && (z <= 6)) || ((z >= 11) && (z <= 16)) || ((z >= 19) && (z <= 34)) || ((z >= 37) && (z <= 53))
 +
        || ((z >= 55) && (z <= 85)) || ((z >= 87) && (z <= 118))) {
 
       Led_an(z, 1);
 
       Led_an(z, 1);
 
     }
 
     }
Zeile 225: Zeile 412:
 
// **********************************************************************
 
// **********************************************************************
 
void Auswahl_liquid() {
 
void Auswahl_liquid() {
   for (byte z = 1; z < Ausbaustufe; z++) {
+
  Serial.println("191 = flüssig");
 +
   for (byte z = 1; z < Ausbaustufe + 1; z++) {
 
     if ((z == 35) || (z == 80)) {
 
     if ((z == 35) || (z == 80)) {
 
       Led_an(z, 1);
 
       Led_an(z, 1);
Zeile 233: Zeile 421:
 
// **********************************************************************
 
// **********************************************************************
 
void Auswahl_gas() {
 
void Auswahl_gas() {
 +
  Serial.println("192 = gasförmig");
 
   for (byte z = 1; z < Ausbaustufe; z++) {
 
   for (byte z = 1; z < Ausbaustufe; z++) {
     if ((z == 1) || (z == 2) || (z == 7) || (z == 8) || (z == 9) || (z == 10) || (z == 17) || (z == 18) || (z == 36) || (z == 54) || (z == 86)) {
+
     if ((z == 1) || (z == 2) || (z == 7) || (z == 8) || (z == 9) || (z == 10) || (z == 17) || (z == 18)
 +
        || (z == 36) || (z == 54) || (z == 86)) {
 
       Led_an(z, 1);
 
       Led_an(z, 1);
 
     }
 
     }
 
   }
 
   }
 +
}
 +
// **********************************************************************
 +
void Auswahl_Periode() {
 +
  byte Periode = Auswahl - 130;
 +
  Serial.print(Periode);
 +
  Serial.println(". Periode");
 +
  byte anfang;
 +
  byte ende;
 +
  switch (Periode) {
 +
    case 1: anfang = 1; ende = 2; break;      // 1. Periode: 1-H, 2-He
 +
    case 2: anfang = 3; ende = 10; break;
 +
    case 3: anfang = 11; ende = 18; break;
 +
    case 4: anfang = 19; ende = 36; break;
 +
    case 5: anfang = 37; ende = 54; break;
 +
    case 6: anfang = 55; ende = 86; break;
 +
    case 7: anfang = 87; ende = 118; break;  // 7. Periode: Fr-Uuo
 +
    case 8: anfang = 57; ende = 71; break; // Lanthanoide
 +
    case 9: anfang = 89; ende = 103; break; // Actinoide
 +
  }
 +
  for (byte z = anfang; z < ende + 1; z++) {
 +
    Led_an(z, 1);
 +
  }
 +
}
 +
// **********************************************************************
 +
void Auswahl_Programm_x() { // 201
 +
  Serial.println("PSE schwellend aufleuchten lassen");
 +
  Auswahl_alles_an();
 +
  for (byte a = 0; a <= 5; a = a + 1)
 +
  {
 +
    for (byte b = 5; b <= 255; b = b + 1)
 +
    {
 +
      Helligkeit = b;
 +
      Dimmer();
 +
      delay(10);
 +
    }
 +
    for (byte b = 255; b >= 5; b = b - 1)
 +
    {
 +
      Helligkeit = b;
 +
      Dimmer();
 +
      delay(10);
 +
    }
 +
  }
 +
  Helligkeit = Wunschhelligkeit;
 +
  Dimmer();
 +
}
 +
// **********************************************************************
 +
void Auswahl_Programm_y() { // 202
 +
  Serial.println("Flackermann");
 +
  unsigned int LED_Eieruhr_2 = LED_Eieruhr; // alten Wert merken und neu festlegen
 +
  LED_Eieruhr = 3;
 +
  for (byte z = 1; z < Ausbaustufe + 1; z++) {
 +
    byte zufall = random(1, Ausbaustufe);
 +
    // setzt 'zufall' mit einer Zufallszahl
 +
    // zwischen 1 und Ausbaustufe gleich
 +
    Serial.print("Zufalls-Element: ");
 +
    Serial.println(zufall);
 +
    Led_an(zufall, 1);
 +
    Treppenlicht();
 +
    delay(100);
 +
  }
 +
  LED_Eieruhr = LED_Eieruhr_2; // alten Wert zurückschreiben
 +
}
 +
// **********************************************************************
 +
void Auswahl_Programm_z() {
 +
  // TO DO
 
}
 
}
 
// **********************************************************************
 
// **********************************************************************
 
void Auswahl_radioaktiv() {
 
void Auswahl_radioaktiv() {
   for (byte z = 1; z < Ausbaustufe; z++) {
+
  Serial.println("radioaktiv");
 +
   for (byte z = 1; z < Ausbaustufe + 1; z++) {
 
     if ((z == 43) || (z == 61) || ((z >= 84) && (z <= 118)) || (z == 134) || (z == 136)) {
 
     if ((z == 43) || (z == 61) || ((z >= 84) && (z <= 118)) || (z == 134) || (z == 136)) {
 
       Led_an(z, 1);
 
       Led_an(z, 1);
Zeile 248: Zeile 504:
 
}
 
}
 
// **********************************************************************
 
// **********************************************************************
void Auswahl_biatomar() {
+
void Bewegungsmelder_abfragen() {
   for (byte z = 1; z < Ausbaustufe; z++) {
+
   // Falls längere Zeit keine Auswahl getroffen wurde oder keine Bewegung messbar war,
    if ((z == 1) || (z == 7) || (z == 8) || (z == 9) || (z == 17) || (z == 35) || (z == 53) || (z == 138) ) {
+
  // wird der Bewegungsmelder abgefragt.
       Led_an(z, 1);
+
  // Bei Bewegung bleiben die LEDs an.
 +
  if (((Laufzeit_in_sek() > (last_call + Standby_Timer)) || (Bewegungsstatus == LOW))) {
 +
    Bewegungsstatus = digitalRead(BEWEGUNGSMELDER_PIN);
 +
    if ((Bewegungsstatus == LOW) && (neue_Auswahl == 0))
 +
    {
 +
      Helligkeit = 0;
 +
      last_call = 0; // wenn Helligkeit auf 0 gesetzt wurde
 +
    }
 +
    else
 +
    {
 +
       last_call = Laufzeit_in_sek();
 +
      Helligkeit = Wunschhelligkeit;
 
     }
 
     }
 +
    Dimmer();
 
   }
 
   }
 
}
 
}
 
// **********************************************************************
 
// **********************************************************************
void Auswahl_Programm_x() {
+
void debugging() {         // 208
 
+
  Debug_Modus = -(Debug_Modus - 1);
 +
  Serial.print("Debugging ist ");
 +
  if (Debug_Modus) {
 +
    Serial.print("ein");
 +
  }
 +
  else
 +
  {
 +
    Serial.print("aus");
 +
  }
 +
  Serial.println("geschaltet. Umschalten: 208");
 +
}
 +
// **********************************************************************
 +
void Dimmer() // 0 to 255
 +
// Funktion merkt sich Helligkeitswert für LEDs, ausbaubedingt nur Einheitswert für alle Schieberegister
 +
// 0 = dunkel, weil 0% Einschaltdauer, 255 = volle Leistung, weil 100% ED
 +
{
 +
  analogWrite(OUTPUT_ENABLE_PIN, 255 - Helligkeit);
 +
}
 +
// **********************************************************************
 +
void LED_Eieruhr_switchen() {  //  switchen auf 180 oder 30 Sekunden
 +
  Serial.print("LED-Eieruhr switchen von ");
 +
  Serial.print(LED_Eieruhr);
 +
  Serial.print(" auf ");
 +
  switch (LED_Eieruhr) {
 +
    case LED_Eieruhr_normal: LED_Eieruhr = 180; break;      // LEDs 3 Minuten anlassen
 +
    case 180: LED_Eieruhr = LED_Eieruhr_normal; break;      // LEDs 30s anlassen
 +
  }
 +
  Serial.print(LED_Eieruhr);
 +
  Serial.print(" Sekunden");
 
}
 
}
 
// **********************************************************************
 
// **********************************************************************
void Auswahl_Programm_y() {
+
unsigned int Laufzeit_in_sek() {
 
+
  unsigned int t_gesamt_in_sek = millis() / 1000;
 +
  // millis() gibt den Wert in Millisekunden als 'unsigned int' Datentyp zurück, berechnet seitdem das Arduino
 +
  // Board das aktuelle Programm gestartet hat.
 +
  return t_gesamt_in_sek;
 
}
 
}
 +
// void Laufzeit_hhmmss() {
 +
//  t_gesamt_in_sek = millis() / 1000;
 +
// nullt bei ?? ms
 +
//  byte t_gesamt_in_h = millis() / 3600000;
 +
//  byte t_gesamt_in_m = millis() / 60000 - t_gesamt_in_h * 60;
 +
//  byte t_gesamt_in_s = millis() / 1000 - t_gesamt_in_m * 60;
 +
//  Serial.print("Laufzeit hh:mm:ss = ");
 +
//  Serial.print(t_gesamt_in_h);
 +
//  Serial.print(":");
 +
//  Serial.print(t_gesamt_in_m);
 +
//  Serial.print(":");
 +
//  Serial.print(t_gesamt_in_s);
 +
//  Serial.println();
 +
// }
 
// **********************************************************************
 
// **********************************************************************
void Auswahl_Programm_z() {
+
void Led_an(byte Element, boolean an) {
 
+
  // Funktion schaltet durch (Element) bestimmte Pins (= LEDs) an oder aus,
 +
  // plant einen Ausschaltpunkt (led_aus[Element]) und merkt sich die Anzahl_angeschaltete_LEDs.
 +
  // 'Element' ist die OZ, 'an' der Schaltzustand 0/1
 +
  // 'pin' ist der tatsächliche Anschlusspunkt der LED-Matrix, z. B. bei Element 22 (Titan, logisch)
 +
  //  die 27. Led (physikalisch) schalten. Zuordnung Pin/Element:
 +
  byte Pin = Element;  // Probebetrieb ohne Patchmodus: OZ 22 = Pin 22
 +
  if (Patchmodus) {  // Normalfall: OZ 22 = Pin 27
 +
    Pin = Pin_von_Element[Element];
 +
  }
 +
  // mitzählen, wieviel LEDs insgesamt an sind:
 +
  // nur ausführen, wenn (an -> aus) oder (aus -> an), nicht bei (bleibt an) oder (bleibt aus)
 +
  if (an != led[Pin]) {
 +
    Anzahl_angeschaltete_LEDs = Anzahl_angeschaltete_LEDs + an * 2 - 1; // Anz. = Anz. -1 oder +1
 +
  }
 +
  led[Pin] = an;
 +
  //  for (byte z = 1; z < Ausbaustufe + 1; z++) {
 +
  //    if (led[z]) {
 +
  ////      Serial.print("p_");
 +
  ////      Serial.print(z);
 +
  ////      Serial.print("-");
 +
  //    }
 +
  //  }
 +
  //  // nur für Fehlerabfrage
 +
  //  if (Anzahl_angeschaltete_LEDs > Ausbaustufe) {
 +
  //    Serial.println("F E H L E R : zuviele LEDs geschaltet!");
 +
  //    delay(bremse);
 +
  //  }
 +
  // spart Speicher: unsigned long led_Start zu byte einkürzen:
 +
  if (an) {
 +
    led_aus[Element] = Laufzeit_in_sek() + LED_Eieruhr; // vormerken: LED nach (LED_Eieruhr) Sek. wieder ausschalten
 +
    last_Element = Element;  // welches Element wurde zuletzt angeschaltet?
 +
    if (Debug_Modus) {
 +
      Serial.print("LED von Element ");
 +
      Serial.print(Element);
 +
      Serial.print(" -> Pin ");
 +
      Serial.print(Pin);
 +
      Serial.println(" ist an.");
 +
      Serial.println("--------------------");
 +
    }
 +
  }
 +
  resetPins();
 +
  // Schieberegister
 +
  // serielles Einlesen, alle LEDs werden neu geschaltet
 +
  for (byte i = 1; i < Ausbaustufe + 1; i++) {
 +
    // Aktion passiert bei Wechsel von LOW auf HIGH
 +
    digitalWrite(SHIFT_PIN, LOW);
 +
    // Jetzt den Wert der aktuellen Stelle ans Datenpin DS anlegen
 +
    digitalWrite(DATA_PIN, led[i]);
 +
    // Dann SHIFT_PIN SHCP von LOW auf HIGH, damit wird der Wert
 +
    // am Datenpin ins Register geschoben.
 +
    digitalWrite(SHIFT_PIN, HIGH);
 +
  }
 +
  // Wenn alle Stellen im Register sind, jetzt das STORE_PIN STCP
 +
  // von LOW auf HIGH, damit wird Registerinhalt an Ausgabepins
 +
  // kopiert und der Zustand an den LEDs sichtbar
 +
  // neues Muster einschalten:
 +
  digitalWrite(STORE_PIN, HIGH);
 
}
 
}
 
 
// **********************************************************************
 
// **********************************************************************
void Auswahl_Periode(byte anfang, byte ende) {
+
void Legende_an() {
   for (byte z = anfang; z < ende; z++) {
+
  // diese LEDs immer anlassen:
 +
  // TO DO: bei Sondergruppe die anderen ausblenden, z. B. Metalle an,
 +
  // dann Halb- u. Nichtmetalle aus
 +
   for (byte z = Legende_anfang; z < Legende_ende + 1; z++) {
 
     Led_an(z, 1);
 
     Led_an(z, 1);
 
   }
 
   }
 
}
 
}
 
// **********************************************************************
 
// **********************************************************************
void Auswahl_alles_an() {
+
void Patchmodus_umschalten() { // 207
   for (byte z = 1; z < Ausbaustufe; z++) {
+
  Patchmodus = -(Patchmodus - 1);
     Led_an(z, 1);
+
  reset();
 +
  Serial.print("Patchmodus ist ");
 +
  if (Patchmodus) {
 +
    Serial.print("ein");
 +
  }
 +
  else
 +
  {
 +
    Serial.print("aus");
 +
  }
 +
  Serial.println("geschaltet. Umschalten: 207");
 +
}
 +
// **********************************************************************
 +
void reset() { // 209
 +
  Serial.println("********* Reset *********");
 +
  resetPins();
 +
  Helligkeit = 0;
 +
  Dimmer();
 +
  LED_Eieruhr = LED_Eieruhr_normal;
 +
   for (byte i = 1; i < Ausbaustufe + 1; i++) {
 +
    led[i] = 0;
 +
     Led_an(i, 0);
 
   }
 
   }
 +
  Anzahl_angeschaltete_LEDs = 0;
 +
  Helligkeit = Standardhelligkeit;
 +
  Dimmer();
 +
  Legende_an();
 +
  Auswahl = 0;
 +
  neue_Auswahl = 0;
 +
  zyklus = 0; // Schlafmodus beenden
 
}
 
}
 
// **********************************************************************
 
// **********************************************************************
void Auswahl_alles_aus() {
+
void resetPins() {
   for (byte z = 1; z < Ausbaustufe; z++) {
+
   // Zuerst immer alle 3 Pins auf LOW
     Led_an(z, 0);
+
  digitalWrite(STORE_PIN, LOW);
 +
  digitalWrite(SHIFT_PIN, LOW);
 +
  digitalWrite(DATA_PIN, LOW);
 +
}
 +
// **********************************************************************
 +
void serielle_Schnittstelle_abfragen() {
 +
  if  (Serial.available()) {
 +
    Serial.println("Ich bin www-taub!");
 +
    serial_a = 0;
 +
    serial_nr = 0;
 +
    while (Serial.available() > 0)
 +
    {
 +
      serial_nr = serial_nr * 10;
 +
      serial_a = Serial.read() - '0'; // ASCII-Textversatz für 0 entfernen
 +
      serial_nr = serial_nr + serial_a;
 +
      delay(5);  // delay in between reads for stability
 +
    }
 +
    neue_Auswahl = 1;
 +
     Auswahl = int(serial_nr);
 +
    Input = "serieller Schnittstelle";
 
   }
 
   }
 
}
 
}
 
// **********************************************************************
 
// **********************************************************************
void Auswahl_Bingo() {
+
void Treppenlicht() {
   // TO DO: evtl. nur 1x ohne die Schleife
+
   // schaltet eine LED nach [LED_Eieruhr] Sek. wieder aus
   for (byte z = 1; z < Ausbaustufe; z++) {
+
  if (Debug_Modus) {
     byte zufall = random(1, Ausbaustufe);
+
    Serial.println("Treppenlicht");
     // setzt 'zufall' mit einer Zufallszahl
+
    Serial.print("Laufzeit in s = ");
    // zwischen 1 und Ausbaustufe gleich
+
    Serial.println(Laufzeit_in_sek());
    Serial.println(zufall);
+
    Serial.print(Anzahl_angeschaltete_LEDs);
    Led_an(zufall, 1);
+
    Serial.print(" LEDs sind an, davon ");
     delay(500);
+
    Serial.print(Anzahl_Legenden_LEDs);
 +
    Serial.println(" Legenden-LEDs");
 +
    Serial.println();
 +
  }
 +
   for (byte z = 1; z < Ausbaustufe + 1; z++) {
 +
     byte Element = z;
 +
    if (Patchmodus) {  // Normalfall: OZ 22 = Pin 27
 +
      Element = Element_an_Pin[z];
 +
     }
 +
    if (led[z]) {
 +
      // falls an: max. Einschaltzeit überschritten?
 +
      if (Laufzeit_in_sek() > led_aus[Element]) {
 +
        // Legenden-LEDs immer an lassen, sonst Ausschalten:
 +
        if (Element < Legende_anfang || Element > Legende_ende)
 +
        {
 +
          Led_an(Element, 0); // Ausschalten
 +
        }
 +
      }
 +
     }
 
   }
 
   }
 
}
 
}
 
// **********************************************************************
 
// **********************************************************************
void www() {
+
void www_abfragen() {
 
   // Create a client connection
 
   // Create a client connection
 +
  //  Serial.print("Ich horche, ob www ...");
 
   EthernetClient client = server.available();
 
   EthernetClient client = server.available();
 
   if (client) {
 
   if (client) {
 +
    Serial.println("Client ist connected!");
 
     while (client.connected()) {
 
     while (client.connected()) {
 
       if (client.available()) {
 
       if (client.available()) {
 
         char c = client.read();
 
         char c = client.read();
 
         //read char by char HTTP request
 
         //read char by char HTTP request
         if (readString.length() < 100) {
+
         if (readString.length() < 50) {
 
           //store characters to string
 
           //store characters to string
 
           readString += c;
 
           readString += c;
Zeile 313: Zeile 750:
 
         //if HTTP request has ended
 
         //if HTTP request has ended
 
         if (c == '\n') {
 
         if (c == '\n') {
           Serial.println(readString); //print to serial monitor for debuging
+
           Serial.println(readString); //print to serial monitor for debugging
           int pos = 1 + readString.indexOf('z=');
+
          // normalerweise kommt von Browser: "GET /z=[pos] HTTP/1.1"
 +
          String stringOne = readString;
 +
           int pos = 2 + stringOne.indexOf('z');
 
           Serial.println(pos);
 
           Serial.println(pos);
 
           String zahl = readString.substring(pos);
 
           String zahl = readString.substring(pos);
Zeile 320: Zeile 759:
 
           Serial.println(zahl);
 
           Serial.println(zahl);
 
           Auswahl = zahl.toInt();
 
           Auswahl = zahl.toInt();
 +
          neue_Auswahl = 1;
 +
          zahl = String(Auswahl);
 +
          Serial.print("Auswahl:");
 
           Serial.println(Auswahl);
 
           Serial.println(Auswahl);
           //                  delay(1000);
+
           Input = "www";
 
           client.println("HTTP/1.1 200 OK"); //send new page
 
           client.println("HTTP/1.1 200 OK"); //send new page
 
           client.println("Content-Type: text/html");
 
           client.println("Content-Type: text/html");
 
           client.println();
 
           client.println();
 
           client.println("<HTML>");
 
           client.println("<HTML>");
           client.println("<HEAD>");
+
           client.println(zahl);
           client.println("<TITLE>Periodensystem der Elemente</TITLE>");
+
           client.println("<BR>");
           client.println("</HEAD>");
+
           if (Auswahl == 0) {
          client.println("<BODY>");
+
            client.println("Auswahl unklar, Aufruf im Browser durch ");
          client.println("<H1>Periodensystem der Elemente</H1>");
+
            client.println("[IP]/?z=[Auswahl], z. B. <a href='http://192.168.178.104/?z=1'>http://192.168.178.104/?z=1</a>");
          client.println("<hr />");
+
            client.println("<BR>");
          client.println("<br />");
+
           }
          client.println("<H2>Led auswählen</H2>");
+
           client.println("Created by Detlef Giesler. ");
          client.println("<br />");
+
           client.println("Visit <a href='http://www.bs-wiki.de/mediawiki/index.php/222'>bs-wiki.de</a> for more info!");
          client.println("<a href=\"/?z=4\"\">[ 4 ]</a>");
 
          client.println("-");
 
          client.println("<a href=\"/?z=7\"\">[ 7 ]</a><br />");
 
          client.println("<br />");
 
           client.println("<br />");
 
           client.println("<a href=\"/?z=255\"\">[alle an]</a>");
 
          client.println("-");
 
           client.println("<a href=\"/?z=254\"\">[alle aus]</a><br />");
 
          client.println("<p>Created by Detlef Giesler. Visit http://www.bs-wiki.de for more info!</p>");
 
          client.println("<br />");
 
          client.println("</BODY>");
 
 
           client.println("</HTML>");
 
           client.println("</HTML>");
 
           delay(1);
 
           delay(1);
 
           //stopping client
 
           //stopping client
 
           client.stop();
 
           client.stop();
          //controls the Arduino if you press the buttons
 
          Serial.write(Auswahl);
 
 
           //clearing string for next read
 
           //clearing string for next read
 
           readString = "";
 
           readString = "";
Zeile 360: Zeile 789:
 
}
 
}
 
// **********************************************************************
 
// **********************************************************************
void Laufzeit_hhmmss() {
+
void decodeIR() {
   t_gesamt_in_sek = millis() / 1000;
+
   if (bounced) {
   // millis() gibt den Wert in Millisekunden als 'unsigned int' Datentyp zurück, berechnet seitdem das Arduino
+
    return;
   // Board das aktuelle Programm gestartet hat.
+
   }
   // nullt bei ?? ms
+
   bounced = 1;
   byte t_gesamt_in_h = millis() / 3600000;
+
   //stop all interrupts
   byte t_gesamt_in_m = millis() / 60000 - t_gesamt_in_h * 60;
+
   noInterrupts();
   byte t_gesamt_in_s = millis() / 1000 - t_gesamt_in_m * 60;
+
   byte i;
  Serial.print("Laufzeit hh:mm:ss = ");
+
   //for each "bit" in the code
   Serial.print(t_gesamt_in_h);
+
   for (i = 0; i < CODE_LEN; i += 1) {
  Serial.print(":");
+
    //store the duration of the pulse (microseconds)
  Serial.print(t_gesamt_in_m);
+
    durations[i] = pulseIn(IR_PIN, HIGH, 20000);  // 100000 timeout
  Serial.print(":");
+
    // pulseIn(pin, value, timeout) liest einen Puls (HIGH oder LOW) auf einem Pin aus.
  Serial.print(t_gesamt_in_s);
+
    // Zum Beispiel, wenn value gleich HIGH ist, wartet pulseIn() bis der Pin auf HIGH geht, startet die Zeit,
   Serial.println();
+
    // dann wird gewartet, bis der Pin auf LOW ist und die Zeit wird gestoppt.
}
+
    // Zurückgegeben wird die Länge des Puls in Mikrosekunden. Nach einer bestimmten Zeit wird 0 zurückgegeben,
// **********************************************************************
+
    // wenn kein Pulse kommt.
void Led_an(byte Element, boolean an) {
 
  // to do: switch Element/LED, z. B. bei Element 11 (Natrium) die 3. Led schalten
 
  // patch it:
 
  // Element=patch[Element];
 
  Laufzeit_hhmmss();
 
  Serial.print(Element);
 
  Serial.print(". LED wird geschaltet von ");
 
  Serial.print(led[Element]);
 
  Serial.print(" -> ");
 
  Serial.println(an);
 
  // mitzählen, wieviel LEDs insgesamt an sind:
 
  // nur ausführen, wenn (an -> aus) oder (aus -> an), nicht bei (bleibt an) oder (bleibt aus)
 
  if (an != led[Element]) {
 
    Anzahl_angeschaltete_LEDs = Anzahl_angeschaltete_LEDs + an * 2 - 1; // Anz. = Anz. -1 oder +1
 
 
   }
 
   }
   led[Element] = an;
+
   //enable interrupts
   Serial.print(Anzahl_angeschaltete_LEDs);
+
   interrupts();
   Serial.print(" LEDs sind an: ");
+
   if (bounced) {
  for (byte z = 0; z < Ausbaustufe; z++) {
+
    bounced = 0;
    if (led[z]) {
+
    boolean sauberes_signal = 1; // optimistisch sein
       Serial.print(z);
+
    // 8 Adress-Bits + 8 invertierte Adress-Bits + 8 Kommando-Bits + 8 invertierte Kommando-Bits
       Serial.print("-");
+
    // erwartungsgemäß 8 Nullen:
 +
    byte a_code = B00000000;
 +
    for (i = 1; i < 9; i += 1) {
 +
      switch (durations[i]) {
 +
        case 100 ... 840: bitSet(a_code, i - 1); break;  // 560µs Pause ist 0-Bit
 +
        default: sauberes_signal = 0;    return;
 +
       }
 +
    }
 +
    //    Serial.println(a_code);
 +
 
 +
    // erwartungsgemäß 8 Einsen:
 +
    byte a_i_code = B00000000;
 +
    for (i = 9; i < 17; i += 1) {
 +
       switch (durations[i]) {
 +
        case 1400 ... 2100: bitSet(a_i_code, i - 9); break;  // 1690µs Pause ist 1-Bit
 +
        default: sauberes_signal = 0;    return;
 +
      }
 
     }
 
     }
  }
+
    //    Serial.println(a_i_code);
  Serial.println("");
+
 
  // nur für Fehlerabfrage
+
     byte code = B00000000;
  if (Anzahl_angeschaltete_LEDs > Ausbaustufe) {
+
     for (i = 17; i < 25; i += 1) {
     delay(30000);
+
      //     Serial.print(i);
  }
+
      //      Serial.print(" - ");
  // spart Speicher: unsigned long led_Start zu byte einkürzen
+
      //     Serial.println(durations[i]);
  if (an) {
+
      //     Serial.println((unsigned long)durations[i]);
    //  led_Startzeit[Element] = t_gesamt_in_sek;
+
      //     delay(3000);
     led_aus[Element] = t_gesamt_in_sek + Eieruhr; // vormerken: LED nach (Eieruhr) Sek. wieder ausschalten
+
      switch (durations[i]) {
  }
+
        //       case 100 ... 840: bit = 0; break;  // 560µs Pause ist 0-Bit
  resetPins();
+
        case 1400 ... 2100: bitSet(code, i - 17); break; // 1690µs Pause ist 1-Bit
  digitalWrite(storePin, LOW);
+
      }
  for (byte i = 0; i < Ausbaustufe; i++) {
 
    // Aktion passiert bei Wechsel von LOW auf HIGH
 
    digitalWrite(shiftPin, LOW);
 
    // Jetzt den Wert der aktuellen Stelle ans Datenpin DS anlegen
 
    digitalWrite(dataPin, led[i]);
 
    // ALIAS  digitalWrite(dataPin, led[patch[i]]);
 
    // Dann ShiftPin SHCP von LOW auf HIGH, damit wird der Wert
 
    // am Datenpin ins Register geschoben.
 
    digitalWrite(shiftPin, HIGH);
 
  }
 
  // Wenn alle 8 Stellen im Register sind, jetzt das StorePin STCP
 
  // von LOW auf HIGH, damit wird Registerinhalt an Ausgabepins
 
  // kopiert und der Zustand an den LEDs sichtbar
 
  
  //analogWrite(storePin, 254);
+
    }
  // neues Muster einschalten:
+
    if (Debug_Modus) {
  digitalWrite(storePin, HIGH);
+
      Serial.print("IR-Code: ");
  delay(100);
+
      Serial.println(code);
  // Serial.print(Element);
+
    }
  // Serial.print(". LED ist ");
+
    //   Serial.print(" = ");
  // Serial.println(an);
+
    byte i_code = B00000000;
  Serial.println("--------------------");
+
    for (i = 25; i < 33; i += 1) {
  delay(10);
+
      switch (durations[i]) {
}
+
        case 100 ... 840: bitSet(i_code, i - 25); break;  // 560µs Pause ist 0-Bit
// **********************************************************************
+
      }
void resetPins() {
+
    }
  // Zuerst immer alle 3 Pins auf LOW
+
    if (i_code != code) {
  digitalWrite(storePin, LOW);
+
      sauberes_signal = 0;
  digitalWrite(shiftPin, LOW);
+
      return;
  digitalWrite(dataPin, LOW);
+
    }
}
+
    //   Serial.println(i_code);
// **********************************************************************
+
    //   Serial.print("sauberes_signal = ");
void Treppenlicht() {
+
    //   Serial.println(sauberes_signal);
  Serial.println("Treppenlicht");
+
    switch (code) {
   // schaltet die LED nach (Eieruhr) Sek. wieder aus
+
      case 22: IR_Auswahl = 0; break;
  Laufzeit_hhmmss();
+
      case 12: IR_Auswahl = 1; break;
  for (byte z = 1; z < Ausbaustufe; z++) {
+
      case 24: IR_Auswahl = 2;  break;
     if (led[z]) {
+
      case 94: IR_Auswahl = 3; break;
      // max. Einschaltzeit überschritten?
+
      case 8: IR_Auswahl = 4;  break;
       if (t_gesamt_in_sek > led_aus[z]) {
+
      case 28: IR_Auswahl = 5;  break;
         Led_an(z, 0);
+
      case 90: IR_Auswahl = 6;  break;
 +
      case 66: IR_Auswahl = 7; break;
 +
      case 82: IR_Auswahl = 8;  break;
 +
      case 74: IR_Auswahl = 9;  break;
 +
      case 7: IR_Auswahl = 210;  break; // Vol--
 +
      case 9: IR_Auswahl = 213;  break; // [EQ] -> mittlere Helligkeit
 +
      case 21: IR_Auswahl = 215;  break; // Vol++
 +
      case 69: IR_Auswahl = 254;  break; // CH- alles aus
 +
      case 70: IR_Auswahl = 200;  break; // CH Zufallszahl -> Bingo
 +
      case 71: IR_Auswahl = 255; break; // CH+ alles an
 +
      case 64 :  // next
 +
        switch (last_Element) { // Elemente, Hauptgruppen, Perioden ...
 +
          case 1 ... 118:  IR_Auswahl = min(118, last_Element + 1); break;
 +
          case 131 ... 194:  IR_Auswahl = min(194, last_Element + 1); break;
 +
        }
 +
        break;
 +
      case 68 :    // prev
 +
        IR_Auswahl = max(1, last_Element - 1);
 +
        break;
 +
      case 25 : // 100+ als Init für mehrstellige Zahl
 +
        mehrstellig = 1;
 +
        IR_Auswahl = 0;
 +
        break;
 +
      case 13 :   // 200+ als Quit nach mehrstelliger Zahl
 +
        mehrstellig = 0;
 +
        IR_Auswahl = letzte_IR_Auswahl;
 +
        letzte_IR_Auswahl = 0;
 +
        break;
 +
      case 67: IR_Auswahl = 202; break; // Play/Pause -> Programm_y
 +
    }
 +
     if (mehrstellig) {
 +
       if (IR_Auswahl < 10) {
 +
         letzte_IR_Auswahl = letzte_IR_Auswahl * 10 + IR_Auswahl;
 
       }
 
       }
 
     }
 
     }
 
   }
 
   }
   delay(10);
+
   if (mehrstellig == 0) {
  Serial.println();
+
    if (Debug_Modus) {
 +
      Serial.print("IR-Auswahl: ");
 +
      Serial.println(Auswahl);
 +
      Serial.println();
 +
    }
 +
    Auswahl = IR_Auswahl;
 +
    neue_Auswahl = 1;
 +
    Input = "Fernbedienung";
 +
  }
 +
  // last_Element = Auswahl;
 +
  // delay(3000);
 +
  /*
 +
  0: 22
 +
  100+: 25
 +
  200+: 13
 +
  1: 12
 +
  2: 24
 +
  3: 94
 +
  4: 8
 +
  5: 28
 +
  6: 90
 +
  7: 66
 +
  8: 82
 +
  9: 74
 +
  CH-: 69
 +
  CH: 70
 +
  CH+: 71
 +
  prev: 68
 +
  next: 64
 +
  Play: 67
 +
  Vol-: 7
 +
  Vol+:  21
 +
  eq: 9
 +
  */
 
}
 
}
 +
</source>

Aktuelle Version vom 7. November 2017, 23:14 Uhr

// **********************************************************************
// interaktives Periodensystem der Elemente
// schaltet gewünschte LED an
// Detlef Giesler
// BBS Winsen (Luhe)
// **********************************************************************
// letzte Änderungen:
// 2017: to do / Idee Uhrenfunktion, Std. gemäß OZ 1-24, Minuten OZ 1-59 als Herzblinker, z.B. 7:45 als N:Rh, volle Stunden mit 1 und 59, bei h = m Herzblinker links und rechts von h
// - DeT-Pause
// 15.07. www-Schaltaufruf mittels Port Forwarding
// 14.07. Code säubern
// 13.07. Bewegungsmelder, Standby neu
// 12.07. Modi schaltbar
// 11.07. Patchmodus gefixt
// 10.07. const Variablenumbennung
// 08.07. serieller Input in Unterprogramm, www gekürzt
// 07.07. Fernbedienung mit Interrupt
// 05.07. Fernbedienung, Serial.begin(115200);
// 23.06. Reset nach Standby
// 21.06. Weiterleitung i. O.
// 18.06. Weiterleitung kaputt? Abgleich mit 08.06., dort funzts
// 08.05.2015: Patch Panel fix
// 06.05.2015: Patch Panel aktiviert aber irgendwie verschoben
// 05.05.2015: Anpassung an Mega 2560 wg. Speicherproblemen beim Uno
// 04.05.2015: rudimentäre Dimmfunktion
// 03.05.2015: Ausbaustufe = 32, LED #0 gibt es nicht mehr, automatisches Abschalten nach 500 Leerzyklen
// 02.05.2015: Aufruf auch von bs-wiki möglich
// 01.05.2015: Schalten über HTTP GET
// 29.04.2015: Arduino als HTTP Client
// 28.04.2015: Abfrage der seriellen Schnittstelle
// **********************************************************************
// TO DOs:
// Layout La & Ac
// **********************************************************************
// verwendete Bibliotheken:
#include <SPI.h>
#include <Ethernet.h>
// ----------------------------------------------------------------------
// globale Variablen:
// KONSTANTEN
// Pinning Arduino:
// Arduino-Pin 2 mit IR-Sensor verbunden:
const byte IR_PIN = 2;
// Arduino-Pin 3 als "Dimmer" verbunden mit OE des 74HC595 (dort Pin 13, Output Enable):
const byte OUTPUT_ENABLE_PIN = 3;
// Arduino-Pin 7 mit Bewegungsmelder verbunden (dort Pin 2, Out):
const byte BEWEGUNGSMELDER_PIN = 7;
// Arduino-Pin 8 als SHIFT_PIN verbunden mit SH_CP des 74HC595 (dort Pin 11, shift register clock input):
const byte SHIFT_PIN = 8;
// Arduino-Pin 9 verbunden mit ST_CP des 74HC595 (dort Pin 12, storage register clock input = latch pin):
const byte STORE_PIN = 9;
// Arduino-Pin 10 verbunden mit DS des 74HC595 (dort Pin 14, serial data input):
const byte DATA_PIN = 10;
// ----------------------------------------------------------------------
// Internet:
byte mac[6] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // physikalische mac-Adresse
// TO DO: vor Ort anzupassen:
byte ip[4] = { 192, 168, 178, 104 }; // IP im **lokalen** Netzwerk
// Aufruf dann im Browser z. B. über http://192.168.178.104/?z=4
// "Arduino an IP 192..., schalte Led Nr. 4 an!"
//   Falls ein "echter", also **globaler** www-Aufruf ermöglicht werden soll, muss im Router eine Portweiterleitung eingerichtet werden.
//   Bei meiner Fritzbox 7270 (Router-IP ist 31.19.122.16) über Internet:Freigaben:Portfreigabe mit den Einstellungen:
//   andere Anwendungen, TCP, Port 80, an IP-Adresse 192.168.178.104. Die lokale IP hier im Sketch bleibt unverändert,
//   allerdings kann dann der Schaltaufruf ebenso mit "http://31.19.122.16/?z=4" erfolgen.
byte gateway[4] = { 192, 168, 1, 1 }; // Internetaccess via Router
byte subnet[4] = { 255, 255, 255, 0 }; // subnet mask
EthernetServer server(80); // Server port
String readString;
// String URL = "http://www.bs-wiki.de/mediawiki/index.php?title=";
// ----------------------------------------------------------------------
// LED-Wand:
// Hardware-Info: 12m²-PSE aus 6 Teildisplays, 144/6 = 24 LEDs/Teildisplay,
// ... jedes Teildisplay angesteuert durch 3x8 Datenleitungen (3 Spalten, 8 Zeilen),
// ... pro Spalte ein 8-bit-Schieberegister = 18 SR insgesamt
// Pinning Schieberegister:
// Elemente und LEDs:
// Ausbaustufe 144 LEDs
const byte Ausbaustufe = 144;  // 144
byte Anzahl_Legenden_LEDs = 0;
byte Legende_anfang = 121;
byte Legende_ende = 140;
boolean Patchmodus;
// Compilerfehler erforderdert Vergrößerung der Arrays um ein Feld, andernfalls Überlauf in andere Variablen
boolean led[Ausbaustufe + 1] = {0};
unsigned int led_aus[Ausbaustufe + 1];
// virtuelles Patchpanel: Zuordnung Ordungszahl/Pin, z. B. Natrium mit OZ 11 an *Pin 3*:
byte Pin_von_Element[Ausbaustufe + 1] = { 0, 1, 137
                                          , 2, 9, 97, 105, 113, 121, 129, 138
                                          , 3, 10, 98, 106, 114, 122, 130, 139
                                          , 4, 11, 19, 27, 35, 43, 51, 59, 67, 75, 83, 91, 99, 107, 115, 123, 131, 140
                                          , 5, 12, 20, 28, 36, 44, 52, 60, 68, 76, 84, 92, 100, 108, 116, 124, 132, 141
                                          , 6, 13, 23, 31, 39, 47, 55, 63, 71, 79, 87, 95, 103, 111, 119, 127, 21, 29, 37, 45, 53, 61, 69, 77, 85, 93, 101, 109, 117, 125, 133, 142
                                          , 7, 14, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128, 22, 30, 38, 46, 54, 62, 70, 78, 86, 94, 102, 110, 118, 126, 134, 143, 15, 16, 17, 18, 25, 26, 33, 34, 41, 42, 49, 50, 57, 58, 65, 66, 73, 74, 81, 82, 89, 90, 135, 136, 144
                                          , 8
                                        };
// Pinning ohne eine "Led #0"
//                                          p1 p2 p3  p4  p5  p6
byte Element_an_Pin[Ausbaustufe + 1] = { 0, 1, 3, 11, 19, 37, 55
                                         //
                                         //p7  p8 - p9 p10 p11 p12 p13 p14 p15  p16 -p17  p18  p19 p20 p21 p22  p23 p24-
                                         , 87, 144, 4, 12, 20, 38, 56, 88, 119, 120, 121, 122, 21, 39, 71, 103, 57, 89
                                         //
                                         // p25 p26  p27 p28 p29 p30  p31 p32-p33  p34  p35 p36 p37 p38  p39 p40-p41  p42  p43 p44 p45 p46  p47 p48
                                         , 123, 124, 22, 40, 72, 104, 58, 90, 125, 126, 23, 41, 73, 105, 59, 91, 127, 128, 24, 42, 74, 106, 60, 92
                                         //
                                         // p49 p50  p51 p52 p53 p54  p55 p56-p57  p58  p59 p60 p61 p62  p63 p64-p65  p66  p67 p68 p69 p70  p71 p72
                                         , 129, 130, 25, 43, 75, 107, 61, 93, 131, 132, 26, 44, 76, 108, 62, 94, 133, 134, 27, 45, 77, 109, 63, 95
                                         //
                                         // p73 p74  p75 p76 p77 p78  p79 p80-p81  p82  p83 p84 p85 p86  p87 p88-p89  p90  p91 p92 p93 p94  p95 p96
                                         , 135, 136, 28, 46, 78, 110, 64, 96, 137, 138, 29, 47, 79, 111, 65, 97, 139, 140, 30, 48, 80, 112, 66, 98
                                         //
                                         // p97p98 p99 p100p101p102 p103p104-p105p106p107p108p109p110p111p112-p113p114p115p116p117p118p119p120
                                         ,  5, 13, 31, 49, 81, 113, 67, 99, 6, 14, 32, 50, 82, 114, 68, 100, 7, 15, 33, 51, 83, 115, 69, 101
                                         //
                                         //p121p122p123p124p125p126p127p128-p129p130p131p132p133p134p135 p136-p137p138p139p140p141p142p143p144
                                         , 8, 16, 34, 52, 84, 116, 70, 102, 9, 17, 35, 53, 85, 117, 141, 142, 2, 10, 18, 36, 54, 86, 118, 143
                                       };
// ----------------------------------------------------------------------
// Auswahl im laufenden Programm:
String Input; // IR, Seriell oder www
// Ordnungszahl definiert Element 1...118
int Auswahl = 0;   // 254
boolean neue_Auswahl;
boolean Bewegungsstatus = HIGH; // bei Systemstart Bewegung simulieren
byte Anzahl_angeschaltete_LEDs = 0;
// TO DO: über Poti einstellen und von Pin einlesen oder über Auswahl (180)
const unsigned int LED_Eieruhr_normal = 30;  // Vorgabe der Einschaltdauer einer LED in Sekunden
unsigned int LED_Eieruhr = LED_Eieruhr_normal;  // gewählte Einschaltdauer einer LED in Sekunden
unsigned int Standby_Timer = 180;  // Zeit in Sekunden bis zum Standby
const byte Standardhelligkeit = 127;
byte Helligkeit = Standardhelligkeit; // beliebiger Wert für Dimmer
byte Wunschhelligkeit = Standardhelligkeit; // durch Menüauswahl bestimmt
byte last_Element = 0;
int zyklus = 0; // loop-Zyklen
unsigned int last_call = Laufzeit_in_sek();
int serial_a = 0;
int serial_nr = 0;
// ----------------------------------------------------------------------
// Debugging
boolean Debug_Modus = 1; // mit Zusatzinfos über seriellen Monitor, kann über 208 umgeschaltet werden
int bremse = 0;  // 1 ... 60000 Standardwert für Entschleunigung in ms zwischen einigen Befehlen zwecks Debugging
// ----------------------------------------------------------------------
// IR - Fernbedienung
// Arduino IR Remote Sniffer
// Portions © Andrew Ippoliti - acipo.com
// const byte IR_PIN = 2;
// volatile damit es auch in INT funktioniert
volatile boolean bounced = 0;
const byte CODE_LEN = 40;
volatile unsigned long durations[CODE_LEN];
int letzte_IR_Auswahl;
int IR_Auswahl;
boolean mehrstellig;
// **********************************************************************
void setup() {
  Serial.begin(115200); // Kontrollausgabe über seriellen Monitor
  Serial.flush(); // löscht den Inhalt des seriellen Puffers
  // CHECK Fenster: es kommt Müll, wenn nicht 'kein Zeilenende' eingestellt ist!
  // Ausgabe-Pins: 3, 8, 9, 10:
  pinMode(OUTPUT_ENABLE_PIN, OUTPUT); // Dimmer
  analogWrite(OUTPUT_ENABLE_PIN, 255); // entspricht 5 Volt an OE und damit LEDs aus
  pinMode(STORE_PIN, OUTPUT);
  pinMode(SHIFT_PIN, OUTPUT);
  pinMode(DATA_PIN, OUTPUT);
  // Eingabe-Pins: 2, 7:
  pinMode(BEWEGUNGSMELDER_PIN, INPUT);
  // IR-Fernbedienung
  pinMode(IR_PIN, INPUT);
  attachInterrupt(0, decodeIR, FALLING);
  //FALLING for when the Digitalpin 2 goes from high to low.
  Serial.println("PSE");
  Serial.println("--------------------------------");
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip, gateway, subnet);
  // give the Ethernet shield 3 seconds to initialize:
  delay(3000);
  server.begin();
  Serial.print("Server ist an IP ");
  Serial.println(Ethernet.localIP());
  Anzahl_Legenden_LEDs = 1 + Legende_ende - Legende_anfang;
  Serial.print("Anzahl Legenden-LEDs: ");
  Serial.println(Anzahl_Legenden_LEDs);
  Serial.println();
  // TO DO: löschen:
  // Element_an_Pin[] nach steigender Ordungszahl notieren:
  // Switchen, Element_an_Pin[] nach steigender Ordungszahl merken:
  //  for (byte z = 1; z < 144 + 1; z++) {
  //    patch[Element_an_Pin[z]] = z;
  //    //  //    // Ordnungszahl
  //  }
  //  for (byte z = 1; z < 144 + 1; z++) {
  //    //    Serial.print("Pin: ");
  //    //    Serial.print(z);
  //    //    Serial.print(" = OZ: ");
  //    //    Serial.print(Element_an_Pin[z]);
  //    //    Serial.print(" = Patch(OZ): ");
  //    Serial.print(patch[z]);
  //    //    Serial.println();
  //    Serial.print(", ");
  //  }
  //  Serial.println();
  // ***********************
  // Kontrolle
  //  for (byte spalte = 1; spalte < 19; spalte++) {
  //    Serial.println();
  //    Serial.print(spalte);
  //    Serial.println(". Spalte = #IC");
  //    Serial.println("------------------");
  //    for (byte zeile = 1; zeile < 9; zeile++) {
  //      Serial.print(zeile);
  //      Serial.println(". Zeile");
  //      byte z = zeile + 8 * (spalte - 1);
  //      Serial.print("OZ ");
  //      Serial.print(z);
  //      Serial.print(" - Pin ");
  //      Serial.println(Pin_von_Element[z]);
  //    }
  //  }
  // für Testphase LED von Element = 7 im Setup einschalten:
  Led_an(7, 1);
  Patchmodus_umschalten();  // kann über 207 umgeschaltet werden
  debugging();  // kann über 208 umgeschaltet werden
  Serial.println("Setup fertig, jetzt startet die Loop-Schleife ......");
  Serial.println("----------------------------------------------------");
}
// **********************************************************************
void loop () {
  zyklus = zyklus + 1;
  //  Serial.print(zyklus);
  //  Serial.println(". Loop");
  // horche an IR-FB (Interrupt), der seriellen Schnittstelle und über Ethernet-Shield an www
  // erfrage Element; nach Ordnungszahl o. ä. auswählen:
  // z. B. OZ 1 - Wasserstoff:
  serielle_Schnittstelle_abfragen();
  www_abfragen();
  Bewegungsmelder_abfragen();
  if (neue_Auswahl) {
    Auswahl_auswerten();
  }
  if (Anzahl_angeschaltete_LEDs > Anzahl_Legenden_LEDs) {
    Treppenlicht();
  }
  //  if (zyklus > 9999) {         // 999
  //    // 1000-mal is nichts passiert, daher:
  //    reset();
  //    Serial.println("-----ALLE LEDS AUS -------------------------------");
  //    delay(3000);
  //  }
}
// **********************************************************************
// ############### Funktionen nach ABC ##############################
// **********************************************************************
void Auswahl_auswerten()
{
  Bewegungsstatus = HIGH;
  zyklus = 0; // Schlafmodus beenden
  neue_Auswahl = 0;
  last_call = Laufzeit_in_sek();
  if (Debug_Modus) {
    Serial.print("neue Auswahl von ");
    Serial.println(Input);
    Serial.println(Auswahl);
    Serial.println();
  }
  switch (Auswahl) {
    // 0 = existiert nicht
    case 1 ... 118: Led_an(Auswahl, 1); break; // 1 = Wasserstoff, 2 = Helium ... 118 = Uuo
    case 131 ... 139: Auswahl_Periode(); break;      // = 1. - 7. Periode, Lanthanoide, A.
    case 141 ... 148: Auswahl_Hauptgruppe(); break;  // = 1. - 8. Hauptgruppe
    case 160: Auswahl_Metalle(); break;
    case 161: Auswahl_Halbmetalle(); break;
    case 162: Auswahl_Nichtmetalle(); break;
    case 180: LED_Eieruhr_switchen(); break;  //  auf 180 Sekunden oder LED_Eieruhr_normal
    case 190: Auswahl_fest(); break;
    case 191: Auswahl_liquid(); break;
    case 192: Auswahl_gas(); break;
    case 193: Auswahl_radioaktiv(); break;
    case 194: Auswahl_biatomar(); break;
    case 200: Auswahl_Bingo(); break;
    case 201: Auswahl_Programm_x(); break;
    case 202: Auswahl_Programm_y(); break;
    case 203: Auswahl_Programm_z(); break;
    case 207: Patchmodus_umschalten(); break;
    case 208: debugging(); break;     // Debugging-Modus
    case 209: reset(); break;
    case 210 ... 215: Auswahl_Helligkeit(); break;
    // 222 = Browserfenster umschalten auf Arduino-Auswahlmenü
    //    case 222: www_abfragen(); break;
    case 254: Auswahl_alles_aus(); break;
    case 255: Auswahl_alles_an(); break;
    default:  // unbelegte Zahlen sind unsinnig und werden genullt:
      Serial.println("keine neue Auswahl");
  }
  // vergesse die bisherige Auswahl, LED nicht erneut anschalten:
  Auswahl = 0;
}
// **********************************************************************
void Auswahl_alles_an() {             // 255
  Serial.println("alle_Elemente_an");
  for (byte z = 1; z < Ausbaustufe + 1; z++) {
    Led_an(z, 1);
  }
  Serial.println("alle_Elemente sind an");
}
// **********************************************************************
void Auswahl_alles_aus() {
  Helligkeit = 0;
  Dimmer();
  // schaltet alle LEDs außer die für die Legende aus
  Serial.println("alle_Elemente_aus");
  for (byte z = 1; z < Ausbaustufe + 1; z++) {
    Led_an(z, 0);
  }
  Serial.println("alle_Elemente sind aus");
  Legende_an();
  Helligkeit = Standardhelligkeit;
  Dimmer();
}
// **********************************************************************
void Auswahl_biatomar() {
  Serial.println("Auswahl_biatomar");
  for (byte z = 1; z < Ausbaustufe + 1; z++) {
    if ((z == 1) || (z == 7) || (z == 8) || (z == 9) || (z == 17) || (z == 35) || (z == 53) || (z == 138) ) {
      Led_an(z, 1);
    }
  }
}
// **********************************************************************
void Auswahl_Bingo() {
  Serial.println("Elemente-Bingo");
  byte zufall = random(1, Ausbaustufe);
  // setzt 'zufall' mit einer Zufallszahl
  // zwischen 1 und Ausbaustufe gleich
  Serial.print("Zufalls-Element: ");
  Serial.println(zufall);
  Led_an(zufall, 1);
}
// **********************************************************************
void Auswahl_Hauptgruppe() {
  byte Hauptgruppe = Auswahl - 140;
  Serial.print(Hauptgruppe);
  Serial.println(". Hauptgruppe");
  switch (Hauptgruppe) {
    case 1: // 1. Hauptgruppe
      Led_an(1, 1); Led_an(3, 1); Led_an(11, 1); Led_an(19, 1); Led_an(37, 1); Led_an(55, 1); Led_an(87, 1); break;
    case 2: // 2. Hauptgruppe
      Led_an(4, 1); Led_an(12, 1); Led_an(20, 1); Led_an(38, 1); Led_an(56, 1); Led_an(88, 1); break;
    case 3: // 3. Hauptgruppe
      Led_an(5, 1); Led_an(13, 1); Led_an(31, 1); Led_an(49, 1); Led_an(81, 1); Led_an(113, 1); break;
    case 4: // 4. Hauptgruppe
      Led_an(6, 1); Led_an(14, 1); Led_an(32, 1); Led_an(50, 1); Led_an(82, 1); Led_an(114, 1); break;
    case 5: // 5. Hauptgruppe
      Led_an(7, 1); Led_an(15, 1); Led_an(33, 1); Led_an(51, 1); Led_an(83, 1); Led_an(115, 1); break;
    case 6: // 6. Hauptgruppe
      Led_an(8, 1); Led_an(16, 1); Led_an(34, 1); Led_an(52, 1); Led_an(84, 1); Led_an(116, 1); break;
    case 7: // 7. Hauptgruppe
      Led_an(9, 1); Led_an(17, 1); Led_an(35, 1); Led_an(53, 1); Led_an(85, 1); Led_an(117, 1); break;
    case 8: // 8. Hauptgruppe
      Led_an(2, 1); Led_an(10, 1); Led_an(18, 1); Led_an(36, 1); Led_an(54, 1); Led_an(86, 1); Led_an(118, 1); break;
  }
}
// **********************************************************************
void Auswahl_Helligkeit() {
  //  210 ... 215
  Wunschhelligkeit = 5 + 50 * (Auswahl - 210);
  // 210 -> 5, 211 -> 55, ... 215 -> 255
  Helligkeit = Wunschhelligkeit;
  Dimmer();
}
// **********************************************************************
void Auswahl_Metalle() {  // 160
  Serial.println("Metalle");
  for (byte z = 1; z < Ausbaustufe + 1; z++) {
    if ((z == 3) || (z == 4) || (z == 11) || (z == 12) || (z == 13) || ((z >= 19) && (z <= 31))
        || ((z >= 37) && (z <= 50))
        || ((z >= 55) && (z <= 84)) || ((z >= 87) && (z <= 118)) || (z == 133)) {
      Led_an(z, 1);
    }
  }
}
// **********************************************************************
void Auswahl_Halbmetalle() {
  Serial.println("Halbmetalle");
  for (byte z = 1; z < Ausbaustufe + 1; z++) {
    if ((z == 5) || (z == 14) || (z == 32) || (z == 33) || (z == 34) || (z == 51) || (z == 52) || (z == 85)
        || (z == 135)) {
      Led_an(z, 1);
    }
  }
}
// **********************************************************************
void Auswahl_Nichtmetalle() {
  Serial.println("Nichtmetalle");
  for (byte z = 1; z < Ausbaustufe + 1; z++) {
    if ((z == 1) || (z == 2) || ((z >= 6) && (z <= 10)) || ((z >= 15) && (z <= 18)) || ((z >= 35) && (z <= 36))
        || ((z >= 53) && (z <= 54)) || (z == 86) || (z == 137)) {
      Led_an(z, 1);
    }
  }
}
// **********************************************************************
void Auswahl_fest() {
  Serial.println("190 = fest");
  for (byte z = 1; z < Ausbaustufe + 1; z++) {
    if (((z >= 3) && (z <= 6)) || ((z >= 11) && (z <= 16)) || ((z >= 19) && (z <= 34)) || ((z >= 37) && (z <= 53))
        || ((z >= 55) && (z <= 85)) || ((z >= 87) && (z <= 118))) {
      Led_an(z, 1);
    }
  }
}
// **********************************************************************
void Auswahl_liquid() {
  Serial.println("191 = flüssig");
  for (byte z = 1; z < Ausbaustufe + 1; z++) {
    if ((z == 35) || (z == 80)) {
      Led_an(z, 1);
    }
  }
}
// **********************************************************************
void Auswahl_gas() {
  Serial.println("192 = gasförmig");
  for (byte z = 1; z < Ausbaustufe; z++) {
    if ((z == 1) || (z == 2) || (z == 7) || (z == 8) || (z == 9) || (z == 10) || (z == 17) || (z == 18)
        || (z == 36) || (z == 54) || (z == 86)) {
      Led_an(z, 1);
    }
  }
}
// **********************************************************************
void Auswahl_Periode() {
  byte Periode = Auswahl - 130;
  Serial.print(Periode);
  Serial.println(". Periode");
  byte anfang;
  byte ende;
  switch (Periode) {
    case 1: anfang = 1; ende = 2; break;      // 1. Periode: 1-H, 2-He
    case 2: anfang = 3; ende = 10; break;
    case 3: anfang = 11; ende = 18; break;
    case 4: anfang = 19; ende = 36; break;
    case 5: anfang = 37; ende = 54; break;
    case 6: anfang = 55; ende = 86; break;
    case 7: anfang = 87; ende = 118; break;  // 7. Periode: Fr-Uuo
    case 8: anfang = 57; ende = 71; break; // Lanthanoide
    case 9: anfang = 89; ende = 103; break; // Actinoide
  }
  for (byte z = anfang; z < ende + 1; z++) {
    Led_an(z, 1);
  }
}
// **********************************************************************
void Auswahl_Programm_x() { // 201
  Serial.println("PSE schwellend aufleuchten lassen");
  Auswahl_alles_an();
  for (byte a = 0; a <= 5; a = a + 1)
  {
    for (byte b = 5; b <= 255; b = b + 1)
    {
      Helligkeit = b;
      Dimmer();
      delay(10);
    }
    for (byte b = 255; b >= 5; b = b - 1)
    {
      Helligkeit = b;
      Dimmer();
      delay(10);
    }
  }
  Helligkeit = Wunschhelligkeit;
  Dimmer();
}
// **********************************************************************
void Auswahl_Programm_y() { // 202
  Serial.println("Flackermann");
  unsigned int LED_Eieruhr_2 = LED_Eieruhr; // alten Wert merken und neu festlegen
  LED_Eieruhr = 3;
  for (byte z = 1; z < Ausbaustufe + 1; z++) {
    byte zufall = random(1, Ausbaustufe);
    // setzt 'zufall' mit einer Zufallszahl
    // zwischen 1 und Ausbaustufe gleich
    Serial.print("Zufalls-Element: ");
    Serial.println(zufall);
    Led_an(zufall, 1);
    Treppenlicht();
    delay(100);
  }
  LED_Eieruhr = LED_Eieruhr_2; // alten Wert zurückschreiben
}
// **********************************************************************
void Auswahl_Programm_z() {
  // TO DO
}
// **********************************************************************
void Auswahl_radioaktiv() {
  Serial.println("radioaktiv");
  for (byte z = 1; z < Ausbaustufe + 1; z++) {
    if ((z == 43) || (z == 61) || ((z >= 84) && (z <= 118)) || (z == 134) || (z == 136)) {
      Led_an(z, 1);
    }
  }
}
// **********************************************************************
void Bewegungsmelder_abfragen() {
  // Falls längere Zeit keine Auswahl getroffen wurde oder keine Bewegung messbar war,
  // wird der Bewegungsmelder abgefragt.
  // Bei Bewegung bleiben die LEDs an.
  if (((Laufzeit_in_sek() > (last_call + Standby_Timer)) || (Bewegungsstatus == LOW))) {
    Bewegungsstatus = digitalRead(BEWEGUNGSMELDER_PIN);
    if ((Bewegungsstatus == LOW) && (neue_Auswahl == 0))
    {
      Helligkeit = 0;
      last_call = 0; // wenn Helligkeit auf 0 gesetzt wurde
    }
    else
    {
      last_call = Laufzeit_in_sek();
      Helligkeit = Wunschhelligkeit;
    }
    Dimmer();
  }
}
// **********************************************************************
void debugging() {         // 208
  Debug_Modus = -(Debug_Modus - 1);
  Serial.print("Debugging ist ");
  if (Debug_Modus) {
    Serial.print("ein");
  }
  else
  {
    Serial.print("aus");
  }
  Serial.println("geschaltet. Umschalten: 208");
}
// **********************************************************************
void Dimmer() // 0 to 255
// Funktion merkt sich Helligkeitswert für LEDs, ausbaubedingt nur Einheitswert für alle Schieberegister
// 0 = dunkel, weil 0% Einschaltdauer, 255 = volle Leistung, weil 100% ED
{
  analogWrite(OUTPUT_ENABLE_PIN, 255 - Helligkeit);
}
// **********************************************************************
void LED_Eieruhr_switchen() {   //  switchen auf 180 oder 30 Sekunden
  Serial.print("LED-Eieruhr switchen von ");
  Serial.print(LED_Eieruhr);
  Serial.print(" auf ");
  switch (LED_Eieruhr) {
    case LED_Eieruhr_normal: LED_Eieruhr = 180; break;      // LEDs 3 Minuten anlassen
    case 180: LED_Eieruhr = LED_Eieruhr_normal; break;      // LEDs 30s anlassen
  }
  Serial.print(LED_Eieruhr);
  Serial.print(" Sekunden");
}
// **********************************************************************
unsigned int Laufzeit_in_sek() {
  unsigned int t_gesamt_in_sek = millis() / 1000;
  // millis() gibt den Wert in Millisekunden als 'unsigned int' Datentyp zurück, berechnet seitdem das Arduino
  // Board das aktuelle Programm gestartet hat.
  return t_gesamt_in_sek;
}
// void Laufzeit_hhmmss() {
//  t_gesamt_in_sek = millis() / 1000;
// nullt bei ?? ms
//  byte t_gesamt_in_h = millis() / 3600000;
//  byte t_gesamt_in_m = millis() / 60000 - t_gesamt_in_h * 60;
//  byte t_gesamt_in_s = millis() / 1000 - t_gesamt_in_m * 60;
//  Serial.print("Laufzeit hh:mm:ss = ");
//  Serial.print(t_gesamt_in_h);
//  Serial.print(":");
//  Serial.print(t_gesamt_in_m);
//  Serial.print(":");
//  Serial.print(t_gesamt_in_s);
//  Serial.println();
// }
// **********************************************************************
void Led_an(byte Element, boolean an) {
  // Funktion schaltet durch (Element) bestimmte Pins (= LEDs) an oder aus,
  // plant einen Ausschaltpunkt (led_aus[Element]) und merkt sich die Anzahl_angeschaltete_LEDs.
  // 'Element' ist die OZ, 'an' der Schaltzustand 0/1
  // 'pin' ist der tatsächliche Anschlusspunkt der LED-Matrix, z. B. bei Element 22 (Titan, logisch)
  //  die 27. Led (physikalisch) schalten. Zuordnung Pin/Element:
  byte Pin = Element;  // Probebetrieb ohne Patchmodus: OZ 22 = Pin 22
  if (Patchmodus) {   // Normalfall: OZ 22 = Pin 27
    Pin = Pin_von_Element[Element];
  }
  // mitzählen, wieviel LEDs insgesamt an sind:
  // nur ausführen, wenn (an -> aus) oder (aus -> an), nicht bei (bleibt an) oder (bleibt aus)
  if (an != led[Pin]) {
    Anzahl_angeschaltete_LEDs = Anzahl_angeschaltete_LEDs + an * 2 - 1; // Anz. = Anz. -1 oder +1
  }
  led[Pin] = an;
  //  for (byte z = 1; z < Ausbaustufe + 1; z++) {
  //    if (led[z]) {
  ////      Serial.print("p_");
  ////      Serial.print(z);
  ////      Serial.print("-");
  //    }
  //  }
  //  // nur für Fehlerabfrage
  //  if (Anzahl_angeschaltete_LEDs > Ausbaustufe) {
  //    Serial.println("F E H L E R : zuviele LEDs geschaltet!");
  //    delay(bremse);
  //  }
  // spart Speicher: unsigned long led_Start zu byte einkürzen:
  if (an) {
    led_aus[Element] = Laufzeit_in_sek() + LED_Eieruhr; // vormerken: LED nach (LED_Eieruhr) Sek. wieder ausschalten
    last_Element = Element;  // welches Element wurde zuletzt angeschaltet?
    if (Debug_Modus) {
      Serial.print("LED von Element ");
      Serial.print(Element);
      Serial.print(" -> Pin ");
      Serial.print(Pin);
      Serial.println(" ist an.");
      Serial.println("--------------------");
    }
  }
  resetPins();
  // Schieberegister
  // serielles Einlesen, alle LEDs werden neu geschaltet
  for (byte i = 1; i < Ausbaustufe + 1; i++) {
    // Aktion passiert bei Wechsel von LOW auf HIGH
    digitalWrite(SHIFT_PIN, LOW);
    // Jetzt den Wert der aktuellen Stelle ans Datenpin DS anlegen
    digitalWrite(DATA_PIN, led[i]);
    // Dann SHIFT_PIN SHCP von LOW auf HIGH, damit wird der Wert
    // am Datenpin ins Register geschoben.
    digitalWrite(SHIFT_PIN, HIGH);
  }
  // Wenn alle Stellen im Register sind, jetzt das STORE_PIN STCP
  // von LOW auf HIGH, damit wird Registerinhalt an Ausgabepins
  // kopiert und der Zustand an den LEDs sichtbar
  // neues Muster einschalten:
  digitalWrite(STORE_PIN, HIGH);
}
// **********************************************************************
void Legende_an() {
  // diese LEDs immer anlassen:
  // TO DO: bei Sondergruppe die anderen ausblenden, z. B. Metalle an,
  // dann Halb- u. Nichtmetalle aus
  for (byte z = Legende_anfang; z < Legende_ende + 1; z++) {
    Led_an(z, 1);
  }
}
// **********************************************************************
void Patchmodus_umschalten() { // 207
  Patchmodus = -(Patchmodus - 1);
  reset();
  Serial.print("Patchmodus ist ");
  if (Patchmodus) {
    Serial.print("ein");
  }
  else
  {
    Serial.print("aus");
  }
  Serial.println("geschaltet. Umschalten: 207");
}
// **********************************************************************
void reset() { // 209
  Serial.println("********* Reset *********");
  resetPins();
  Helligkeit = 0;
  Dimmer();
  LED_Eieruhr = LED_Eieruhr_normal;
  for (byte i = 1; i < Ausbaustufe + 1; i++) {
    led[i] = 0;
    Led_an(i, 0);
  }
  Anzahl_angeschaltete_LEDs = 0;
  Helligkeit = Standardhelligkeit;
  Dimmer();
  Legende_an();
  Auswahl = 0;
  neue_Auswahl = 0;
  zyklus = 0; // Schlafmodus beenden
}
// **********************************************************************
void resetPins() {
  // Zuerst immer alle 3 Pins auf LOW
  digitalWrite(STORE_PIN, LOW);
  digitalWrite(SHIFT_PIN, LOW);
  digitalWrite(DATA_PIN, LOW);
}
// **********************************************************************
void serielle_Schnittstelle_abfragen() {
  if  (Serial.available()) {
    Serial.println("Ich bin www-taub!");
    serial_a = 0;
    serial_nr = 0;
    while (Serial.available() > 0)
    {
      serial_nr = serial_nr * 10;
      serial_a = Serial.read() - '0'; // ASCII-Textversatz für 0 entfernen
      serial_nr = serial_nr + serial_a;
      delay(5);  // delay in between reads for stability
    }
    neue_Auswahl = 1;
    Auswahl = int(serial_nr);
    Input = "serieller Schnittstelle";
  }
}
// **********************************************************************
void Treppenlicht() {
  // schaltet eine LED nach [LED_Eieruhr] Sek. wieder aus
  if (Debug_Modus) {
    Serial.println("Treppenlicht");
    Serial.print("Laufzeit in s = ");
    Serial.println(Laufzeit_in_sek());
    Serial.print(Anzahl_angeschaltete_LEDs);
    Serial.print(" LEDs sind an, davon ");
    Serial.print(Anzahl_Legenden_LEDs);
    Serial.println(" Legenden-LEDs");
    Serial.println();
  }
  for (byte z = 1; z < Ausbaustufe + 1; z++) {
    byte Element = z;
    if (Patchmodus) {   // Normalfall: OZ 22 = Pin 27
      Element = Element_an_Pin[z];
    }
    if (led[z]) {
      // falls an: max. Einschaltzeit überschritten?
      if (Laufzeit_in_sek() > led_aus[Element]) {
        // Legenden-LEDs immer an lassen, sonst Ausschalten:
        if (Element < Legende_anfang || Element > Legende_ende)
        {
          Led_an(Element, 0);  // Ausschalten
        }
      }
    }
  }
}
// **********************************************************************
void www_abfragen() {
  // Create a client connection
  //  Serial.print("Ich horche, ob www ...");
  EthernetClient client = server.available();
  if (client) {
    Serial.println("Client ist connected!");
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        //read char by char HTTP request
        if (readString.length() < 50) {
          //store characters to string
          readString += c;
        }
        //if HTTP request has ended
        if (c == '\n') {
          Serial.println(readString); //print to serial monitor for debugging
          // normalerweise kommt von Browser: "GET /z=[pos] HTTP/1.1"
          String stringOne = readString;
          int pos = 2 + stringOne.indexOf('z');
          Serial.println(pos);
          String zahl = readString.substring(pos);
          Serial.print("Zahl-String:");
          Serial.println(zahl);
          Auswahl = zahl.toInt();
          neue_Auswahl = 1;
          zahl = String(Auswahl);
          Serial.print("Auswahl:");
          Serial.println(Auswahl);
          Input = "www";
          client.println("HTTP/1.1 200 OK"); //send new page
          client.println("Content-Type: text/html");
          client.println();
          client.println("<HTML>");
          client.println(zahl);
          client.println("<BR>");
          if (Auswahl == 0) {
            client.println("Auswahl unklar, Aufruf im Browser durch ");
            client.println("[IP]/?z=[Auswahl], z. B. <a href='http://192.168.178.104/?z=1'>http://192.168.178.104/?z=1</a>");
            client.println("<BR>");
          }
          client.println("Created by Detlef Giesler. ");
          client.println("Visit <a href='http://www.bs-wiki.de/mediawiki/index.php/222'>bs-wiki.de</a> for more info!");
          client.println("</HTML>");
          delay(1);
          //stopping client
          client.stop();
          //clearing string for next read
          readString = "";
        }
      }
    }
  }
}
// **********************************************************************
void decodeIR() {
  if (bounced) {
    return;
  }
  bounced = 1;
  //stop all interrupts
  noInterrupts();
  byte i;
  //for each "bit" in the code
  for (i = 0; i < CODE_LEN; i += 1) {
    //store the duration of the pulse (microseconds)
    durations[i] = pulseIn(IR_PIN, HIGH, 20000);   // 100000 timeout
    // pulseIn(pin, value, timeout) liest einen Puls (HIGH oder LOW) auf einem Pin aus.
    // Zum Beispiel, wenn value gleich HIGH ist, wartet pulseIn() bis der Pin auf HIGH geht, startet die Zeit,
    // dann wird gewartet, bis der Pin auf LOW ist und die Zeit wird gestoppt.
    // Zurückgegeben wird die Länge des Puls in Mikrosekunden. Nach einer bestimmten Zeit wird 0 zurückgegeben,
    // wenn kein Pulse kommt.
  }
  //enable interrupts
  interrupts();
  if (bounced) {
    bounced = 0;
    boolean sauberes_signal = 1; // optimistisch sein
    // 8 Adress-Bits + 8 invertierte Adress-Bits + 8 Kommando-Bits + 8 invertierte Kommando-Bits
    // erwartungsgemäß 8 Nullen:
    byte a_code = B00000000;
    for (i = 1; i < 9; i += 1) {
      switch (durations[i]) {
        case 100 ... 840: bitSet(a_code, i - 1); break;  // 560µs Pause ist 0-Bit
        default: sauberes_signal = 0;    return;
      }
    }
    //    Serial.println(a_code);

    // erwartungsgemäß 8 Einsen:
    byte a_i_code = B00000000;
    for (i = 9; i < 17; i += 1) {
      switch (durations[i]) {
        case 1400 ... 2100: bitSet(a_i_code, i - 9); break;  // 1690µs Pause ist 1-Bit
        default: sauberes_signal = 0;    return;
      }
    }
    //    Serial.println(a_i_code);

    byte code = B00000000;
    for (i = 17; i < 25; i += 1) {
      //      Serial.print(i);
      //      Serial.print(" - ");
      //      Serial.println(durations[i]);
      //      Serial.println((unsigned long)durations[i]);
      //      delay(3000);
      switch (durations[i]) {
        //       case 100 ... 840: bit = 0; break;  // 560µs Pause ist 0-Bit
        case 1400 ... 2100: bitSet(code, i - 17); break; // 1690µs Pause ist 1-Bit
      }

    }
    if (Debug_Modus) {
      Serial.print("IR-Code: ");
      Serial.println(code);
    }
    //    Serial.print(" = ");
    byte i_code = B00000000;
    for (i = 25; i < 33; i += 1) {
      switch (durations[i]) {
        case 100 ... 840: bitSet(i_code, i - 25); break;  // 560µs Pause ist 0-Bit
      }
    }
    if (i_code != code) {
      sauberes_signal = 0;
      return;
    }
    //    Serial.println(i_code);
    //    Serial.print("sauberes_signal = ");
    //    Serial.println(sauberes_signal);
    switch (code) {
      case 22: IR_Auswahl = 0; break;
      case 12: IR_Auswahl = 1; break;
      case 24: IR_Auswahl = 2;  break;
      case 94: IR_Auswahl = 3; break;
      case 8: IR_Auswahl = 4;  break;
      case 28: IR_Auswahl = 5;  break;
      case 90: IR_Auswahl = 6;  break;
      case 66: IR_Auswahl = 7; break;
      case 82: IR_Auswahl = 8;  break;
      case 74: IR_Auswahl = 9;  break;
      case 7: IR_Auswahl = 210;  break; // Vol--
      case 9: IR_Auswahl = 213;  break; // [EQ] -> mittlere Helligkeit
      case 21: IR_Auswahl = 215;  break; // Vol++
      case 69: IR_Auswahl = 254;  break; // CH- alles aus
      case 70: IR_Auswahl = 200;  break; // CH Zufallszahl -> Bingo
      case 71: IR_Auswahl = 255;  break; // CH+ alles an
      case 64 :  // next
        switch (last_Element) {  // Elemente, Hauptgruppen, Perioden ...
          case 1 ... 118:  IR_Auswahl = min(118, last_Element + 1); break;
          case 131 ... 194:  IR_Auswahl = min(194, last_Element + 1); break;
        }
        break;
      case 68 :    // prev
        IR_Auswahl = max(1, last_Element - 1);
        break;
      case 25 : // 100+ als Init für mehrstellige Zahl
        mehrstellig = 1;
        IR_Auswahl = 0;
        break;
      case 13 :   // 200+ als Quit nach mehrstelliger Zahl
        mehrstellig = 0;
        IR_Auswahl = letzte_IR_Auswahl;
        letzte_IR_Auswahl = 0;
        break;
      case 67: IR_Auswahl = 202;  break; // Play/Pause -> Programm_y
    }
    if (mehrstellig) {
      if (IR_Auswahl < 10) {
        letzte_IR_Auswahl = letzte_IR_Auswahl * 10 + IR_Auswahl;
      }
    }
  }
  if (mehrstellig == 0) {
    if (Debug_Modus) {
      Serial.print("IR-Auswahl: ");
      Serial.println(Auswahl);
      Serial.println();
    }
    Auswahl = IR_Auswahl;
    neue_Auswahl = 1;
    Input = "Fernbedienung";
  }
  // last_Element = Auswahl;
  // delay(3000);
  /*
  0: 22
  100+: 25
  200+: 13
  1: 12
  2: 24
  3: 94
  4: 8
  5: 28
  6: 90
  7: 66
  8: 82
  9: 74
  CH-: 69
  CH: 70
  CH+: 71
  prev: 68
  next: 64
  Play: 67
  Vol-: 7
  Vol+:  21
  eq: 9
  */
}