Go Down

Topic: Millis Befehl, Steuerung Schattenbahnof.  (Read 2169 times) previous topic - next topic

noiasca

#75
Sep 24, 2020, 05:16 pm Last Edit: Sep 24, 2020, 05:18 pm by noiasca
Käme doch nur auf die Fahrrichtung an: bei der Einfahrt über West W1 fragst auf den ersten LOW/HIGH von LSBG5 (der vorderste Wagen ab), LSEG5 wird mit jeden Wagen pulsen, aber soll egal sein.
Einfahrt über Ost, dürfte es nicht geben, weil da keine Weichen beschriftet sind.
how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

kgbrus

Hallo Franz Peter,

LSH in der Zeichnung ist LSHaupt im Sketch.
Die Abschaltung der Gleise, bzw die Fahrt der Lokomotive bis zum erreichen der Endposition LSBGxübernimmt ein anderer Arduino. Der schaltet auch die Zufahrt zum SBH ab, wenn LShaupt schaltet
Das Programm hab ich theoretisch fertig, theoretisch weil, Bandwurm :-)

Bist du im Forum Alte Modellbahn? Wenn ja könntest du in meinen thread "neue Anlage "mein Nick ist da KGBRUS, schauen. Da steht alles drin.
Da dort aber niemand auf meine Arduino Berichte reagiert, denke ich mal nicht :-)
Zum Abfangen der Zwischenräume werde ich zwei oder drei Lichtschranken nebeneinander betreiben. Brauche ich aber nur bei LSEGx sprich bei der Einfahrt in die Einzelnen Gleise

Gruss

Kay

kgbrus

Käme doch nur auf die Fahrrichtung an: bei der Einfahrt über West W1 fragst auf den ersten LOW/HIGH von LSBG5 (der vorderste Wagen ab), LSEG5 wird mit jeden Wagen pulsen, aber soll egal sein.
Einfahrt über Ost, dürfte es nicht geben, weil da keine Weichen beschriftet sind.
Von Prinzip richtig nur muss bei LSEG (lichtschranke Einfahrt) sichergestellt werden, das der Zug nicht so steht, das die LS zwischen 2 Wagons durch scheint. Dann steht der Rest noch auf dem Hauptgleis. Sprich, wenn LSBG (lichtschranke gleis besetzt) und LSEG high sind, ist der Zug zu lang für das Gleis und muss wieder raus fahren.

MicroBahner

#78
Sep 24, 2020, 05:51 pm Last Edit: Sep 24, 2020, 05:52 pm by MicroBahner
Die Abschaltung der Gleise, bzw die Fahrt der Lokomotive bis zum erreichen der Endposition LSBGxübernimmt ein anderer Arduino. Der schaltet auch die Zufahrt zum SBH ab, wenn LShaupt schaltet
Das Programm hab ich theoretisch fertig, theoretisch weil, Bandwurm :-)
Ist das nicht unnötig kompliziert und aufwändig? Das schafft ein Arduino doch alles locker. Und der weis dann auch über alles Bescheid und es ist keine Abstimmung notwendig. Das Fahren, Stoppen und Weichenstellen gehört doch logisch alles zusammen.

Bist du im Forum Alte Modellbahn?
Wie Du schon vermutet hast - nein. Wenn treibe ich mich eher im Stummiforum rum. Wenn bei meinem Fuhrpark auch ein paar über 40 Jahre alte Schätzchen dabei sind, ist es insgesamt doch eher eine moderne MoBa - auch wenn keine einzige Lok einen Decoder hat ;)

Gruß, Franz-Peter

noiasca

#79
Sep 24, 2020, 05:55 pm Last Edit: Sep 24, 2020, 06:08 pm by noiasca
Quote
Von Prinzip richtig nur muss bei LSEG (lichtschranke Einfahrt) sichergestellt werden,
Das ist doch auch einfach: wenn das LSBG meldet (also ein Zug angekommen) und die letzten Statuswechsel von LSEG noch "jung" oder LSEG sogar HIGH ist, heißt das dass der Zug da drüber ragt. Damit hast du das Kriterium den Zug weiterzuschicken.

