Mu(h)rmelbahn

Die alte Uhr musste weg. Also musste eine neue her in Form einer Murmelbahn. Mit 9 Servomotoren, durch ein Programm gesteuert, zeigt sie durch die Anzahl der Murmeln die Uhrzeit an.

Im Grundlegenden ist dieses Projekt eine automatisierte Murmelbahn, welche in 5 verschiedenen Plexiglasröhren die Uhrzeit anzeigen kann. Der Streckenverlauf wurde an die gegebenen Umstände, also die Raumaufteilung, angepasst und könnte theoretisch auch verändert werden. Dadurch muss jede Nachbildung individuell gestaltet werden, sowohl Hardware als auch Software. Dieses ist hardwaretechnisch eines der aufwendigsten und umfangreichsten Projekte. Das Programm, welches die Zeitliche Steuerung übernimmt, ist nicht all zu kompliziert, aber sehr umfangreich. Wer die Murmelbahn reproduzieren will, müsste Software wie Hardware zwar anpassen aber nicht komplett neu erfinden.

Hardware

Schienenbau

Die Schienen bestehen aus 1,6mm dickem Draht. Dieser wird so zurechtgebogen, dass man aus meistens 3 Drähten, welche mit Verbindungsdrähten aneinander gelötet werden, einen gewünschten Streckenverlauf herstellen kann. Manchmal muss über den Murmeln ein weiterer Draht verlaufen, um die Murmeln vor Hausrausfallen zu sichern. Um die Drähte am Anfang gerade zu bekommen, spannt man diese einfach in einen Akkuschrauber ein, befestigt diese mit der anderen Seite und zieht, während man den Akkuschrauber langsam in eine Richtung drehen lässt.

Wie man genau solche Schienen herstellt, ist in diesem Video gut erklärt.

Anzeige

Um die Uhrzeit mit Murmeln anzeigen zu können, benötigt man eine Art Anzeige. Dafür haben wir 5 Plexiglasröhren aufrecht in eine Halterung gestellt und mit 5 Servomotoren unten verschlossen. Die erste Röhre auf der linken Seite stellt die Stunden dar, die 4 rechts daneben die Minuten. Jede Murmel, steht somit entweder für eine Stunde oder eine Minute. Das Stundenformat ist in unserem Fall 12-stündig. Damit kontrolliert werden kann, welche Murmel in welche Röhre fällt, ist über der Anzeige eine drehbare Vorrichtung, welche verschiedene Schienenlängen fasst. Je nachdem wie diese Vorrichtung ausgerichtet ist, fallen die Kugeln in die bestimmten Röhren. Die Lichtschranke davor, zählt die Murmeln, welche bereits durch die Weiche gelaufen sind. Um die Röhren bei voller Stunde oder zu Beginn zu leeren, werden die Servomotoren unter den Röhren nacheinander geöffnet.

Lager

Die Murmeln werden in zwei verschiedenen Lagern gelagert, um auf Befehl auf den Weg zu Anzeige losgelassen werden können. Das erste Lager, wird bei dem „normalen“ Gebrauch benutzt, wenn aktuell nur eine Murmel benötigt wird. Diese Murmel läuft daraufhin die gesamte Strecke der Bahn ab. Da dies nach dem Anschalten der Murmelbahn viel zu lange dauern würde alle 10 Sekunden eine Murmel loszuschicken, benötigt man ein zweites Lager, welches es ermöglicht einen Großteil der Bahn zu überspringen, um Zeit zu ersparen. Der zeitliche Abstand der Murmeln muss individuell auf die Strecke angepasst werden. Dies hängt vor allem von Aufzügen ab, welche nicht viele Murmeln auf einmal transportieren können. Das zweite Lager kann man weglassen, wenn man von einem Lager direkt die Anzeige und die restliche Bahn erreichen kann. Durch eine Weiche kann dann der Weg ausgewählt werden. Um das zweite Lager wieder aufzufüllen kann dann wieder das erste Lager benutzt werden. Somit ist die Uhr schneller mit der Zeit synchronisiert. Das zweite Lager (Schnelldosierungslager), sollte genügend Murmeln fassen, um jede Uhrzeit darstellen zu können. Somit benötigt man theoretisch doppelt so viele Kugeln, wenn man zwei Lager wählt. Ein Lager ist eigentlich nur eine normale Schiene, auf welcher die Murmeln hintereinander liegen. Diese Bahn, benötigt aber eine größere Steigung, da die Murmeln aneinander reiben. Wenn das Schnelldosierungslager nicht genügend Murmeln fasst, werden durch eine Lichtschranke neue Murmeln aus dem „normalen“ Lager angefragt.

Dosierung

Die Dosierung der Murmeln wird durch einen einfachen Mechanismus realisiert, welcher immer nur eine Murmel loslassen kann. Dafür wird ein Servomotor benötigt, welcher mit einem 3D gedrucktem Aufsatz die Murmeln aufhält und bei einer Drehung genau eine Murmel durchlässt1Dosierungstechnik von: Wintergatan.

Spiralaufzug

Vor der ersten Dosierung, welche die Murmeln im Normalfall dosiert, ist ein Spiralaufzug verbaut. Dieser Spiralaufzug wird bei uns als Lager benutzt, während die Murmeln nach oben transportiert werden. So wird dieser nur in Bewegung versetzt, wenn das kleinere Lager direkt vor der Dosierung weniger als 6 Murmeln fasst. Vor dem Spiralaufzug befindet sich ein normales Lager, welches in der Theorie direkt in den Aufzug übergehen könnte. Allerdings ist das Gewicht der Murmeln, wenn das Lager voll, ist so stark, dass Murmeln herausgedrückt werden. Somit direkt vor dem Aufzug nochmal eine Dosierung, welche für eine Unterbrechung sorgt und das Gewicht der Murmeln davor abfängt.

Rundaufzug

Der Rundaufzug, welcher die Kugeln nach ihrer Dosierung auf eine gewünschte Höhe befördert, kann immer nur eine Murmel gleichzeitig transportieren. Sobald eine Murmel durch eine Lichtschranke rollt, wird dieser ausgelöst und befördert diese nach oben. eine zweite Lichtschranke im Rundaufzug, legt fest wann der Aufzug wieder stehen bleibt. Dies könnte theoretisch auch über eine zeitliche Konstante gelöst werden.

Weiche

