
//Als erstes werden die Konstanten und Variablen festgelegt bzw. initialisiert:
//Die Konstanten sind nun die entsprechenden Pins im Arduino
const int Halterung = 2;          // An Pin 2 wird der Kugelhalter angeschlossen 
const int Lichtschranke1 = 3;     // An Pin 3 wird der erste IR-Sensor angeschlossen
const int Lichtschranke2 = 4;     // An Pin 4 wird der zweite IR-Sensor angeschlossen
const int Schalter1 = 8;          // An Pin 8 wird der erste Schalter angeschlossen
const int Schalter2 = 9;          // An Pin 9 wird der zweite Schalter angeschlossen

//Variablen ändern sich während dem Durchlaufen, diese müssen zunächst 0 gesetzt werden
int HalterungStatus = 0;         // Liest den Zustand des Kugelhalters aus und schreibt ihn in eine Variable
int LichtschrankenStatus = 0;    // Liest den Zustand der Lichtschranke aus und schreibt ihn in eine Variable
int Schalter1Status = 0; 
int Schalter2Status = 0; 
//Hier werden die Variablen definiert die sich während des Versuchs ändern (unsigned (-positive) long, da große 32-Bit Werte gemessen werden)
unsigned long Startzeit ;                   // Speichert den Wert in ms wann der Haltemagnet gelöst wurde 
unsigned long Lichtschrankenzeit1 ;         // Speichert den Wert in ms wann die Lichtschranke 01 ausgelöst wurde  
unsigned long Lichtschrankenzeit2 ;         // Speichert den Wert in ms wann die Lichtschranke 02 ausgelöst wurde 
unsigned long Zeitdifferenz = 0 ;           // Speichert die Zeitdifferenz der beiden Lichtschranken in ms 


//Hier wird der letzte Status der Sensoren eingetragen um eine Zustandsänderung messen zu können
int vorherigerHalterungStatus = 0;             // Speichert den letzten Zustand des Halterungs und schreibt ihn in eine Variable
int vorherigerLichtschrankenStatus = 0;        // Speichert den letzten Zustand der Lichtschranke und schreibt ihn in eine Variable
int vorherigerSchalter1Status = 0;             // Speichert den letzten Zustand des Schalter1 und schreibt ihn in eine Variable
int vorherigerSchalter2Status = 0;             // Speichert den letzten Zustand des Schalter2 und schreibt ihn in eine Variable


//Damit wird das OLED-Display eingerichtet, #include bedeutet, dass eine Bibliothek verwendet wird, die man vorher herunterladen muss.
#include <Wire.h>
#include "SSD1306Ascii.h"                     //Mit dieser Bibliothek steuert man das OLED-Display an https://www.arduino.cc/reference/en/libraries/ssd1306ascii/
//Hinweis: Diese Bibliothek verwendet nur wenig Arbeitsspeicher, deutlich schönere Darstellungen
// z.B. kein Flackern erhält man mit der Bibliothek #include <U8g2lib.h> https://www.arduino.cc/reference/en/libraries/u8g2/
// Allerdings ist U8g2lib.h für den Arduino Uno mit viel Code zu groß
#include "SSD1306AsciiWire.h"
#define I2C_ADDRESS 0x3C
SSD1306AsciiWire oled;


// Im setup werden die entsprechenden Pins als OUTPUT oder INPUT festgelegt:
void setup() {  
  Serial.begin(9600);                    // Startet die Serielle Kommunikation
  pinMode(Halterung, INPUT);             // Setzt den Pin des Kugelhalters als Eingang
  pinMode(Lichtschranke1, INPUT);        // Setzt den Pin der Lichtschranke1 als Eingang
  pinMode(Lichtschranke2, INPUT);        // Setzt den Pin der Lichtschranke2 als Eingang
  pinMode(Schalter1, INPUT);             // Setzt den Pin des Schalter1 als Eingang
  pinMode(Schalter2, INPUT);             // Setzt den Pin der Schalter2 als Eingang
  
  Serial.println("Bereit zur Messung");  // Schreibt den Text "Bereit" um zu signalisieren, dass der Arduino Hochgefahren ist
  
//Damit wird das OLED-Display gestartet
Wire.begin();
  Wire.setClock(400000L);
  oled.begin(&Adafruit128x64, I2C_ADDRESS);
  oled.setFont(Arial_bold_14);
  oled.println("Bereit zur Messung");
   
}

// Im loop findet die Messung statt:
  
void loop() {

  oled.setFont(Arial_bold_14); // Auswahl der Schriftart
  //Andere Schriftarten findet man in unter Datei-Beispiele-SSD1306Asci1-FontSamplesWire
  //andere Schriftarten der Größe nach geornet: System5x7; TimesNewRoman16 ;TimesNewRoman16_bold; TimesNewRoman16_italic; Arial14; 
Schalter1Status = digitalRead(Schalter1);
Schalter2Status = digitalRead(Schalter2);

  //Hier wird das jeweilige Programm ausgewählt

 if ((Schalter1Status == HIGH && Schalter2Status == HIGH)){          //1.Begrüßungstext
  Serial.println("Modus 1");
  Serial.println("Begrüßungstext");
  Serial.println();
     oled.clear();
     oled.println("Aufgabe 1 ist");
     oled.println("geschafft! ");
     oled.setFont(Arial14);
     oled.println("Fragt bitte bei ");
     oled.print(" Unklarheiten!    ;-) ");
     
 delay(2000);
   
  }
else if ((Schalter1Status == HIGH && Schalter2Status== LOW)){   //2.Pendelzeitmessung
  
  // 2.1 Arduino misst den Status der Lichtschranke1
  
  LichtschrankenStatus = digitalRead(Lichtschranke1);

  // 2.2 Erkennt er, dass die Halterung sich öffnet, dann notiert er die Startzeit:  
  
  if (LichtschrankenStatus == HIGH && vorherigerLichtschrankenStatus == LOW) {
    oled.clear();
    oled.println("Schwingungsdauer");
     
 Lichtschrankenzeit1 = millis(); 
 Zeitdifferenz = Lichtschrankenzeit1 - Startzeit;
    Startzeit = Lichtschrankenzeit1;   //Ändert den letzten Zustand der Lichtschranke um die Schleife zu verlassen.

     oled.clear();
     oled.println("Schwingungsdauer");
     oled.setFont(Arial14);
     oled.println(" ");
     oled.println("Pendelzeit");
     oled.setFont(Arial_bold_14);
     oled.print("T = ");
     oled.print(Zeitdifferenz);
     oled.println(" ms");

    Serial.println("Modus 2");
    Serial.println("Pendelzeitmessung:");
    Serial.println();
    Serial.print("Schwingungsdauer T = "); 
    Serial.print(Zeitdifferenz); 
    Serial.println(" ms");
    Serial.println();
 
  } 
delay(1);
vorherigerLichtschrankenStatus = LichtschrankenStatus;
 }
else if ((Schalter1Status == LOW && Schalter2Status == HIGH)){
  
  // 3.1 Arduino misst den Status von Lichtschranke und Halterung
  
  HalterungStatus = digitalRead(Halterung);
  LichtschrankenStatus = digitalRead(Lichtschranke2);

  // 3.2 Erkennt er, dass die Halterung sich öffnet, dann notiert er die Startzeit:  
  
  if (HalterungStatus == LOW && vorherigerHalterungStatus== HIGH) {
   Startzeit = millis(); 
   vorherigerHalterungStatus = HalterungStatus;   // Ändert den letzten Zustand der Halterung um die Schleife zu verlassen.
    
     oled.clear();
     oled.println("Fallzeitmessung");
     oled.setFont(Arial14);
     oled.println("Bereit zur Messung");
     oled.println("Start");
  } 

  // 3.3 Erkennt er, dass die Lichtschranke verdunkelt ist, wenn vorher die Messung gestartet wurde, so zeigt er die Zeitdifferenz an
else if (LichtschrankenStatus == LOW && vorherigerLichtschrankenStatus == HIGH){ 
  Zeitdifferenz   = millis()- Startzeit;   
    Serial.println("Modus 3");
    Serial.println("Fallzeitmessung:");
    Serial.println();
    Serial.print("Fallzeit t = ");
    Serial.print(Zeitdifferenz);
    Serial.println("ms");
    Serial.println();
    
 vorherigerLichtschrankenStatus = LichtschrankenStatus;    // Ändert den letzten Zustand des Halterungs um die Schleife zu verlassen.
oled.clear();
     oled.println("Fallzeitmessung");
     oled.setFont(Arial14);
     oled.println("Bereit zur Messung");
     oled.println("Start");
     oled.setFont(Arial_bold_14);
     oled.println("");
     oled.print("Fallzeit t = ");
     oled.print(Zeitdifferenz);
     oled.print(" ms");
    
}
// 3.4 Falls keiner der obigen Fälle auftritt, so macht er sich für eine Messung bereit indem er die Variablen zurücksetzt
else{
    vorherigerHalterungStatus = HalterungStatus;                // Ändert den letzten Zustand der Halterung
    vorherigerLichtschrankenStatus = LichtschrankenStatus;      // Ändert den letzten Zustand der Lichtschranke  
   } 
 } 
else if ((Schalter1Status == LOW && Schalter2Status== LOW)){         //4.Momentangeschwindigkeitsmessung

     while (digitalRead(Lichtschranke1) == HIGH) { };
  Lichtschrankenzeit1 = millis();               // misst die interne Zeit der Lichtschranke 1
 
  while (digitalRead(Lichtschranke2) == HIGH) { };
  Lichtschrankenzeit2 = millis();                 // misst die interne Zeit der Lichtschranke 1

Zeitdifferenz = Lichtschrankenzeit2 - Lichtschrankenzeit1; // Zeitdifferenz zwischen den Lichtschranken
    
float geschwindigkeit = 40/(float)Zeitdifferenz;
    
    Serial.println("Modus 4");
    Serial.println("Momentangeschwindigkeitsmessung:");
    Serial.println();
    
oled.clear();
   oled.println("Geschwindigkeits-");
   oled.println("messung");
   oled.setFont(Arial14);
   oled.println("Start");
 
    Serial.print("Zeitdifferenz t =  ");
    Serial.print(Zeitdifferenz);
    Serial.println("  ms");
    Serial.print("Momentangeschwindigkeit v =  ");
    Serial.print(geschwindigkeit,4);
    Serial.println("  m/s");
    Serial.println();
    
   oled.clear();
    oled.setFont(Arial14);
    oled.println("Zeitdifferenz");
    oled.setFont(Arial_bold_14);
    oled.print("t = ");
    oled.print(Zeitdifferenz);
    oled.println(" ms");
    oled.setFont(Arial14);
    oled.println("Momentangeschw.");
    oled.setFont(Arial_bold_14);
    oled.print("v = ");
    oled.print(geschwindigkeit,4);
    oled.println("  m/s");

 
  }
}
