Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

Bereich für alle Themen rund um die Modellbahn-Elektronik und elektr. Umbauten für Analogbetrieb.
Benutzeravatar

Threadersteller
MicroBahner
Metropolitan (MET)
Beiträge: 2548
Registriert: Mi 28. Nov 2012, 14:24
Nenngröße: H0
Stromart: analog DC
Steuerung: Microprozessor-Eigenbau
Gleise: Tillig
Wohnort: Mittelfranken
Alter: 70

Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

#1

Beitrag von MicroBahner »

Hallo liebe Stummies,
der Arduino ist eine feine kleine Plattform, mit der vielfältige Aufgaben auf unseren Mobas gesteuert werden können. Leider liegt - wie so oft - auch hier etwas Schweiß vor dem Spaß, denn das kleine Ding will ja auch programmiert werden.
Häufig gibt es da gerade mit Zeitsteuerungen - die bei unseren Anwendungen sehr oft vorkommen - bei vielen Einsteigern Probleme. Zunächst erscheint das mit dem delay() - Aufruf recht einfach, aber man merkt doch recht schnell, dass man damit in einer Sackgasse landet, aus der es keinen Ausweg gibt: mehrere Dinge gleichzeitig zu machen funktioniert so nicht.
Die Frage von Thomas (alias Reibuch) in seinem Thread zu diesem Thema, war für mich der Anstoß, eine Lösung dieses Problems in einem kleinen Tutorial vorzustellen. Wie immer gibt es viele Wege nach Rom, aber für einen Einsteiger ist es erstmal wichtig wenigstens einen (möglichst einfachen ;) ) zu kennen.

Als Beispiele möchte ich die Anfrage von Thomas verwenden: Einen Wechselblinker (Andreaskreuz) und eine einfache Ampelsteuerung mit einem Arduino zu realisieren, so daß beides vollkommen unabhängig voneinander funktioniert. Ich werde dabei auch meine MobaTools verwenden, da die doch einiges vereinfachen.
Schritt für Schritt soll so dann das komplette Programm entstehen. Erst für den Wechselblinker, dann für die Ampel. Und zum Schluß wird sich zeigen, wie einfach man beides kombinieren kann, wenn man von Anfang an 'richtig' :wink: vorgegangen ist.

Der Schlüssel für das Ganze ist ein 'Zustandsautomat'. Mit dieser Technik lassen sich seehr viel Aufgaben auf dem Arduino erschlagen, weshalb es erstmal wichtig ist, dieses Prinzip zu verstehen.

Bevor wir mit dem Programmieren anfangen, müssen wir unser Problem dazu erstmal in kleine 'Häppchen' zerlegen. Diese 'Häppchen' sind die verschiedene Zustände, in denen sich das System befinden kann. Außerdem die Ereignisse, die - je nach Zustand - unterschiedliche Aktionen und Zustandswechsel auslösen.

Fangen wir erstmal mit dem Wechselblinker am Bü an. Rechts und links von der Straße steht jeweils ein Andreaskreuz mit einem Blinklicht. Bei Annäherung eines Zuges gehen kurz beide Lampen an, dann blinken sie im Wechseltakt. Hat der Zug den Bü überquert, gehen die Lampen wieder aus.
Welche Zustände können wir nun für dieses System identifizieren:
  1. Der Blinker ist im Ruhezustand. Alle Lampen sind aus. Das System wartet darauf, dass sich ein Zug nähert.
    >>Kommt der Zug, werden beide Lampen angeschaltet, die Stoppuhr gestartet, und wir wechseln in den 2. Zustand
  2. Der Zug hat den Kontakt ausglöst, beide Lampen sind für einen kurzen Zeitraum an. Die Stoppuhr für diese Zeit läuft.
    >>Ist die Stoppuhr abgelaufen, schalten wir die rechte Lampe aus, starten die Stoppuhr erneut mit der Blinkzeit und wir wechseln in den 3. Zustand.
  3. Jetzt ist nur noch die linke Lampe an, die rechte ist aus. Die Blinkzeit läuft.
    >>Ist die Blinkzeit abgelaufen, wird die linke Lampe aus, und die rechte Lampe eingeschaltet. Die Blinkzeit wird neu gestartet und wir wechseln in den 4. Zustand
  4. Jetzt ist nur die rechte Lampe an, die linke ist aus. Die Blinkzeit läuft.
    >>Ist die Blinkzeit abgelaufen, wird die reche Lampe aus, und die linke Lampe eingeschaltet. Die Blinkzeit wird neu gestartet und wir wechseln wieder in den 3. Zustand
    >>hat der Zug den Bü verlassen, werden beide Lampen ausgeschaltet, und wir wechseln in den 1. Zustand.
Jetzt haben wir unseren Wechselblinker also in 4 Zustände zerlegt, in denen sich das System befinden kann. In jedem Zustand wartet dieser Automat nun auf ein Ereigns ( mit '>>' markiert ). Tritt das Ereignis ein, wird eine Aktion gestartet, und dann der Zustand gewechselt. Im letzten Zustand warten wir sogar auf 2 Ereignisse. Das Ereignis, dass zuerst eintritt, bestimmt die ausgeführte Aktion und den Zustandswechsel.
Damit haben wir unser Problem in kleine Schritte zerlegt, die wir nun auch gedanklich durchgehen können, ob das auch alles so passt.
Da ist noch keine einzige Zeile Code geschrieben.

Im nächsten Post will ich dann vorstellen, wie man diesen noch theoretischen Ablauf in konkreten Code umsetzen kann.

Ihr dürft aber auch gerne schon Fragen zur Theorie stellen 8) , wenn etwas unklar ist, oder mir bei obigem Ablauf ein Fehler unterlaufen ist :roll: .
Benutzeravatar

Reibuch
InterRegio (IR)
Beiträge: 234
Registriert: So 27. Aug 2006, 10:30
Nenngröße: H0
Stromart: AC
Steuerung: WDP TAMS MC
Gleise: Märklin C-Gleis
Wohnort: Hunsrück
Deutschland

Re: Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

#2

Beitrag von Reibuch »

Hallo Franz —Peter

Bin gespannt :gfm:

Bisher alles verstanden

VG
Thomas
Gruß Thomas
Benutzeravatar

modellbahnelektronik
CityNightLine (CNL)
Beiträge: 1509
Registriert: Sa 6. Mai 2017, 08:07
Nenngröße: H0
Stromart: digital
Steuerung: Intellibox 2 / SpDrS60
Gleise: Roco / Tillig
Wohnort: Hagen
Alter: 43
Deutschland

Re: Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

#3

Beitrag von modellbahnelektronik »

Guten Morgen