Direkt nach dem Rundaufzug gibt es drei verschiedene Wege, welche die Murmel laufen kann. Einmal in das Schnelldosierungslager, wenn dieses nicht mehr voll ist oder den restlichen Streckenverlauf in die Anzeige. Um die Auswahl der Wege zu bestimmen, kann eine Weiche benutzt werden. Es gibt viele verschiedene Ansätze eine Weiche zu bauen. Wir haben uns für eine horizontale Weiche entschieden, welche mit einem Servomotor einen Schienenteil bewegt. Der dritte Weg, welchen die Murmel laufen kann, führt zu dem Schussmechanismus, welchen ich im Anschluss beschreibe.

Schussmechanismus

Direkt nach dem Rundaufzug kann die Murmel durch die dortige Weiche, einen Weg wählen, welcher der Murmel entlang eines Balkens, gegen einen Gong schießt. Der Schuss wird durch einen Solenoid 2Solenoid auf Amazon verwirklicht. Der Solenoid gibt durch einen Elektromagnet einen kurzen, aber sehr starken Impuls auf die Murmel weiter, wodurch diese sehr schnell beschleunigt werden kann. Jedoch benötigt dieser bei 12V, 2A (24W), um eine maximale Leistung zu garantieren. Um die Spannungsversorgung möglichst einfach zu gestalten, haben wir einfach einen 12V Bleiakku in die Nähe des Schussmechanismus gestellt.

Am Ende der Schussbahn, befindet sich ein Uhrengong 3Tonfeder welchen die Murmel anschlägt. Eine Sekunde nach dem Abschuss der Kugel wird außerdem eine Weiche umgestellt, welche die Kugel beim Zurücklaufen auf der Schussbahn, auf den ursprünglichen Streckenverlauf in die Anzeige umleitet.

Es werden jedoch nicht alle Murmeln geschossen. Die Weiche wird nur umgestellt, wenn eine Stundenkugel kommt oder wenn ein Knopf gedrückt wird, wird die nächste Murmel geschossen.

Kuckuck

Der Mechanismus um die zwei Kuckuckpfeifen 4Kuckuckpfeifen auszulösen, sitzt hinter dem Schussmechanismus, und wird somit nur zur vollen Stunde ausgelöst. Da die Murmeln nicht genug Kraft haben selbst die Kuckuckpfeifen gegen eine Feder herunterzudrücken, muss der Mechanismus zuvor von einem Servo aufgezogen werden.

Steuerung

Die Steuerung übernimmt ein ESP-32, da dieser über W-Lan eine Internetverbindung herstellen kann und über genügend Anschlüsse verfügt, um verschiedenste Sensoren, Motoren oder ähnliches verbinden zu können.

Ich verwende zudem auch noch ein kleines Display5OLED Display auf Amazon, welches über SDA und SCL angeschlossen wird und somit nur wenige Ports (verbraucht). Über das Display gebe ich wichtige Variablen aus, wie die Anzahl der Murmeln, welche noch dosiert werden müssen, die Anzahl der Murmeln, welche noch durch eine Weiche rollen müssen und natürlich die Uhrzeit. Somit lässt sich mit einem Blick auf das Display feststellen, ob die Uhr noch im richtigen Takt ist und keine Murmeln herausgefallen sind.

Software

Die Uhrzeit bekommt der ESP über die Library „NTPClient“. Da in Deutschland zwischen Sommer- und Winterzeit umgestellt werden muss, benötigt man einen Schalter, welcher 3600 oder 7200 Sekunden „Offset“ zur UDP-Zeitzone einstellt.

Das gesamte Programm zu erklären, würde viel zu lange dauern. Zudem ist jeder Befehl im Programm erklärt.

Ein paar Besonderheiten, erkläre ich allerdings trotzdem. So musste ich die Lichtschranke vor dem Rundaufzug (Pin23) mit einem Interrupt6attachInterrupt belegen, da die Murmeln bei dieser Lichtschranke oft nicht erkannt wurden, da sie zu schnell waren.

Die Zeitlichen Abstände zwischen verschiedenen Vorgängen, habe ich zunächst viel zu lange ausgewählt, um dann immer näher durch Ausprobieren an einen idealen Wert zu gelangen.

Generell sind in dem gesamten Loop des Codes keine delay() Befehle über einer Millisekunde, um Pausen in zum Beispiel der Erkennung von Murmeln zu verhindern. Der Befehl delay(1); scheint Unsinnig zu wirken, jedoch muss man diesen vor allem bei ESP’s verwenden, wenn man eine while-Schleife verwenden will.

//Murmelbahn_v2 mit schießen


//Searchindex:
//Bsp.:  MUZU01
//MU: Murmelbahn (Der Programmname)
//ZU: Zusammenhalt (Das Unterprogramm oder der Programmabschnitt)
//01: 01 (Unterteilung des Programmabschnitts)




//Display
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

