Modellbahn Taster an Nano

Hallo zusammen,
ich hätte mal folgende Frage:
ich habe einen Reedkontakt unter den Gleisen sitzen, bei dem tritt das Problem auf das er in Längsrichtung 2x schaltet. Also zu Beginn und um Ende. Warum auch immer. Quer, wo er funktioniert kann ich ihn nicht reinbauen, da sitzt er dann zu tief (schaltet der Lokmagnet nicht) und höher trifft er an die Gleiskontakte an (Fremdspannung).
Wie kann ich den zweiten Teil des Codes verändern, daß das Relais nicht gleich zurück geschaltet wird? Also eine Art Sperre/Verzögerung einprogrammieren?
Danke schonmal für eure Hilfe.

Blockquote

// Programm Kehrschleife

int rel1 = 7 ; // PIN für Relais1
int rel2 = 8 ; // PIN für Relais2
int rel3 = 9 ; // PIN für Relais3
int mhSensor1 =  2 ; // PIN für den Magnetischen Hall Sensors 1
int mhSensor2 =  3 ; // PIN für den Magnetischen Hall Sensors 2
int mhSensor3_4 =  4 ; // PIN für den Magnetischen Hall Sensors 3 und 4

int buttonstatus = 0;
int buttonZaehler = 0;
int letzterStatus = 0;

void setup () {
  pinMode (rel1, OUTPUT) ; // definieren des PIN's für Relais1 als Ausgangssignal
  pinMode (rel2, OUTPUT) ; // definieren des PIN's für Relais2 als Ausgangssignal
  
  pinMode (mhSensor1, INPUT_PULLUP) ;  // definieren des PIN's für den Sensor1 als Eingangssignal
  pinMode (mhSensor2, INPUT_PULLUP) ;  // definieren des PIN's für den Sensor2 als Eingangssignal
  
}

void loop () {
  int val = digitalRead (mhSensor1) ; // Lesen des Zustandes des Sensors1.
  if (val == LOW) { //Wenn dieser AN ist dann soll Relais1 anziehen.
    digitalWrite (rel1, LOW);
    delay (15000);

  } else { //Wenn dieser AUS ist dann soll Relais1 NICHT anziehen.
    digitalWrite (rel1, HIGH);
  }


  {
    int val = digitalRead (mhSensor2) ; // Lesen des Zustandes des Sensors2.
    if (val == LOW) { //Wenn dieser AN ist dann soll Relais2 anziehen.
      digitalWrite (rel2, LOW);
      delay (15000);

    } else { //Wenn dieser AUS ist dann soll Relais2 NICHT anziehen.
      digitalWrite (rel2, HIGH);
    }

  }
  {

    Serial.begin(9600);
    pinMode(rel3, OUTPUT);
    pinMode(mhSensor3_4, INPUT_PULLUP);

  }

  {

    buttonstatus = digitalRead(mhSensor3_4);

    if (buttonstatus != letzterStatus)
    {
      if (buttonstatus == 1)
      {
        buttonZaehler++;
      }

      else
      {
        digitalWrite(rel3, HIGH);
      }
    }

    if (buttonZaehler % 2 == 0)
    {
      digitalWrite(rel3, LOW);
      buttonZaehler = 0;
    }

    else
    {
      digitalWrite(rel3, HIGH);
    }
    letzterStatus = buttonstatus;
    Serial.println(buttonZaehler);
    delay(10);
  }
}

weg mit delay().

merk die die Zeit (millis()) beim ersten Kontakt in einer Variable previousMillis() und werte aus, ob millis()-previousMillis > z.B. eine Sekunde ist.

eigentlich genau das was in "BlinkWithoutDelay" erklärt wird.
Das ist die Mutter aller Sketche für dich!

p.s:
drück mal strg T in der IDE zum formatieren.

das im loop() macht nicht viel Sinn oder?

    Serial.begin(9600);
    pinMode(rel3, OUTPUT);
    pinMode(mhSensor3_4, INPUT_PULLUP);

Ohje
da beschäftige ich mich zu wenig und zu selten damit, da ich es weniger brauche.
Wo find ich :
"BlinkWithoutDelay" ?

Das sind ja mal etwas einfachere Sachen :unamused:

Sowas ist ganz schlecht. Da ist der Arduino 15 Sekunden lang 'blind'. Da reagiert er nicht wenn ein anderer Sensor schaltet.

Das gehört ins setup()