Ich programmiere Zeitsteuerung schon seit vielen Jahren ohne Delay da dieser den Microcontroller blockiert.
Arduino Basis verwende ich nicht sondern die Programmiersprache C+.

Zwar ist Delay im MC eine sinnvolle Sache aber nützt ja nix wenn ich der Zeit nix anderes passieren kann.

Grüsse
Patrick
Irgendwo im Ruhrgebiet

- Moderner Hauptstreckenverkehr für Nah/Güterverkehr
- Industrieanbindung
- SpDrS60-Stellwerk

Meine HO-Anlage: viewtopic.php?f=64&t=179346
YouTube: https://www.youtube.com/channel/UCfgRbZ ... R5I5hvN3wQ
Benutzeravatar

Threadersteller
MicroBahner
Metropolitan (MET)
Beiträge: 2548
Registriert: Mi 28. Nov 2012, 14:24
Nenngröße: H0
Stromart: analog DC
Steuerung: Microprozessor-Eigenbau
Gleise: Tillig
Wohnort: Mittelfranken
Alter: 70

Re: Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

#4

Beitrag von MicroBahner »

@Patrick: für Leute wie dich ist dieses Tutorial ja auch nicht gedacht. Mal nebenbei bemerkt: die Basis von Arduino ist die Programmiersprache C++


Nun geht's weiter in diesem Tutorial für Einsteiger.

Die Liste im ersten Post müssen wir nun in einen Programmablauf umsetzten. Ich möchte das hier mal - die Programmierspezialisten mögen mir verzeihen - für die Einsteiger 'stummilike' an einem Gleisplan demonstrieren. Der Arduino ist der Lokführer, der mit seiner Lok (=dem Prozessor) diesen Gleisplan abfährt. Programmverzweigungen sind die Weichen und es gibt Stationen, an denen unser Lokführer etwas zu tun hat.

Bild

Am Anfang steht eine 4-Wege Weiche, die entsprechend dem aktuellen Zustand gestellt ist. Wie in einem Rangierbahnhof verzweigt es sich, und die folgenden Weichen in jedem Zweig sind je nachdem gestellt, ob ein erwartetes Ereignis eingetrofffen ist oder nicht. Am Ende kommen alle Zweige wieder zusammen, und es geht wieder von vorn los.
Ihr könnt jetzt mal in Gedanken ( oder mit dem Finger :wink: ) die 'Lok' kreisen lassen, und den Programmablauf durchspielen. In den weißen Kastchen ist was zu tun, ansonsten geht es ohne Unterbrechung immer im Kreis herum - mal hier, mal da lang :D

Natürlich gibt es für solche Abläufe auch informationstechnisch korrekte Symboldarstellungen - aber letztendlich zeigen die auch nichts anders :D :D .
Vielleicht macht es Euch so mehr Spaß, das ganze gedanklich durchzuspielen.
Wie immer - wenn was unklar ist, einfach fragen.

Im nächsten Schritt wirds dann wieder seriös 8) - wir werden das Ganze dann in korrekten C++ Code umsetzen.
Zuletzt geändert von MicroBahner am Mo 5. Nov 2018, 14:47, insgesamt 1-mal geändert.
Benutzeravatar

Donautal
InterCity (IC)
Beiträge: 503
Registriert: So 7. Jan 2018, 01:57
Nenngröße: H0
Stromart: analog AC
Gleise: M-Gleis
Wohnort: Tuttlingen
Alter: 48
Deutschland

Re: Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

#5

Beitrag von Donautal »

Hervorragend erklärt und die „Schienendarstellung“ wunderbar.
:gfm:

Ich freue mich auf die Fortsetzung. Obwohl ich ja programmieren kann (weil das u.a. Teil meiner Ausbildung und Berufs ist) freue ich mich dennoch über eine „für Anfänger möglichst einfache“ Erklärung und Programmierweise.
:gfm:
Eine 50 Jahre alte, über 30 Jahre abgebaute (und somit nicht bespielte) Anlage wird für die nächste Generation wieder restauriert.
https://stummiforum.de/viewtopic.php?f=15&t=156146

Mein echter Name: Michael - sofern ich es unter einem Posting mal vergesse

Egon
InterCity (IC)
Beiträge: 713
Registriert: Do 14. Jan 2010, 12:34

Re: Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

#6

Beitrag von Egon »

Hallo Franz-Peter,

auch von mir ein :gfm:
Bitte mach weiter, es wird bestimmt sehr interessant. Und wenn ich mir deine Videos anschaue, weiss ich dass es fundiert weiter gehen wird.
Gruß
Egon
Benutzeravatar

Reibuch
InterRegio (IR)
Beiträge: 234
Registriert: So 27. Aug 2006, 10:30
Nenngröße: H0
Stromart: AC
Steuerung: WDP TAMS MC
Gleise: Märklin C-Gleis
Wohnort: Hunsrück
Deutschland

Re: Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

#7

Beitrag von Reibuch »

Hallo Franz —Peter

:gfm: :gfm: :gfm: :gfm: :gfm: :gfm:

Klasse ,bin gespannt :D

VG
Thomas
Gruß Thomas

4fangnix
InterRegio (IR)
Beiträge: 111
Registriert: So 18. Okt 2015, 12:26
Nenngröße: H0
Stromart: digital
Steuerung: Rocrail / DCC BiDiB
Gleise: C-Gleis
Wohnort: Weiterstadt
Deutschland

Re: Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

#8

Beitrag von 4fangnix »

Hallo Franz-Peter,

da kann ich mich nur anschließen.
Ich bin ein Arduino-Wiedereinsteiger und will die kleinen Kerlchen als zweite Zentrale, neben meiner BiDiB-Zentrale, in Rocrail zur zeitgesteuerten Lichtsteuerung (Häuser- und Straßenlicht und diverse andere Dinge) einsetzen.
Bin gerade daran die Anlage aufzubauen, so dass die Arduinos erst später zum Zuge kommen.
Aber Deine Moba-Tools und die sonstigen Beiträge verfolge ich schon jetzt mit großem Vergnügen.


Schöne Grüße
Armin
Rocrail, 1x OpenDCC GBMboost, 1x BiDiB RF-Basis (OpenCar), 5x GBM16T, 2x LightControl, 2x OneControl, 5x Mobalist, DMX-RGB-Dimmer, MobaLedLib mit 768 LED über WS2811 oder 256 WS2812 RGB-LED, Intellibox - Märklin C- und K-Gleis, Bahn im Aufbau.
Jandrosch
Ehemaliger Benutzer

Re: Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

#9

Beitrag von Jandrosch »