//Murmeln
int hourskugeln = 0;        //...kugeln Variable ist für das Zählen der Minuten welche schon abgezählt wurden
int minuteskugeln = 0;
int sekundenpufferm = 40;   //...puffer Variable ist die Sekunde in der Minute davor, wann die Kugel abgelassen wird wegen der Verzögerung
int sekundenpufferh = 40;     //Das wird vllt doof aber egal
int sperrem = 0;            //sperre... Variable ist wenn vor beendigung der Stude oder oder des Tages die Anzeige geleert wird, dass nicht gleich wieder Kugeln kommen
int sperreh = 0;
int hoursdiff = 0;          //...diff Variable ist die Anzahl der Kugeln welche noch abgelassen werden müssen
int minutesdiff = 0;
int fastdoslagerdiff = 0;    //Ist 1 wenn die Lichtschranke nicht unterbrochen ist und somit das Fastdosierungslager aufgefüllt werden muss, könnte theoretisch auch bool sein, verwirrt aber egal
int dosierungslagerdiff = 0;    //Ist 1 wenn die Lichtschranke nicht unterbrochen ist und somit das Dosierungslager aufgefüllt werden muss, könnte theoretisch auch bool sein, verwirrt aber 
int hourswei = 0;           //...wei ist die Anzahl der Kugeln, welche die Weiche in eine bestimmte Richtung passieren müssen
int minuteswei = 0;
int uhrwei = 0;             //uhrwei, fastdoswei und schiesswei entscheiden wieviele Kugeln noch in das Fastdosierungslager, wieviele für die Uhr und wie viele Kugeln geschossen werden müssen (Dosierung)
int fastdoswei = 0;
bool schiesswei = 0;        //Ist nur bool, weil immer nur eine Kugel geschossen werden soll (nur Stundenkugel aus Dosierung), haben priorität
unsigned long Zeittime = 0;     //Für delay von Zeitabfrage
unsigned long Servo0time = 0;   //Für delay von Servo 0 loslassen
unsigned long Servo1time = 0;   //Für delay von Servo 1 loslassen
bool Servo0sperre = 0;          //Die Sperre für die Dosierun, welche vom Rundaufzug aufgehoben wird
bool Servo0spak = 0;            //Die Aktivierung der Zeitzählung von der Aufhebung der Sperre von Servo0 (Dosierung)
unsigned long Servo0sptime = 0; //Die Zeitvariable, welche die Zeit zwischen Durchlaufen der LS am Rundaufzug und der Aufhebung der Dosierungssperre macht
bool Servo0akh = 0;             //Wenn 1 dann muss der Servo 0 noch zugemacht werden und Stunden abgezogen werden
bool Servo0akm = 0;             //Wenn 1 dann muss der Servo 0 noch zugemacht werden und Minuten abgezogen werden
bool Servo0akl = 0;             //Wenn 1 dann muss der Servo 0 noch zugemacht werden (Fastlager auffüllen)
int Servo1akh = 0;              //Wenn 1 dann muss der Servo 1 noch zugemacht werden und Stunden abgezogen werden
int Servo1akm = 0;              //Wenn 1 dann muss der Servo 1 noch zugemacht werden und Minuten abgezogen werden
bool Fastlagerweicheschranke = 0;       //Wenn 1 dann muss der Counter der Fastdosweiche noch gezählt werden
unsigned long Fastlagerweichetime = 0;    //Zeitvariable dass nach bestimmter Zeit der Counter der Weiche noch gezählt wird
int fastdosweistellung = 0;               //gibt die aktuelle Stellung der Fastdosweiche an
int Weichenstellung = 0;        //gibt die aktuelle Stellung der Weiche an
int Weicheschranke = 0;         //Sperre für die Lichtschranke der Weiche
unsigned long Weischranketime = 0;    //Die Zeitvariable die den delay von der Kugel durch die Weiche bestimmt, damit danach die Weiche umgestellt werden kann
int min15 = 0;                        //Die Anzahl der Kugeln die in der 15 min Röhre liegen
int min30 = 0;
int min45 = 0;
int min60 = 0;
int Stunden = 0;                      //Die Anzahl der Kugeln die in der Stundenröhre liegen
bool Hleeren = 0;                     //Ist 1 wenn die Stunden geleert werden sollen
bool M15leeren = 0;                   //Ist 1 wenn die 15 min geleert werden sollen
bool M30leeren = 0;                   //Die hätte mna auch zusammenfassen können weil die minuten ja immer alle zusammen geleert werden, aber die dürfen nicht gleichzeitig aufgehen, ist somit übersichtlicher
bool M45leeren = 0;
bool M60leeren = 0;
unsigned long leerentime = 0;             //DIe Zeitvariable die den delay zwischen Leeren aufmachen und wieder zumachen bestimmt
bool leerensperre = 0;                    //Das immer nur eine Röhre auf einmal geleert wird
bool Aufzug1schranke = 0;                 //Die Sperre für die Lichtschranke vor dem Rundaufzug (Aufzug1)
unsigned long Aufzug1schranketime = 0;    //Ist die Zeitliche Sperre für den Rundaufzug, ist glaube ich nicht nötig, aber ka
unsigned long Aufzug1btime = 0;           //Die Zeitvariable nach der der Aufzug1 anfängt, um das auspendeln zu beachten
bool Aufzug1b = 0;                        //Das der Aufzug1 überhaupt nach bestimmter Zeit auslöst, könnte man auch mit ner fetten Rechnung mit Aufzug1btime machen ist mir aber zu viel aufwand
bool Aufzug1s2 = 0;                       //Ist 1 wenn die Motorlichtschranke vom Aufzug1 unterbrochen wurde und dann nach bestimmter Zeit der Aufzug anhalten soll
unsigned long Aufzug1etime = 0;           //Die Zeitvariable nach der der Aufzug anhält das "e" steht für end :)
bool Spiralauf = 0;                       //Ist 1 wenn der Spiralaufzug gerade läuft
unsigned long Spiralauftime = 0;          //Die Zeitvariable die bestimmt wie lange der Spiralaufzug pro Kugel laufen soll
bool notaufa = 0;                         //Für den Interrupt bei dem Rundaufzug
bool Servo9sperre = 0;                    //Sperre für den Spiralaufzugsservo unten
bool Spiraldiff = 0;                      //Aufforderung den Spiralservo unten aufzumachen
unsigned long Servo9time = 0;             //Zeitliche Variable für die Sperre von dem Spiralservo unten
bool Balkenwei = 0;                       //Bei Null soll Weiche auf gerader Stellung zum Schuss stehen, bei 1 schräg, um die rücklaufende Kugel richtung Uhr zu leiten
bool Balkenweistellung = 0;               //Gibt die aktuelle Stellung der Balkenweiche an
bool Schuss = 0;                          //Wenn 0 dann kann geschossen werden, wenn 1 dann wurde Schuss bereits angefragt
unsigned long Schusstime = 0;             //Schusstime sperrt den Schuss für bestimmte Zeit
unsigned long Schusstimesperre = 0;       //Schuss kann erst nach 500 ms Angefragt werden, damit der Letzte Schuss durch den Arm nicht die Lichtschranke auslöst
bool Schusssperre = 0;                         //Damit sich nicht 2 mal aktiviert wird


//Zeit
#include <NTPClient.h>
//bei ESP32
#include <WiFi.h>
//Bei ESP8266
//#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

const char *ssid = "Peters Netzwerg";
const char *password = "chrpetlispau";
const long utcOffsetInSeconds = 3600;
char daysOfTheWeek[7][12] = {"So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"};


WiFiUDP ntpUDP;
//NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds);
NTPClient timeClient(ntpUDP, "pool.ntp.org");

#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C //Adresse für Display steht auf Datasheet oder hinten drauf per Widerstand umlöten; 0x3D für 128x64, 0x3C für 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

//Servo
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
#define SERVOMIN 80 //Minimum Pulse Length (out of 4096) 80 bei kleinen, 150 bei großen Servos
#define SERVOMAX 470  //Maximum Pulse Length (out of 4096) 470  bei kleinen, 480 bei großen Servos
#define SERVOGMIN 150
#define SERVOGMAX 480
#define SERVO_FREQ 50

uint8_t servonum = 0;
uint16_t pulselen = SERVOMAX;
uint16_t apulselen = SERVOMAX;
int movement = 0;

