Montag, 15. Juli 2013

Fotomarathon - die Ausstellung - der Gewinner - der Rant

Dieses Posting ist ein zu lang gewordener Kommentar meinerseits zu diesen Blog Post von "BerlinMetropolis". Es macht also viel Sinn erst dort zu lesen. ;)

Also eins Vorweg, ich finde die Fotos von Platz 1 auch sch... und es ist ja auch zu sehen, dass er die 12 Themen noch gar nicht alle hatte. (EXIF sagt 19 Uhr) Ein Motiv, 12x in Serie (na gut Bild 1 halt die Karten drin, Bild 2 den Wachmann (<- der ist imo aber Zufall), der Rest in Serie.)

Warst du bei der Preisverleihung direkt da? Hast du gehört, was Platz 1 gesagt hat zu seinen Fotos? :D Er meinte die Idee ist ihm im letzten Jahr gekommen, es sei ein Experiment gewesen und er wollte sehen ob er es durchhält(??). Die Erklärung war schon super. ;) Ich kenne die Gewinner vom letzten Jahr nicht, aber vielleicht gefiehlen sie ihm ja auch "so gut", dass er sich dachte, ey so einen Mist kann ich auch! ;) Wer weiß..

Ich war jetzt das dritte mal dabei, beim ersten mal haben wir (mein Team + ich) 24 Fotos zu den jeweiligen Themen gemacht. Auf den roten Faden haben wir nicht wirklich geachtet... aber es hat Spaß gemacht. Beim zweiten mal, hatte wir uns euf einen roten Faden geeinigt, die Idee ansich war super - aber sie war so schwer umzusetzen, dass sie letztendlich scheiterte und ich das zu spät einsah - also nicht ins Ziel gekommen. Dieses Jahr konnten wir uns nach einigem hin und her auf einen "roten Faden" einigen, wobei "was für eine Überraschung" echt eine harte Nuss war... und wenn ich die anderen Foto Ideen so sah, muss ich sagen, vielen ging es wohl ähnlich - jedenfalls thematisch / roter Faden technisch.
Der Gewinner bei meinem ersten FM (Hauptthema: XY Ungelöst) hatte ein Flatterband auf jedem Bild. Das Flatterband war der "Rote Faden". Somit konnte er die restlichen 24 Fotos relativ einfach konstruieren. Und während Andere sich bei Themen wie "Mr. X" einen abgebrochen haben, hat er einfach mit dem Flatterband ein X gemacht, fertig. Ich fand das damals eher blöd, aber je länger ich mir die Bilder ansah, desto genialer fand ich die Idee. Die 24 Stück waren ansich super simpel, aber eine Serie. Passend. Und das Flatterband... passt zum Überthema. Ausserdem waren sie von der Belichtung / Schärfe / Farben super. Fazit: ich / wir hatten diese Idee nicht, wir haben uns tlw. echt die Haare gerauft was wir foten sollen... und er hatte da immer sein olles Flatterband. Im Nachhinein muss ich sagen, verdient gewonnen.

Hier ist unser Beitrag zum FM 2008. Die 24 kleinen Themen stehen immer unter dem Thumbnailblock. http://real-dark.de/gallery/albums/marathon08/

Ich bezweifle allerdings, dass ich das später - rückblickend -  auch über den Gewinner 2013 sagen werde. Aber was solls? Das ist eben "Kunst". Allein das wir beide so lange Texte drüber schreiben zeigt, dass er irgendetwas richtig gemacht hat. ;)

Und ich ärger mich auch ganz sicher nicht über mein bezahltes Geld. Oder die investierte Zeit. Wozu auch? Ich habe das Geld bezahlt, damit ich Teilnehmen kann, damit das Team seine Arbeit machen kann damit evt. Kosten - welche nicht von den Sponsoren gedeckt werden - von uns gedeckt werden. Ich habe nicht bezahlt um einen ersten Gewinner zu sehen, der mich glücklich macht. Und ich habe ganz sicher nicht teilgenommen, um einen Gewinner zu sehen, der mich Glücklick macht. - Außer natürlich - wir wären es gewesen. Dann wäre es ein netter Zufall und ich / wir wären glücklich. ;)

Der FM soll Spaß machen. Es geht (für mich) eher um den Tag des FMs. Klar würde ich auch gerne gewinnen, der Ehrgeiz packt uns jedes mal wieder - aber dieses Jahr hat es mir gereicht zu sehen, dass mir unsere Serie - im Vergleich zu den anderen - auch sehr gut gefällt. Obwohl ich am Anfang alles andere als Glücklich mit ihr war. Gefällt mir der Gewinner? Nein. Mir gefiel auch nicht, wie die Jury tlw. überhaupt nichts weiter zu den Bildern gesagt hat. "Also hier die Farben sind schön, *kicher kicher*, oh ich kann meine eigene Schrift gar nicht lesen *hihi*". Aber so ist der FM irgendwie? Das abholen der Startnummern ist ja schon immer ein Chaos für sich - jedes mal.