Wobei sinnvoller wäre, vorher die Zuglänge zu ermitteln und ihn dann auf ein passendes - lang genuges - freies Gleis zu senden. Ich nehme an, das macht man in echt auch so, und das "Weiterschicken" ist eher der Worstcase ;-)
how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

MicroBahner

Wobei sinnvoller wäre, vorher die Zuglänge zu ermitteln und ihn dann auf ein passendes - lang genuges - freies Gleis zu senden.
Sicher, so mache ich das in meinem Sbf auch.
Aber wir sollten ihn nicht gleich überfordern und verschrecken  ;) . Immer eins nach dem anderen. Mit der einfacheren Variante kann er auch erstmal Erfahrung sammeln  8)
Gruß, Franz-Peter

agmue

#81
Sep 24, 2020, 07:58 pm Last Edit: Sep 24, 2020, 08:00 pm by agmue
Zu Deiner Variante mit delay: Da die Weichen alle nacheinender geschaltet werden, benögt der Schaltzyklus 5 Sekunden oder mehr. Da fällt das "Blinken" nicht so auf. Mit millis geht der Zyklus schneller, da merkt man es dann. Man könnte Deine delay-Variante beschleunigen, in dem erst alle Weichen gestellt werden, dann die Verzögerung, dann alle Ausgänge auf LOW. Dann braucht es nur eine Sekunde.

Neben der Problematik mit den millis fehlt mir eine (gut erkennbare) Schrittkette (=endlicher Automat, =finite state machine). Ja, das jetzt auch noch. Ist bei mir nur ein switch/case und zumindest für mich erschließt sich der Ablauf viel einfacher. Ein Vergleich der Anzahl der Variablen macht das schon plausibel.

Dein Durchfahrgleis kannst Du später ergänzen, ich bleibe vorerst bei meiner einfachen Harfe. Durchfahrgleis ist mit D markiert.

Ne ich kann 5 Loks abstellen, und kann immer noch durchfahren du nur 4 :-)
Und schon habe ich ein Gleis ergänzt:



Das passende Programm (ungetestet):

Code: [Select]
const byte AnzahlGleise = 5;
enum {Gleis1, Gleis2, Gleis3, Gleis4, Gleis5};

// Lichtschranke zur Gleisbesetzmeldung LSBG1-5
const byte LSBG[AnzahlGleise] = {PA8, PB15, PB14, PB13, PB12};

// Lichtschranke SBH Haupt
const byte LSHaupt = PA9;  // Lichtschranke zur Einfahrt in den SBH

// Ausgänge für Relais  der Weichenstellung weiche 1-5
const byte WA[AnzahlGleise] = {PA0, PA2, PA4, PA6, PB0};          // Weichen Abbiegen
const byte WG[AnzahlGleise] = {PA1, PA3, PA5, PA7, PB1};          // Weichen Geradeaus

// variable definieren
unsigned long RELAIS_timestore = 0; // Variable Speicher für Impulszeit Weichen

enum {EINFAHRT, UMFAHRUNG, STELLEN, WARTEN, AUS};
byte schritt = {EINFAHRT};

void setup()
{
  for (byte g = Gleis1; g < AnzahlGleise; g++)
  {
    // Pin Mode für Lichtschranken Gleisbesetztmeldung Gleis 1 - 5
    pinMode(LSBG[g], INPUT_PULLUP);
  }
  pinMode(LSHaupt, INPUT_PULLUP);

  for (byte g = Gleis1; g < AnzahlGleise; g++)
  {
    // Pin Mode für Gleis an schalten
    pinMode(WA[g], OUTPUT);
    pinMode(WG[g], OUTPUT);
  }
}

