Drehscheibe Modellbahn mit RF24

Hab mal ein wenig weiter gemacht. Nur leider scheint er die While Schleife nicht auszuführen.

#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);


int messungPin1 = HIGH;
int messungPin1Alt = HIGH;
byte encoderWert = 0; // -1 ( eins weniger als 0 ) == 255
const byte hal = 3;
const byte encoderPinA = 10;            // Phase A vom Drehencoder
const byte encoderPinB = 11;             // Phase B vom Drehencoder
const byte tasterEnter = 12;                   // Pin an dem der Encoder Taster angeschlossen ist
int wertSpeichern = 0;                  // gespeicherter Encoderwert
int encoderGedrueckt = 0;              // Statusspeicher ob Encodertaster betätigt wurde
int encoderTaster = HIGH;             // Taster im Encoder
int gleisAlt = 0;                     // Scheibe Position alt
int gleisNeu = 0;                     // Position welche die Scheibe anfahren soll
bool enter = false;                   // Bestätigung das der Encoder gedrückt wurde
int schritte =0;                      // Schritte die deer Motor (Hallsensor betätigt) zurücklegen muss

unsigned long encoderDruckzeit;       // Zeit wann der Encodertaster betätigt wurde
unsigned long entprellZeit = 200;     // Zeit die nach der betätigung eines Tasters gewartet wird


 void setup() { 
 pinMode(encoderPinA, INPUT);
 pinMode(encoderPinB, INPUT);
 pinMode(tasterEnter, INPUT);
 pinMode(hal, INPUT);
 Serial.begin(9600);
 lcd.begin(16, 2);
 lcd.setCursor(0, 0);
 lcd.print("Encoder");
 lcd.setCursor(0, 1);
 lcd.print("Test");
 delay (2000);
 lcd.clear();
 lcd.begin(16, 2);
 lcd.setCursor(0, 0);
 lcd.print("Wert");
 lcd.setCursor(0, 1);
 lcd.print(encoderWert);
 } 

 void loop() {
 
 messungPin1 = digitalRead(encoderPinA);
 if ((messungPin1 == LOW) && (messungPin1Alt == HIGH)) {
 if (digitalRead(encoderPinB) == HIGH) {
 if (encoderWert < 24) encoderWert++ ;
} else {
 if (encoderWert > 1) encoderWert-- ;

  }
 
 lcd.begin(16, 2);
 lcd.setCursor(0, 0);
 lcd.print("Wert");
 lcd.setCursor(0, 1);
 lcd.print(encoderWert);
 
 }

 {
  encoderTaster = digitalRead(tasterEnter);
  if (encoderTaster == LOW)
  {
    encoderDruckzeit = millis();
    encoderGedrueckt = 1;
  }

  if ((millis() - encoderDruckzeit > entprellZeit) && encoderGedrueckt ==1) {
    
    
    wertSpeichern = encoderWert;
    Serial.println(wertSpeichern);
    encoderGedrueckt=0;
    enter = true;
  }

if (enter == true) {
  gleisNeu = wertSpeichern;
  schritte = gleisNeu - gleisAlt;
  Serial.print ("benoetigte Schritte  ");
  Serial.println(schritte);
  //gleisAlt = wertSpeichern;
  Serial.println(gleisNeu);
  Serial.println(gleisAlt);
  Serial.println(enter);
  

  if ((gleisNeu != gleisAlt) && (enter == true)) {
    while (schritte >0);{
    if (hal == LOW);
    schritte--;
    Serial.println("Schritte");
    Serial.println(schritte);
    }
  }
    else {
      enter = false;
    }
    
  }
//if ((schritte >12)&& (enter== true)) {
 // Serial.println("rechts");
  //enter = false;
}
//  else {
   // Serial.println("links"); 
    //enter = false;
//}

//}

  
 
 
 messungPin1Alt = messungPin1;

 
  }

Habt ihr ne Idee?

while (schritte >0);  // ??

Die while-Schleife geht nur bis zum Semikolon
Wenn (schritte > 0) hängt der Sketch hier für immer

So ganz habe ich die Sketch-Logik aber nicht verstanden ...