Wir sind nächstes Jahr also sicher wieder dabei. Und genauso wie der Gewinner in diesem Jahr, haben wir auch schon eine super Idee für den FM im nächsten! Ich bin gespannt ob wir dieses Experiment durchhalten! *feix*

Ehrenamtlich würde ich da aber auch nichts machen - viel zu chaotisch! ;)

PS: Ich fand die Aufmachung der Ausstellung  (also den teil der TU) übrigens nicht sehr prickelnd. 14 Tage Konzept, dafür? Najaaaa.... und oben bei den Gewinnerfotos, gab es nichtmal Licht. Nur die giftgrünen Funzeln. Hmm... das geht besser... Masterstudiengang? ... eieiei (sollten die Gewinnerfotos erst im letzten Moment dort hoch gekommen sein (hallo Chaosteam!) und das war so gar nicht im Konzept vorgesehen, habe ich nichts gesagt...)

Samstag, 22. Juni 2013

Fotomarathon 2013

Wieder einmal fand in Berlin ein Fotomarathon statt. Das 13. mal hier und zum 3. mal mit uns. Nach dem Desaster des letzten, hatten wir uns vorgenommen, es diesmal alles "ganz locker" anzugehen. Erst einmal entspannt die ersten Themen holen und dann schön Frühstücken. Dieser Teil des Plans klappte soweit auch, aber lange hielt die Entspannung nicht an, denn schon bald packte uns wieder der Ehrgeiz im Nacken und steckte uns in eine Kiste Stress. Drei Persönlichkeiten - drei Meinungen. Und oft nicht die Meinung des Anderen. Was sich anhört wie ein kreativer Pool voll bunter Farbe, erwies sich sich stellenweise als zähe Masse aus der man einfach keine einstimmige Meinung ziehen konnte. Wie baut man das Hauptthema in alle 12 Bilder? Wie setzt man die 12 Einzelthemem um, ohne sie komplett zu konstruieren (da waren wir uns alle einig, dass wir das nicht wollen ;) ). Was ist eine gute Idee für jedes Einzelthema, aber nicht so "gut" das sie jeder hat. etc. etc.. Am Ende kamen wir - im Gegensatz zum letzten mal - immerhin ins Ziel. :D

Das Überthema lautete "So eine Überraschung...". Nach einigem Ringen und mehr oder weniger guten Einfällen, einigten wir uns darauf, durch Berlins bunte Straßen zu ziehen und uns davon überaschen zu lassen, was wir so an Schildern, Schriftzügen, Plakaten, Aufklebern und Symbolen finden können. Da bietet Berlin ja doch einiges an schrägen Ecken, man muss sie nur finden .. oder wie in diesem Jahr, sich von ihnen überraschen lassen. ;) Es ist jetzt zwar schon eine Woche her, aber ich möchte euch die Bilder trotzdem nicht vorenthalten.

Los gehts: "So eine Überraschung..."
(die 12 Themen sind frei aus meiner Erinnerung ;) )


1. Eintauchen



2. Irrwege


3. Ausgetrickst


4. Hauptgewinn


5. Wie gewonnen so zerronnen


6. Verschwommen


7. Das Schicksal nimmt seinen Lauf


8. Froschkönig


 9. Verzaubern


10. Halbwelten


11. Verflucht


12. Abtauchen
 

Freitag, 31. Mai 2013

Been there, done that. Try again.

Hallo,
Herzlich Willkommen zum 13. Fotomarathon Berlin!

Wir haben für Dich einen Platz im Startfeld bestätigt. Deine Anmeldung ist bestätigt und es kann los gehen.

Montag, 20. Mai 2013

Lange While?

Mein Arduino Code zur Ampelschaltung war, wie ich schon erwähnte, nicht der Eleganteste. Zu allem Überfluss war er sogar fehlerhaft. ;)

Als ich den Code säuberte und passende Stellen zu einer While-Schleife umbaute, fiel mir auf, dass die Logik nicht ganze passte. Die Abfrage der verstrichenen Zeit grenzte die einzelnen Ampelphasen überhaupt nicht eindeutig ab.

Die überprüfung der Phase fand nur mit einer "ist die Differenz von millis() - Zeitstempel größer als Pause?" statt. Und im nächsten Fall: "ist die Differenz von millis() - Zeitstempel größer als Pause + Pause?" Hier schlägt nun wieder einmal die Endlosschleife zu, denn wenn:

"ist die Differenz von millis() - Zeitstempel größer als Pause + Pause?"

 zutrifft, dann trifft natürlich auch die vorherige Phase zu:

"ist die Differenz von millis() - Zeitstempel größer als Pause?"

es werden also nochmal beide Phasen ausgeführt. Durch die Trägheit der LEDs war das aber nicht wirklich zu sehen. Die LEDs wirkten zwar als wäre sie aus aber die "glimmten" noch ein bisschen. ;)

Meine Logik damit das verhindert wird ist jetzt:

"ist die Differenz von millis() - Zeitstempel größer als Pause?" UND "ist die Differenz von millis() - Zeitstempel kleiner als Pause + Pause?"

Jetzt glimmt nix mehr!

Bitteschön:

/*

Ampel mit While

 */

// reichen da nicht bytes? oO
byte red = 9; // Verkehrsampel Rot
byte yel = 8; // Verkehrsampel Gelb
byte gre = 7; // Verkehrsampel Grün
byte sig = 5; // "Signal kommt" liefert dem Fußgänger zurück, ob er gedrückt hat oder nicht.
byte wred = 3; // Fußgängerampel Rot
byte wgre = 2; // Fußgängerampel Grün
byte but = 6; // Button Pin
byte safe = 0; // war butr für buttonread

// Pausen
int pred = 3000; // 3 Sekunden Rot
int pyel = 1000 ; // 1 Sekunde Gelb
int pgre = 5000; // 5 Sekunden Grün
int psafety = 1000; // Puffer für Fußgänger, bis Verkehrsampel wieder auf grün springt
unsigned long time;

// the setup routine runs once when you press reset:
void setup() {
  // die pins als output.
  pinMode(red, OUTPUT);
  pinMode(yel, OUTPUT);
  pinMode(gre, OUTPUT);
  pinMode(sig, OUTPUT);
  pinMode(wred, OUTPUT);
  pinMode(wgre, OUTPUT);
  pinMode(but, INPUT);
  time = millis(); // einmal die aktuelle Zeit festlegen
  digitalWrite(red, HIGH); // erstmal alles schön auf Rot
  digitalWrite(wred, HIGH); // erstmal alles schön auf Rot
}

// the loop routine runs over and over again forever:
void loop() {

   /* 
   Wenn der Button etwas anderes als 0 zurück gibt hat
   ihn wohl jemand gedrückt. Wenn das so ist, setze
   safe auf 1 und schalte die "Signal kommt" LED an.
   */
   
if(digitalRead(but) != 0)
{
  safe=1;
  digitalWrite(sig,HIGH);
}

   /*
   Solange wie safe kleiner oder gleich 1 ist,
   läuft die Verkehrsampel.
   */

while (safe <= 1)
    {
     digitalWrite(wred, HIGH); // Fußgängerampel auf Rot und bleibt auch so
     
     /*
     Nun vergleichen wir immer Schritt für Schritt, ob die abgelaufene Zeit
     GRÖßER ist als für diese Phase vorgesehen ABER AUCH ob sie bis jetzt
     noch UNTER der Zeit der übernächste Phase liegt.
     */
     
     if (millis() - time > pred && millis() - time < pred + pyel)digitalWrite(yel,HIGH); // LÄNGER als Pause Rot aber KÜRZER als Pause Rot + Pause Gelb? -> schalte Gelb dazu.
     if (millis() - time > pred + pyel && millis() - time < pred + pyel + pgre)  // LÄNGER als Pause Rot + Pause Gelb aber KÜRZER als Pause Rot + Pause Gelb + Pause Grün?
     {
      digitalWrite(red,LOW); // schalte Rot aus
      digitalWrite(yel,LOW); // schalte Gelb aus
      digitalWrite(gre,HIGH); // schalte Grün an
     }
     if (millis() - time > pred + pyel + pgre && millis() - time < pred + pyel + pgre + pyel) // LÄNGER als Pause Rot + Pause Gelb + Pause Grün aber KÜRZER als Pause Rot + Pause Gelb + Pause Grün + Pause Gelb
     {
      digitalWrite(gre,LOW); // schalte Grün aus
      digitalWrite(yel,HIGH); // schalte Gelb an
     }
     if (millis() - time > pred + pyel + pgre + pyel) // Hier prüfen wir nur noch obs länger ist als... denn die Anderen schließen sich ja schon vorher aus.
     {
      digitalWrite(yel,LOW); // schalte Gelb aus
      time = millis(); // Zeit reseten
      digitalWrite(red,HIGH); // schalte Rot an
      if (safe == 1)safe++; // Falls jemand den Knopf gedrückt hatte und safe damit auf 1 steht, ist es Zeit zur Fußgänger Schleife zu springen. Dazu erhöhren wir safe um 1 also auf 2.
     }
    break; // raus aus der while Schleife
    }

while (safe == 2) // wenn der Knopf gedrückt wurde (safe = 1) UND der Verkehr einmal durchlief (safe = 1 + 1) dann mache...
    {
      digitalWrite(red, HIGH); // Verkehrsampel auf Rot.. sollte sie zwar schon, aber doppelt hält besser. Geht ja schließlich um die Sicherheit ;)
      if (millis() - time > psafety && millis() - time < psafety + pgre) // LÄNGER als Sicherheitspuffer aber KÜRZER als Sicherheitspuffer + Pause Grün?
      {                                      // falls dem so ist...
        digitalWrite(wred,LOW); // Fußgänger Rot aus
        digitalWrite(sig,LOW); // "Signal kommt" aus
        digitalWrite(wgre,HIGH); // Fußgänger Grün an
      }
      if (millis() - time > psafety + pgre && millis() - time < psafety + pgre + psafety) // LÄNGER als Sicherheitspuffer + Pause Grün aber KÜRZER als Sicherheitspuffer + Pause Grün + Sicherheitspuffer?
      {                                    // falls ja
        digitalWrite(wgre,LOW); // Fußgänger Grün aus
        digitalWrite(wred,HIGH); // Fußgänger Rot an
      }
      if (millis() - time > psafety + pgre + psafety) // Wenn wieder Rot ist, warte noch die Safety Zeit ab (Safety + Grünphase + Safety)
        {
         time = millis(); // Und resete die Zeit, damit es von vorn los gehen kann
         safe = 0; // Setzte Safe auf 0 damit wieder mind. 1x der Vekehr läuft
        }
        break; // raus aus der Schleife
  }
delay(1); // kleine Pause gg. Überlastung
}