Hallo Franz-Peter,
vielen Dank, dass Du Dich den Sorgen und Nöten der Arduino Anfängern widmest. Kommt mir sehr gelegen, da ich vor Kurzem etwas frustriert meinem ersten Baustein gegenüber gesessen habe.
Thema ist für mich jetzt Pflichtlektüre.
Benutzeravatar

Threadersteller
MicroBahner
Metropolitan (MET)
Beiträge: 2548
Registriert: Mi 28. Nov 2012, 14:24
Nenngröße: H0
Stromart: analog DC
Steuerung: Microprozessor-Eigenbau
Gleise: Tillig
Wohnort: Mittelfranken
Alter: 70

Re: Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

#10

Beitrag von MicroBahner »

Hallo liebe Stummies,
das freut mich, das mein kleiner Beitrag so viel Anklang findet. Das motiviert natürlich auch zum Weitermachen 8)

Aber zuerst vielleicht noch eine kleine Zeitbetrachtung zu unserem Ablaufplan. Unsere Arduino-Lok ist schnell - sehr schnell sogar. Betrachten wir mal die Zeiten, um dies es da geht, wenn wird die Station 'Zeit starten' abarbeiten. Für einen schönen Wechselblinker werden wir da Zeiten so um eine 1/2 Sekunde, also 500ms verwenden. Für unseren Arduino ist das eine halbe Ewigkeit. Wenn der dann beim nächsten Durchlauf an der Weiche mit 'zeit abgelaufen?' vorbeikommt, hat sich da sicher noch nichts getan, und er flitzt einfach durch das frei Gleis durch. Bis die Weiche sich umstellt auf 'zeit abgelaufen' ist unsere Arduino-Lok schon mehrere Tausend Male im Kreis gelaufen ohne irgendetwas tun zu müssen. Ein aktueller ICE ist nix dagegen :redzwinker: :mrgreen: .

Vielleicht dämmert euch auch schon ein wenig, wie wir es später schaffen, dass der Arduino mehrere Dinge 'gleichzeitig' macht. Richtig, wenn wir die weitere(n) Aufgaben genauso strukturieren wie unseren Wechselblinker, können wir das im 'Gleiskreis' einfach hintereinander hängen. Jeder dieser 'Rangierbahnhöfe' stellt seine Weichen dann intern selbst - so wie unser Wechselblinker auch - und die Arduino-Lok fährt dann nacheinander durch jeden hindurch. Und je nach Weichenstellung muss der Lokführer kurz was erledigen, oder es geht ohne weitere Stationen einfach hindurch.

Diese Ablaufpläne zeigen etwas sehr schön, was man später im Code nicht mehr so einfach erkennt: Die Parallelität und damit Exklusivität der jeweiligen Pfade. In jeder Runde kann immer nur genau eins von den parallelen Gleisen (Aufgaben) befahren werden. Wie in dem Moment die Weichen in einem anderen Pfad stehen ist da dann vollkommen irrelevant.
Später im Code steht alles untereinander, da ist das nicht mehr so gut zu erkennen. Deshalb ist es immer sinnvoll, sich die Abläufe vor dem Codieren mit so einem Plan klarzumachen. Da reicht auch eine einfache Bleistiftzeichnung. Und Gleispläne zeichnen könnt ihr doch schließlich alle :redzwinker: :mrgreen:

Den Plan oben habe ich nochmal ein klein wenig überarbeitet. Nicht das sich an den Abläufen grundsätzlich etwas geändert hätte. Aber die 'Weichen' sind etwas anders platziert. So sieht man besser, dass zu jeder Verzweigung auch das genaue Gegenstück beim Zusammenführen gehört. Man kann jetzt um so einen Verzweigungblock quasi einen Kringel drummachen mit genau einem Eingang und einem Ausgang, und das entspricht dann auch genau einem Programmblock im Code.

Bild
Benutzeravatar

Threadersteller
MicroBahner
Metropolitan (MET)
Beiträge: 2548
Registriert: Mi 28. Nov 2012, 14:24
Nenngröße: H0
Stromart: analog DC
Steuerung: Microprozessor-Eigenbau
Gleise: Tillig
Wohnort: Mittelfranken
Alter: 70

Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

#11

Beitrag von MicroBahner »

Hallo,
weiter geht's.
Nun wollen wir mal darangehen, unseren Ablaufplan auch in ablauffähigen Code umzusetzen. Die einfachen 'Weichen' sind sicher jedem klar: das sind einfache if-Anweisungen. Gibt es in beiden Zweigen etwas zu tun, brauchen wir auch einen else Zweig, ist ein Zweig ein 'leeres Gleis' reicht ein einfaches if.
Aber wo bekommen wir unsere 4-Wege-Weiche her?. Klar könnte man das in einzelne Verzweigungen auflösen, aber das ist nicht notwendig.
C++ bietet für sowas eine eigene Anweisung: die 'switch' Anweisung.
Die Grundstruktur sieht so aus:

Code: Alles auswählen

switch ( switchVariable ) {
  case 1:
    // Codeblock, der ausgeführt wird, wenn die switchVariable den Wert 1 hat
    break; // Ende des Codeblocks, das Programm läuft hinter dem Switch-Block weiter
  case 2:
     // Codeblock, der ausgeführt wird, wenn die switchVariable den Wert 2 hat
    break; // Ende des Codeblocks, das Programm läuft hinter dem Switch-Block weiter
  default: 
    // Codeblock, der ausgeführt wird wenn die switchVariable einen Wert hat, der in
    // keiner der obigen case-Zeilen vorkommt
    // der 'default-Block' ist optional. Fehlt das default:, so verhält er sich genauso, als wenn
    // dieser Codeblock leer ist. D.h. passt keine der obigen case-Zeilen, wird das gesamte switch 
    // übersprungen, und es geht danach weiter
}
In Abhängigkeit vom Wert der switchVariable wird die passende case-Zeile angesprungen. Dann werden die dortigen Anweisungen ausgeführt, und mit dem 'break;' springt das Programm zum Ende des gesamten switch-Blocks und macht dahinter weiter.
Hinter dem 'case' Schlüsselwort sind nur Konstante erlaubt, und natürlich müssen sie eindeutig sein. D.h. 2 case-Zeilen mit dem gleichen Konstantenwert sind nicht erlaubt. Wenn man das 'break;' vergisst, springt das Programm nicht ans Ende des switch-Blockes, sondern macht einfach mit dem Code hinter der nächsten case-Zeile weiter. Für die Zahl der case-Zeilen gibt es keine fest Grenze.