Ein Zahnrad welches in einem Getriebe eingebaut ist, besitzt einen drei Magneten an unteschiedlichen Stellen. Über den Encoder wähle ich aus welche position das Zahnrad nach betätigung des Encoder Tasters einehmen soll. Über den Hallsensor werden die Schritte gezählt wie oft der Magnet schon am Sensor vorbeikommen ist. Solange die Schritte noch nicht abgelaufen sind, Bekommt der Motor Strom. Wenn die Schritte dann null sind, wird der Motor abgeschalten. Der Motor ist noch nicht im Code eingebaut.

Ich hoffe ich habe etwas Licht ins dunkle gebracht.

Hallo,

du musst dich noch mal mit den Themen

while
if
Klannern { } und ; beschäfitgen

das geht bei Dir alles ein wenig durcheinander das führt dazu das der Sketch nicht das macht was Du erwartetst.

da wir nicht wissen was Du erwartest wird das schwer für uns 8)

Heinz

Dmit hast du Recht. Das mit den Klammern (), und Semikolons hab ich auch noch nicht begriffen. Habt ihr da nen Tip wo das verständlich erklärt wird?

#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);


int messungPin1 = HIGH;
int messungPin1Alt = HIGH;
byte encoderWert = 0; // -1 ( eins weniger als 0 ) == 255
const byte hal = 3;
const byte encoderPinA = 10;            // Phase A vom Drehencoder
const byte encoderPinB = 11;             // Phase B vom Drehencoder
const byte tasterEnter = 12;                   // Pin an dem der Encoder Taster angeschlossen ist
int wertSpeichern = 0;                  // gespeicherter Encoderwert
int encoderGedrueckt = 0;              // Statusspeicher ob Encodertaster betätigt wurde
int encoderTaster = HIGH;             // Taster im Encoder
int gleisAlt = 0;                     // Scheibe Position alt
int gleisNeu = 0;                     // Position welche die Scheibe anfahren soll
bool enter = false;                   // Bestätigung das der Encoder gedrückt wurde
int schritte =0;                      // Schritte die deer Motor (Hallsensor betätigt) zurücklegen muss

unsigned long encoderDruckzeit;       // Zeit wann der Encodertaster betätigt wurde
unsigned long entprellZeit = 200;     // Zeit die nach der betätigung eines Tasters gewartet wird


 void setup() { 
 pinMode(encoderPinA, INPUT);
 pinMode(encoderPinB, INPUT);
 pinMode(tasterEnter, INPUT);
 pinMode(hal, INPUT);
 Serial.begin(9600);
 lcd.begin(16, 2);
 lcd.setCursor(0, 0);
 lcd.print("Encoder");
 lcd.setCursor(0, 1);
 lcd.print("Test");
 delay (2000);
 lcd.clear();
 lcd.begin(16, 2);
 lcd.setCursor(0, 0);
 lcd.print("Wert");
 lcd.setCursor(0, 1);
 lcd.print(encoderWert);
 } 

 void loop() {
 
 messungPin1 = digitalRead(encoderPinA);
 if ((messungPin1 == LOW) && (messungPin1Alt == HIGH)) {
 if (digitalRead(encoderPinB) == HIGH) {
 if (encoderWert < 24) encoderWert++ ;
} else {
 if (encoderWert > 1) encoderWert-- ;

  }
 
 lcd.begin(16, 2);
 lcd.setCursor(0, 0);
 lcd.print("Wert");
 lcd.setCursor(0, 1);
 lcd.print(encoderWert);
 
 }

 {
  encoderTaster = digitalRead(tasterEnter);
  if (encoderTaster == LOW)
  {
    encoderDruckzeit = millis();
    encoderGedrueckt = 1;
  }

  if ((millis() - encoderDruckzeit > entprellZeit) && encoderGedrueckt ==1) {
    
    
    wertSpeichern = encoderWert;
    Serial.println(wertSpeichern);
    encoderGedrueckt=0;
    enter = true;
  }

if (enter == true) {
  gleisNeu = wertSpeichern;
  schritte = gleisNeu - gleisAlt;
  Serial.print ("benoetigte Schritte  ");
  Serial.println(schritte);
  //gleisAlt = wertSpeichern;
  Serial.println(gleisNeu);
  Serial.println(gleisAlt);
  Serial.println(enter);
}  


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

  
 
 
 messungPin1Alt = messungPin1;

 
  }

Hab den Code noch mal bearbeitet.

Hallo,

in der IDE Hilfe //Referenz da findest Du den grundsätzlichen Syntax zu den einzelnen Funktionen auch mit Beispielen. Es geht um eine Sprache da gibts feste Regeln, leider ist C da besonders streng.

üben , üben und möglichst wenig mit past&copy arbeiten. Englisch lernst Du auch nur wenn Du es sprichst und schreibst 8)