void loop()
{
  switch (schritt)
  {
    case EINFAHRT:
      if (digitalRead(LSHaupt))     // Abfrage ob Zug einfäht. Lichtschranke an der Zufahrt
      {
        schritt = STELLEN;
      }
      break;
    case STELLEN:
      for (byte g = Gleis1; g < AnzahlGleise; g++)
      {
        if (digitalRead(LSBG[g]))     // Abfrage ob SBH voll
        {
          digitalWrite (WG[g], HIGH);
        }
        else
        {
          digitalWrite (WA[g], HIGH);
        }
      }
      RELAIS_timestore = millis();
      schritt = WARTEN;
      break;
    case WARTEN:
      if (millis() - RELAIS_timestore >= 1000)
      {
        for (byte g = Gleis1; g < AnzahlGleise; g++)
        {
          digitalWrite (WG[g], LOW);
          digitalWrite (WA[g], LOW);
        }
        schritt = AUS;
      }
      break;
    case AUS:
      if (!digitalRead(LSHaupt))     // Abfrage ob Zug nicht mehr einfährt. Lichtschranke an der Zufahrt
      {
        schritt = EINFAHRT;
      }
      break;
  }
}

Was macht das bei Dir?

Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

MicroBahner

#82
Sep 24, 2020, 09:58 pm Last Edit: Sep 24, 2020, 10:09 pm by MicroBahner
Man könnte Deine delay-Variante beschleunigen, in dem erst alle Weichen gestellt werden, dann die Verzögerung, dann alle Ausgänge auf LOW. Dann braucht es nur eine Sekunde.
Da die Weichen beim Umschalten einen rel. hohen Stromimpuls ziehen, ist das nacheinander Schalten definitiv die bessere Methode, als alle auf einen Schlag umschalten zu lassen. Wobei 1sek da schon sehr viel ist. Eine Weiche mit Magnetspulenantrieb, die 1Sek zum Umschalten braucht ist kaputt.

(ungetestet):
Da ich ja so eine Blue Pill habe, kann ich nach einem Kurztest sagen, dass es mal grundsätzlich tut ( Mit Leds für die Weichen, und Steckkabel als LS ) ;) . Aber es schaltet eben auch alle Weichen auf einen Schlag um, was ich vermeiden würde.
Der endliche Automat ist definitiv der richtige Ansatz ( aber wo ist er das nicht ... :D ). Und aus meiner Sicht gehöt das Schalten des Fahrwegs und das Schalten der Fahrspannung ebenso definitiv zusammen. Man muss die kleinen Dinger ja nicht maßlos unterfordern - und erst Recht nicht so einen 32-Bitter. Der stirbt ja vor Langeweile  :smiley-twist:
Gruß, Franz-Peter

kgbrus

#83
Sep 25, 2020, 08:08 am Last Edit: Sep 25, 2020, 08:24 am by kgbrus
Moin zusammen,

Denkt Ihr bitte daran, das ich blutiger Anfänger bin? :-) Ich beschäftige mich gerade mal 3 Monate damit und bin froh das ich irgendwas hin bekommen habe, was so einigermaßen tut, was ich will.
Nach millis sind wir dann über Funktionen auf Strukturen und nun bei endlichen Automaten gelandet... Für mich (noch) Raketenwissenschaft :-)
Also hösch langsam mit die jungen Pferde :-)

Hier ein Video vom SBH der von 2 extrem gelangweilten STM´s gesteuert wird.
https://youtu.be/dzpy0XcvznU


Nun zur Beantwortung der in den letzten Threads aufgetauchten Fragen

1. Warum arbeite ich mit 2 Boards?
Erstens stellt das Board 26 I/O´s die nach dem booten schon so verwendet werden können zur Verfügung (ohne Remap).  Ich benötige für die bisherige Lösung aber 27,
Der zweite Grund ist, das das Board nun mal nix Kostet, und zu guter letzt bleiben die Programme kurz. Ich hab ja erst jetzt von euch aufgezeigt bekommen, wie man Bandwürmer verhindert.
Das vereinfacht für mich auch die ganze Sache, da ich mich beim programmieren auf die einzelnen Abschnitte konzentrieren kann. Später zusammenzuführen sollte ja nicht so das Problem sein.

2. Ändern des SBH
den zu Ändern ist kein Problem.

3. länge eines Zuges erkennen und auf passendes Gleis schicken
Das ist bei mir nicht notwendig, da alle Gleise in den SBH´s gleich Lang sind. Die Gleise sind ca 1,8mtr lang. Wird wohl eher nicht vorkommen aber sicher ist sicher bei der Bahn,