Diese Anweisung ist nun perfekt für unseren Zustandsautomaten geeignet. Die switch-Variable enthält immer den Wert für den aktuellen Zustand unseres Automaten und so wird bei jedem Durchlauf der entsprechende Codeblock ausgeführt. Damit werden wir nun unseren 'Rangierbahnhof' :wink: realisieren.
Benutzeravatar

Threadersteller
MicroBahner
Metropolitan (MET)
Beiträge: 2548
Registriert: Mi 28. Nov 2012, 14:24
Nenngröße: H0
Stromart: analog DC
Steuerung: Microprozessor-Eigenbau
Gleise: Tillig
Wohnort: Mittelfranken
Alter: 70

Re: Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

#12

Beitrag von MicroBahner »

So jetzt geht's schon etwas ans Eingemachte :D - es wird codiert 8) .

Wie wir gesehen haben, ist die switch-Anweisung der richtige Rahmen, um unseren Ablaufplan in Code umzusetzten. Nun müssen also die einzelnen case-Blöcke noch mit Leben gefüllt werden. Zunächst möchte ich jeden case-Block - also die Automatenzustände - einzeln aus unserem Ablaufplan ableiten.
Dann bauen wir das zu der kompletten switch Anweisung zusammen. Zum Schluß müssen wir dann sehen, was wir noch 'drumherum' brauchen, damit es ein lauffähiger Sketch wird.

Als erstes ein paar Bemerkungen zu den verwendetetn Variablen und Funktionen:
bueBelegt
Diese Variable zeigt uns an, dass ein Zug auf den Bü zufährt. Sie wird TRUE sobald sich der Zug nähert, und FALSE wenn er den Bü komplett überquert hat. Im einfachsten Fall kann das ein entsprechender Belegtabschnitt sein, dann ist es einfach ein Einganspin, den wir abfragen. Evtl. kann dies aber auch eine komplexere Logik sein. In unserem Zustandsautomaten soll uns aber erstmal noch nicht interessieren, wie diese Variable gesetzt wird.
wBlinkerZustand
Das ist unsere Zustandsvariable, die bestimmt, in welchem Zustand sich unser Automat befindet. Also sozusagen die Stellung der 4-Wege Weiche am Anfang.

LampeLinks LampeRechts
Das sind SoftLed-Objekte der MobaTools. Damit können wir ganz einfach durch die Methoden .on() und .off() unsere Led's im Andreaskreuz weich auf- und abblenden.
StoppUhr
Das ist ein EggTimer Objekt der MobaTools. Damit können wir unsere Zeit setzen, und abfragen ob sie abgelaufen ist.

Wie wir die MobaTools Objekte einrichten und initiieren werden wir später sehen, wenn der switch-Block ( also unser Zustandsautomat ) zum kompletten Sketch erweitert wird.

Zustand 1 - Ruhezustand

Bild

Code: Alles auswählen

      case 1: // Grundzustand, abfragen, ob sich ein Zug nähert ( z.B. über einen Belegtmelder )
        if ( bueBelegt ) {
          // Der Zug ist in den Belegtabschnitt vor der Schranke eingefahren
          // beide Lampen einschalten
          LampeLinks.on();
          LampeRechts.on();
          // Stoppuhr mit der Zeit die beide Lampen an sein sollen vorbelegen
          StoppUhr.setTime( STARTZEIT ); // StoppUhr 'aufziehen'
          // in den 2. Zustand wechseln
          wBlinkerZustand = 2; // Ab dem nächsten loop-Durchlauf werden nur die Anweisungen des case 2 ausgeführt
        }
        break; // Ende der Anweisungen für den 1. Zustand
Zustand 2 - beide Lampen sind an
Bild

Code: Alles auswählen

      case 2: // beide Lampen ein, wir fragen ab, ob die Stoppuhr abgelaufen ist.
        if ( not StoppUhr.running() ) {
          // Die Stoppuhr läuft nicht mehr, die Zeit ist um
          LampeRechts.off();
          StoppUhr.setTime( BLINKZEIT ); // Stoppuhr 'aufziehen'
          // in den 3. Zustand wechseln
          wBlinkerZustand = 3; // Ab dem nächsten loop-Durchlauf werden nur die Anweisungen des case 3 ausgeführt
        }
        break; // Ende der Anweisungen für den 2. Zustand
Zustand 3 - links an / rechts aus
Bild

Code: Alles auswählen

      case 3: // linke Lampen ist an, rechte aus: wir fragen ab, ob die Stoppuhr abgelaufen ist.
        if ( not StoppUhr.running() ) {
          // Die Stoppuhr läuft nicht mehr, die Zeit ist um, Lampen umschalten
          LampeLinks.off();
          LampeRechts.on();
          StoppUhr.setTime( BLINKZEIT ); // Stoppuhr 'aufziehen'
          // in den 4. Zustand wechseln
          wBlinkerZustand = 4; // Ab dem nächsten loop-Durchlauf werden nur die Anweisungen des case 4 ausgeführt
        }
        break; // Ende der Anweisungen für den 3. Zustand
Zustand 4 - links aus / rechts an
Bild

Code: Alles auswählen

      case 4: // linke Lampen ist aus, rechte an: wir fragen ab, ob die Stoppuhr abgelaufen ist.
        if ( not StoppUhr.running() ) {
          // Die Stoppuhr läuft nicht mehr, die Zeit ist um, Lampen umschalten
          LampeLinks.on();
          LampeRechts.off();
          StoppUhr.setTime( BLINKZEIT ); // Stoppuhr 'aufziehen'
          // wieder in den 3. Zustand wechseln
          wBlinkerZustand = 3; // Ab dem nächsten loop-Durchlauf werden nur die Anweisungen des case 3 ausgeführt
        }
        // Im 4. Zustand müssen wir auch noch abfragen, ob der Zug den Belegtabschnitt verlassen hat
        if ( not bueBelegt ) {
          // Der Zug ist komplett über den Bü gefahren, die Straße ist wieder frei
          // Beide Lampen ausschalten
          LampeLinks.off();
          LampeRechts.off();
          // wieder in den 1. Zustand wechseln. Eine Zeitüberwachung wird nicht gebraucht
          wBlinkerZustand = 1; // Ab dem nächsten loop-Durchlauf werden nur die Anweisungen des case 1 ausgeführt
        }  
        break; // Ende der Anweisungen für den 4. Zustand
Einer der 4 Zustände ist übrigens nicht exakt so codiert wie es dem Ablaufplan entspricht. Erkennt ihr welcher? Und wo ist der Unterschied?
Benutzeravatar

Threadersteller
MicroBahner
Metropolitan (MET)
Beiträge: 2548
Registriert: Mi 28. Nov 2012, 14:24
Nenngröße: H0
Stromart: analog DC
Steuerung: Microprozessor-Eigenbau
Gleise: Tillig
Wohnort: Mittelfranken
Alter: 70

