Pin an zwei stellen im Programm aufrufen ?

Guten Tag zusammen.
Aufgrund eines Problems, das ich so nicht lösen kann (I.-Net Suche ohne Erfolg) wende ich mich an euch.
Sketchbeschreibung:
Hintergrund ist eine Signalsteuerung im Modellbau.
Ein-/ ausfahrende Züge sollen sowohl die Signalsteuerung (simpel, klappt) als auch die Weichnstellung übernehmen (Problem).
die Weiche wird über Pin 8 auf "Abzeig" gestellt, über pin 9 auf Geradausfahrt.
Im ersten Teil des Sketches läuft die Ansteuerung des Pin 8 problemlos.
Im zweiten Teil wird der Pin 8 wiederum aufgerufen und hier wird statt der eingestellten Dauer von ca. 2 sec(Testzeit), der Pin nur bei Auslösung Hallsensor (im Versuchsaufbau = Taster) aktiv: Taster ein = aktiv,Taster Ruhe = Pin inaktiv.
Nun find ich den Fehler nicht.
Bei Auskommentierung jeweils in einen Teil klappt es wiederum.
Frage der Woche:
ist der Mehrfach Aufruf so nicht möglich?
Hinweis:
als Arbeitstier fungiert ein Arduino UNO ( z.Zeit Ersatz aus China, bis Fa. R. aus Sande liefert)
Hinweis zum Code:
viele zukünftige Dinge sind schon vorbereitet, Deklariert und startklar gemacht.
Möglicherweise reicht der Kommentar aus, sonst gern auf Zuruf mehr...

// Arduino UNO als stationäres Gerät einsetzen
/*Signalsteuerung Hauptstrecke B und Nebenstrecke
Richtungen:
Nebenstrecke aus Richtung Chateau d'Or
Hauptstrecke/ Güterverkehr aus Richtung Industriegebiet

Input über Hallsensoren
Output= Ansteuerung Relais (Last über Impuls schalten)
Signale:
Einfahrt HBF S1
Ausfahrt Flötzingen S2

- Input 1 = Hallsensor Ausfahrt Flötzingen Gleis 41
- Input 2 = Hallsensor Ausfahrt HBF Gleis 21
- Input 3 = Hallsensor Einfahrt HBF Gleis 23 (aus Richtung Fabrik)
- Input 4 = Hallsensor Ausfahrt HBF Gleis 21

  -Output  1 = Signal S1 Halt Einfahrt HBF Gleis 23 (aus Richtung Fabrik)
  -Output  2 = Signal S1 Fahrt Einfahrt HBF Gleis 23 (aus Richtung Fabrik)
  -Output  3 = Fahrstrom "B" aus/ Fahrstrom Gleis 41 ein
  -Output  4 = Fahrstrom "B" ein/ Fahrstrom Gleis 41 aus
  -Output  5 = Weiche xx (= Abzweig Nebenstrecke)
  -Output  6 = Weiche xx (=geradeaus Hauptbahn)
  -Output  7 = Signal S2 "Halt"
  -Output  8 = Signal S2 "Fahrt"
  -Output  9 = Abschaltung Hallsensor Hall_1 Gleis 41
  -Output 10 = Einschalten Hall_1 Gleis 41
  -Output 11 = Abschaltung Hallsensor  Hall_2 Gleis 21
  -Output 12 = Einschalten Hallsensor  Hall_2 Gleis 21
  -Output 13 = Abschalten Hallsensor Hall_3 Gleis 21
  -Output 14 = Einschalten Hallsensor Hall_3 Gleis 21
  -Output 15 = Abschalten Hallsensor Hall_4 Gleis 41


 */
// Deklaration I/O Pin
// Hallsensoren
const int Hall_1 = 0;  // Hallsensor 1
const int Hall_2 = 1;  // Hallsensor 2
const int Hall_3 = 2;  // Hallsensor 3
const int Hall_4 = 3;  // Hallsensor 4