4. Schalten der Weichen
Da die Weichen einen eigen Trafo bekommen sollte das bei 30VA wenig ausmachen. Da muß ich aber noch Rechnen bzw Testen. Edit: 5 Weichen gleichzeitig sind zu viel!
Zu der einen Sekunde, die das Relais anzieht. Ich denke 1 Sekunde ist eine gute Zeit, da so sichergestellt ist, das die Weiche auch zuverlässig schaltet. Wenn ich die Weichen über einen Taster mit der Hand schalte dürfte das mindestens eine Sekunde sein. Die sind dann auch nie Kaputt :-)

5. Wann sollen die Weichen geschaltet werden?
Richtig ist, das das schalten jeder Weiche bei einfahrt eines Zuges Blödsinn ist. Aber für mich am einfachsten zu realisieren :-). Es wird noch eine Variable (die ist oben im Sketch auch schon drin "geschaltet" eingepflegt, die nur ein einmaliges schalten zu lässt.

6. Sketch von Agmue
Dankeschön, den werde ich gleich testen.

Ich hoffe ich keine Frage bzw Anmerkung übersehen

Nun aber zu meinen Fragen.

Wenn ich in meinem letzten sketch, bei dem ich den delay Befehl in eine Funktion gelegt habe, eben diesen delay mit millis ersetzten will, muss ich den auch als Variable  mit dem Bezug Pin machen?

aus dem:
Code: [Select]
void Weicheschalt(byte pin)                // Funktion zum Schalten der Weichen, diese wird bei bedarf aufgerufen
{
  digitalWrite (pin, HIGH);
  delay (1000);
  digitalWrite (pin, LOW);
}


wird sowas:
Code: [Select]
void Weicheschalt(byte pin)                // Funktion zum Schalten der Weichen, diese wird bei bedarf aufgerufen
{
  digitalWrite (pin, HIGH);
  Relaistimestore(Pin) = millis()
  digitalWrite (pin, LOW);
}


Brauche ich das Pin hinter Relaistimestore? Ich weis das es so nicht funktioniert mir gehts nur um das "PIN"

Noch ein Frage, es gibt keinen befehl, der einen Ausgang für Zeitraum x auf HIGH Pegel hält, der nicht den Prozessor zum anhalten biringt? es muß über den millis Befehl realisiert werden?


Also "hold HIGH for 20 Secounds..."


agmue

Hier ein Video vom SBH der von 2 extrem gelangweilten STM´s gesteuert wird.
Ich liebe es anschaulich, Danke!

Brauche ich das Pin hinter Relaistimestore?
Nein, es genügt eine Zeit.

5 Weichen gleichzeitig sind zu viel!
Vor ein paar Jahren habe ich mich mal mit einer Modelleisenbahnsimulation beschäftigt, da konnte ich so viel Weichen gleichzeitig schalten, wie ich brauchte ::)

Nach millis sind wir dann über Funktionen auf Strukturen und nun bei endlichen Automaten gelandet...
Bei mir ohne Funktionen und Strukturen :)

Felder, millis und Schrittkette kann ich Dir nicht ersparen, wenn Du das einigermaßen zukunftssicher lösen möchtest.

6. Sketch von Agmue
Dankeschön, den werde ich gleich testen.
Da hätte ich dann auch noch eine Variante mit dem Schalten der Weichen nacheinander (ungetestet):

Code: [Select]
const byte AnzahlGleise = 5;
const uint32_t STELLZEIT = 1000; // in Millisekunden

// Lichtschranke zur Gleisbesetzmeldung LSBG1-5
const byte LSBG[AnzahlGleise] = {PA8, PB15, PB14, PB13, PB12};

// Lichtschranke SBH Haupt
const byte LSHaupt = PA9;  // Lichtschranke zur Einfahrt in den SBH

// Ausgänge für Relais  der Weichenstellung weiche 1-5
const byte WA[AnzahlGleise] = {PA0, PA2, PA4, PA6, PB0};          // Weichen Abbiegen
const byte WG[AnzahlGleise] = {PA1, PA3, PA5, PA7, PB1};          // Weichen Geradeaus

// variable definieren
uint32_t RELAIS_timestore = 0; // Variable Speicher für Impulszeit Weichen

enum {EINFAHRT, STELLEN, AUS};
byte schritt = EINFAHRT;
byte gleis = 0; // Gleis 1 entspricht dem Zähler 0