Re: Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

#13

Beitrag von MicroBahner »

Hallo liebe Stummis und Arduino-Interessierte :D
nach den theoretischen Vorüberlegungen wollen wir uns jetzt daranmachen und das Ganze zu einem lauffähigen Sketch zusammenbauen. Dann bleibt das nicht so theoretisch, und es tut sich schon was, bevor wir das Ganze um eine unabhängige Ampelsteuerung erweitern (Multitasking 8) ).

Da rufen wir uns in Erinnerung, wie so ein Sketch aufgebaut ist. So ein Sketch besteht zumindest aus 3 Abschnitten:
  1. Im ersten Block sagen wir dem Arduino, was wir alles benutzen wollen. Wir binden Bibliotheken ein, definieren die globalen Variablen und Libraryobjekte, die wir verwenden und ordnen gegebenenfalls konstanten Zahlen auch einen Namen zu, damit man sie im Bedarfsfall einfacher ändern kann (z.B. die Pin-Nummern).
  2. der setup-Block. In der setup-Funktion werden alle die Dinge erledigt, die beim Starten des Sketches einmalig gemacht werden müssen. Dazu gehört die Festlegung ob die verwendeten Pins Ein- oder Ausgänge sind und das Initiieren der verwendeten Library-Objekte
  3. der loop-Block. Das eigentliche 'Herzstück' des Sketches. Hier dreht unsere 'Arduino-Lok' dann endlos ihre Runden :D :D
Was gehört bei unserem Sketch nun alles in den ersten Block?
Da wir die MobaTools Lib verwenden wollen, muss die als erstes mal eingebunden werden:

Code: Alles auswählen

#include <MobaTools.h>
Wer sie noch nicht auf seinem Rechner hat, kann sie hier herunterladen. Die zip-Datei an einem beliebigen Ort speichern. Dann in der Arduino IDE unter 'Sketch'->'Bibliothek einbinden'->'.ZIP-Bibliothek hinzufügen...' zu der heruntergeladenen Datei navigieren und OK drücken. Den Rest macht die IDE, und nun kann die Lib verwendet werden.

Dann müssen wir festlegen, welche Pins wir verwenden wollen:

Code: Alles auswählen

// Festlegen der Anschlüsse (Pinnummer) für Ein- und Ausgänge
const byte linksPin = 4;     // linke Lampe
const byte rechtsPin = 5;    // rechte Lampe
const byte belegtPin = 8;    // Eingang 'Zug kommt'
Die könnt ihr gegebenenfalls anpassen. Der 'belegtPin' Eingang schaltet in unserer ersten Version den Warnblinker einfach an bzw. aus. Die Schaltung dazu ist recht simpel ( auf dem UNO funktioniert es mit den gleichen Pinnr. natürlich genauso ):
Bild

Von den MobaTools verwenden wir den EggTimer für die Zeitmessung, und SoftLed für die 'weiche' Ansteuerung der Leds. Timer brauchen wir nur einen, Softleds aber 2 ( für rechts und links )

Code: Alles auswählen

// Benötigte MobaTools Objekte:
EggTimer StoppUhr; // Zum Messen von Zeiten
SoftLed LampeLinks;
SoftLed LampeRechts;

// Zeiten für den Blinkrhythmus ( in ms )
const int STARTZEIT = 500;
const int BLINKZEIT = 600;
const int FADEZEIT = 200;
Für die Lampen des Wechselblinkers habe ich da auch gleich noch die Zeiten festgelegt: wie lange sind beim Start beide gleichzeitig an, und in welchem Rhythmus blinken sie danach. Mit den Zeiten kann man dann auch ein wenig experimentieren. FADEZEIT gibt an, wie lange das auf/Abblenden dauert.

Ja, und dann brauchen wir noch 2 Variable, die wir oben im Code für unseren Zustandsautomaten schon verwendet haben:

Code: Alles auswählen

// Variable
boolean bueBelegt; // = TRUE, wenn sich ein Zug im Bereich des Bue befindet
byte    wBlinkerZustand;    // aktueller Zustand unseres Blinkerautomaten
Damit ist unser erster Block komplett.

Im Setup
müssen wir den Eingangspin als 'Eingang' definieren, und unsere 'SoftLed Objekte initiieren. Das Schalten der Pins auf 'Ausgang' macht die MobaTools Lib. Als letztes setzen wir dann noch den Startzustand unseres Blinkautomaten:

Code: Alles auswählen

void setup() {

    // Pins einrichten
    pinMode( belegtPin, INPUT_PULLUP ); // Mit einem Schalter nach GND wird Blinker eingeschaltet
    LampeLinks.attach( linksPin );      // Zuordnung der Softleds zu den Ausgangspins
    LampeRechts.attach( rechtsPin );
    LampeLinks.riseTime( FADEZEIT );    // Überblendzeit einstellen
    LampeRechts.riseTime( FADEZEIT );

    wBlinkerZustand = 1;        // Startzustand des Blinkautomaten.
}

Nun noch zum loop()

Der besteht im Wesentlichen ja nur aus der switch-Anweisung mit den case-Blöcken aus dem vorigen Post. Ganz am Anfang muss unser Lokführer aber noch kurz Station machen, unseren Eingangspin abfragen und den gelesenen Wert in der Variablen 'bueBelegt' ablegen:

Code: Alles auswählen

    bueBelegt = not digitalRead( belegtPin ); // ein LOW-Level am Eingangspin schaltet den Blinker ein
Der fertige Sketch
Damit haben wir jetzt den ganzen Sketch zusammem, den wir so in der IDE übersetzen und auf den Arduino laden können:

Code: Alles auswählen

/* Tutorial 'Zeitabläufe ohne delay() '
 *  Einfacher Wechselblinker ( unbeschrankter Bahnübergang )
 */

#include <MobaTools.h>

// Festlegen der Anschlüsse (Pinnummer) für Ein- und Ausgänge
const byte linksPin = 4;     // linke Lampe
const byte rechtsPin = 5;    // rechte Lampe
const byte belegtPin = 8;    // Eingang 'Zug kommt'

// Benötigte MobaTools Objekte:
EggTimer StoppUhr; // Zum Messen von Zeiten
SoftLed LampeLinks;
SoftLed LampeRechts;

// Zeiten für den Blinkrhythmus ( in ms )
const int STARTZEIT = 500;
const int BLINKZEIT = 600;
const int FADEZEIT = 200;

// Variable
boolean bueBelegt; // = TRUE, wenn sich ein Zug im Bereich des Bue befindet
byte    wBlinkerZustand;    // aktueller Zustand unseres Blinkerautomaten