//Signal 1 Einfahrt HBF
const int Signal_1H = 4; // Fluegel Halt
const int Signal_1F = 5; // Fluegel Fahrt

//Fahrstrom
const int F_Strom_aus = 6;  //Fahrstrom B aus
const int F_Strom_ein = 7;  // Fahrstrom B ein
// Weiche 1
const int WeicheA = 8;
const int WeicheG = 9; 
// Signal 2 Ausfahrt Flötzingen
const int Signal_2H = 10; // Fluegel Halt
const int Signal_2F = 11; // Fluegel Fahrt
// Hallsensoren aus/ ein
const int Hall_1aus = 12;  // Hallsensor 1 abschalten
const int Hall_1ein = 13;  // Hallsensor 1 einschalten
const int Hall_2aus = 14;  // Hallsensor 2 abschalten
const int Hall_2ein = 15;  // Hallsensor 2 einschalten
const int Hall_3aus = 16;  // Hallsensor 3abschalten
const int Hall_3ein = 17;  // Hallsensor 3 einschalten
const int Hall_4aus = 18;  // Hallsensor 4 abschalten
const int Hall_4ein = 19;  // Hallsensor 4 einschalten
// Zeiten 
unsigned long Startzeit1 =0;
unsigned long Startzeit2 =0;
unsigned long Startzeit3 =0;
unsigned long Startzeit4 =0;

void setup() {
// Hallsensoren
pinMode (Hall_1, INPUT_PULLUP);  // Pin 0 (PD0)
pinMode (Hall_2, INPUT_PULLUP); // Pin 1 (PD1)
pinMode (Hall_3, INPUT_PULLUP); // Pin 2 (PD2)
pinMode (Hall_4, INPUT_PULLUP); // Pin 3 (PD3)
// Signal 1 HBF
pinMode (Signal_1H,OUTPUT); // Pin 4 (PD4)
pinMode (Signal_1F,OUTPUT); // Pin 5 (PD5)
//Fahrstrom
pinMode (F_Strom_aus,OUTPUT); //Pin 6 (PD6)
pinMode (F_Strom_ein,OUTPUT); // Pin 7 (PD7)
// Weichensteuerung
pinMode (WeicheA, OUTPUT); // Pin 8 (PB0)
pinMode (WeicheG, OUTPUT); // Pin 9 (PB1)
// Signal 2 Flötzingen
pinMode (Signal_2H, OUTPUT);  // Pin 10 (PB2)
pinMode (Signal_2F, OUTPUT);  // Pin 11 (PB3)
// Hallsensoren aus
pinMode (Hall_1aus, OUTPUT);  // Pin 12 (PB4)
pinMode (Hall_1ein, OUTPUT);  //Pin  13 (PB5)
pinMode (Hall_2aus, OUTPUT);  //Pin  14 (PC0)
pinMode (Hall_2ein, OUTPUT);  //Pin  15 (PC1)
pinMode (Hall_3aus, OUTPUT);  //Pin  16 (PC2)
pinMode (Hall_3ein, OUTPUT);  //Pin  17 (PC3)
//pinMode (Hall_4aus, OUTPUT);  //Pin  18 (PC4) Bei Bedarf verwendbar
//pinMode (Hall_4ein, OUTPUT);  //Pin  19 (PB5) Bei Bedarf verwendbar
}