Woran liegt das, das die While Schleife ausgefhrt wird, obwohl der Hal gar nicht betätigt wird?

#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

int messungPin1 = HIGH;
int messungPin1Alt = HIGH;
byte encoderWert = 0; // -1 ( eins weniger als 0 ) == 255
const byte hal = 3;
const byte encoderPinA = 10;            // Phase A vom Drehencoder
const byte encoderPinB = 11;             // Phase B vom Drehencoder
const byte tasterEnter = 12;                   // Pin an dem der Encoder Taster angeschlossen ist
int wertSpeichern = 0;                  // gespeicherter Encoderwert
int encoderGedrueckt = 0;              // Statusspeicher ob Encodertaster betätigt wurde
int encoderTaster = HIGH;             // Taster im Encoder
int gleisAlt = 0;                     // Scheibe Position alt
int gleisNeu = 0;                     // Position welche die Scheibe anfahren soll
bool enter = false;                   // Bestätigung das der Encoder gedrückt wurde
int schritte = 0;                     // Schritte die deer Motor (Hallsensor betätigt) zurücklegen muss
unsigned long encoderDruckzeit;       // Zeit wann der Encodertaster betätigt wurde
unsigned long entprellZeit = 200;     // Zeit die nach der betätigung eines Tasters gewartet wird

void setup() {
  pinMode(encoderPinA, INPUT);
  pinMode(encoderPinB, INPUT);
  pinMode(tasterEnter, INPUT);
  pinMode(hal, INPUT);
  Serial.begin(9600);
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Encoder");
  lcd.setCursor(0, 1);
  lcd.print("Test");
  delay (2000);
  lcd.clear();
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Wert");
  lcd.setCursor(0, 1);
  lcd.print(encoderWert);
}

void loop() {
  messungPin1 = digitalRead(encoderPinA);
  if ((messungPin1 == LOW) && (messungPin1Alt == HIGH)) {
    if (digitalRead(encoderPinB) == HIGH) {
      if (encoderWert < 24) encoderWert++ ;
    } else {
      if (encoderWert > 1) encoderWert-- ;
    }
    lcd.begin(16, 2);
    lcd.setCursor(0, 0);
    lcd.print("Wert");
    lcd.setCursor(0, 1);
    lcd.print(encoderWert);
  }
  {  //<-- WTF macht diese Klammer???
    encoderTaster = digitalRead(tasterEnter);
    if (encoderTaster == LOW)
    {
      encoderDruckzeit = millis();
      encoderGedrueckt = 1;
    }
    if ((millis() - encoderDruckzeit > entprellZeit) && encoderGedrueckt == 1) {
      wertSpeichern = encoderWert;
      Serial.println(wertSpeichern);
      encoderGedrueckt = 0;
      enter = true;
    }
    if (enter == true) {
      gleisNeu = wertSpeichern;
      schritte = gleisNeu - gleisAlt;
      Serial.print ("benoetigte Schritte  ");
      Serial.println(schritte);
      Serial.println(gleisNeu);
      Serial.println(gleisAlt);
      Serial.println(enter);
    }
    if ((gleisNeu != gleisAlt) && (enter == true)) {
      while (schritte != 0) {
        if (digitalRead (hal) == LOW); {
          schritte--;
          Serial.println("Schritte");
          Serial.println(schritte);
          delay(2000); //ein Hall-Sensor prellt nicht und hier machst Du ganze 2 Sekunden NICHTS - mir ist bewusst, was Du hier willst
          enter = false;
          gleisAlt = wertSpeichern;
        }
      }
    }
  } // hier WTF-Klammer Nummer 2
  messungPin1Alt = messungPin1;
}  //DAS war Mal Zeile 128, jetzt 91 8-)

MfG