void setup() {

    // Pins einrichten
    pinMode( belegtPin, INPUT_PULLUP ); // Mit einem Schalter nach GND wird Blinker eingeschaltet
    LampeLinks.attach( linksPin );      // Zuordnung der Softleds zu den Ausgangspins
    LampeRechts.attach( rechtsPin );
    LampeLinks.riseTime( FADEZEIT );    // Überblendzeit einstellen
    LampeRechts.riseTime( FADEZEIT );

    wBlinkerZustand = 1;        // Startzustand des Blinkautomaten.
}

void loop() {

    // Belegtzusatnd abfragen. Das machen wir hier jetzterstmal ganz einfach: Letztendlich
    // schalten wir mit dem Eingang einfach den Wechselblinker ein und aus.
    // Im realen Praxisfall könnte hier gegebenenfalls auch ein komplexere Logik stehen, um zu
    // erkennen, ob ein Zug sich nähert oder den Bü wieder verlassen hat.
    bueBelegt = not digitalRead( belegtPin ); // ein LOW-Level am Eingangspin schaltet den Blinker ein
    
    switch ( wBlinkerZustand ) {
      // je nach Wert der Variable wBlinkerZustand, wird die entsprechende 'case' Zeile angesprungen
      case 1: // Grundzustand, abfragen, ob sich ein Zug nähert ( z.B. über einen Belegtmelder )
        if ( bueBelegt ) {
          // Der Zug ist in den Belegtabschnitt vor der Schranke eingefahren
          // beide Lampen einschalten
          LampeLinks.on();
          LampeRechts.on();
          // Stoppuhr mit der Zeit die beide Lampen an sein sollen vorbelegen
          StoppUhr.setTime( STARTZEIT ); // StoppUhr 'aufziehen'
          // in den 2. Zustand wechseln
          wBlinkerZustand = 2; // Ab dem nächsten loop-Durchlauf werden nur die Anweisungen des case 2 ausgeführt
        }
        break; // Ende der Anweisungen für den 1. Zustand
      //-------------------------------------------------------------------------
      case 2: // beide Lampen ein, wir fragen ab, ob die Stoppuhr abgelaufen ist.
        if ( not StoppUhr.running() ) {
          // Die Stoppuhr läuft nicht mehr, die Zeit ist um
          LampeRechts.off();
          StoppUhr.setTime( BLINKZEIT ); // Stoppuhr 'aufziehen'
          // in den 3. Zustand wechseln
          wBlinkerZustand = 3; // Ab dem nächsten loop-Durchlauf werden nur die Anweisungen des case 3 ausgeführt
        }
        break; // Ende der Anweisungen für den 2. Zustand
      //-------------------------------------------------------------------------
      case 3: // linke Lampen ist an, rechte aus: wir fragen ab, ob die Stoppuhr abgelaufen ist.
        if ( not StoppUhr.running() ) {
          // Die Stoppuhr läuft nicht mehr, die Zeit ist um, Lampen umschalten
          LampeLinks.off();
          LampeRechts.on();
          StoppUhr.setTime( BLINKZEIT ); // Stoppuhr 'aufziehen'
          // in den 4. Zustand wechseln
          wBlinkerZustand = 4; // Ab dem nächsten loop-Durchlauf werden nur die Anweisungen des case 4 ausgeführt
        }
        break; // Ende der Anweisungen für den 3. Zustand
      //-------------------------------------------------------------------------
      case 4: // linke Lampen ist aus, rechte an: wir fragen ab, ob die Stoppuhr abgelaufen ist.
        if ( not StoppUhr.running() ) {
          // Die Stoppuhr läuft nicht mehr, die Zeit ist um, Lampen umschalten
          LampeLinks.on();
          LampeRechts.off();
          StoppUhr.setTime( BLINKZEIT ); // Stoppuhr 'aufziehen'
          // wieder in den 3. Zustand wechseln
          wBlinkerZustand = 3; // Ab dem nächsten loop-Durchlauf werden nur die Anweisungen des case 3 ausgeführt
        }
        // Im 4. Zustand müssen wir auch noch abfragen, ob der Zug den Belegtabschnitt verlassen hat
        if ( not bueBelegt ) {
          // Der Zug ist komplett über den Bü gefahren, die Straße ist wieder frei
          // Beide Lampen ausschalten
          LampeLinks.off();
          LampeRechts.off();
          // wieder in den 1. Zustand wechseln. Eine Zeitüberwachung wird nicht gebraucht
          wBlinkerZustand = 1; // Ab dem nächsten loop-Durchlauf werden nur die Anweisungen des case 1 ausgeführt
        }  
        break; // Ende der Anweisungen für den 4. Zustand
    } // Ende des switch-Blockes   
}
 
Bevor es weitergeht, sollte das bei Euch so funktionieren. Deshalb mache ich hier jetzt erstmal etwas Pause. Über Rückmeldungen würde ich mich natürlich freuen. Ich habe versucht den Sketch möglichst ausführlich zu kommentieren, damit man - zusammen mit diesem Tutorial - auch versteht was da abläuft.
Wenn noch etwas unklar ist - einfach fragen. Ich weis, am Anfang klemmt es oft an Stellen, die einem später ganz selbstverständlich erscheinen.
Zuletzt geändert von MicroBahner am Di 11. Dez 2018, 22:22, insgesamt 1-mal geändert.

Erich Müller
ICE-Sprinter
Beiträge: 6336
Registriert: Do 3. Dez 2015, 20:53
Nenngröße: H0
Stromart: digital
Gleise: Mittelleiter
Wohnort: jottweedee

Re: Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

#14

Beitrag von Erich Müller »

Hallo Franz-Peter,

Die "Stoppuhr" ist eine Countdown-Funktion, richtig?
MicroBahner hat geschrieben: Mo 5. Nov 2018, 22:16 Einer der 4 Zustände ist übrigens nicht exakt so codiert wie es dem Ablaufplan entspricht. Erkennt ihr welcher? Und wo ist der Unterschied?
Ich denke schon: der vierte. Hier wird in jedem Durchlauf abgefragt., ob der Zug noch da ist. Im Ablaufdiagramm entfällt die Abfrage, wenn der Timer abgelaufen ist und die Lampen umschalten.
Gewissermaßen besteht im Code Case 4 nicht aus drei parallelen Gleisen, sondern aus zwei aufeinander folgenden jeweils zweigleisigen Abschnitten, zwischen denen auf dasselbe Hauptgleis zurückgeführt wird.
In Turbo-Pascal, das ich vor ca. 30 Jahren mal kennenlernen durfte, wäre das mit einem "else" vor der zweiten If-Abfrage gemacht worden. Der Code ist natürlich sinnvoller ohne Else.
Freundliche Grüße
Erich