void loop() 
{
// Start Void
// Abfrage Hallsensor
// Nebenstrecke Flötzingen -> HBF
if(digitalRead(Hall_1)== LOW)     // Pin 0           // Abfrage Taster
{
 digitalWrite(Signal_1H,HIGH);   // Pin 4            // Einschalten und Timer starten
  Startzeit1=millis();                               // Zeitpunkt Start
}
else if (millis()-Startzeit1>1000)                   // Vergleich Start und abgelaufene Zeit
{  
 digitalWrite (Signal_1H,LOW);     // Pin 4          // Ausschalten   
}
if(digitalRead(Hall_1)== LOW)      // Pin 0 
{
 digitalWrite(F_Strom_aus,HIGH);   // Pin 6
Startzeit1=millis();
}
else if (millis()-Startzeit1>1500)
{  
 digitalWrite (F_Strom_aus,LOW);  // Pin 6       
}
//------------Markierung fuer C&P Beginn
if(digitalRead(Hall_1)== LOW)
    {
     digitalWrite(WeicheA,HIGH);      // Pin 8, erste Nutzung
     Startzeit1=millis();
    }
else if (millis()-Startzeit1>2000)
    {  
    digitalWrite (WeicheA,LOW);   // Pin 8, erste Nutzung   
    }
    // ------------Markierung fuer C&P Ende
if(digitalRead(Hall_1)== LOW)
{
 digitalWrite(Hall_2aus,HIGH); 
Startzeit1=millis();
}
else if (millis()-Startzeit1>2500)
{  
 digitalWrite (Hall_2aus,LOW);        
}
 // - Nebensttrecke HBF -> Flötzingen - //
if(digitalRead(Hall_2)== LOW)             
  {
   digitalWrite(Signal_1F,HIGH);              
   Startzeit2=millis();                      
  }
else if (millis()-Startzeit2>1000)       
   {  
   digitalWrite (Signal_1F,LOW);                 
   }
// Fahrstrom aus „B“
    if(digitalRead(Hall_2)== LOW)
    {
    digitalWrite(F_Strom_ein,HIGH); 
    Startzeit2=millis();
    }
     else if (millis()-Startzeit2>1500)
    {  
    digitalWrite (F_Strom_ein,LOW);        
   } 
 // Beginn Problembereich // 
 if(digitalRead(Hall_2)== LOW)
    {
     digitalWrite(WeicheA,HIGH);      // Pin 8, zweite Nutzung
     Startzeit2=millis();
    }
else if (millis()-Startzeit2>2000)
    {  
   digitalWrite (WeicheA,LOW);   // Pin 8, zweite Nutzung   
    }

// Bereich für weitere Programmteile...

    
}// Ende Void

...hoffe, ich war verständlich genug.
Vielen schon jetzt, freue mich auf Lösungsidee.
Und sollte jemand einen Vorschlag zum verbessern des Sketches haben, gern lerne ich was dazu.
lieben Gruß aus OWL
Flötzinger

Ich würde bei der Abfrage der Hallsensoren nur die Startzeit auf die aktuellen millis() setzen.

An der Stelle würde ich den Ausgang noch nicht auf HIGH setzen.

Der nächste Schritt mit dem vergleichen der Zeit würde ich in eine separate if- else Schleife setzen, und nicht in die Abfrage des Hallsensors als if else....

Und dann sagst du dann einfach, dass der Ausgang den einen Zustand haben soll, wenn die Zeit noch nicht abgelaufen ist, anderenfalls den anderen Zustand annehmen soll...

ist der Mehrfach Aufruf so nicht möglich?

Hab jetzt nur grob draufgeschaut, aber so ist es vermutlich nicht möglich.

Ein loop-Durchlauf dauert keine Zeit, und wenn darin
beide Anweisungen

  digitalWrite (WeicheA,LOW);   // Pin 8, erste Nutzung   
...
  digitalWrite(WeicheA,HIGH);      // Pin 8, zweite Nutzung

im gleichen Durchlauf drankommen, ist das einfach schlecht und es lohnt nicht zu überlegen wie sich der Pin 8 in Wirklichkeit verhält.

Es sollte dir als Eisenbahner klar sein, was passieren soll, wenn beide if zutreffen.
Vermutlich darf WeicheA nur dann auf LOW geschaltet werden, wenn beide Zeiten abgelaufen sind.

MaHa's Vorschlag (den Zustand der Verzögerungen über die jeweiligen Startzeit Variablen zu merken und nur einmal die Ausgänge zu setzen, je nach laufender/abgelaufener Zeit) scheint mir erfolgversprechend.


Ganz am Rande: void heisst nur "ungültig". Wir reden über die Funktion loop()
( die keinen Ergebniswert liefert )