void setup() {
  pinMode(2, OUTPUT);   //LED_BUILDIN
  pinMode(27, INPUT);    //Weichenschranke
  pinMode(23, INPUT);    //Aufzug1schranke
  pinMode(13, INPUT);    //Aufzug1motorschranke
  pinMode(26, INPUT);    //Dosierungslager
  pinMode(32, INPUT);    //Fastdosierungslager
  pinMode(25, OUTPUT);   //Spiralaufzug Motor
  pinMode(33, OUTPUT);   //Aufzug1Motor
  pinMode(19, INPUT);    //Spiralschranke (unten)
  pinMode(14, INPUT_PULLUP);    //Sommerzeit / Winterzeit
  pinMode(4, OUTPUT);    //Solenoid (schießmechanismus)
  pinMode(5, OUTPUT);   //Kerze
  pinMode(34, INPUT);    //Schiesslichtschranke
  pinMode(35, INPUT_PULLUP);    //Schussknopf

  digitalWrite(4, LOW);
  digitalWrite(5, LOW);
  digitalWrite(33, LOW);
  digitalWrite(25, LOW);

  Serial.begin(115200);
  //Display
    if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
  display.clearDisplay();
  display.setCursor(0, 0);
  display.setTextSize(2);
  display.setTextColor(SSD1306_WHITE);
  //WiFi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    display.print(".");
    display.display();
  }
  timeClient.begin();
  if(digitalRead(14) == HIGH) {
    timeClient.setTimeOffset(7200); //7200 Sommerzeit
  } else {
    timeClient.setTimeOffset(3600);//3600 Winterzeit
  }
  
//Servo
  pwm.begin();
pwm.setPWMFreq(SERVO_FREQ);
delay(10);
//Kleine Servo
double pulselength = map(60, 0, 180, SERVOMIN, SERVOMAX);
pwm.setPWM(0, 0, pulselength);                            //Dosierung
pulselength = map(40, 0, 180, SERVOMIN, SERVOMAX);
pwm.setPWM(1, 0, pulselength);                            //Schnelldosierung
pulselength = map(0, 0, 180, SERVOMIN, SERVOMAX);
pwm.setPWM(2, 0, pulselength);                            //Uhr-Weiche
pulselength = map(180, 0, 180, SERVOMIN, SERVOMAX);
pwm.setPWM(3, 0, pulselength);                            //Stundenleeren
pulselength = map(180, 0, 180, SERVOMIN, SERVOMAX);
pwm.setPWM(4, 0, pulselength);                            //15Minutenleeren
pulselength = map(175, 0, 180, SERVOMIN, SERVOMAX);
pwm.setPWM(5, 0, pulselength);                            //30Minutenleeren
pulselength = map(160, 0, 180, SERVOMIN, SERVOMAX);
pwm.setPWM(6, 0, pulselength);                            //45Minutenleeren
pulselength = map(180, 0, 180, SERVOMIN, SERVOMAX);
pwm.setPWM(7, 0, pulselength);                            //60Minutenleeren
pulselength = map(97, 0, 180, SERVOMIN, SERVOMAX);
pwm.setPWM(8, 0, pulselength);                            //Fastlager-Auffüllweiche
pulselength = map(150, 0, 180, SERVOMIN, SERVOMAX);
pwm.setPWM(9, 0, pulselength);                            //Vor Spiralaufzug
pulselength = map(0, 0, 180, SERVOMIN, SERVOMAX);
pwm.setPWM(10, 0, pulselength);                           //Balkenweiche  (Schießweiche war schon vergeben bei[Fastlager-Auffüllweiche])
pulselength = map(0, 0, 180, SERVOMIN, SERVOMAX);
pwm.setPWM(11, 0, pulselength);                            //Kuckuck-Aufziehen

//Display
display.clearDisplay();
display.display();

//Leeren
Serial.println("leeren");
delay(500);

pulselength = map(0, 0, 180, SERVOMIN, SERVOMAX);
pwm.setPWM(3, 0, pulselength);
delay(3000);
pulselength = map(180, 0, 180, SERVOMIN, SERVOMAX);
pwm.setPWM(3, 0, pulselength);
pulselength = map(0, 0, 180, SERVOMIN, SERVOMAX);
pwm.setPWM(4, 0, pulselength);
delay(3000);
pulselength = map(180, 0, 180, SERVOMIN, SERVOMAX);
pwm.setPWM(4, 0, pulselength);
pulselength = map(0, 0, 180, SERVOMIN, SERVOMAX);
pwm.setPWM(5, 0, pulselength);
delay(3000);
pulselength = map(175, 0, 180, SERVOMIN, SERVOMAX);
pwm.setPWM(5, 0, pulselength);
pulselength = map(0, 0, 180, SERVOMIN, SERVOMAX);
pwm.setPWM(6, 0, pulselength);
delay(3000);
pulselength = map(160, 0, 180, SERVOMIN, SERVOMAX);
pwm.setPWM(6, 0, pulselength);
pulselength = map(15, 0, 180, SERVOMIN, SERVOMAX);    //der ist auf 15° weil der scheiße eingebaut ist
pwm.setPWM(7, 0, pulselength);
delay(3000);
pulselength = map(180, 0, 180, SERVOMIN, SERVOMAX);
pwm.setPWM(7, 0, pulselength);



digitalWrite(33, HIGH);
while(digitalRead(13) == LOW) {
delay(1);
}
delay(2500);
digitalWrite(33, LOW);
attachInterrupt(23, notaufzug, HIGH);

//timeClient.update();
delay(300);

}