void setup()
{
  for (byte g = 0; g < AnzahlGleise; g++)
  {
    // Pin Mode für Lichtschranken Gleisbesetztmeldung Gleis 1 - 5
    pinMode(LSBG[g], INPUT_PULLUP);
  }
  pinMode(LSHaupt, INPUT_PULLUP);

  for (byte g = 0; g < AnzahlGleise; g++)
  {
    // Pin Mode für Gleis an schalten
    pinMode(WA[g], OUTPUT);
    pinMode(WG[g], OUTPUT);
  }
}

void loop()
{
  switch (schritt)
  {
    case EINFAHRT:
      if (digitalRead(LSHaupt))     // Abfrage ob Zug einfäht. Lichtschranke an der Zufahrt
      {
        gleis = 0;
        schritt = STELLEN;
      }
      break;
    case STELLEN:
      if (millis() - RELAIS_timestore >= STELLZEIT)
      {
        if (gleis > 0)
        {
          digitalWrite (WG[gleis - 1], LOW);
          digitalWrite (WA[gleis - 1], LOW);
        }
        if (gleis < AnzahlGleise)
        {
          if (digitalRead(LSBG[gleis]))     // Abfrage ob SBH voll
          {
            digitalWrite (WG[gleis], HIGH);
          }
          else
          {
            digitalWrite (WA[gleis], HIGH);
          }
          RELAIS_timestore = millis();
          gleis++;
        }
        else
        {
          schritt = AUS;
        }
      }
      break;
    case AUS:
      if (!digitalRead(LSHaupt))     // Abfrage ob Zug nicht mehr einfährt. Lichtschranke an der Zufahrt
      {
        schritt = EINFAHRT;
      }
      break;
  }
}
Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

MicroBahner

Denkt Ihr bitte daran, das ich blutiger Anfänger bin? :-)
Wir bemühen uns ;). Und das muss ja nicht so bleiben 8) .

Hier ein Video vom SBH der von 2 extrem gelangweilten STM´s gesteuert wird.
Mir fällt auf, dass Die Züge beim Einfahren in ihr Gleis mehrfach stoppen/starten. Möglich, dass das an der Aufteilung auf 2 Prozessoren liegt, die nichts voneinander wissen. Aber das ist nicht sauber und sollte eigentlich nicht sein. Möglich dass da noch was drin ist, dass dir später auf die Füße fällt.

Erstens stellt das Board 26 I/O´s die nach dem booten schon so verwendet werden können zur Verfügung (ohne Remap).  Ich benötige für die bisherige Lösung aber 27,
Dafür gibt es Port-Expander. Ok, Du bist da noch nicht so tief drin, aber das ist eigentlich kein Hexenwerk. In meinem Sbf verwaltet der Hauptprozessor über 200 I/Os. Das ist grundsätzlich auch kein Problem.

Der zweite Grund ist, das das Board nun mal nix Kostet
Das ist kein Argument. Wichtig ist, was technisch die sinnvolle Lösung ist. Ich behaupt mal glatt, dass die 1-Prozessor Lösung am Ende auch die einfachere ist ( auch wenn Du das jetzt vielleicht noch nicht glaubst ;) )

Später zusammenzuführen sollte ja nicht so das Problem sein.
Vorausgesetzt Du berücksichtigst das von Anfang an, so wie ich das in meinem schon angesprochenen Link erklärt habe. Wenn nicht, fängst Du u.U. beim Zusammenführen wieder von vorn an.

Die sind dann auch nie Kaputt :-)
Ich habe auch nicht gemeint, dass die durch den 1-Sekunden Impuls kaputt gehen. Ich hatte nur gemeint, wenn sie wirklich einen 1-Sekunden Impuls brauchen, dass sie dann nicht mehr in Ordnung sind. Aber wenn Du nicht immer alle, sondern nur die notwendigen Weichen schaltest, geht es ja eh schneller.


Brauche ich das Pin hinter Relaistimestore? Ich weis das es so nicht funktioniert mir gehts nur um das "PIN"
Nein, Ausschalten darfst Du das Relais an der Stelle noch nicht.