@Michael_x:
kurz eingeworfen:
es Gott sei dank nur eine Weiche, Bezeichnung leicht irritierend, da das A den Abzweig und G die Geradeaufahrt
benennt.
Mein Fehler, next Time besser benennen.
Und ja bei 2 Weichen wärs ne echte Katastrophe, mehrere Preiserlein kämen zu Schaden..
Danke für den Hinweis.
Bei // Void geschlampt, sollte Loop() noch dazu (Gedächnisstütze, weil gerne mal eine Klammer mehr oder zu wenig ...)

@MaHa:
ähh, noch nicht ganz verstande, werde ich aber seperat aufbauen und probieren, vielleicht kommt dann der AHA Moment.

Ergänzend zum Weichenstellen:
die "Schaltzeit H und L wird vermutlich ca 1 sec. betragen müssen, da der z.Zeit verbaute "ServoVerwalter" recht lahm im Erkennen von eingangssignalen ist.
käme mir da die Schleife nicht zu schnell bei schalten?

....festgestellt:
wenn ich die zugeordneten "Startzeiten" (jeweils zu den Hallsensoren( da versch. Abschnitte) zu Pin 8 in allen genutzten Bereichen (1,2,3) immer der Startzeit 1 zuordne, klappt es....
kommt mir grad merkwürdig vor.
Sollte nicht die Zeit über Millis immer eigenständig sein?
Falls das jemand nachbaut und eine Fehlerreproduktion mach kann, wäre ich u.U. doch nicht so doof.
am nichtoriginalen UNO kann es wohl dann nicht liegen.

Gibt es (verständliche, weil einfache Interpreter/Compiler) Datenwroschler, die man nutzen kann?
Vielleicht sogar was zum simulieren?
Habt jetzt schon Dank.
mit Wünschen für einen geruhsamen Abend verbleibe ich mit sommerlichen Grüßen.
Flötzinger

Hallo Flötzinger,
zunächst mal ein Hinweis zur Nutzung der Ports: Du solltest Pin 0 und 1 nicht nutzen. Das ist beim UNO die serielle Schnittstelle, die am seriell-USB Wandler hängt. Das kann Probleme machen. Ausserdem verbaust Du dir damit die Möglichkeit, den seriellen Monitor zum Debuggen zu verwenden.

Zu deinem Problem:

  if (digitalRead(Hall_1) == LOW)
  {
    digitalWrite(WeicheA, HIGH);     // Pin 8, erste Nutzung
    Startzeit1 = millis();
  }
  else if (millis() - Startzeit1 > 2000)
  {
    digitalWrite (WeicheA, LOW);  // Pin 8, erste Nutzung
  }

Das schaltet den Pin8 IMMER auf LOW, wenn Hall_1 nicht aktiv ist und die Zeit einmal abgelaufen ist.
Wenn Du jetzt hier:

  // Beginn Problembereich //
  if (digitalRead(Hall_2) == LOW)
  {
    digitalWrite(WeicheA, HIGH);     // Pin 8, zweite Nutzung
    Startzeit2 = millis();
  }
  else if (millis() - Startzeit2 > 2000)
  {
    digitalWrite (WeicheA, LOW);  // Pin 8, zweite Nutzung
  }

Durch aktiviern von Hall_2 den Pin8 einschaltest, wird er von dem Codesegment oben sofort wieder ausgeschaltet, da ja beides im loop andauernd abwechselnd ausgeführt wird.
Benutzt Du nun für beide Segmente die gleiche 'Startzeit'-Variable, reagiert auch dein 1. Segment darauf, und schaltet eben nicht sofort ab.
Du solltest die Zeitvariablen nicht den Eingängen, sondern den Ausgängen zuordnen. Dann - wie schon von MaHa vorgeschlagen bei der Abfrage der Hallsensoren nur die Zeiten setzen und dann in einem eigenen Programmblock dementsprechend die Ausgänge setzen/Rücksetzen.
Ich würde die Aktivitäten, die durch die Hall-Sensoren ausgelöst werden auch zusammenfassen. D.h. einmal den Hall-Sensor abfragen, und dann dort alles aktivieren, was der Hallsensor auslösen soll.

Hallo zusammen.
@MicroBahner:
Danke für den Tip mit Port 0 und 1.
War mir nicht bekannt. wird korrigiert.
zum Tip von MaHa, bin ich noch nicht zugekommen. Macht aber, jetzt nach den Erklärungen meinen Blick dafür frei.Habe ich verstanden und versuch ich mal umzustzen.

Die Ansage " in Böcken" bedeutet, ich könnte, sollte tunlichst etwas über Blöcke ( Case?) lernen.
Oder liege ich mit "Case" falsch?

Dann schnippel ich mal die "überschüssigen" Abfragen vom Hallsensor heraus.
...bin mal gespannt, was ich da so lerne (oder auch nicht).

Jetzt muss ich allerdings erstmal Neu-Flötzinger bespassen.
bis dann und Danke!
Flötzinger

Mit 'Programmblock' waren erstmal einfach ein paar Zeilen logisch zusammengehöriger Anweisungen gemeint. Ob das in einer switch-Anweisung oder einem if-Block oder sonstwo :wink: steht, hangt dann vom konkreten Einzelfall ab.

guten Abend,
Tip mit den Programmblock ist klasse, weniger ist tatsächlich deutlich mehr an Leserlichkeit.Zeitfktor kann ich allerdings nicht beurteilen.
nun kommt noch eine weitere Frage:

if(digitalRead(Hall_1)== LOW)     // Pin 0    Abfrage Hallsensor 1           
{
  digitalWrite(Signal_1H,HIGH);        // Pin 4     einschalten     
  digitalWrite(WeicheA,HIGH);          // Pin 8         "
  digitalWrite(Hall_2aus,HIGH);        // Pin 14        "    
  digitalWrite(F_Strom_aus,HIGH);      // Pin 6         "
    Startzeit1=millis();               // Zeitpunkt Start
}
  else if (millis()-Startzeit1>1500)   // Vergleich Start und abgelaufene Zeit
  {  
    digitalWrite (Signal_1H,LOW);      // Pin 4    Ausschalten   
    digitalWrite (WeicheA,LOW);        // Pin 8       "
    digitalWrite (F_Strom_aus,LOW);    // Pin 6       "
// DigitalWrite verzögert ausführen    
    digitalWrite (Hall_2aus,LOW);      // Pin 14      "
   
   }

Pin 14 soll erst nach 15 sekunden wieder"Low" gesetzt werden.
welche Möglichkeit gibts? mein Versuch mit Delay() ist , wie immer, kläglich gescheitert.
any hints?
Danke für eure Mühen.
wbr. Flötzinger

  ...
  else if (millis()-Startzeit1>1500)   // 1.5 sec verzögert 
  { 
    digitalWrite (Signal_1H,LOW);      // Pin 4    Ausschalten   
    digitalWrite (WeicheA,LOW);        // Pin 8       "
    digitalWrite (F_Strom_aus,LOW);    // Pin 6       "
    if (millis()-Startzeit1>15000)  // 15 sec verzögert
    {
        digitalWrite (Hall_2aus,LOW);      // Pin 14      "
    }
  }
   ...

kopfklatsch (wahlweise auch Kopf meets Tisch)
Danke Michael_x, war auch zu simpel, als das ich darauf gekommen wäre.
beschämt nach links abgeht

Hallo "Gemeinde":
möchte mich jetzt noch mal recht herzlich für eure Hilfe bedanken.
Nach einigen (widerholten) üben habe ich das Sketch so wie ich es brauche.
ordentlich zusammen gestrichen, kommentiert (weil man ist ja vergesslich).
Meine nächste Aufgabe ist nun, die Steuersignale über Darlington Arrays zu verstärken, um
die zugehörigen Relais zu schalten.

Sicherlich wird es noch das ein oder andere Sketch geben, wo ich eure Hilfe benötige.

mit herzlichen Grüssen aus OWL
Flötzinger