void loop() {
  //////////MUZE
  /////MUZE01
  //Zeitabfrage alle Sekunde
  if(millis() >= Zeittime + 1000) {
    timeClient.update();
    Zeittime = millis();
  }

  /////MUZE02
  //Stunden in 12-Format
  if(timeClient.getHours() > 12 && timeClient.getHours() - 12 != Stunden) {
    Stunden = timeClient.getHours() - 12;
  } else if(timeClient.getHours() <= 12 && timeClient.getHours() != Stunden) {
    Stunden = timeClient.getHours();
  }

  //////////MUAN
  /////MUAN01
  //Anzeige refresh
  anzeige();

  //////////MUZA
  /////MUZA01
  if(timeClient.getHours() == 23 && timeClient.getMinutes() == 59 && timeClient.getSeconds() >= 30 && sperreh == 0) {   //Wenn es 30 Sekunden vor Mitternacht ist, werden die Stunden gelehrt und eine Sperre für diese Minute aktiviert, da diese eigentlich dann weitere Kugeln anforderen würde
    Serial.println("Leeren H ");
    Hleeren = 1;
    hourskugeln = 0;
    sperreh = 1;
    Serial.print(timeClient.getSeconds());
    Serial.print("Sperreh: ");
    Serial.println(sperreh);
  } 
  if(timeClient.getHours() == 12 && timeClient.getMinutes() == 59 && timeClient.getSeconds() >= 30 && sperreh == 0) {   //Wenn es 30 Sekunden vor Mittertag ist, werden die Stunden gelehrt und eine Sperre für diese Minute aktiviert, da diese eigentlich dann weitere Kugeln anforderen würde
    Serial.println("Leeren H ");
    Hleeren = 1;
    hourskugeln = 0;
    sperreh = 1;
    Serial.print(timeClient.getSeconds());
    Serial.print(" Sperreh: ");
    Serial.println(sperreh);
  } 
  if(timeClient.getHours() != 23 && sperreh == 1 && timeClient.getHours() != 12 && timeClient.getMinutes() != 59) {    //Wenn die 23. Stunde rum ist, wird die Sperre aufgehoben
    sperreh = 0;
    Serial.print(timeClient.getSeconds());
    Serial.print("Sperreh: ");
    Serial.println(sperreh);
  }


  /////MUZA02
  //Minutes
  while(minuteskugeln < timeClient.getMinutes() && sperrem == 0) {  //Wenn mehr als eine Kugel zu wenig drin ist, werden diese sofort alle angefragt
    minuteskugeln = minuteskugeln + 1;
    minutesdiff = minutesdiff + 1;
    delay(1);
  }

  /////MUZA03
  //Wenn die Kugeln in den Minuten mehr als die eigentlichen Minuten sind wird gelehrt
  if(minuteskugeln > timeClient.getMinutes() + 1) {
    Serial.println("Leeren M fehler");
    M15leeren = 1;
    M30leeren = 1;
    M45leeren = 1;
    M60leeren = 1;
    Serial.println(timeClient.getMinutes());
    minuteskugeln = 0;
    min15 = 0;
    min30 = 0;
    min45 = 0;
    min60 = 0;
  } else if(minuteskugeln == timeClient.getMinutes() && timeClient.getSeconds() >= sekundenpufferm && timeClient.getMinutes() != 59) {          //40 sekunden bevor die Minute anbricht wird die Kugel angefragt
    //Serial.print("LOS M ");
    minuteskugeln = minuteskugeln + 1;
    minutesdiff = minutesdiff + 1;
  } /*else if(minuteskugeln < timeClient.getMinutes() && sperrem == 0) {    //Wenn mehr als eine Kugel zu wenig drin ist, werden diese sofort alle angefragt
    minuteskugeln = minuteskugeln + 1;
    minutesdiff = minutesdiff + 1;
  }*/

 /* while(minuteskugeln < timeClient.getMinutes() && sperrem == 0) {  //Wenn mehr als eine Kugel zu wenig drin ist, werden diese sofort alle angefragt
    minuteskugeln = minuteskugeln + 1;
    minutesdiff = minutesdiff + 1;
    delay(1);
  }*/

  /////MUZA04
  if(timeClient.getMinutes() == 59 && timeClient.getSeconds() >= 20 && sperrem == 0) {      //Bei Minute 59 und 20 Sekunden also 40 Sekunden vor Stunde, werden die Minuten gelehrt und eine Sperre für Nachfüllen wird aktiviert, weil ja dann zu wenig Kugeln für die Minute drin wären
    Serial.println("Leeren M ");
    M15leeren = 1;
    M30leeren = 1;
    M45leeren = 1;
    M60leeren = 1;
    minuteskugeln = 0;
    sperrem = 1;
    min15 = 0;
    min30 = 0;
    min45 = 0;
    min60 = 0;
  } else if(timeClient.getMinutes() != 59 && sperrem == 1) {    //Wenn die Minute 59 rum ist, wird die Sperre aufgehoben
    sperrem = 0;
  }


  /////MUZA05
  //Stunden

  while(hourskugeln < Stunden && sperreh == 0) {     //Wenn mehr als eine Kugel zu wenig in der Stunde sind, werden alle auf einmaln angefragt
    hourskugeln = hourskugeln + 1;
    hoursdiff = hoursdiff + 1;
    Serial.print(timeClient.getSeconds());
    Serial.print(" Hourskugeln: ");
    Serial.println(hourskugeln);
  }
  if(hourskugeln > Stunden + 1) {   //Wenn die Kugeln in den Stunden mehr als die eigentlichen Stunden sind, wird gelehrt
    Serial.println("Leeren H fehler");
    Hleeren = 1;
    hourskugeln = 0;
    Serial.print(timeClient.getSeconds());
    Serial.print(" Hourskugeln-1: ");
  Serial.println(hourskugeln);
  } else if(hourskugeln == Stunden && timeClient.getMinutes() == 59 && timeClient.getSeconds() >= sekundenpufferh && timeClient.getHours() != 23 && timeClient.getHours() != 12) {     //Wenn es 30 Sekunden vor der nächten Stunde ist, wird die Kugel angefragt
    //Serial.print("LOS H ");
    hourskugeln = hourskugeln + 1;
    hoursdiff = hoursdiff + 1;
    Serial.print(timeClient.getSeconds());
    Serial.print(" Hourskugeln: ");
  Serial.println(hourskugeln);
  } /*else if(hourskugeln < Stunden && sperreh == 0) {    //Wenn mehr als eine Kugel zu wenig in der Stunde sind, werden alle auf einmaln angefragt
    hourskugeln = hourskugeln + 1;
    hoursdiff = hoursdiff + 1;
  }*/
  

  

  //////////MUFA
  //Fastdosierungslager auffüllen
  if(digitalRead(32) == LOW && fastdoslagerdiff == 0) {      //Wenn die Lichtschranke von dem Fastdosierungslager nicht unterbrochen ist dann wird dann werden Kugeln für das Lager angefragt
    fastdoslagerdiff = 1;
  }
  if(digitalRead(32) == HIGH && fastdoslagerdiff != 0) {     //Wenn das Lager voll ist werden die Anfragen für Kugeln gelöscht
    fastdoslagerdiff = 0;
  }

  //////////MUDA
  //Dosierungslager auffüllen
  if(digitalRead(26) == LOW && dosierungslagerdiff == 0) {      //Wenn die Lichtschranke von dem Dosierungslager nicht unterbrochen ist dann wird dann werden Kugeln für das Lager angefragt
    dosierungslagerdiff = 1;
  }
  if(digitalRead(26) == HIGH && dosierungslagerdiff != 0) {     //Wenn das Lager voll ist werden die Anfragen für Kugeln gelöscht
    dosierungslagerdiff = 0;
  }


  //////////MUSP
  //Spiralaufzug
  if(dosierungslagerdiff >=1 && Spiralauf == 0) {             //Geht an wenn Kugeln per Lichtschranke angefragt wurden
    digitalWrite(25, HIGH);
    Spiralauf = 1;
    Spiralauftime = millis();
  } else if(Spiralauf == 1 && millis() >= Spiralauftime + 1000) {         //So lange läuft der Spiralaufzug pro Anmachen
    digitalWrite(25, LOW);
    Spiralauf = 0;
  }

  //////////MUSU
  /////MUSU01
  if(digitalRead(19) == LOW && Spiraldiff == 0) {
    Spiraldiff = 1;
  } else if(digitalRead(19) == HIGH && Spiraldiff != 0) {
    Spiraldiff = 0;
  }

  if(Spiraldiff == 1 && millis() >= Servo9time + 500 && Servo9sperre == 0) {
    Servo9los();
    Servo9time = millis();
    Servo9sperre = 1;
  }

  if(Servo9sperre == 1 && millis() >= Servo9time + 500) {
    Servo9zu();
    Servo9time = millis();
    Servo9sperre = 0;
  }


  //////////MUDS
  //Dosierungssperre
  if(Servo0spak == 1 && millis() >= Servo0sptime + 5500) {         //Zeit von LS durchlaufen bis Sperre wieder aufgehoben wird
    Servo0spak = 0;
    Servo0sperre = 0;
  }


  //////////MUDO
  /////MUDO01
  //Dosierungssteuerung
  //Viele Servoak... Variablen sind unnötig weil sich durch die Zeitsperre eh nicht zwei gleichzeitig öffnen können ist aber zur sicherheit, falls während der if Schleife die Zeit freigegeben wird
  //Bei Servo0 also der Dosierung, ist die Servo0time eigentlich auch unnötig weil der Rundaufzug die Zeit eh begrenzt, jedoch auch als Sicherung und weil ich kein Bock hab die weg zu machen
  //Die Servo0sperre gilt nur für die Dosierung weil diese durch den Rundaufzug gebremst wird
  if(hoursdiff > 1 && millis() >= Servo1time + 4000 && Servo1akh == 0 && Servo1akm == 0  && Servo0akh == 0 && Servo0akm == 0 && Servo0akl == 0) {     //Fastdosierung aufmachen für Stunden
    fastloslassen();
    Servo1time = millis();
    Servo1akh = 1;
  } else if(hoursdiff == 1 && millis() >= Servo1time + 4000 && Servo1akh == 0 && Servo1akm == 0 && minutesdiff > 1  && Servo0akh == 0 && Servo0akm == 0 && Servo0akl == 0) {    //Sonderfall Fastdosierung: Muss vor Dosierung Stunden kommen;Wenn danach noch Minuten kommen muss die letzte Stundenkugel durch Fastdosierung laufen
    fastloslassen();
    Servo1time = millis();
    Servo1akh = 1;
  } else if(minutesdiff > 1 && millis() >= Servo1time + 4000 && Servo1akm == 0 && Servo1akh == 0  && Servo0akh == 0 && Servo0akm == 0 && Servo0akl == 0) {      //Fastdosierung aufmachen für Minuten
    fastloslassen();
    Servo1time = millis();
    Servo1akm = 1;
  } else if(hoursdiff == 1 && millis() >= Servo0time + 500 && Servo0akh == 0 && Servo0akm == 0 && Servo1akh == 0  && Servo1akm == 0 && minutesdiff <= 1 && Servo0akl == 0 && Servo0sperre == 0) {       //Dosierung aufmachen für Stunden
    loslassen();
    Servo0time = millis();
    Servo0akh = 1;
    Servo0sperre = 1;
  } else if(minutesdiff == 1 && millis() >= Servo0time + 500 && Servo0akm == 0 && Servo0akh == 0 && Servo1akm == 0  && Servo1akh == 0 && Servo0akl == 0 && Servo0sperre == 0) {   //Dosierung aufmachen für Minuten
    loslassen();
    Servo0time = millis();
    Servo0akm = 1;
    Servo0sperre = 1;
  } else if(fastdoslagerdiff == 1 && millis() >= Servo0time + 500 && Servo0akm == 0 && Servo0akh == 0 && Servo0akl == 0 && Servo0sperre == 0) {
    loslassen();
    Servo0time = millis();
    Servo0akl = 1;
    Servo0sperre = 1;
  }
  //minutesdiff ist die anzahl die noch freigegeben werden müssen; Servo0time ist die Sperre der Zeit -> delay; Servo0akm und Servo0akh ist die Sperre falls der Servo erst noch zugemacht werden muss


  //Servo0akh nur wenn schon aufgemacht wurde; Servo0time ist Zeit für Servo -> delay;

  /////MUDO02

  if(Servo0akh == 1 && millis() >= Servo0time + 500) {      //Dosierung zumachen für Stunden
    zumachen();
    hoursdiff = hoursdiff - 1;
    hourswei = hourswei + 1;
    schiesswei = 1;
    digitalWrite(5, HIGH);            //Kerze wird angeschaltet
    uhrwei = uhrwei + 1;        //Braucht man ebenfalls, wegen dem Knopf der Schuss anfragt, weil der nur wenn uhr wei >= 1 ist schießen darf, sonst schießt der Fastdoslagerkugeln
    Servo0akh = 0;
    Servo0time = millis();
  }else if(Servo0akm == 1 && millis() >= Servo0time + 500) {    //Dosierung zumachen für Minuten
    zumachen();
    minutesdiff = minutesdiff - 1;
    minuteswei = minuteswei + 1;
    uhrwei = uhrwei + 1;
    Servo0akm = 0;
    Servo0time = millis();
  }else if(Servo0akl == 1 && millis() >= Servo0time + 500) {
    zumachen();
    fastdoswei = fastdoswei + 1;
    Servo0akl = 0;
    Servo0time = millis();
  }


  /////MUDO03
  if(Servo1akh == 1 && millis() >= Servo1time + 500) {        //Fastdosierung zumachen; hier ist kein uhrwei, weil dies nur für die Dosierung ist weil nur die die erste Weiche durchläuft
    fastzumachen();
    hoursdiff = hoursdiff - 1;
    hourswei = hourswei + 1;
    Servo1akh = 0;
    Servo1time = millis();
  }else if(Servo1akm == 1 && millis() >= Servo1time + 500) {
    fastzumachen();
    minutesdiff = minutesdiff - 1;
    minuteswei = minuteswei + 1;
    Servo1akm = 0;
    Servo1time = millis();
  }


  //////////MUFW
  //////MUFW01
  //Fastdosierungslagerweichensteuerung (Das längste Wort)
  if(Fastlagerweicheschranke == 1 && millis() >= Fastlagerweichetime + 4500) {
    Fastlagerweiche();
    Fastlagerweicheschranke = 0;
  }

    //////MUFW02
  if(schiesswei == 1 && uhrwei >= 1 && fastdosweistellung != 3) {                      //Die Weichenstellung (3) ist weil ich kein Bock hab die anderen zu Tauschen macht also von der Anordnung kein Sinn
    double pulselength = map(97, 0, 180, SERVOMIN, SERVOMAX);                          //uhrwei muss >= 1 sein, damit nur Uhrkugeln geschossen werden
    pwm.setPWM(8, 0, pulselength);
    fastdosweistellung = 3;
  } else if(uhrwei >= 1 && fastdosweistellung != 1) {
    double pulselength = map(70, 0, 180, SERVOMIN, SERVOMAX);
    pwm.setPWM(8, 0, pulselength);
    fastdosweistellung = 1;
  } else if(fastdoswei >= 1 && uhrwei == 0 && fastdosweistellung != 2) {          //Default einstellung ist Uhr weil das andere bäuchte Zeitverzögerung und des is zu doof
    double pulselength = map(135, 0, 180, SERVOMIN, SERVOMAX);
    pwm.setPWM(8, 0, pulselength);
    fastdosweistellung = 2;
  }

  //////////MUWE
  /////MUWE01
  //Weichensteuerung
  if(digitalRead(27) == HIGH && Weicheschranke == 0 && millis() >= Weischranketime + 500) {
    Weiche();
    Weicheschranke = 1;
  }else {
    Weicheschranke = 0;
  }

  /////MUWE02
  if(hourswei >= 1 && Weichenstellung != 1 && millis() >= Weischranketime + 1000) {
    double pulselength = map(180, 0, 180, SERVOMIN, SERVOMAX);
    pwm.setPWM(2, 0, pulselength);
    Weichenstellung = 1;
  } else if(minuteswei >= 1 && hourswei == 0 && min15 < 15 && Weichenstellung != 2 && millis() >= Weischranketime + 1000) {
    double pulselength = map(145, 0, 180, SERVOMIN, SERVOMAX);
    pwm.setPWM(2, 0, pulselength);
    Weichenstellung = 2;
  } else if(minuteswei >= 1 && hourswei == 0 && min15 >= 15 && min30 < 15 && Weichenstellung != 3 && millis() >= Weischranketime + 1000) {
    double pulselength = map(105, 0, 180, SERVOMIN, SERVOMAX);
    pwm.setPWM(2, 0, pulselength);
    Weichenstellung = 3;
  } else if(minuteswei >= 1 && hourswei == 0 && min15 >= 15 && min30 >= 15 && min45 < 15 && Weichenstellung != 4 && millis() >= Weischranketime + 1000) {
    double pulselength = map(65, 0, 180, SERVOMIN, SERVOMAX);
    pwm.setPWM(2, 0, pulselength);
    Weichenstellung = 4;
  } else if(minuteswei >= 1 && hourswei == 0 && min15 >= 15 && min30 >= 15 && min45 >= 15 && min60 < 15 && Weichenstellung != 5 && millis() >= Weischranketime + 1000) {
    double pulselength = map(30, 0, 180, SERVOMIN, SERVOMAX);
    pwm.setPWM(2, 0, pulselength);
    Weichenstellung = 5;
  }


  //Servo0akh und Servo0akm müssen getrennt sein, da die Variable minutesdiff bzw. hoursdiff darin verändert wird
  //Servo0time muss in beiden das selbe sein, da dies die Zeitbeschränkung (delay) ist, welche der Servo für öffnen und schließen braucht, in beiden Fällen wird Servo0 gesteuert und braucht somit die selbe Variable.


    //////////MULE
    /////MULE01
    //Leeren
  if(Hleeren == 1 && leerensperre == 0) {
    double pulselength = map(0, 0, 180, SERVOMIN, SERVOMAX);
    pwm.setPWM(3, 0, pulselength);
    leerensperre = 1;
    hourskugeln = 0;
    leerentime = millis();
    Hleeren = 0;
  } else if(M15leeren == 1 && leerensperre == 0) {
    double pulselength = map(0, 0, 180, SERVOMIN, SERVOMAX);
    pwm.setPWM(4, 0, pulselength);
    leerensperre = 1;
    leerentime = millis();
    M15leeren = 0;
  } else if(M30leeren == 1 && leerensperre == 0) {
    double pulselength = map(0, 0, 180, SERVOMIN, SERVOMAX);
    pwm.setPWM(5, 0, pulselength);
    leerensperre = 1;
    leerentime = millis();
    M30leeren = 0;
  } else if(M45leeren == 1 && leerensperre == 0) {
    double pulselength = map(0, 0, 180, SERVOMIN, SERVOMAX);
    pwm.setPWM(6, 0, pulselength);
    leerensperre = 1;
    leerentime = millis();
    M45leeren = 0;
  } else if(M60leeren == 1 && leerensperre == 0) {
    double pulselength = map(15, 0, 180, SERVOMIN, SERVOMAX);
    pwm.setPWM(7, 0, pulselength);
    leerensperre = 1;
    minuteskugeln = 0;
    leerentime = millis();
    M60leeren = 0;
  }

  /////MULE02
  if(leerensperre == 1 && millis() >= leerentime + 3000) {
    double pulselength = map(180, 0, 180, SERVOMIN, SERVOMAX);
    pwm.setPWM(3, 0, pulselength);
    pulselength = map(180, 0, 180, SERVOMIN, SERVOMAX);
    pwm.setPWM(4, 0, pulselength);
    pulselength = map(175, 0, 180, SERVOMIN, SERVOMAX);
    pwm.setPWM(5, 0, pulselength);
    pulselength = map(160, 0, 180, SERVOMIN, SERVOMAX);
    pwm.setPWM(6, 0, pulselength);
    pulselength = map(180, 0, 180, SERVOMIN, SERVOMAX);
    pwm.setPWM(7, 0, pulselength);
    leerensperre = 0;
  }


    //////////MURA
    /////MURA01
    //Aufzug1(Rundaufzug)
  if(notaufa == 1 && Aufzug1schranke == 0 && millis() >= Aufzug1schranketime + 7000) {     //Auslösen dass Aufzug ausgelöst wird
    Aufzug1btime = millis();
    Aufzug1schranketime = millis();
    Aufzug1b = 1;
    Aufzug1schranke = 1;
    Fastlagerweicheschranke = 1;
    Fastlagerweichetime = millis();
    Servo0spak = 1;
    Servo0sptime = millis();
  }
  if(digitalRead(23) == LOW) {        //Hier ist ne änderung drin
    Aufzug1schranke = 0;              // Das ist drin damit der Interruppt nicht zweimal auslöst
    notaufa = 0;                      //Die Interruppt Variable wird wieder auf 0 gesetzt
  }

  //////MURA02
  if(Aufzug1b == 1 && millis() >= Aufzug1btime + 150) {      //Auslösen des Aufzugs nach soviel zeit wie die Lichtschranke unterbrochen wurde
    digitalWrite(33, HIGH);
    Aufzug1b = 0;
  }

  /////MURA03
  if(digitalRead(13) == HIGH && Aufzug1s2 == 0) {         //Auslöser der Lichtschranke zum Stoppen
    Aufzug1etime = millis();
    Aufzug1s2 = 1;
  }

  /////MURA04
  if(Aufzug1s2 == 1 && millis() >= Aufzug1etime + 2400) {       //So lange läuft der Aufzug noch nach der Lichtschranke
    Aufzug1s2 = 0;
    digitalWrite(33, LOW);
  }

  ////////MUBW
  ////MUBW01
  if(Balkenwei == 0 && Balkenweistellung != 0) {                    //Balkenweiche auf Schussstellung stellen
    double pulselength = map(30, 0, 180, SERVOMIN, SERVOMAX);
    pwm.setPWM(10, 0, pulselength);
    Balkenweistellung = 0;
  } else if(Balkenwei == 1 && Balkenweistellung != 1) {             //Balkenweiche auf schräge Stellung stellen
    double pulselength = map(30, 0, 180, SERVOMIN, SERVOMAX);
    pwm.setPWM(10, 0, pulselength);
    Balkenweistellung = 1;
  }

  ////////MUSC
  ////MUSC01
  if(digitalRead(34) == HIGH && Schuss == 0 && millis() >= Schusstimesperre + 500) {    //Schuss wird angefragt, wenn Lichtschranke unterbrochen, und seit 500 ms kein Schuss ausgeführt wurde, damit der Schussarm nicht die Lichtschranke auslöst
    Schuss = 1;
    Schusstime = millis();
    pulselength = map(180, 0, 180, SERVOMIN, SERVOMAX);                                 //Kuckuckaufladen wird angefangen
    pwm.setPWM(11, 0, pulselength);    
  }

  ////MUSC02
  if(Schuss == 1 && millis() >= Schusstime + 1000 && Schusssperre == 0) {               //Schuss wird 1 Sekunde später ausgeführt, damit sich die Kugel berühigt
    Schusstime = millis();
    digitalWrite(5, LOW);                                                             //Kerze wird ausgeschaltet
    digitalWrite(4, HIGH);
    Schusssperre = 1;
    pulselength = map(0, 0, 180, SERVOMIN, SERVOMAX);                                   //Kuckuckaufladen wird beendet
    pwm.setPWM(11, 0, pulselength);
  }

  ////MUSC03
  if(Schusssperre == 1 && millis() >= Schusstime + 1000) {                            //1 Sekunde später wird der Arm zurückgeholt und die Weiche umgestellt
    Balkenwei = 1;
    digitalWrite(4, LOW);
    Schusssperre = 0;
    Schusstimesperre = millis();
    Schuss = 0;
  }

  ////MUSC04
  if(digitalRead(35) == LOW && schiesswei == 0) {                                     //Wenn der Knopf gedrückt wird, wird schuss angefragt (Weiche)
    schiesswei = 1;
    digitalWrite(5, HIGH);                                                             //Kerze geht an wenn der Knopf gedrückt wurde
  }

}