Noch ein Frage, es gibt keinen befehl, der einen Ausgang für Zeitraum x auf HIGH Pegel hält, der nicht den Prozessor zum anhalten biringt? es muß über den millis Befehl realisiert werden?
Nein, sowas gibt es nicht direkt. Etwas einfacher geht es mMn mit dem Timer der MobaTools. Du kannst die pro Weiche einen Timer definieren. Am Anfang des lopp rufst Du eine Funktion auf, die grundsätzlich beim Ablauf des Timers das Weichen-Relais abschaltet. So in der Art
Code: [Select]
If ( WTimer[1].expired() ) digitalWrite( Rel[1], LOW );
 In deiner Weichenschalt-Funktion startest Du den Timer mit WTimer[1].setTime(1000);
Ist natürlich jetzt nur prinzipiell - im echten Programm steht da natürlich nicht fest '1' als Weichennummer und DU musst ja auch nach geradeaus und Abzweig berücksichtigen. Beim Timerablauf könntest Du da aber auch einfach immer beide abschalten.
Die Weichen dann nacheinander schalten zu lassen, ist bei der blockadefreien Variante etwas aufwändiger - wenn immer nur die notwendigen Weichen geschaltet werden aber vielleicht auch nicht notwendig. Edit: agmue war ja schnell, und hat schon was gezeigt ;)



Gruß, Franz-Peter

MicroBahner

Felder, millis und Schrittkette kann ich Dir nicht ersparen, wenn Du das einigermaßen zukunftssicher lösen möchtest.
Das sehe ich auch so. Das sind absolute Basics - da musst Du durch. Funktionen finde ich auch wichtig - aber da bist Du ja schon dran. Und die delay-freie Programmierung kann man sich mit den MobaTools etwas einfacher gestalten - aber das ist Ansichtssache. Meine Stummi-Kollegen fanden das jedenfalls immer einfacher so.
Gruß, Franz-Peter

kgbrus

Korrekt, das mit dem blutigem Anfänger wird NICHT so bleiben. Würdet Ihr gar nicht zu lassen :-)

ich teste die Tage mal die MOBA Tools.

Port expander, das sagte mir mein Kollege schon. Ich möchte es am Anfang möglichst einfach halten. Zumindest die SW kann ich ja immer weiter verfeineren und verbessern. Gut bei den Port Expandern geht das nicht. Aber eventuell sehe ich im weiteren Verlauf ja, das ich den einen oder anderen Port doch nicht brauche, dann geht das auch ohne Port expander.

Selbiges, (einfach halten  zumindest noch) wollte ich auch für die SW. Der Delay Befehl ist da ein prima Beispiel. So wie es jetzt ist funktioniert der delay Befehl innerhalb der Weichenschaltung 1A. Packe ich die komplette SW auf ein Board wird es wahrscheinlich nicht mehr gehen. Deshalb hatte ich ja nach dem millis Befehl gefragt.

Aber wie Ihr seht beschäftige ich mich ja trotzdem damit eine bessere Lösung zu finden.
Und Ihr seit ne prima Unterstützung (mit leichtem Hang zum Anfänger verwirren :-)) !

Quote
Mir fällt auf, dass Die Züge beim Einfahren in ihr Gleis mehrfach stoppen/starten. Möglich, dass das an der Aufteilung auf 2 Prozessoren liegt, die nichts voneinander wissen. Aber das ist nicht sauber und sollte eigentlich nicht sein. Möglich dass da noch was drin ist, dass dir später auf die Füße fällt.
Nein daran liegt es nicht. Folgendes passiert:

Zug fährt auf Gleis 1 ein LSBG1 wird High - Ausgang GLAS1 (Gleis Abschaltung 1) wird High und Relais schaltet den Bahnstrom für 2 Sekunden (übrigens mittels millis) an. dann wird GLAS1 wieder LOW und das Relais fällt ab. somit wird der Fahrstrom (Relais) wieder abgeschaltet.
Dies wiederholt sich bis die Lok die vordere Endposition (LSBG1)erreicht hat.
mir wäre ein sanftes bremsen auch wesentlich lieber. Da Märklin aber AC hat, ist das nicht so einfach. Ich denke das geht nur über eine Phasenanschnittsteuerung um die Wechselspannung zu regeln.
Ist dann auch etwas für später. Auch könnte ich über einen Schrittmotor einfach den Regler vom Trafo bewegen......