PS: Ggf., weil schritte ungleich Null ist?
PS²: Ggf. hilft Die hier die serielle Ausgabe weiter - wenn hier die benötigten Schritte <0 sind, hast Du bei Deiner Abfrage ein neues Problem
PPS: STRG+T und entfernen von unnötigen Leerzeilen ... ich wiederhole mich

Hi,

siehe #19 , #21

du darfst das was wir schreiben nicht nur lesen, sondern auch verstehen :wink:

Hab es gerade gemacht. Strg + T kannte ich noch nicht.
Aber ich frage doch in der While Schleife den Hal ab? Steh irgendwie auf dem Schlauch

Ich hoffe so ist es besser:-)

Was für ein Problem meinst du. Wenn die Schritte 0 sind kann ich die nächste Position wählen und es werden die von der jetzigen Position bis zur neuen Position benötigten Schritte berechnet und ausgeführt.

#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);


int messungPin1 = HIGH;
int messungPin1Alt = HIGH;
byte encoderWert = 0; // -1 ( eins weniger als 0 ) == 255
const byte hal = 3;
const byte encoderPinA = 10;            // Phase A vom Drehencoder
const byte encoderPinB = 11;             // Phase B vom Drehencoder
const byte tasterEnter = 12;                   // Pin an dem der Encoder Taster angeschlossen ist
int wertSpeichern = 0;                  // gespeicherter Encoderwert
int encoderGedrueckt = 0;              // Statusspeicher ob Encodertaster betätigt wurde
int encoderTaster = HIGH;             // Taster im Encoder
int gleisAlt = 0;                     // Scheibe Position alt
int gleisNeu = 0;                     // Position welche die Scheibe anfahren soll
bool enter = false;                   // Bestätigung das der Encoder gedrückt wurde
int schritte = 0;                     // Schritte die deer Motor (Hallsensor betätigt) zurücklegen muss

unsigned long encoderDruckzeit;       // Zeit wann der Encodertaster betätigt wurde
unsigned long entprellZeit = 200;     // Zeit die nach der betätigung eines Tasters gewartet wird


void setup() {
  pinMode(encoderPinA, INPUT);
  pinMode(encoderPinB, INPUT);
  pinMode(tasterEnter, INPUT);
  pinMode(hal, INPUT);
  Serial.begin(9600);
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Encoder");
  lcd.setCursor(0, 1);
  lcd.print("Test");
  delay (2000);
  lcd.clear();
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Wert");
  lcd.setCursor(0, 1);
  lcd.print(encoderWert);
}

void loop() {
  messungPin1 = digitalRead(encoderPinA);
  if ((messungPin1 == LOW) && (messungPin1Alt == HIGH)) {
    if (digitalRead(encoderPinB) == HIGH) {
      if (encoderWert < 24) encoderWert++ ;
    } else {
      if (encoderWert > 1) encoderWert-- ;
    }
    lcd.begin(16, 2);
    lcd.setCursor(0, 0);
    lcd.print("Wert");
    lcd.setCursor(0, 1);
    lcd.print(encoderWert);
  }
     encoderTaster = digitalRead(tasterEnter);
    if (encoderTaster == LOW)
    {
      encoderDruckzeit = millis();
      encoderGedrueckt = 1;
    }
    if ((millis() - encoderDruckzeit > entprellZeit) && encoderGedrueckt == 1) {
      wertSpeichern = encoderWert;
      Serial.println(wertSpeichern);
      encoderGedrueckt = 0;
      enter = true;
    }
    if (enter == true) {
      gleisNeu = wertSpeichern;
      schritte = gleisNeu - gleisAlt;
      Serial.print ("benoetigte Schritte  ");
      Serial.println(schritte);
      //gleisAlt = wertSpeichern;
      Serial.println(gleisNeu);
      Serial.println(gleisAlt);
      Serial.println(enter);
    }
    if ((gleisNeu != gleisAlt) && (enter == true)) {
      while (schritte != 0) {
        if (digitalRead (hal) == LOW); {
          schritte--;
          Serial.println("Schritte");
          Serial.println(schritte);
          delay(2000);
          enter = false;
          gleisAlt = wertSpeichern;
        }
      }
    }
    //if ((schritte >12)&& (enter== true)) {
    // Serial.println("rechts");
    //enter = false;
   //  else {
  // Serial.println("links");
  //enter = false;
  //}
  //}
  messungPin1Alt = messungPin1;
}