//////////MUWE03
void Weiche() {

  if(hourswei >= 1) {
    Weischranketime = millis();
    hourswei = hourswei - 1;
  } else if(minuteswei >= 1 && min15 < 15) {
    Weischranketime = millis();
    min15 = min15 + 1;
    minuteswei = minuteswei - 1;
  } else if(minuteswei >= 1 && min30 < 15) {
    Weischranketime = millis();
    min30 = min30 + 1;
    minuteswei = minuteswei - 1;
  } else if(minuteswei >= 1 && min45 < 15) {
    Weischranketime = millis();
    min45 = min45 + 1;
    minuteswei = minuteswei - 1;
  } else if(minuteswei >= 1 && min60 < 15) {
    Weischranketime = millis();
    min60 = min60 + 1;
    minuteswei = minuteswei - 1;
  }


}

/////////MUFW03
void Fastlagerweiche() {
  if(schiesswei == 1) {
    Balkenwei = 0;
    schiesswei = 0;
    uhrwei = uhrwei - 1;      //muss hier auch gemacht werden, weil somit garantiert wird, dass nur Uhrkugeln geschossen werden können
  } else if(uhrwei >= 1) {
    uhrwei = uhrwei - 1;
  } else if(fastdoswei >= 1) {
    fastdoswei = fastdoswei - 1;
  }

}