GRuß

Kay

agmue

Du kannst die pro Weiche einen Timer definieren.
@kgbrus: Das bringt mich auf die Idee, die Weichen mit einem zeitlichen Versatz zu schalten. Daraus folgt dann eine Mischung aus millis und MobaTools (ungetestet):

Code: [Select]
const byte AnzahlGleise = 5;
const uint32_t STELLZEIT = 1000;   // in Millisekunden
const uint32_t UEBERLAPPUNGSZEIT = 600;   // in Millisekunden

#include <MobaTools.h>
MoToTimer WTimer[AnzahlGleise];

// Lichtschranke zur Gleisbesetzmeldung LSBG1-5
const byte LSBG[AnzahlGleise] = {PA8, PB15, PB14, PB13, PB12};

// Lichtschranke SBH Haupt
const byte LSHaupt = PA9;  // Lichtschranke zur Einfahrt in den SBH

// Ausgänge für Relais  der Weichenstellung weiche 1-5
const byte WA[AnzahlGleise] = {PA0, PA2, PA4, PA6, PB0};          // Weichen Abbiegen
const byte WG[AnzahlGleise] = {PA1, PA3, PA5, PA7, PB1};          // Weichen Geradeaus

// variable definieren
uint32_t RELAIS_timestore = 0; // Variable Speicher für Impulszeit Weichen

enum {EINFAHRT, STELLEN, AUS};
byte schritt = EINFAHRT;
byte gleis = 0; // Gleis 1 entspricht dem Zähler 0

void setup()
{
  for (byte g = 0; g < AnzahlGleise; g++)
  {
    // Pin Mode für Lichtschranken Gleisbesetztmeldung Gleis 1 - 5
    pinMode(LSBG[g], INPUT_PULLUP);
  }
  pinMode(LSHaupt, INPUT_PULLUP);

  for (byte g = 0; g < AnzahlGleise; g++)
  {
    // Pin Mode für Gleis an schalten
    pinMode(WA[g], OUTPUT);
    pinMode(WG[g], OUTPUT);
  }
}

void loop()
{
  switch (schritt)
  {
    case EINFAHRT:
      if (digitalRead(LSHaupt))     // Abfrage ob Zug einfäht. Lichtschranke an der Zufahrt
      {
        gleis = 0;
        schritt = STELLEN;
      }
      break;
    case STELLEN:
      if (millis() - RELAIS_timestore >= UEBERLAPPUNGSZEIT)
      {
        if (gleis < AnzahlGleise)
        {
          if (digitalRead(LSBG[gleis]))     // Abfrage ob SBH voll
          {
            digitalWrite (WG[gleis], HIGH);
          }
          else
          {
            digitalWrite (WA[gleis], HIGH);
          }
          WTimer[gleis].setTime(STELLZEIT);
          RELAIS_timestore = millis();
          gleis++;
        }
        else
        {
          schritt = AUS;
        }
      }
      break;
    case AUS:
      if (!digitalRead(LSHaupt))     // Abfrage ob Zug nicht mehr einfährt. Lichtschranke an der Zufahrt
      {
        schritt = EINFAHRT;
      }
      break;
  }
  for (byte g = 0; g < AnzahlGleise; g++)
  {
    if ( WTimer[g].expired() )
    {
      digitalWrite (WG[g], LOW);
      digitalWrite (WA[g], LOW);
    }
  }
}
Die Vorstellungskraft ist wichtiger als Wissen, denn Wissen ist begrenzt. (Albert Einstein)

MicroBahner

Der Delay Befehl ist da ein prima Beispiel. So wie es jetzt ist funktioniert der delay Befehl innerhalb der Weichenschaltung 1A. Packe ich die komplette SW auf ein Board wird es wahrscheinlich nicht mehr gehen.
Da Du den Fahrstrom ja besser erst einschalten solltest, wenn alle Weichen korrekt geschaltet sind, dürfte sogar das kein Problem sein.
Gruß, Franz-Peter

Go Up