„Es hat nie einen Mann gegeben, der für die Behandlung von Einzelheiten so begabt gewesen wäre. Wenn er sich mit den kleinsten Dingen abgab, so tat er das in der Überzeugung, daß ihre Vielheit die großen zuwege bringt.“
Friedrich II. über Fr. Wilhelm I.
Benutzeravatar

Threadersteller
MicroBahner
Metropolitan (MET)
Beiträge: 2548
Registriert: Mi 28. Nov 2012, 14:24
Nenngröße: H0
Stromart: analog DC
Steuerung: Microprozessor-Eigenbau
Gleise: Tillig
Wohnort: Mittelfranken
Alter: 70

Re: Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

#15

Beitrag von MicroBahner »

Hallo Erich,
dem ist nichts hinzuzufügen :D :D . Alles ist so wie Du es schreibst.
Erich Müller hat geschrieben: Di 6. Nov 2018, 19:13 In Turbo-Pascal, das ich vor ca. 30 Jahren mal kennenlernen durfte, wäre das mit einem "else" vor der zweiten If-Abfrage gemacht worden.
bei C++ auch 8) . Bei der 'dreigleisigen Variante' ( mit else :wink: ) wäre es sinnvoller erst nach dem Zug zu schauen, und dann nach dem Timer. Allerdings macht es nur einen Unterschied, wenn die Ereignisse 'kein Zug mehr' und 'Timer abgelaufen' exakt beim gleichen Schleifendurchlauf auftreten, was recht unwahrscheinlich ist.
Benutzeravatar

Reibuch
InterRegio (IR)
Beiträge: 234
Registriert: So 27. Aug 2006, 10:30
Nenngröße: H0
Stromart: AC
Steuerung: WDP TAMS MC
Gleise: Märklin C-Gleis
Wohnort: Hunsrück
Deutschland

Re: Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

#16

Beitrag von Reibuch »

Hallo Franz Peter,

Schaltung habe ich nachgebaut , und funktioniert :fool:

klasse :D

VG
Thomas

PS.Ob ich das alles verstanden habe wie der Sketch sich Aufbaut :roll: :roll: :roll: ich glaube ich muss es noch ein paar mal lesen bis ich das Verstanden habe :D
Gruß Thomas
Benutzeravatar

Threadersteller
MicroBahner
Metropolitan (MET)
Beiträge: 2548
Registriert: Mi 28. Nov 2012, 14:24
Nenngröße: H0
Stromart: analog DC
Steuerung: Microprozessor-Eigenbau
Gleise: Tillig
Wohnort: Mittelfranken
Alter: 70

Re: Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

#17

Beitrag von MicroBahner »

Hallo Thomas,
ja, anfangs ist das Eindenken in diese Zustandsautomaten nicht ganz einfach, erfordert es doch ein ziemliches Umdenken. Aber es lohnt sich. Wenn Du das einmal verinnerlicht hast, tuen sich mit dem Arduino ganz neue Welten auf. Wenn Du mein 'elektromechanisches Stellwerk' ( s.u.) mal betrachtest: Da werkelt auch nur genauso ein Prozessor drin wie im Arduino. Liegt - was Speicher und Anschlüsse angeht so zwischen UNO und Mega. Und der managed das ganze Stellwerk mit Fahrstraßen und Zugüberwachung. Das ist weitgehend mit genau dieser Technik realisiert. Da werkeln ein paar Dutzend solcher Automaten drin :D .

Die Analogie mit der Arduino-Lok und dem Gleiskreis passt schon recht gut. Daran kann man sich das klarmachen. Man muss sich eben wirklich in Gedanken neben den Lokführer stellen und die Gleise abfahren.

Wenn Du irgendwo noch ein spezielles Problem hast und etwas unklar ist - frag einfach.
Gilt natürlich genauso für alle anderen Mitleser. Den bisherigen Code solltet ihr schon verstanden haben, bevor es weitergeht.
Benutzeravatar

sebi0410
InterCity (IC)
Beiträge: 565
Registriert: Fr 12. Aug 2005, 19:28
Nenngröße: H0
Stromart: AC
Steuerung: MSII und mit 6021
Gleise: K-Gleise
Wohnort: Howi

Re: Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

#18

Beitrag von sebi0410 »

Halo Franz-Peter,

sehr cool gemacht ich habe den Thread mal in die Abo's genommen :-) Bisher fehlt mir allerdings der Arduino.

Bitte mach weiter so, ist total interessant was das kleine Teil alles kann.
Gruß
Sebastian
Benutzeravatar

Threadersteller
MicroBahner
Metropolitan (MET)
Beiträge: 2548
Registriert: Mi 28. Nov 2012, 14:24
Nenngröße: H0
Stromart: analog DC
Steuerung: Microprozessor-Eigenbau
Gleise: Tillig
Wohnort: Mittelfranken
Alter: 70

Re: Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

#19

Beitrag von MicroBahner »

Hallo Sebastian,
sebi0410 hat geschrieben: So 11. Nov 2018, 15:46Bisher fehlt mir allerdings der Arduino.
Dann ist das aber ziemlich trockener Stoff :roll: . Aber was nicht ist, kann ja noch werden.
Wobei sich das Tutorial sicher nicht an den absoluten Erstanwender richtet. Zumindest ein paar grundlegende Beispiele aus der IDE oder einem Einsteiger-Kit sollte man schon zum Laufen gebracht haben. Diese Beispiele verwenden ja auch meistens das delay() und hier geht es dann darum. wie man das wieder los wird :mrgreen: .

TecnoWorld
InterRegioExpress (IRE)
Beiträge: 269
Registriert: Mi 11. Mär 2015, 15:49
Nenngröße: TT
Stromart: digital
Gleise: TT
Wohnort: Chiclana
Alter: 52
Kontaktdaten:
Spanien

Re: Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

#20

Beitrag von TecnoWorld »

Nur mal so am Rande:
Schön, das mal jemand so ein Tutorial macht, um "sauberer" programmieren zu können und nix mit Schleifen und delay().

Aber sollte man dann nicht gleich "unten" anfangen und erst mal die Hardware erklären? Also, Event-System, DMA, Interrupts. Damit erschlägt man nämlich schon sehr viele Dinge und braucht bei den meisten Aktionen noch nicht mal den Prozessor dazu (Weil DMA und Events alleine laufen).

Aber sorry - ich wollte nicht stören - nur eine Anregung.
__________________________
LG aus Andalusien.
RailSolution - das Lichtprojekt von Modellbahnern für die Modellbahn
Benutzeravatar