Hi,

Keine Ahnung worauf du stehst ,

Die Abfrage des Hallsensors hat doch nichts mit dem While zu tun , richtig ist das die Abfrage des Hallsensors nur erfolgt wenn die while schleife erfüllt ist.

nochmals der Vorschlag zurück zu #19 u #21

was willst Du in der while schleife eigentlich machen , wenn der Sensor belegt ist runter zählen bis 0 , das jedesmal anzeigen und dazwischen 2s warten. ?

Heinz

Jedes mal einen Schritt runterzählen wenn der Sensor vom Magneten betätigt wird. Bis die Schritte 0 sind. Die 2 Sekunden habe ich nur eingebaut, damit ich im Seriellen Monitor was sehe. Weil ja sobald ich den encoder Taster betätige die While Schleife ausgeführt wird, obwohl der Hal gar nicht betätigt ist.

Hi

Die Sache ist viel einfacher - diese 2 Sekunden wartet Er, damit der Hall-Sensor eben nur 1x erkannt wird.
NUR: Das Runterzählen der Schritte ist 'suboptimal'.
Was, wenn von Gleis 19 auf Gleis 18 gefahren werden soll?
Schritte=-1 ... und der Sketch läuft einige Runden, bis Das auf Null kommt (int geht bis -16768 runter ... nur Mal so)

Eigentlich eine schöne Aufgabe - nur hat sich der To hier schon etwas verrannt.
Der Ansatz ist stimmig, die Abarbeitung bedarf einer Verbesserung.
Aktuell wäre Es besser, Du lässt den Motor laufen, bis Dein IST-Gleis dem SOLL-Gleis entspricht - geht nur bei einer Drehscheibe und sieht Da dann auch noch blöd aus, wenn 23 Gleise nach links gedreht wird, wo eine Drehung um 1 Gleis nach Rechts gereicht hätte.

ODER: Du merkst Dir den Abstand der Positionen, stellst die Drehrichtung ein, und wartest drauf, daß diese Schrittanzahl Null wird.

MfG

PS: MALE Dir auf, was Du erreichen willst, mit möglichst kleinen Zwischenschritten

PPS: Oha . DANN habe ich mich mit dem delay(2000); vertan - Du wirst aber nicht sonderlich glücklich ohne das delay, da die While-Schleife für einen Durchlauf nicht wirklich lange braucht - die Schritte sind ruck-zuck auf Null runter gezählt - sobald der Hall-Sensor auslöst.
Du wartest hier NICHT darauf, daß der Hall-Sensor wieder sperrt, zählst also die Erkennung Mehrfach!

Ich will mich halt Schrit für Schritt ran tasten. Es soll dann auch immer der kürzere Weg genommen werden. Es muss dann so zu sagen auch noch recht oder linksdrehen entschieden werden. Zum schluss möchte ich auch mal noch langsam anfahren und bremsen. Aber bis dahin....

PS. das mit dem Hall und der Zeit stimmt. Da habe ich noch gar nicht dran gedacht.
Mit den negativen und positiven Schritten hab ich auch noch keine Idee.

ODER: Du merkst Dir den Abstand der Positionen, stellst die Drehrichtung ein, und wartest drauf, daß diese Schrittanzahl Null wird.

genau so wollte ich es ja machen.

Hi

Dann ist aber die Start-Schrittzahl eher

schritte = abs(gleisNeu - gleisAlt);  //ABSOLUT, liefert negative Werte positiv zurück
if (gleisNeu<gleisAlt){
  richtung=links;
}else{
  richtung=rechts;
}

Damit kannst Du dann den Motor so lange drehen lassen (eben je nach 'richtung' links oder rechts rum), bis der HallSensor so oft 'gesehen' wurde, wie Schritte abzuwarten ist.

MfG

Danke dir. Funktioniert das auch wenn ich von Gleis 1 zu Gleis 23 Fahren will das sie dann links rum läuft?

Hallo,

Habt ihr ne Idee warum die for Schleife läuft obwohl der Hall nicht betätigt wird. Er ist über einen Pullup angeschlossen.

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;
}

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