Das verstehe ich nicht so ganz ( was ist hier 'Beginn' und was ist 'Ende' ) ? Soll das zugehörige Relais erst beim 2. Schalten anziehen, oder sofort beim ersten?

Meine MobaTools enthalten Funktionalitäten, die dir hier das Leben erleichtern können. Speziell das Einlesen der Sensoren mit Flankenerkennung und das Zurückschalten der Relais nach einer vorgegebenen Zeit.
Das Beispiel Zeitgeber_02 zeigt das zeitgesteuerte Abschalten anhand von 2 Leds und 2 Tastern. Ist aber im Prinzip das gleiche wie bei dir.

danke :grinning:

Teile dein Loop auf und schmeiss unnötige Klammern raus.

Der untere Teil soll dann vermutlich der sein, den ich jetzt in die Funktion getSensor34() gepackt habe.
Im loop() dazu einfach einen Aufruf machen - das wird dann schon...

void loop ()
{
  getSensor34();
  int val = digitalRead (mhSensor2) ; // Lesen des Zustandes des Sensors2.
[...]

und dei Funktion als solches:

void getSensor34()
{
  constexpr unsigned bounceTime = 20;
  static unsigned long lastmillis = 0;
  if (millis() - lastmillis > bounceTime)
  {
    buttonstatus = digitalRead(mhSensor3_4);
    if (buttonstatus != letzterStatus)
    {
      lastmillis = millis();
      if (buttonstatus == 1)
      {
        buttonZaehler++;
      }
      else
      {
        digitalWrite(rel3, HIGH);
      }
    }
    if (buttonZaehler % 2 == 0)
    {
      digitalWrite(rel3, LOW);
      buttonZaehler = 0;
    }
    else
    {
      digitalWrite(rel3, HIGH);
    }
    letzterStatus = buttonstatus;
    Serial.println(buttonZaehler);
  }
}

mit der Variablen bounceTime kannst Du die "Sperrzeit" einstellen, die ablaufen muss, bevor ein nächster Impuls ausgewertet werden kann.

Irgendwie sieht mir die Zeile

    letzterStatus = buttonstatus;

an der falschen Stelle aus....

Zeitgeber 02 probiert, geht im Prinzip. Aber das es sich um eine Fahrspannungsumschaltung handelt, merkt er sich das Signal und die Lok fährt nach 2sec. (zB) wieder zurück. Wäre eine perfekte Pendelzugautomatik. Das heißt das zweite Signal muß komplett ausgeblendet / ignoriert werden.

Hallo
Zeige mal ein Gleisbild mit allen Blöcken und verbauten Kontakten.

Da verstehe ich jetzt nicht so ganz, wie das letztendlich funktionieren soll.

Wie @paulpaulson schon schrieb, brauchen wir wohl etwas mehr Info zu deinem Gleisbild mit den Kontakten und Relais. Dann kann man besser helfen.

Er hat das Problem, das bei einer Überfahrt zwei Impulse ausgelöst werden. Gezählt werden soll nur einer. So mein Verständnis.

Ich sehe nur ein Problem mit seinem Merker letzterStatus, den er an einer nicht plausiblen Stelle auf buttonstatus setzt.

Das habe ich schon verstanden. Aber das liesse sich ja auch lösen, indem man während der ablaufenden Zeit den Eingang ignoriert. Das scheint es aber nicht zu sein. Wirklich Tip's geben, kann man nur, wenn man das Umfeld kennt, und nicht nur sein Programm. Deshalb die Bitte, etwas mehr dazu zu schreiben.
Das die/ein Relais eine Fahrspannungsumschaltung macht, wurde vorher ja nicht geschrieben.
Es ist immer etwas schwierig, Vorschläge zur Programmverbesserung zu machen, wenn man nicht wirklich weis, was da letztendlich wie gesteuert werden soll.

Man kann vieleicht auch das Problem an der Wurzel lösen.
Du kannst am Reed am richtigen Ort (experimentell gefunden) einen kleinen Magneten anbringen sodaß der Reed entweder als Öffner arbeitet oder daß er sich nur einmal schließt.

Laut https://standexelectronics.com/de/services/interaktion-von-reed-schaltern-magneten/
hängt einmaliges oder mehrfaches Schalten des Reedkontakts bei Vorbeifahren eines Stabmagneten von der Entfernung ab ( Bild 13 und 15 am Ende der Seite).

Grüße Uwe

Flasche Magnet nicht S-N in horizontaler Position Benutzen nur S - N in Vertikaler S oben N unten.



so anbei die Bilder. F wäre der Reedkontakt. Genau das zweite Signal müsste ausgeblendet werden.

Bist du #9 gefolgt?
Warum habe ich auf meine angedeutete Frage keine Antwort bekommen?
Schade.

Das habe ich versucht, kam aber der gleiche Effekt.
Sorry das ich nicht beantwortet habe.

Bei uns funktioniert dieser Readkontakt quer montiert super. Vielleicht hilft ein stärkerer Magnet.

Aber davon abgesehen, sollte es doch funktionieren, nach dem ersten Signal des Readkontakt ein weiteres Signal vom Readkontakt in einen gewissen Zeitfenster zu ignorieren.

Kannst Du mal bitte das aufspielen, und die Ausgaben aus dem SerMon hier reinkopieren, wenn Du über den Reed fährst?
Ohne Zeiten fehlt mir jedes Gefühl.
Danke!

const byte mhSensor3_4 =  4 ; // PIN für den Magnetischen Hall Sensors 3 und 4
bool letzterStatus;
void setup ()
{
  Serial.begin(9600);
  pinMode(mhSensor3_4, INPUT_PULLUP);
  letzterStatus = digitalRead(mhSensor3_4);
}
void loop ()
{
  if (digitalRead(mhSensor3_4) != letzterStatus)
  {
    Serial.print(F("Tik: "));
    letzterStatus = !letzterStatus;
    Serial.print(millis());
    Serial.print(" ");
    Serial.println(letzterStatus);
  }
}

oder habe ich einen Fehler eingebaut:

Blockquote

// Programm Kehrschleife

int rel1 = 7 ; // PIN für Relais1
int rel2 = 8 ; // PIN für Relais2
int rel3 = 9 ; // PIN für Relais3
int mhSensor1 =  2 ; // PIN für den Magnetischen Hall Sensors 1
int mhSensor2 =  3 ; // PIN für den Magnetischen Hall Sensors 2
int mhSensor3_4 =  4 ; // PIN für den Magnetischen Hall Sensors 3 und 4

int buttonstatus = 0;
int buttonZaehler = 0;
int letzterStatus = 0;

void setup () {
  pinMode (rel1, OUTPUT) ; // definieren des PIN's für Relais1 als Ausgangssignal
  pinMode (rel2, OUTPUT) ; // definieren des PIN's für Relais2 als Ausgangssignal
  pinMode (mhSensor1, INPUT_PULLUP) ;  // definieren des PIN's für den Sensor1 als Eingangssignal
  pinMode (mhSensor2, INPUT_PULLUP) ;  // definieren des PIN's für den Sensor2 als Eingangssignal
  Serial.begin(9600);
  pinMode(rel3, OUTPUT);
  pinMode(mhSensor3_4, INPUT_PULLUP);
}

void loop () {
  int val = digitalRead (mhSensor1) ; // Lesen des Zustandes des Sensors1.
  if (val == LOW) { //Wenn dieser AN ist dann soll Relais1 anziehen.
    digitalWrite (rel1, LOW);
    delay (15000);

  } else { //Wenn dieser AUS ist dann soll Relais1 NICHT anziehen.
    digitalWrite (rel1, HIGH);
  }


  {
    int val = digitalRead (mhSensor2) ; // Lesen des Zustandes des Sensors2.
    if (val == LOW) { //Wenn dieser AN ist dann soll Relais2 anziehen.
      digitalWrite (rel2, LOW);
      delay (15000);

    } else { //Wenn dieser AUS ist dann soll Relais2 NICHT anziehen.
      digitalWrite (rel2, HIGH);
    }

  }
  { constexpr unsigned bounceTime = 2000;
    static unsigned long lastmillis = 0;
    if (millis() - lastmillis > bounceTime)
    {
      buttonstatus = digitalRead(mhSensor3_4);

      if (buttonstatus != letzterStatus)
      {
        if (buttonstatus == 1)
        {
          buttonZaehler++;
        }

        else
        {
          digitalWrite(rel3, HIGH);
        }
      }

      if (buttonZaehler % 2 == 0)
      {
        digitalWrite(rel3, LOW);
        buttonZaehler = 0;
      }

      else
      {
        digitalWrite(rel3, HIGH);
      }
      letzterStatus = buttonstatus;
      Serial.println(buttonZaehler);
      delay(10);
    }
  }
}