//////////MUDO04
void loslassen() {
  double pulselength = map(120, 0, 180, SERVOMIN, SERVOMAX);
  pwm.setPWM(0, 0, pulselength);
}
void zumachen() {
  double pulselength = map(60, 0, 180, SERVOMIN, SERVOMAX);
  pwm.setPWM(0, 0, pulselength);
}

void fastloslassen() {
  double pulselength = map(110, 0, 180, SERVOMIN, SERVOMAX);
  pwm.setPWM(1, 0, pulselength);
}

void fastzumachen() {
  double pulselength = map(40, 0, 180, SERVOMIN, SERVOMAX);
  pwm.setPWM(1, 0, pulselength);
}

//////////MUSU02
void Servo9los(){
  double pulselength = map(60, 0, 180, SERVOMIN, SERVOMAX);
  pwm.setPWM(9, 0, pulselength);
}

void Servo9zu(){
  double pulselength = map(150, 0, 180, SERVOMIN, SERVOMAX);
  pwm.setPWM(9, 0, pulselength);
}


//////////MUNA
void notaufzug() {
  notaufa = 1;
}

//////////MUAN02
void anzeige() {
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(SSD1306_WHITE);
  display.drawLine(0, 25, 128, 25, SSD1306_WHITE);
  display.drawLine(0, 45, 128, 45, SSD1306_WHITE);
  display.drawLine(60, 45, 60, 80, SSD1306_WHITE);
  display.drawLine(60, 0, 60, 25, SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println(daysOfTheWeek[timeClient.getDay()]);
  display.setCursor(0, 28);
  display.print(timeClient.getHours());
  display.print(":");
  display.print(timeClient.getMinutes());
  display.print(":");
  display.println(timeClient.getSeconds());
  display.setCursor(65, 0);
  display.print(fastdoswei);
  display.setCursor(100, 0);
  display.print(uhrwei);
  display.setCursor(0, 50);
  display.print(hoursdiff);
  display.setCursor(35, 50);
  display.print(minutesdiff);
  display.setCursor(65, 50);
  display.print(hourswei);
  display.setCursor(100, 50);
  display.print(minuteswei);
  display.display();
}

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert