Session 2 - Ampelschaltung mit Taster und Interrupt




/* Programm zum Ansteuern einer T-Kreuzung mit drei Fahrzeugampeln Ampeln und zweier gekoppelter Fussgaengerampeln.
 * Durch ein Druecken des Tasters werden zunaechst die Fussgaengerampeln auf rot geschaltet. Nach einer vollstaendigen
 * Ampelperiode werden die Fahrzeugampeln auf rot und die Fussgaengerampeln auf gruen geschaltet. Dieser Zustand wird
 * fuer drei Sekunden gehalten, ehe der normale Ablauf wieder startet.
 *
 *  Pinbelegung:
 *  D0:        rote LED von Ampel 1
 *  D1:        gelbe LED von Ampel 1
 *  D2:        gruene LED von Ampel 1
 *  D4:        rote LED von Ampel 2
 *  D5:        gelbe LED von Ampel 2
 *  D6:        gruene LED von Ampel 2
 *  D7:        rote LED von Ampel 3
 *  D8:        gelbe LED von Ampel 3
 *  D9:        gruene LED von Ampel 3
 *  D11:       rote LED von Fussgaengerampel 1
 *  D10:       gruene LED von Fussgaengerampel 1
 *  D13:       rote LED von Fussgaengerampel 2
 *  D12:       gruene LED von Fussgaengerampel 2
 *  D3:        Taster
 *
 * Skizze des Layouts:
 *
 *             1 =     =
 *             | =     =  F1
 *             v =     =  v  <-3
 * ===============     ===============
 *                        -
 *                        -
 * ===================================
 *             2->        ^
 *                        F2
 *
 * 1, 2, 3: Ampeln für Fahrzeuge
 * F1, F2: Fussgaengerampeln (werden identisch geschaltet)
 */



int ampel1_rot   = 0;  // Pin 3 des Arduino wird zur Ansteuerung der roten LED der 1. Ampel verwendet
int ampel1_gelb  = 1;  // Pin 4 des Arduino wird zur Ansteuerung der gelben LED der 1. Ampel verwendet
int ampel1_gruen = 2;  // Pin 5 des Arduino wird zur Ansteuerung der gruenen LED der 1. Ampel verwendet

int ampel2_rot   = 4;  // Pin 3 des Arduino wird zur Ansteuerung der roten LED der 2. Ampel verwendet
int ampel2_gelb  = 5;  // Pin 4 des Arduino wird zur Ansteuerung der gelben LED der 2. Ampel verwendet
int ampel2_gruen = 6;  // Pin 5 des Arduino wird zur Ansteuerung der gruenen LED der 2. Ampel verwendet

int ampel3_rot   = 7;  // Pin 3 des Arduino wird zur Ansteuerung der roten LED der 3. Ampel verwendet
int ampel3_gelb  = 8;  // Pin 4 des Arduino wird zur Ansteuerung der gelben LED der 3. Ampel verwendet
int ampel3_gruen = 9;  // Pin 5 des Arduino wird zur Ansteuerung der gruenen LED der 3. Ampel verwendet

int fussgaenger1_rot = 11;    // Pin 3 des Arduino wird zur Ansteuerung der roten LED der Fussgängerampel 1 verwendet
int fussgaenger1_gruen = 10;  // Pin 4 des Arduino wird zur Ansteuerung der gruenen LED der Fussgängerampel 1 verwendet
int fussgaenger2_rot = 13;    // Pin 3 des Arduino wird zur Ansteuerung der roten LED der Fussgängerampel 2 verwendet
int fussgaenger2_gruen = 12;  // Pin 4 des Arduino wird zur Ansteuerung der gruenen LED der Fussgängerampel 2 verwendet

int fussgaenger_taster = 3;  // Pin 3 des Arduino wird zum Auslesen des Tasters verwendet; muss an einem Interrupt (INTX)-Pin haengen!

volatile int fussgaengerFlag = 0; // Zeigt an, ob ein Fussgaenger die Strasse ueberqueren will
                                  // volatile bedeutet, dass die Variable ihren Wert zwischen zwei Aufrufen den Wert veraendern kann.
                                  // Damit wird durch den Optimierer kein Aufruf darauf "wegoptimiert".


void fussgaenger()
{               // Die fussgaenger()-Funktion wird bei einem Druck des Tasters aufgerufen
  // Wird bereits ein Fussgaenger ueber die Strasse gelassen?
  if( fussgaengerFlag == 2 )
    return;

  // Schalte beide Fussgaengerampeln auf rot
  digitalWrite(fussgaenger1_rot, HIGH);
  digitalWrite(fussgaenger2_rot, HIGH);
  // Signalisiere der loop()-Funktion, dass ein Fussgaenger die Strasse ueberqueren will
  fussgaengerFlag = 1;
}