Sonntag, 19. Mai 2013

Smile

 
Posted by Picasa

Eigentlich...

Eigentlich ist ein tolles Wort. Eigentlich lässt mich über so viele Dinge reden, die ich eigentlich gar nicht gemacht habe. Ein Beispiel?

Was habe ich heute gemacht? Ausgeschlafen, zu Marlen und Sascha gegangen, Katzen gehütet und mit meinem Arduino gespielt. Eine Ampelschaltung. Fertig.

Kurz.

Eigentlich könnte das alles viel länger sein. Denn eigentlich wollte ich an diesem verlängerten Pfingstwochenende ein defektes Apfelbook reparieren. Eigentlich sollte es diese Woche eintreffen. Scheinbar (auch ein tolles Wort) gibt es hier jedoch ein paar Verzögerungen. Da macht auch überhaupt nichts, eigentlich. Denn eigentlich war ich heute sowieso im Volkspark FHain verabredet. Inliner fahren. Nun hat es aber geregnet und im Regen ist es so richtig schlecht mit Inlinern. Eigentlich hatte ich also scheinbar nichts zu tun (Doublekill!).

Aber ich hab ja noch mein Arduino und seit ich ein Buch darüber lese, musste die praktische Seite des Projektes hinten anstellen. Bis heute.

Eigentlich ist so eine Ampelschaltung schnell gemacht, nimm 3 LEDs und schalte sie wie eine Ampel.

// Edit
Die hier gezeigt Logik ist Fehlerhaft, auch wenn der der Aufbau ansich zu funktionieren scheint.
Die Berichtigung gibts hier: http://ya365pb.blogspot.de/2013/05/lange-while.html


/*

Ampel Versuch

 */

// Wieso steht in den Bsp. immer int, reichen da nicht bytes? oO
byte red = 9; // Rot ist an Pin 9 usw.
byte yel = 8;
byte gre = 7;

// Pausen
int pred = 3000; // so lang ist rot (p(ause)red)
int pyel = 1000; // so lang ist gelb (p(ause)yel(low))
int pgre = 5000; // so lang ist grün (p(ause)gre(en))
int pswitch = 500; // schaltphasen