DL7BJ
Regionalbahn (RB)
Beiträge: 38
Registriert: Mi 29. Nov 2017, 19:36
Nenngröße: H0
Stromart: DC
Steuerung: DCC
Gleise: Peco Code 75
Wohnort: JO43GC
Kontaktdaten:

Re: Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

#21

Beitrag von DL7BJ »

MicroBahner hat geschrieben: Mo 12. Nov 2018, 17:23 Dann ist das aber ziemlich trockener Stoff :roll: . Aber was nicht ist, kann ja noch werden.
Dem kann man abhelfen, nicht nur die Modellbahn laesst sich auf dem PC simulieren ;-)
https://www.smashingrobotics.com/arduin ... eal-board/

Wenn ich es recht sehe, hast Du vor, die State-Machine nur in einer Schleife laufen zu lassen. Mit Timer-Interrupts koennte man das noch eleganter loesen, aber fuer den Anfaenger ist das schon ok und die Erklaerung finde ich super!

Gruss,
Tom
Zuletzt geändert von DL7BJ am Mo 12. Nov 2018, 21:27, insgesamt 1-mal geändert.
https://isnix.de * Life is too long for QRO * https://twitter.com/dl7bj
Benutzeravatar

DL7BJ
Regionalbahn (RB)
Beiträge: 38
Registriert: Mi 29. Nov 2017, 19:36
Nenngröße: H0
Stromart: DC
Steuerung: DCC
Gleise: Peco Code 75
Wohnort: JO43GC
Kontaktdaten:

Re: Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

#22

Beitrag von DL7BJ »

TecnoWorld hat geschrieben: Mo 12. Nov 2018, 18:23 Weil DMA und Events alleine laufen
Auf einem 8-Bit ATMega? Da muesste man schon einen anderen Controller waehlen.

Gruss
Tom
https://isnix.de * Life is too long for QRO * https://twitter.com/dl7bj
Benutzeravatar

ThKaS
CityNightLine (CNL)
Beiträge: 1602
Registriert: Do 28. Apr 2005, 08:37
Wohnort: München
Kontaktdaten:
Jamaika

Re: Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

#23

Beitrag von ThKaS »

Moin moin Franz-Petrr,

danke für das Tutorial. Super! Sehr verständlich.

Habe es mal „nachgebaut“ mit einem Nano. Hat geklappt.
Habs dann mal erweitert auf mehrere Ausgänge und Zeit- und Variablenvariationen. Hat auch geklappt.
(obwohl ich bisher das Programmieren immer gescheut habe)

Nun aber doch noch eine Frage dazu.
Wieviele Schleifendurchläufe pro Zeiteinheit macht denn der Nano da? Kann man das errechnen?
lieben Gruss von südlich des Weisswurst-Äquators
Thomas

guckst: www.thkas-moba.de ‹(•¿•)› www.mucis.de

Bild

Mä-K-Gleis, Tams MC, Multi-Kulti Decoder, WDP
Benutzeravatar

Threadersteller
MicroBahner
Metropolitan (MET)
Beiträge: 2548
Registriert: Mi 28. Nov 2012, 14:24
Nenngröße: H0
Stromart: analog DC
Steuerung: Microprozessor-Eigenbau
Gleise: Tillig
Wohnort: Mittelfranken
Alter: 70

Re: Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

#24

Beitrag von MicroBahner »

Hallo Thomas,
super, das freut mich. So ist es gedacht, und wenn es für dich verständlich ist, habe ich ja nicht alles falsch gemacht :mrgreen:.

Was die Schleifendurchläufe angeht: Berechnen ist da kaum möglich, aber man kann es mit ein paar zusätzlichen Programmzeilen messen. Klar verfälschen die das Ergebnis etwas. Aber so genau muss es ja gar nicht sein, es geht eher um die Größenordnung. Ich habe das mal eben gemacht, und das Ergebnis:
im Ruhezustand( warten auf Zug ) : ca 107000 Durchläufe/Sek.
Während des Blinkens : ca. 80000 Durchläufe / Sek.

So ein Blinker ist für den Arduino also keine echte Herausforderung. Da dreht er hauptsächlich Däumchen - und das ziemlich flott :fool:
Benutzeravatar

Threadersteller
MicroBahner
Metropolitan (MET)
Beiträge: 2548
Registriert: Mi 28. Nov 2012, 14:24
Nenngröße: H0
Stromart: analog DC
Steuerung: Microprozessor-Eigenbau
Gleise: Tillig
Wohnort: Mittelfranken
Alter: 70

Re: Arduino: Zeitsteuerungen ohne Delay - ein kleines Tutorial

#25

Beitrag von MicroBahner »

Hallo liebe Freunde der Kombination Arduino+Moba :D ,
ich hoffe, der eine oder andere hat es inzwischen doch geschafft, den bisherigen Sketch in der Praxis umzusetzen und auch nachzuvollziehen, was da passiert. Wenn nicht - bitte melden :charles: :charles:

Nichts desto trotz mach ich jetzt mal einfach weiter. Wir wollten ja auch noch ein Ampelschaltung einbauen. Also werden wir jetzt in gleicher Art und Weise einen Ampelsketch realisieren, und dann beide kombinieren.
Ich weis jetzt nicht genau, was Thomas da als Ampelschaltung im Sinn hatte. Im einfachsten Fall haben wir nur eine Kreuzung, und da sehen unsere Ampelbilder dann so aus:
Bild
In der Reihenfolge müssen die Ampeln geschaltet werden ( wobei die 'Übergangsphasen' mit dem gelben Licht natürlich kürzer zu sehen sind, als die reinen Rot/Grün Phasen 1+5 ).
Die 8 Signalbilder sind nun auch unsere Automatenzustände. Auf irgendwelche Eingänge brauchen wir erstmal nicht zu reagieren. Die Zustände werden einfach von 1 bis 8 und wieder bei 1 beginnend zeitgesteuert im Kreis herum geschaltet.
Damit wir mit dem Wechselblinker nicht in Konflikt kommen, müssen wir natürlich unsere Pins entsprechend verteilen. Die jeweils gegenüberliegenden Ampeln einer Straße können parallel geschaltet werden, so dass wir insgesamt 6 Ausgänge benötigen:
Bild

So das wäre nun die Basis für unseren Ampel-Sketch. Wenn das zu einfach ist - ihr könnt noch Ideen einbringen 8)
Ich hatte da schonmal an eine per Schalter aktivierbare Nachtschaltung gedacht ( gelbes Blinklicht auf der Nebenstraße )
Antworten

Zurück zu „Elektrik und Elektronik“