void setup()
{               // Die setup()-Funktion wird einmal durchlaufen und dient der Initialsierung
  // definiere alle Pins fuer die Ampeln als OUTPUT
  pinMode(ampel1_rot, OUTPUT);
  pinMode(ampel1_gelb, OUTPUT);
  pinMode(ampel1_gruen, OUTPUT);
  pinMode(ampel2_rot, OUTPUT);
  pinMode(ampel2_gelb, OUTPUT);
  pinMode(ampel2_gruen, OUTPUT);
  pinMode(ampel3_rot, OUTPUT);
  pinMode(ampel3_gelb, OUTPUT);
  pinMode(ampel3_gruen, OUTPUT);
  pinMode(fussgaenger1_rot, OUTPUT);
  pinMode(fussgaenger1_gruen, OUTPUT); 
  pinMode(fussgaenger2_rot, OUTPUT);
  pinMode(fussgaenger2_gruen, OUTPUT);
  
  // definiere den Pin fuer den Taster als INPUT
  pinMode(fussgaenger_taster, INPUT);

  // erstelle einen Interrupt fuer den Fussgaengertaster
  attachInterrupt(0, fussgaenger, FALLING);
}

void loop()
{               // Die loop()-Funktion wird wiederholt durchlaufen

  // Test auf Fussgaenger
  if( fussgaengerFlag == 1 )
  {
    // Merken, dass derzeit die Fussgaengerampeln auf gruen geschaltet sind, damit bei einem erneuten Druecken
    // die Fussgaengerampeln kein zweites mal aktiviert werden
    fussgaengerFlag = 2;
    
    // Alle Fahrzeugampeln auf rot schalten
    digitalWrite(ampel1_rot, HIGH);
    digitalWrite(ampel2_rot, HIGH);
    digitalWrite(ampel3_rot, HIGH);
    
    // Beide Fussgaengerampeln auf gruen
    digitalWrite(fussgaenger1_gruen, HIGH);
    digitalWrite(fussgaenger2_gruen, HIGH);
    digitalWrite(fussgaenger1_rot, LOW);
    digitalWrite(fussgaenger2_rot, LOW);    
    
    // Zustand fuer drei Sekunden halten
    delay(3000);

    // Fussgaengerampeln auf rot schalten
    digitalWrite(fussgaenger1_gruen, LOW);
    digitalWrite(fussgaenger2_gruen, LOW);
    digitalWrite(fussgaenger1_rot, HIGH);
    digitalWrite(fussgaenger2_rot, HIGH);

    // Rote Lichter der Fahrzeugampeln ausschalten
    digitalWrite(ampel1_rot, LOW);
    digitalWrite(ampel2_rot, LOW);
    digitalWrite(ampel3_rot, LOW);

    // Neuen Fussgaenger zulassen
    fussgaengerFlag = 0;
  }

  // Durchgangsstrasse wird gelb
  digitalWrite(ampel1_rot, HIGH);
  digitalWrite(ampel2_rot, HIGH);
  digitalWrite(ampel3_rot, HIGH);
  digitalWrite(ampel2_gelb, HIGH);
  digitalWrite(ampel3_gelb, HIGH);
  delay(1000);

  // Durchgangsstrasse hat fuer drei Sekunden gruen
  digitalWrite(ampel2_rot, LOW);
  digitalWrite(ampel3_rot, LOW);
  digitalWrite(ampel2_gelb, LOW);
  digitalWrite(ampel3_gelb, LOW);
  digitalWrite(ampel2_gruen, HIGH);
  digitalWrite(ampel3_gruen, HIGH);
  delay(3000);

  // Durchgangsstrasse fuer eine Sekunde auf gelb schalten; Fussgaengerampeln deaktivieren, wenn zuvor einer ruebergelassen wurde
  digitalWrite(ampel2_gruen, LOW);
  digitalWrite(ampel3_gruen, LOW);
  digitalWrite(ampel2_gelb, HIGH);
  digitalWrite(ampel3_gelb, HIGH);
  if( fussgaengerFlag == 0 )
  {
    digitalWrite(fussgaenger1_rot, LOW);
    digitalWrite(fussgaenger2_rot, LOW);
  }
  delay(1000);

  // Durchgangsstrasse hat rot
  digitalWrite(ampel2_rot, HIGH);
  digitalWrite(ampel3_rot, HIGH);
  delay(1000);

  // Abzweigestrasse auf gelb-rot
  digitalWrite(ampel1_gelb, HIGH);
  delay(1000);

  // Abzweigestrasse hat fuer drei Sekunden gruen
  digitalWrite(ampel1_rot, LOW);
  digitalWrite(ampel1_gelb, LOW);
  digitalWrite(ampel1_gruen, HIGH);
  delay(3000);

  // Abzweiugestrasse wird gelb
  digitalWrite(ampel1_gruen, LOW);
  digitalWrite(ampel1_gelb, HIGH);
  delay(1000);

  // Abzweigestrasse wird rot
  digitalWrite(ampel1_gelb, LOW);
  digitalWrite(ampel1_rot, HIGH);
  delay(1000);
}