// the setup routine runs once when you press reset:
void setup() {                
  // die pins als output.
  pinMode(red, OUTPUT);
  pinMode(yel, OUTPUT);
  pinMode(gre, OUTPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(red, HIGH);
    delay(pred);
      digitalWrite(yel,HIGH);
      delay(pswitch);
    digitalWrite(red,LOW);
    delay(pyel);
  digitalWrite(yel,LOW);
  digitalWrite(gre,HIGH);
  delay(pgre);
  digitalWrite(gre,LOW);
  digitalWrite(yel,HIGH);
  delay(pyel);
 digitalWrite(yel,LOW);
  
}

Das ist aber selbst mir zu langweilig. In oben verlinktem Buch, gibts es aber ein schönes Beispiel, für eine Ampelschaltung mit angeschlossener Fußgängerampel. Also: Verkehrsampel macht Rot, Gelb, Grün. Wenn Fußgänger Knopf drückt (und nur dann), mache Verkehrsampel Rot und Fußgänger Grün. Soweit so schön, eigentlich. Denn für die Pausen wurde die delay() Funktion benutzt. Hier mein Code approach dazu:

/*

Ampel Versuch

 */

// reichen da nicht bytes? oO
byte red = 9; // Verkehrsampel Rot
byte yel = 8; // Verkehrsampel Gelb
byte gre = 7; // Verkehrsampel Grün
byte wred = 3; // Fußgängerampel Rot  (w(alker)red)
byte wgre = 2; // Fußgängerampel Grün (w(alker)gre(en))
byte but = 6; // Button Pin

// Pausen
int pred = 3000; // so lang ist rot
int pyel = 1000; // so lang ist gelb
int pgre = 5000; // so lang ist grün
int pswitch = 500; // schaltphasen
int psafety = 1000; // Puffer für Fußgänger, bis Verkehrsampel wieder auf grün springt
int butr = 0;

// the setup routine runs once when you press reset:
void setup() {                
  // die pins als output.
  pinMode(red, OUTPUT);
  pinMode(yel, OUTPUT);
  pinMode(gre, OUTPUT);
  pinMode(wred, OUTPUT);
  pinMode(wgre, OUTPUT);
  pinMode(but, INPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  if (butr == HIGH) {
  
  digitalWrite(red, HIGH);
  // Start Fußgänger ampel
  // Bei Verkehr Rot = Fußgänger grün
    digitalWrite(wred, LOW);
    digitalWrite(wgre, HIGH); 
  // Wartezeit für Verkehrsampel
  delay(pred);
  // Verkehrsampel fertig, aber erst Fußgängerampel auf Rot
    digitalWrite(wgre, LOW);
    digitalWrite(wred, HIGH);
    delay(psafety); // Pause für Fußgänger, die noch auf der Straße sind.
  // weiter mit Verkehrsampel   
      digitalWrite(yel,HIGH);
      delay(pswitch);
    digitalWrite(red,LOW);
    delay(pyel);
  digitalWrite(yel,LOW);
  digitalWrite(gre,HIGH);
  delay(pgre);
  digitalWrite(gre,LOW);
  digitalWrite(yel,HIGH);
  delay(pyel);
 digitalWrite(yel,LOW);
  }
  
  else {
    for (byte i=0; i < 5; i++) {
    digitalWrite(red, HIGH);
    digitalWrite(wred, LOW);
    delay(pswitch);
    digitalWrite(red, LOW);
    digitalWrite(wred, HIGH);
    } // for zu
  } // else zu
} // alles zu

Die blinkende else Abfrage am Ende ist nur zum debuggen, damit ich weiß wann das Board "denkt", dass der Knopf nicht gedrückt wurde. Für die Ampel selbst ist sie egal.

Eigentlich ganz nett so. Funktioniert ja scheinbar. Die delay() Funktion hat aber einen entscheidenden Nachteil und dieser wurde eigentlich auch bereits in einem vorherigen Kapitel im Buch beschrieben und gelöst. Die delay() Funktion ist ähnlich wie sleep in der Bash. Hier hält das Skript also tatsächlich für eine definierte Zeit an. Nachteil? Wenn das Skript wartet, kann es den Status des Buttons gar nicht überprüfen. Der Fußgänger kann also lange auf dem Knopf herum drücken, solange das Skript nicht an der "richtigen" Stelle ist, erkennt es den Knopfdruck nicht.

Die Lösung wurde, wie bereits erwähnt, eigentlich schon mehrere Kapitel vorher gegeben. (mit millis() statt delay() arbeiten) Daher verwunderte es mich doch, dass hier wieder delay() benutzt wurde und ich entschied mich, es besser zu machen.

Ein Bash Skript oder ein Windows cmd Skript zu schreiben, dass fiel mir bisher immer recht leicht. Stapelverarbeitung, Schritt für Schritt, da glänzt mein Hirn. Die delay() Funktion und die damit verbundene Logik ging daher ähnlich leicht von der Hand. Mit der Entscheidung aus diesem gemachten Nest auszubrechen besiegelte ich unwissentlich meinen restlichen Samstag, denn eine Logik, welche immer und immer wieder von oben beginnt, egal ob sie unten fertig ist, bringt mehr Stolpersteine mit sich als mir bewusst war. Und da ich mit der "echten" Programmierung bisher auf Kriegsfuß stand, fehlt(e) mir da eindeutig die Erfahrung.

Legen wir los. Das Arduino Board Zählt die Zeit die vergangen ist, seit das Programm läuft. Die Funktion heißt millis() und gibt die Zeit in Millisekunden zurück.

Wir setzen uns also irgendwo einen Zeitstempel und vergleichen diesen mit der aktuellen Zeit. Die Differenz daraus ist die verstrichene Zeit, welche wir statt delay()  nutzen können.

Ich setze zu Beginn des Programms die Variable 'time' und prüfe mit ihr, wie weit wir schon in der Zeit gereist sind und ob es Zeit ist die Ampel zu schalten. Einfach indem ich sie von der aktuellen Zeit millis() abziehe und das Ergebnis mit meiner Rotpause vergleiche. 

if (millis() - time > pred)    // Prüfe ob die abgelaufene Zeit länger ist als die Zeit die Rot sein soll.

ist das Ergebnis größer als 3000 (pred = 3000) dann mach etwas, nämlich Gelb dazu schalten. Nun 'time' reseten und wieder warten bis die nächste Pause abgelaufen ist. Und einfach so weiter... ja?

      if (millis() - time > pred)   // Prüfe ob die abgelaufene Zeit länger ist als die Zeit die Rot sein soll.
      {                                // falls dem so ist...
        digitalWrite(yel,HIGH);        // schalte Gelb dazu 
        time = millis()                // time reseten, müssen ja die neue pause zählen
        if (millis() - time > pyel  ) // Prüfe ob die abgelaufene Zeit länger ist als Rot und Gelb leuchten sollte)
          {                             // falls dem so ist...
            digitalWrite(red,LOW);      // schalte Rot ab
            digitalWrite(yel,LOW);      // schalte Gelb ab
            digitalWrite(gre,HIGH);     // und Grün an
          }

NEIN! Wäre eine Stapelverarbeitung, dann würde das so gehen... ist es aber nicht. Denn das Skript fängt ständig wieder oben an, es wartet nicht. In dem Moment als ich also 'time' auf 0 Setze, greift wieder die Erste if Abfrage.

"Sind schon 3 Sekunden rum damit ich Gelb dazu schalten kann? Ja -> Schalte Gelb dazu, setze 'time' auf 0. Sind schon 3 Sekunden rum, damit ich Gelb dazu schalten kann? Ja -> Schalte Gelb dazu, setze 'time' auf 0. Sind schon 3 Sekunden rum, damit ich Gelb dazu schalten kann?"

Meine Erste Idee war, statt relativen Zeiten (Pausen) absolute Zeiten zu setzen:

0 - 3 Sekunden: Rot
3 - 3,5 Sekunden: Rot & Gelb
3,5 - 4,5 Sekunden: Gelb
4,5 - 10 Sekunden: Grün

usw.

Das ist aber auch blöd, denn wenn man die Schaltpausen mal ändern möchte, muss man immer Umrechnen. Aber die Lösung ist recht simpel... wenn man drüber nachdenkt. ;) Denn statt absoluter Zahlen oder dem falschen Ansatz "sind denn schon 3 Sekunden rum? Ja -> reset", fragt man in der Zweiten Phase einfach "Sind denn schon 3 Sekunden + 0,5 Sekunden rum?" und in der Dritten "Sind denn schon 3 Sekunden + 0,5 Sekunden + 1 Sekunde rum?". Die Variable 'time' reseten wir auch noch, aber erst ganz zum Schluss. Das sieht dann so aus:


    if (millis() - time > pred)              // Prüfe ob die abgelaufene Zeit länger ist als die Zeit die Rot sein soll.
      {                                      // falls dem so ist...
        digitalWrite(yel,HIGH);              // schalte Gelb dazu
          if (millis() - time > pyel + pred) // Prüfe ob die abgelaufene Zeit länger ist als Rot und Gelb leuchten sollte (Pause Rot + Pause Gelb)
          {                                  // falls dem so ist...
            digitalWrite(red,LOW);           // schalte Rot ab
            digitalWrite(yel,LOW);           // schalte Gelb ab
            digitalWrite(gre,HIGH);          // und Grün an
          }
            if (millis() - time > pgre + pyel + pred) // Prüfe ob die abgelaufene Zeit länger ist als Pause Rot + Pause Rot & Gelb + Pause Gelb
            {                                         // falls dem so ist...
              digitalWrite(gre,LOW);                  // schalte Gelb aus
              digitalWrite(yel,HIGH);                 // und Grün an
            }                                         // usw.usf ;)
              if (millis() - time > pyel + pgre + pyel + pred)
              {
                digitalWrite(yel,LOW);               // wenn wir fertig sind, Gelb abschalten
                time = millis();                     // und die Zeit reseten!

Schön, dann haben wir es doch jetzt eigentlich, oder? Einfach diesen Code auch auf die Fußgängerampel anwenden und vorher abfragen ob jmd. den Knopf gedrückt hat oder nicht. Falls nein, schalte weiter die Verkehrsampel, falls ja schalte Verkehrsampel auf Rot und lass die Fußgänger über die Straße.

Aber wieder macht die endlose loop() Funktion diese Logik zunichte, denn wieder wartet sie nicht.

"Hat jemand den Knopf gedrückt? Nein -> prüfe ob die Zeit schon abgelaufen ist. Hat jemand den Knopf gedrückt? Nein -> prüfe ob die Zei.... Hat jemand den Knopf gedrückt? Nein -> Zeit ist abgel.... Hat jemand den Knopf gedrückt? Nein -> ...schalte auf Gelb... Hat jemand den K.... grün... Knopf?" Hilfe!

Man muss diese Stränge also irgendwie trennen, so dass sie trotz der Schleife nicht gleichzeit abgefragt und ausgeführt werden. Hat man diese Logik erst einmal auseinander gefummelt und die zwei Stränge Verkehrsampel und Fußgängerampel soweit getrennt, dass sie sich nicht mehr in die Quere kommen, kommt noch eine ganz kleine Kleinigkeit dazu. Wieder ist die scheinbar parallele Verarbeitung schuld. Die ganze Zeit wird abgefragt, "Knopf gedrückt, ja oder nein?" Wenn die Autos nun also gerade anfahren, weil seit 1 Sekunde Grün gezeigt wird, und ein Fußgänger sein Knöpfchen drückt, springt die Verkehrsampel *sofort* auf Rot und der Fußgänger hat Grün. Toll oder? Nö!

Wir benötigen also eine Logik ala "Hat jemand den Knopf gedrückt? Ja? Dann mach erst die Verkehrsampel zuende und gib danach für die Fußgänger frei" Diese Logik verhindert ausserdem, dass die Fußgänger dauergrün haben. Würde man blind den Button der Fußgänger abfragen und damit entscheiden ob Verkehr oder Fußgängerampel geschaltet wird, könnte man unweigerlich einen "immer nur Fußgänger" Zyklus provozieren.
Dazu habe ich die alte Variable "butr" (but(ton)r(read)) in safe umbenannt. Quasi "ist es safe jetzt Fußgänger gehen zu lassen?". Diese wird beim deklarieren auch gleich auf 0 gesetzt.  Und dann:

if (safe == 0) // falls safe 0 ist, prüfe den Knopf
{
  if (digitalRead(but) == HIGH) // wenn er gedrückt ist, setze safe auf 1
 {
   safe = 1;
 }
}
  if (safe == 0 | safe == 1) // Egal ob ein Fußgänger gedrückt hat oder nicht, lass den Verkehr mindestens 1x laufen
   {
Da sowohl bei 0 als auch bei 1 die Verkehrampel erstmal ihren Zyklus abarbeitet, bleibt die Fußgängerampel so lang Rot, bis sie an der Reihe ist. Das triggern wir in der letzten Phase der Verkehrsampel:
if (millis() - time > pyel + pgre + pyel + pred)
              {
                digitalWrite(yel,LOW);               // wenn wir fertig sind, Gelb abschalten
                time = millis();                     // und die Zeit reseten!
                if (safe == 1) safe = safe++;        // Falls ein Fußgänger gedrückt hatte und der Verkehr nun 1x durchgelaufen ist, mache aus safe eine 2 (1+1)
Wir setzen also safe auf 2, und das wiederrum ist das Startsignal für die Fußgängerampel:
else if (safe == 2) // wenn der Knopf gedrückt wurde (safe = 1) UND der Verkehr einmal durchlief (safe = 1 + 1) dann mache...
Uff. Geschafft. Der gesamte Code sieht so aus:
/*

Ampel Versuch

 */

// reichen da nicht bytes? oO
byte red = 9; // Verkehrsampel Rot
byte yel = 8; // Verkehrsampel Gelb
byte gre = 7; // Verkehrsampel Grün
byte sig = 5; // "Signal kommt"
byte wred = 3; // Fußgängerampel Rot
byte wgre = 2; // Fußgängerampel Grün
byte but = 6; // Button Pin
byte safe = 0; // war butr für buttonread

// Pausen
int pred = 3000; // 3 Sekunden Rot
int pyel = 1000 ; // 1 Sekunde Gelb
int pgre = 5000; // 5 Sekunden Grün
int psafety = 1000; // Puffer für Fußgänger, bis Verkehrsampel wieder auf grün springt
unsigned long time;

// the setup routine runs once when you press reset:
void setup() {
  // die pins als output.
  pinMode(red, OUTPUT);
  pinMode(yel, OUTPUT);
  pinMode(gre, OUTPUT);
  pinMode(sig, OUTPUT);
  pinMode(wred, OUTPUT);
  pinMode(wgre, OUTPUT);
  pinMode(but, INPUT);
  time = millis(); // einmal die aktuelle Zeit festlegen
}

// the loop routine runs over and over again forever:
void loop() {
if (safe == 0) // falls safe 0 ist, prüfe den Knopf
{
  if (digitalRead(but) == HIGH) // wenn er gedrückt ist, setze safe auf 1
 {
   safe = 1;
 }
}

  if (safe == 0 | safe == 1) // Egal ob ein Fußgänger gedrückt hat oder nicht, lass den Verkehr mindestens 1x laufen
   {
    digitalWrite(red, HIGH);
    digitalWrite(wred, HIGH);                // Fußgängerampel auch auf Rot und bleibt auch so 
    if (millis() - time > pred)              // Prüfe ob die abgelaufene Zeit länger ist als die Zeit die Rot sein soll.
      {                                      // falls dem so ist...
        digitalWrite(yel,HIGH);              // schalte Gelb dazu
          if (millis() - time > pyel + pred) // Prüfe ob die abgelaufene Zeit länger ist als Rot und Gelb leuchten sollte (Pause Rot + Pause Gelb)
          {                                  // falls dem so ist...
            digitalWrite(red,LOW);           // schalte Rot ab
            digitalWrite(yel,LOW);           // schalte Gelb ab
            digitalWrite(gre,HIGH);          // und Grün an
          }
            if (millis() - time > pgre + pyel + pred) // Prüfe ob die abgelaufene Zeit länger ist als Pause Rot + Pause Rot & Gelb + Pause Gelb
            {                                         // falls dem so ist...
              digitalWrite(gre,LOW);                  // schalte Gelb aus
              digitalWrite(yel,HIGH);                 // und Grün an
            }                                         // usw.usf ;)
              if (millis() - time > pyel + pgre + pyel + pred)
              {
                digitalWrite(yel,LOW);               // wenn wir fertig sind, Gelb abschalten
                time = millis();                     // und die Zeit reseten!
                if (safe == 1) safe = safe++;        // Falls ein Fußgänger gedrückt hatte und der Verkehr nun 1x durchgelaufen ist, mache aus safe eine 2 (1+1)
              }
      }
  }
  
  if (safe == 1)
  {
    digitalWrite(sig,HIGH);
  }
  
  else if (safe == 2) // wenn der Knopf gedrückt wurde (safe = 1) UND der Verkehr einmal durchlief (safe = 1 + 1) dann mache...
  {
    digitalWrite(red,HIGH); // erstmal alles auf Rot, damit auch keiner überfahren wird
    digitalWrite(wred,HIGH);// falls wir irgendwo einen Logikfehler haben.
    if (millis() - time > psafety)           // Prüfe ob die sicherheits Zeit vorbei ist
      {                                      // falls dem so ist...
        digitalWrite(wred,LOW);
        digitalWrite(sig,LOW);
        digitalWrite(wgre,HIGH);             // gib den Fußgängern Grün
      }
        if (millis() - time > psafety + pgre)// Prüfe ob abgelaufene Zeit länger als Safety + Grünphase ist.
        {                                    // falls ja
          digitalWrite(wred,HIGH);           // Fußgänger bekommen Rot
          digitalWrite(wgre,LOW);
        }
        if (millis() - time > psafety + pgre + psafety) // Wenn wieder Rot ist, warte noch die Safety Zeit ab (Safety + Grünphase + Safety)
        {
          time = millis();                              // Und resete die Zeit, damit es von vorn los gehen kann
          safe = 0;
        }
  }
delay(1);
} // alles zu





Und ja, ich bin mir im klaren darüber, dass eine if Schleife Abfrage eigentlich nicht die eleganteste Wahl ist.

Mittwoch, 15. Mai 2013

Mal Luft holen

Wie ja hoffentlich aufgefallen ist, gab es seit Sonntag kein Update mehr. In den letzten Wochen ergab sich etwas mehr Stress als gewünscht und dieser Stress kriecht bis ins Private. Im Privaten spielen sich aber auch mein(e) Hobby(s) ab, wie z.B. meine Fotografie und damit dieser Blog. Eine Sache die ich noch nie besonders mochte ist die schmale Grat an dem ein Hobby zur Pflicht wird und der Spaß auf der Strecke bleibt. Die letzten Bilder entstanden aber auf diese Weise, als reine Pflicht. Dementsprechend sehen sie auch aus. ;) Ich möchte weder schlechte Fotos veröffentlichen, noch möchte ich den Spaß an einem geliebten Hobby verlieren. Also habe ich mich entschieden eine Pause einzulegen bzw. nicht mehr täglich Fotos zu machen.

Eine Freundin meinte "nicht mal ein halbes Jahr!" (...hast du es durchgehalten) ich meine: 133 Fotos und keines wirklich "schlecht". Und so soll es auch weiter gehen.


z.B. mit SPS, ähhh SPM

 
Posted by Picasa