Drehscheibe Modellbahn mit RF24

Hi
Jupp :slight_smile:

if (digitalRead (hal) == LOW);

Die IF-Abfrage ist an dem ; zuende.
Die Klammerung hat dahinter keinen höheren Sinn mehr - der Code wird ausgeführt, weil Er eben hinter der IF steht.

Entferne das ; , dann greift die Klammer wieder, wenn die Bedingung wahr ist.

MfG

if ((gleisNeu != gleisAlt) && (enter == true)) {
    if (digitalRead (hal) == LOW) {
    for (schritte != 0; schritte >0; schritte-- ) {
    //if (digitalRead (hal) == LOW);{
    //schritte--;
    Serial.println("Schritte");
    Serial.println(schritte);
    delay(2000);}
    enter = false;
    gleisAlt = wertSpeichern;
}

hm... Funktionirt aber trotzdem nicht. Der code rast jetzt durch und wenn ich den Hall einmal betätige läuft die Schleife wieder automatisch. Aber sie soll jedesmal wenn der Hall betätigt wird jedesmal die Variable schritte um 1 runter zählen.

Hi

Du wartest, bis der ein neues Gleis gewählt wurde und Enter gedrückt wurde
Jetzt wartest Du darauf, daß der Hall-Sensor LOW zeigt
Jetzt Startest Du eine Schleife, Die alle 2 Sekunden einen Wert runter zählt.

Ich denke, der Sketch macht genau Das, was Du geschrieben hast.
Mit ziemlicher Sicherheit aber nicht Das, was Du willst.

Du willst:

  • den Hall-Sensor IMMER abfragen - direkt in der loop
  • den Motor starten, wenn eine Fahrt gestartet wird (und der Abstand !=0 ist)
  • den Motor stoppen, wenn der Abstand ==0 ist
  • die Schritte (um 1) herunterzählen, wenn der Hall-Sensor von HIGH nach LOW wechselt
    ... die loop() wird tausend Mal die Sekunde durchrannt und trotzdem wird nur dann auf etwas reagiert, wenn's dafür 'an der Zeit ist'.

Ob der Motor nach dem letzten Hall-Impuls noch weiterlaufen muß, bis die Gleise übereinander stehen - kA - wenn nicht, müsste man einen Schritt vorher mit der Bremsrampe beginnen.

Das lässt sich wunderbar in eine State-Maschine einbauen.
Dazu hat combie bereite eine Liste hier im Forum - solltest Du Dir ansehen.

MfG

[
Du willst:

  • den Hall-Sensor IMMER abfragen - direkt in der loop

Nein der Hall soll nur abgefragt werden, wenn die Bühne dreht und der Motor läuft

  • den Motor starten, wenn eine Fahrt gestartet wird (und der Abstand !=0 ist)

Ja genau

  • den Motor stoppen, wenn der Abstand ==0 ist

ja genau

  • die Schritte (um 1) herunterzählen, wenn der Hall-Sensor von HIGH nach LOW wechselt

Stimmt auch

Wenn die Schritte abgelaufen sind kann, kann man über den Drehencoder erst das nächste Zielgleis wählen.

... die loop() wird tausend Mal die Sekunde durchrannt und trotzdem wird nur dann auf etwas reagiert, wenn's dafür 'an der Zeit ist

Hi

Was stört Dich daran, daß der Hall-Sensor abgefragt wird, wenn die Bühne Sich nicht dreht?
Ohne Drehung wird auch keine Flanke kommen, Die man auswerten könnte - und ausgewertet wird eh nur, wenn der Motor drehen soll.

Motor = stop ;// Drehrichtung des Motor bei Start auf STOP (oder ggf. Referenz-Fahrt)
...
setup(){
//Motor-Pin auf OUT, Hall-Pin auf IN, ...
}
...
loop(){
  //... Encoder auswerten und 'Soll' hoch/runter zählen
  static boolean flanke=false;
  static boolean hallalt=false;
  boolean hallneu=digitalRead(hall_pin);
  if (hallalt==true && hallneu==false){
     flanke=true;
  }else{
     flanke=false;
  }
  hallalt=hallneu;
  Wenn (Motor!=stop && Flanke=true){
    schritt--;
  }
  Wenn (schritt==0 && Motor!=stop){
    Motor=stop;
  }
  Wenn (Enter=gedrückt && Soll != Ist && Motor==stop){
     byte linksrum=abs(Soll-Ist);
     byte rechtsrum=abs(Ist-Soll);
     Wenn (linksrum <= rechtsrum){
        schritte=linksrum;
     }else{
        schritte=rechtsrum;
     }
  }
  if (motor==stop && schritte!=0){
     if (schritte==linksrum){
        Motor=links;
     }else{
        Motor=rechts;
     }
  }
}

So in der Art würde ich's versuchen.

Das Zielgleis kann IMMER eingestellt werden.
Eine neue Fahrt kann nur gestartet werden, wenn die Bühne nicht dreht, dann wird das eingestellte Gleis als Ziel übernommen (bzw. die Schritte dahin berechnet und der Motor gestartet).
Während der Motor fährt, werden bei fallender Flanke jeweils ein Schritt abgezogen.
Bei Schritt auf Null wird der Motor angehalten.
Es wird jeweils in die Richtung der kürzeren Entfernung gestartet.
Man kann, sobald die Bühne läuft, problemlos ein neues Zielgleis anwählen, die Übernahme geht aber erst, wenn die vorherige Fahrt beendet wurde.

Man kann einige der Abfragen kombinieren - so ist Es nicht wirklich nötig, in mehreren auf einander folgenden IF-Abfragen 'Motor==stop' abzufragen - Das könnte man in einer IF erschlagen und in Deren Körper die anderen IFs verarbeiten.

Man kann den Motor auch in ein switch-case einsetzen und dort z.B. die Referenz-Fahrt abfrühstücken, bei stop die Fahrt starten, sofern Soll!=Ziel und Enter gedrückt sowie bei links/rechts prüfen, ob wir bereits am Ziel sind (= Motor stoppen) bzw. die Flanke des Hal-Sensor auswerten.
= State-Maschine

MfG

Das mit der Statemachine verstehe ich nicht. Wie soll mir das bei meinem Projekt helfen?

Oder besser gesagt womit fange ich da in meinem Projekt an?

Keiner ne Idee?

Hi

Ein klein Wenig darfst Du schon selber machen - Ideen habe ich genug, bekomme Diese aber, auch aus Mangel an Zeit, kaum umgesetzt.
Und nur ein kleiner Teil davon hat was mit Arduino zu tun!!

Ach so ... Du sprichst von DEINEM Sketch?
Meine Idee dazu steht weiter oben, mit etwas erkennbarem 'guten Willen' wäre wohl nicht nur ich auch bereit, Dich weiter in die richtige Richtung zu schubsen.

Du verstehst die State-Maschine nicht?
DAS kann man (in diesem Fall Du) ja ändern.

MfG

Sorry ich habe mich falsch ausgedrückt. Ich meinte ich verstehe nicht wie eine Statemachine mir dabei helfen soll.

-Es muss der Encoder eingelesen werden (das macht der Code)
-Schritte berechnet werden (das macht der Code)
-Motor angesteuert werden bis Schritte auf 0 sind (Hall am Magnet vorbei ist) das macht der Code noch nicht (da häng ich momentan)

  • entscheidung ob der Motor links oder rechts drehen muss (das macht er auch noch nicht)

Könnt ihr mir einen Tip geben wie man es hinbekommt das man bei der Berechnung 48+1=1 bekommt und nicht 48+1=49?

(48+1)%48

Aber ob Dir das was bringt?

Gruß Tommy

So bin mal wieder bei dem Projekt. Also wäre es richtig das die Abfrage des des Drehencoders in dem Zustandsautomaten immer der Grundzustand (Schleife) ist?

Könnte man das auch so machen?

 if (schritte != 0){
      while ((schritte != 0) && (enter == true) && (sensor == HIGH)) {
       
          schritte--;
          Serial.println("Schritte");
          Serial.println(schritte);
          delay(2000);
      }
    }
     else if (schritte == 0) {
          enter = false;
          gleisAlt = wertSpeichern;
       }

Zu if (schritte != 0) ist else schon schritte != 0.
Da musst Du nicht noch ein zusätzliches if (schritte == 0) hinzufügen.

Ansonsten weiß ich nicht, was Du damit aussagen willst.

Gruß Tommy

Das Problem ist das die While Schleife permanent läuft obwohl der Sensor nicht betätigt wird. ?

Was brauchst Du ein while? Du hast doch loop.
Was sagt den die Ausgabe der Schritte?

Gruß Tommy

Naja ich versuche halt die errechneten Schritte über den Sensor runter zu zählen. Immer wenn der Sensor betätigt wird, soll schritte - 1 gerechnet werden bis schritte = 0 sind.

Hi

DAS könnte daran liegen, daß der Sensor NIE neu gesetzt wird.
Nur, weil Du einer Speicherstelle den Namen Sensor gegeben hast und auch irgend wo einen Digital-In darin speicherst, steht darin nicht automatisch der aktuelle Zustand von besagtem Sensor.

Schritte wird wohl negativ sein und immer negativer werden - vermute ich.
Sonst sollte die While-Schleife nach 'Schritte' Schritten auch beendet werden.

MfG

PS: Weder enter noch sensor werden innerhalb der Schleife neu eingelesen - dann müssen Die auch nicht in die While-Bedingung.
Oder, wie Tommy schon schrieb: loop() ist eine Schleife - Die reicht dafür komplett.

Also müsste ich den Sensor Zustand zwischenspeichern und dann wieder zurück setzen?