Arduino Forum

International => Deutsch => Topic started by: Acki1985 on Dec 31, 2018, 12:46 pm

Title: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Dec 31, 2018, 12:46 pm
Hallo alle zusammen,

ich spiele gerade mal ein wenig mit dem Drehencoder. Ziel ist es mir Werte von 0-23 auf dem Display anzeigen zu lassen. Das funktioniert auch schon ganz gut. Nur habe ich ein Problem:

Wenn ich den Arduino starte und dann am Encoder drehe, geht dieser Wert zuerst nur bis 15. Wenn ich einmal die 15 erreicht habe dann geht er komischerweise bis Wert 23. Drehe ich ihn dann wieder auf 0 zurück, springt er nach Wert 0 wieder auf Wert 15 und nicht auf Wert 23.

Habt ihr ne Idee woran das liegen könnte?

Code: [Select]
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
int messungPin1 = LOW;
int messungPin1Alt = LOW;
int encoderWertA = 0;
byte encoderWert = 0;

 void setup() {
 pinMode(10, INPUT);
 pinMode(11, 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();
 
 }

 void loop() {
 messungPin1 = digitalRead(10);
 if ((messungPin1 == HIGH) && (messungPin1Alt == LOW)) {
 if (digitalRead(11) == HIGH) {
 encoderWertA = (encoderWert++)%24;
 } else {
 encoderWertA =(encoderWert--)%24;
 }
 Serial.println (encoderWertA);
 lcd.begin(16, 2);
 lcd.setCursor(0, 0);
 lcd.print("Wert");
 lcd.setCursor(0, 1);
 lcd.print(encoderWertA);
 
 }
 messungPin1Alt = messungPin1;
 }
Title: Re: Drehencoder Test
Post by: postmaster-ino on Dec 31, 2018, 12:56 pm
Hi

Du lässt zwar encoderWertA auf 23 begrenzen, aber Deine eigentliche Zähl-Variable encoderWert zählt 25 ... 26 ... 27 ...
Oder 1 ... 0 ... -1 ... -2 ...

MfG

*Edit*
Der RF24 kam erst bei Post 120 dazu - Link:#120 (http://forum.arduino.cc/index.php?topic=588018.msg4053031#msg4053031).
Dort klappt die Drehbühne anscheinend bereits, wie hier zu Beginn angedacht.
Title: Re: Drehencoder Test
Post by: Acki1985 on Dec 31, 2018, 01:00 pm
Hi,

Danke für den Hinweis, aber wie könnte ich das ändern?
Title: Re: Drehencoder Test
Post by: michael_x on Dec 31, 2018, 01:01 pm
byte encoderWert = 0xff; // -1 ( eins weniger als 0 ) == 255
int encoderWertA = encoderWert %24;  // 255 % 24 =15

encoderWertA braucht man nicht:
Code: [Select]
if (digitalRead(11) == HIGH) {
 if (encoderWert < 23) encoderWert++ ;
} else {
 if (encoderWert > 0) encoderWert-- ;
}
mit Begrenzung auf 0 .. 23
Title: Re: Drehencoder Test
Post by: postmaster-ino on Dec 31, 2018, 01:09 pm
Hi
Danke für den Hinweis, aber wie könnte ich das ändern?
Indem Du den begrenzten encoderWertA auf Deinen encoderWert kopierst.

encoderWert=encoderWertA;

Sollte 'tun'.

MfG
Title: Re: Drehencoder Test
Post by: uwefed on Dec 31, 2018, 01:13 pm
andere Fallstricke:

Hast Du Pullup/Pulldown Widerstände an den Pins 10 und 11?
Vieleicht solltest Du ein delay(10); nach if ((messungPin1 == HIGH) && (messungPin1Alt == LOW)) {" einfügen um den Kontakt zu entprellen.

Grüße Uwe
Title: Re: Drehencoder Test
Post by: Acki1985 on Dec 31, 2018, 01:20 pm
Hi,

es sind Pullup Wiederstände eingebaut. Das es am Prellen liegt kann ich mir eigentlich nicht vorstellen. Es geht ja nur beim ersten mal drehen bis Wert 15 und dann von 0 bis 23.

Title: Re: Drehencoder Test
Post by: Acki1985 on Dec 31, 2018, 01:26 pm
HiIndem Du den begrenzten encoderWertA auf Deinen encoderWert kopierst.

encoderWert=encoderWertA;

Sollte 'tun'.

MfG
Wenn ich das mache erhalte ich immer Wert 0.
Title: Re: Drehencoder Test
Post by: Rentner on Dec 31, 2018, 01:35 pm
Wenn ich das mache erhalte ich immer Wert 0.
Hallo,

die Lösung von Michael in #3 hast Du gesehen , die wäre auch mein Vorschlag gewesen.

Heinz
Title: Re: Drehencoder Test
Post by: postmaster-ino on Dec 31, 2018, 01:54 pm
Hi
Wenn ich das mache erhalte ich immer Wert 0.
Kommt drauf an, WO Du Das machst.
Aber kein Problem, in Salami-Taktik bin ich lernfähig.
Dein Problem: Dein Tempo

MfG
Title: Re: Drehencoder Test
Post by: Acki1985 on Dec 31, 2018, 02:05 pm
Wenn ich das so wie in #3 mache, ist der Startwert 255. Diesen muss ich dann auf 0 runter regeln. Danach geht der Wert von 0 bis 23 und von 23 bis 0.

Code: [Select]

#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
int messungPin1 = LOW;
int messungPin1Alt = LOW;
byte encoderWert = 0xff; // -1 ( eins weniger als 0 ) == 255
int encoderWertA = encoderWert %24;  // 255 % 24 =15


 void setup() {
 pinMode(10, INPUT);
 pinMode(11, 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();
 
 }

 void loop() {
 messungPin1 = digitalRead(10);
 if ((messungPin1 == HIGH) && (messungPin1Alt == LOW)) {
 if (digitalRead(11) == HIGH) {
 if (encoderWert < 23) encoderWert++ ;
} else {
 if (encoderWert > 0) encoderWert-- ;

  }
 Serial.println (encoderWertA);
 lcd.begin(16, 2);
 lcd.setCursor(0, 0);
 lcd.print("Wert");
 lcd.setCursor(0, 1);
 lcd.print(encoderWert);
 
 }
 
 messungPin1Alt = messungPin1;
 }
Title: Re: Drehencoder Test
Post by: Acki1985 on Dec 31, 2018, 02:38 pm
Hab es rausbekommen. Liegt an dem Variablentyp Byte. Der kann ja nur psitive Zahlen. Wenn ich da eine negative Zahl eingebe, ist der Startwert = 255. Gebe ich da 0 ein Startet er bei 1. Muss dann aber auch null runteregeln bevor ich den Wertebereich 0 bis 23 nutzen kann.

Hat da noch wer ne Idee?
Title: Re: Drehencoder Test
Post by: Acki1985 on Dec 31, 2018, 05:43 pm
Hab es hinbekommen :-)

Code: [Select]
#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
int encoderWertA = encoderWert %24;  // 255 % 24 =15
int 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

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(10, INPUT);
 pinMode(11, INPUT);
 pinMode(12, 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(10);
 if ((messungPin1 == LOW) && (messungPin1Alt == HIGH)) {
 if (digitalRead(11) == HIGH) {
 if (encoderWert < 23) encoderWert++ ;
} else {
 if (encoderWert > 0) encoderWert-- ;

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

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

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


 
 }
 
 messungPin1Alt = messungPin1;

 
  }
 
 
Title: Re: Drehencoder Test
Post by: uwefed on Dec 31, 2018, 06:38 pm
Es kommt darauf an was man will.

Code: [Select]
if (digitalRead(11) == HIGH) {
 if (encoderWert < 23) encoderWert++ ;
} else {
 if (encoderWert > 0) encoderWert-- ;
}

bringt Dir Werte zwischen 0 und 23

wenn man nach der 23 die null kommen soll dann muß man es anders machen
Grüße Uwe
Title: Re: Drehencoder Test
Post by: postmaster-ino on Dec 31, 2018, 07:16 pm
Hi
Code: [Select]

#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //Hier wäre Es übersichtlicher, wenn man den
                                     //Zahlen sprechende Namen geben würde, um ein
                                     //Anpassen an andere Pins einfacher zu gestallten
int messungPin1 = HIGH;
int messungPin1Alt = HIGH;
byte encoderWert = 0; // -1 ( eins weniger als 0 ) == 255
//int encoderWertA = encoderWert % 24; // 255 % 24 =15  //Wird im Sketch nicht benutzt - wohl nicht angemeckert, da eine Zuweisung stattfindet
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
byte encoderGedrueckt = 0;              // Statusspeicher ob Encodertaster betätigt wurde
byte encoderTaster = HIGH;             // Taster im Encoder
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);
  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 < 23) encoderWert++ ;
    } else {
      if (encoderWert > 0) 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;
    }
  }  // <-- ???
  messungPin1Alt = messungPin1;
}

Compiliert ohne Wqarnungen.
Ich habe mir gestattet, die Pins außerhalb einzustellen und im Code die 'magic numbers' durch sprechende Namen zu ersetzen.
Da sich die Pinzuweisungen wohl während der Laufzeit nicht mehr ändern, sind Diese als const deklariert - der Compiler kann Diese somit fest im Code verbauen - wenn Er mag.
Entfernen unnötiger Leerzeilen und ein STRG+T brachten bessere Lesbarkeit.
Woher hast Du die Klammerung innerhalb loop()? Von mir mit // <-- ?? gekennzeichnet?
Diese Klammerung sollte - überhaupt Nichts - bewirken (lasse mich Da gerne korrigieren)

MfG
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 01, 2019, 12:46 pm
Gesundes neues Jahr wünsche ich allen  :)

Ich danke dir Postmaster.

Ich bin schon ein Schritt weiter. Ich möchte mit dem Encoder Positionen einstellen können die ein Motor zurücklegen (Stepps) muss. Das mit der Berechnung funktioniert schon ganz gut. Nur wie mache ich das, das die Schritte mit einem Hallsensor mittels Magnet am Zahnrad.vergleicht und wenn die Schritte zurückgelegt wurden der Motor abschaltet?

Code: [Select]


#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 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);
 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;
  enter = false;
}

//if ((schritte >12)&& (enter== true)) {
 // Serial.println("rechts");
  //enter = false;
}
//  else {
   // Serial.println("links");
    //enter = false;
//}

//}

 
 
 
 messungPin1Alt = messungPin1;

 
  }
 
 
 
Title: Re: Drehencoder Test
Post by: Rentner on Jan 01, 2019, 01:47 pm
Hallo,

DC Motor , Schrittmotor , eine Richtung , zwei Richtungen, wie schnell dreht das Zahnrad, Welche Übersetztung mit Bezug auf die Motorwelle ? Willst du wirklich  nur so viel Zähne fahren we Du mit den Werten des Encoders vorgibst ( 0-23)

Jetzt mal ganz grob

Bei einem Schrittmotor macht der Hallsensor keinen Sinn. Bei DC Motor must du halt die Impulse des Hallsensors beim fahren zählen, mit deinem Sollwert vergleichen und dann abschalten. Mit einem DC Motor kannst Du keine kleinen Winkelschritte fahren.
Mit nur einem Hallsensor am Zahnrad weist Du nicht wie die Richtung ist. Dann must Du Dir die aktuelle Position aus den gefahren Impulsen bilden und in einer Variablen abspeichern. Aus der Differenz zwischen neuem Sollwert und Istwert die Richtung bestimmen und abhängig davon den Istwert hoch oder runter zählen. Probleme bekommst Du damit beim starten nach Power on , da Du nicht weist wo du stehst. Ein " Refferenzfahren " währe dazu die Lösung.

Heinz
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 01, 2019, 02:01 pm
Hallo Heinz,

Ich danke dir. Also es wird ein DC Motor über Motortreiber angesteuert. Die Bühne wird über ein großes Zahnrad angetrieben. Dieses Zahnrad besitzt 3 Kerben wo bei erreichen ein Stift einrastet. Dieser Stift wird Bei Start zurückgesogen und gibt das Zahnrad frei. Nach ablauf der Schritte, soll der Stift wieder in die entsprechende Kerbe einrasten. Der Weg den die Bühne zurückgelegt hat, wird über den Hallsensor ermittelt. An jeder Kerbe ist ein Magnet angebracht. Jede Kerbe bedeudet einen Gleisabgang. Ich hoffe ich konnte es einigermasen verständlich erklären. Der Start ab Gleis 1 wird immer bei Poweron über eine Referenzfahrt festgelegt.
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 01, 2019, 04:01 pm
Hab mal ein wenig weiter gemacht. Nur leider scheint er die While Schleife nicht auszuführen.

Code: [Select]




#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?
Title: Re: Drehencoder Test
Post by: michael_x on Jan 01, 2019, 04:11 pm
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 ...
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 01, 2019, 04:29 pm
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.
Title: Re: Drehencoder Test
Post by: Rentner on Jan 01, 2019, 04:38 pm
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
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 01, 2019, 04:44 pm
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?

Code: [Select]



#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.
Title: Re: Drehencoder Test
Post by: Rentner on Jan 01, 2019, 05:06 pm
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)

Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 01, 2019, 05:35 pm
Woran liegt das, das die While Schleife ausgefhrt wird, obwohl der Hal gar nicht betätigt wird?
Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 01, 2019, 05:37 pm
Code: [Select]
#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
Title: Re: Drehencoder Test
Post by: Rentner on Jan 01, 2019, 05:41 pm
Hi,

siehe #19 , #21

du darfst  das was wir schreiben nicht nur lesen, sondern auch verstehen  ;)
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 01, 2019, 05:42 pm
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
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 01, 2019, 05:48 pm
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.

Code: [Select]




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



Title: Re: Drehencoder Test
Post by: Rentner on Jan 01, 2019, 05:51 pm
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
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 01, 2019, 05:55 pm
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.
Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 01, 2019, 06:11 pm
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!
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 01, 2019, 06:26 pm
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.
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 01, 2019, 07:15 pm
Quote
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.
Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 01, 2019, 08:10 pm
Hi

Dann ist aber die Start-Schrittzahl eher
Code: [Select]

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
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 01, 2019, 08:28 pm
Danke dir. Funktioniert das auch wenn ich von Gleis 1 zu Gleis 23 Fahren will das sie dann links rum läuft?
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 02, 2019, 05:58 pm
Hallo,

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

Code: [Select]


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

Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 02, 2019, 06:03 pm
Hi
Jupp :)
Code: [Select]
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
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 02, 2019, 06:17 pm
Code: [Select]


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.
Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 02, 2019, 06:38 pm
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 (http://forum.arduino.cc/index.php?topic=586959.msg3993031#msg3993031) - solltest Du Dir ansehen.

MfG
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 02, 2019, 07:39 pm
Quote
[
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
Quote
- den Motor starten, wenn eine Fahrt gestartet wird (und der Abstand !=0 ist)
Ja genau
Quote
- den Motor stoppen, wenn der Abstand ==0 ist
ja genau
Quote
- 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
Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 02, 2019, 08:33 pm
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.
Code: [Select]

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
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 05, 2019, 07:15 pm
Das mit der Statemachine verstehe ich nicht. Wie soll mir das bei meinem Projekt helfen?
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 05, 2019, 07:29 pm
Oder besser gesagt womit fange ich da in meinem Projekt an?
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 05, 2019, 10:20 pm
Keiner ne Idee?
Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 05, 2019, 11:33 pm
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
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 05, 2019, 11:55 pm
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)
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 06, 2019, 07:29 pm
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?
Title: Re: Drehencoder Test
Post by: Tommy56 on Jan 06, 2019, 07:31 pm
(48+1)%48

Aber ob Dir das was bringt?

Gruß Tommy
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 11, 2019, 09:22 pm
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?
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 11, 2019, 10:29 pm
Könnte man das auch so machen?

Code: [Select]

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

Title: Re: Drehencoder Test
Post by: Tommy56 on Jan 11, 2019, 10:37 pm
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
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 11, 2019, 10:44 pm
Das Problem ist das die While Schleife permanent läuft obwohl der Sensor nicht betätigt wird. ?
Title: Re: Drehencoder Test
Post by: Tommy56 on Jan 11, 2019, 10:47 pm
Was brauchst Du ein while? Du hast doch loop.
Was sagt den die Ausgabe der Schritte?

Gruß Tommy
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 11, 2019, 10:52 pm
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.
Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 11, 2019, 10:52 pm
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.
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 11, 2019, 10:59 pm
Also müsste ich den Sensor Zustand zwischenspeichern und dann wieder zurück setzen?
Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 11, 2019, 11:06 pm
Hi

Nein - Du musst den Sensor-Zustand EINLESEN, wenn DU auf Veränderungen wartest.
Diese While macht nicht, was Du Dir denkst.
Schreibe auf, WAS darin passieren soll - wie immer: möglichst kleine Schritte

Akut wirfst Du die While-Schleife an und machst, bis auf das Runterzählen der Schrtte, Einen pro While-Durchlauf, Nichts.
Da ist kein Sensor drin, Nicht, ob vll. Jemand zwischenzeitlich irgendwo einen Knopf gedrückt hat, weil Da eine Lok nicht richtig stand und die Drehbühne gerade Gehacktes draus machen will ... der Arduino hört erst auf, wenn Er fertig ist!!

Überdenke Dein Konzept, Blink_without_delay wirst Du hier im Thread schon gehört haben - darin besteht Deine Lösung.

MfG
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 11, 2019, 11:12 pm
Jetzt weis ich was du meinst. Klar die 2 Sekunden macht er ja nix, weder auf nen Sensor reagieren sonst noch irgendwas anderes. Hatte am Anfang zum einlesen des Encoder Tasters vorallem schon mit millis() gearbeiteitet und baue mir dann hier mit dem Delay ne Krücke rein.
Title: Re: Drehencoder Test
Post by: Tommy56 on Jan 11, 2019, 11:24 pm
Nicht nur mit dem delay. Du prüfst auch enter und sensor nicht ab. Wenn die egal sind, kannst Du sie aus der Bedingung raus lassen, ansonsten musst Du im while deren Zustand prüfen und aktualisieren.

Gruß Tommy
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 11, 2019, 11:50 pm
Code: [Select]


 sensor = digitalRead (hal);
    if ((schritte != 0)&& (enter == true)){
     
      while ((schritte != 0) && (sensor == HIGH)) {
          startZeit = millis();
          if ((millis() - startZeit >= interval) && sensor == LOW) {
                 
          schritte--;
          vergangeneZeit = startZeit;
          Serial.println("Schritte");
          Serial.println(schritte);
         
           Serial.println("Ziel");
          enter = false;
          gleisAlt = wertSpeichern;
       }



also so ungefähr?
Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 12, 2019, 12:10 am
Hi

Ja, die Richtung stimmt schon.
Wofür das While?
loop() kommt eh direkt wieder hier vorbei.
Du musst 'nur' gucken, ob der Hall-Sensor 'jetzt gedrückt ist' und Dir Das merken.
Und in der nächsten Zeile, ob der Hall-Sensor 'jetzt nicht gedrückt ist'.
Jeweils die aktuelle Zeit merken beim Umschalten und nach 20ms ohne weitere Umschaltung wird der Pegel stabil sein (eigentlich prellt ein elektronischer Sensor nicht, schadet aber auch nicht).

Die ganzen Einzel-Probelme
- Gleiswahl per Zifferneingabe/per Drehencoder/per Serial
- Entfernung und Richtungsbestimmung (bei Return)
- starten/stoppen des Motor in die entsprechende Richtung
- Hallsensor erkennen und schritte runter zählen
packst Du in einzelne Funktionen.
Deine loop() ruft dann nur noch diese Funktionen nach einander auf.
Wenn kein neues Gleis eingegeben wurde, kommt kein Return, wird also keine (neue) Entfernung berechnet.
Wenn wir keine Entfernung zum Ziel haben, muß der Motor nicht laufen.
Wenn der Motor nicht läuft, werden auch keine Hall-Signale verarbeitet - es kommen schlicht Keine.

Die Probleme vereinzeln und die möglichst in möglichst kleine Einzelprobleme auch einzeln lösen.

MfG
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 12, 2019, 12:33 am
Habe mal versucht während du den Beitrag geschrieben hast, Den codeumzuschreiben. Habe ihn aber noch nicht weiter getestet. Aber so ungefähr habe ich mir das gedacht.

Code: [Select]





#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
int sensor = LOW;
bool start = false;

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

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 < 48) 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 = abs (gleisNeu - gleisAlt);
      Serial.print ("benoetigte Schritte  ");
      Serial.println(schritte);
      //gleisAlt = wertSpeichern;
      Serial.println(gleisNeu);
      Serial.println(gleisAlt);
      Serial.println(enter);
    }
   sensor = digitalRead (hal);
   startZeit=millis();
    if ((schritte != 0)&& (enter == true)){
      start = true;
      if ((startZeit - vergangeneZeit >= interval) && (sensor == LOW) && (start ==true)) {
          schritte--;
          Serial.println("Schritte");
          Serial.println(schritte);
      }
          else
          start = false;
           Serial.println("Ziel erreicht");
          enter = false;
          gleisAlt = wertSpeichern;
       }
  //    }
//    }
    //if ((schritte >12)&& (enter== true)) {
    // Serial.println("rechts");
    //enter = false;
   //  else {
  // Serial.println("links");
  //enter = false;
 // }
 // }
  messungPin1Alt = messungPin1;
   
}




Vielleicht bin ich ja jetzt auf dem richtigen weg. Werd jetzt erst mal schlafen. Bis später und vielen Dank für die bisherige Hilfe.

MfG Daniel
Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 12, 2019, 12:56 am
Hi
Aber so ungefähr habe ich mir das gedacht.
....
Vielleicht bin ich ja jetzt auf dem richtigen weg. Werd jetzt erst mal schlafen....
Der Weg wird immer besser, dürfte so aber noch nicht funktionieren.
Das heimische Bettchen aufsuchen klingt nach einem sinnvollem Plan - mache ich hier auch Mal.

MfG
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 12, 2019, 10:27 pm
Guten Abend,

ich habe es jetzt mal mit Funktionen versucht zu schreiben. Meint ihr es so in der Art?

Code: [Select]


#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
int sensor = LOW;
bool start = false;
bool ergebnis = false;

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

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() {
  encoder_lesen();
  schritt();
  schritteZaehlen();

}

void encoder_lesen () {
  messungPin1 = digitalRead(encoderPinA);
  if ((messungPin1 == LOW) && (messungPin1Alt == HIGH)) {
    if (digitalRead(encoderPinB) == HIGH) {
      if (encoderWert < 48) 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;
     
    }
    messungPin1Alt = messungPin1;
}

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

void schritteZaehlen () {
  sensor = digitalRead (hal);
   startZeit = millis();
    if ((schritte != 0)&& (ergebnis == true)){
      start = true;
      if ((startZeit - vergangeneZeit >= interval) && (sensor == LOW) && (start ==true)) {
          vergangeneZeit = startZeit;
          schritte--;
          Serial.println("Schritte");
          Serial.println(schritte);
      }
    }
          else if (schritte == 0){
          start = false;
           Serial.println("Ziel");
          ergebnis = false;
          gleisAlt = wertSpeichern;
       }
}






Edit: Code geändert
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 12, 2019, 11:09 pm
Jetzt macht die Steuerung das was sie bis jetzt soll. Der nächste Schritt ist die Richtungsbestimmung. Kann mir da wer auf die Sprünge helfen?

Code: [Select]


#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
int sensor = LOW;
bool start = false;
bool ergebnis = false;

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

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() {
  encoder_lesen();
  schritt();
  schritteZaehlen();

}

void encoder_lesen () {
  messungPin1 = digitalRead(encoderPinA);
  if ((messungPin1 == LOW) && (messungPin1Alt == HIGH)) {
    if (digitalRead(encoderPinB) == HIGH) {
      if (encoderWert < 48) 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;
     
    }
    messungPin1Alt = messungPin1;
}

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

void schritteZaehlen () {
  sensor = digitalRead (hal);
   startZeit = millis();
    if ((schritte != 0)&& (ergebnis == true)){
      start = true;
      if ((startZeit - vergangeneZeit >= interval) && (sensor == LOW) && (start ==true)) {
          vergangeneZeit = startZeit;
          schritte--;
          Serial.println("Schritte");
          Serial.println(schritte);
      }
    }
          else if ((schritte == 0) && (start == true)){
          start = false;
           Serial.println("Ziel");
          ergebnis = false;
          gleisAlt = wertSpeichern;
       }
}

void best_Richtung(){
 
}

void motor(){
 
}

Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 12, 2019, 11:56 pm
Hi

Na verdammt - dann brauchst Du mich ja gar nicht mehr ;)
Habe mich Mal in Deinem Sketch probiert, ein/zwei Dinge umgebaut.
Unter Anderem sollte die Drehrichtung in die kürzere Richtung gehen.

Sketch ist UNGETESTET
Code: [Select]

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

int messungPin1 = HIGH;               //Temp für Encoder-Pin
int messungPin1Alt = HIGH;            //dito, um Veränderungen erkennen zu können
byte encoderWert = 0;                 // -1 ( eins weniger als 0 ) == 255
const byte hal = 3;                   //Pin vom Hall-Sensor
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 der Motor (Hallsensor betätigt) zurücklegen muss
boolean sensor = LOW;                 // Wert des (Hall) Sensor
bool start = false;                   // Verdrehen gestartet?
bool ergebnis = false;                // Es sind Schritte vorhanden, Motor gestartet
const byte pin_motor_links = 10;      // Richtungspin an H-Brücke für Links
const byte pin_motor_rechts = 11;     // Richtungspin an H-Brücke für Rechts


unsigned long encoderDruckzeit;       // Zeit wann der Encodertaster betätigt wurde
unsigned long entprellZeit = 200;     // Zeit die nach der betätigung eines Tasters gewartet wird
unsigned long startZeit;              // Hilfsvariable für die Startzeit
unsigned long interval = 2000;
unsigned long vergangeneZeit = 0;

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() {
  encoder_lesen();
  schritt();
  schritteZaehlen();

}

void encoder_lesen () {
  messungPin1 = digitalRead(encoderPinA);
  if ((messungPin1 == LOW) && (messungPin1Alt == HIGH)) {
    if (digitalRead(encoderPinB) == HIGH) {
      if (encoderWert < 48) encoderWert++ ;
    } else {
      if (encoderWert > 1) encoderWert-- ;
    }
    //    lcd.setCursor(0, 0);
    //    lcd.print("Wert");
    lcd.setCursor(0, 1);
    lcd.print(encoderWert);
  }
  encoderTaster = digitalRead(tasterEnter);
  if (encoderTaster == LOW)
  {
    encoderDruckzeit = millis();
    encoderGedrueckt = 1;
  } else if ((millis() - encoderDruckzeit > entprellZeit) && encoderGedrueckt == 1) {
    wertSpeichern = encoderWert;
    Serial.println(wertSpeichern);
    encoderGedrueckt = 0;
    enter = true;
  }
  messungPin1Alt = messungPin1;
}

void schritt () {
  if (enter == true) {
    gleisNeu = wertSpeichern;

    // 17 -> 3 links 14, rechts 10
    // links = abs(alt-neu)
    // rechts = 24-abs(alt-neu)

    // 3 -> 17 rechts 14, links 10
    // links = abs(alt-neu)
    // rechts = 24-abs(alt-neu)
    byte rechtsrum = abs(gleisAlt - gleisNeu);                //Weg rechts herum
    byte linksrum = maxpositionen - abs(gleisAlt - gleisNeu); //Weg links herum
    schritte = min(rechtsrum, linksrum);                      //kürzeren Weg nehmen
    Serial.print ("benoetigte Schritte  ");
    Serial.println(schritte);
    Serial.println(gleisNeu);
    Serial.println(gleisAlt);
    Serial.println(enter);
    enter = false;
    if (schritte) {   //wenn Ist = Soll, dann Nichts machen
      ergebnis = true;
      if (linksrum < rechtsrum) {             //Startrichtung des Motor
        //Motor starten links
        digitalWrite(pin_motor_links, HIGH);
      } else {
        //Motor starten rechts
        digitalWrite(pin_motor_rechts, HIGH);
      }
    }
  }
}

void schritteZaehlen () {
  sensor = digitalRead (hal);
  static boolean sensor_old = sensor;
  if (schritte != 0) {          //nur, wenn noch Schritte zu erledigen sind
    if (ergebnis == true) {     //Motor ist gestartet?
      start = true;             //Abarbeitung gestartet
      //Flanken auswerten
      //Entprellzeit beachten
      //bei HIGH-LOW Schritte runterzählen
      if (sensor == HIGH) { //Sensor in Ruhestellung
        startTeit = millis(); //Entprellung neu beginnen
      } else if (millis() - startZeit > interval) {  //Entprellzeit vorbei?
        //fallende Flanke erkannt, da wir hier eh bei == LOW sind
        schritte--;
        Serial.println("Schritte");
        Serial.println(schritte);
      }
    }
  }
  if (schritte == 0 && (start != false) { //die Schritte können in der oberen IF auf Null gegangen sein
  start = false;
  Serial.println("Ziel");
    ergebnis = false;
    gleisAlt = wertSpeichern;
    //Motor AUS
    digitalWrite(pin_motor_links, LOW);
    digitalWrite(pin_motor_rechts, LOW);
  }
}


Sichere Dir Deinen Sketch, bevor Du Meinen drüber kopierst oder Ideen daraus in Deinen einbaust!!
Nichts ist schlimmer, als ein eigenhändig zerstörter Sketch, weil man 'nur Mal schnell diese Kleinigkeit' ...
(ich spreche Da aus leidvoller Erfahrung)

MfG
Title: Re: Drehencoder Test
Post by: Tommy56 on Jan 13, 2019, 12:19 am
Wer keine Versionsverwaltung hat, hatte keine wichtigen Quellcodes - in Abwandlung des Spruchs zu Backups.

Bei mir wird beim Compilieren gespeichert und bei jedem Speichern automatisch eine Kopie mit Zeitstempel hinten dran erzeugt. Das ist zwar nur eine minimale Versionierung, ich kann aber immer auf den alten Stand zurück.

Am Ende muss man dann mal aufräumen.

Gruß Tommy
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 13, 2019, 12:25 am
Ich danke euch.

Kann mir mal einer das erklären was damit gemeint ist?

Code: [Select]


 byte rechtsrum = abs(gleisAlt - gleisNeu);                //Weg rechts herum
    byte linksrum = maxpositionen - abs(gleisAlt - gleisNeu); //Weg links herum
    schritte = min(rechtsrum, linksrum);                      //kürzeren Weg nehmen

Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 13, 2019, 01:56 am
Hi

Äh - 'maxposition' habe ich nicht deklariert :/
Darin steht (sollte stehen) die Anzahl der möglichen Positionen - also bei Dir 48 - wollte Das flexibel halten.
recht/linksrum ist der Abstand vom Start zum Ziel, wenn ich recht oder linksrum fahre.
Dein altes schritte war ja der Abstand der beiden Gleisnummern zueinander.
Gleich 43 und Gleis 2 haben '41 Gleise Anstand' - oder 7, wenn wir anders herum fahren.
Der kürzere Weg wird dann eingeschlagen.

MfG
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 13, 2019, 11:43 am
Hallo alle zusammen. Ich komm damit nicht klar. Vielleicht kann mir das einer erklären. Eine volle Drehung sind 48 Schritte.

// 17 -> 3 links 14, rechts 10
    // links = abs(alt-neu)
    // rechts = 24-abs(alt-neu)

    // 3 -> 17 rechts 14, links 10
    // links = abs(alt-neu)
    // rechts = 24-abs(alt-neu)

Wie das mit der Richtungsbestimmung funktionieren soll, das verstehe ich nicht.
Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 13, 2019, 03:09 pm
Hi

Fehler Meinerseits - bei den Beispielrechnungen habe ich '24' angenommen.
Deshalb steht bei rechts auch die 24 (statt Deiner 48, Die habe ich erst rein korrigiert, nachdem der Sketch soweit beisammen war).

Annahme, wir haben 24 Positionen, dann ist von der Position 17 bis zur 24 der Abstand 7.
Da die 24 aber ebenfalls der Position Null entspricht, haben wir von dirt einen Abstand zur 3 von 3.
7 + 3 = 10.
In die andere Richtung ist's von der 17 bis zur 3 ein Abstand von 14.
10 < 14, somit wird die 10er Richtung gewählt.

Sorry für die Verwirrungen

MfG
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 13, 2019, 03:27 pm
Ah gut. Das mit dem rechts drehen habe ich verstanden. Aber wie funktioniert das mit dem links drehen?

Bietet es sich an die Richtungswahl in eine seperate Funktion zu schreiben und die dann je na Richtung aufzurufen?
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 13, 2019, 07:31 pm
Hab mal versucht eine Refernzfahrt zu programmieren.

Code: [Select]


#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
int sensor = LOW;
bool start = false;
bool ergebnis = false;

unsigned long encoderDruckzeit;       // Zeit wann der Encodertaster betätigt wurde
unsigned long entprellZeit = 200;     // Zeit die nach der betätigung eines Tasters gewartet wird
unsigned long startZeit;
unsigned long interval = 2000;
unsigned long vergangeneZeit = 0;
bool nullStellung = false;
const byte pin_motor_links = A1;      // Richtungspin an H-Brücke für Links
const byte pin_motor_rechts = A2;     // Richtungspin an H-Brücke für Rechts
const byte sensor_referenz = A3;

void setup() {
  pinMode(sensor_referenz, INPUT);
  pinMode(pin_motor_links, OUTPUT);
  pinMode(pin_motor_rechts, OUTPUT);
  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("Drehscheiben-");
  lcd.setCursor(0, 1);
  lcd.print("steuerrung");
  delay (2000);
  //lcd.clear();
  //lcd.begin(16, 2);
  //lcd.setCursor(0, 0);
  //lcd.print("Wert");
  //lcd.setCursor(0, 1);
  //lcd.print(encoderWert);
}


void loop() {
  referenzFahrt();
  encoder_lesen();
  schritt();
  schritteZaehlen();

}

void referenzFahrt(){
  if ((nullStellung == false) && (sensor_referenz == LOW)) {
    lcd.clear();
    lcd.begin(16, 2);
    lcd.setCursor(0, 0);
    lcd.print("Referenzfahrt");
    lcd.setCursor(0, 1);
    lcd.print("gestartet");
    pin_motor_rechts = HIGH;
    pin_motor_links = LOW;
  }
  else {
    nullStellung = true;
    pin_motor_rechts = LOW;
    pin_motor_links = LOW;
    lcd.clear();
    lcd.begin(16, 2);
    lcd.setCursor(0, 0);
    lcd.print("Referenzfahrt");
    lcd.setCursor(0, 1);
    lcd.print("beendet");
    delay(2000);
    lcd.clear();
    lcd.begin(16, 2);
    lcd.setCursor(0, 0);
    lcd.print("Wert");
    lcd.setCursor(0, 1);
    lcd.print(encoderwert);
  }
 
}

void encoder_lesen () {
  messungPin1 = digitalRead(encoderPinA);
  if ((messungPin1 == LOW) && (messungPin1Alt == HIGH)) {
    if (digitalRead(encoderPinB) == HIGH) {
      if (encoderWert < 48) 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;
     
    }
    messungPin1Alt = messungPin1;
}

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

void schritteZaehlen () {
  sensor = digitalRead (hal);
   startZeit = millis();
    if ((schritte != 0)&& (ergebnis == true)){
      start = true;
      if ((startZeit - vergangeneZeit >= interval) && (sensor == LOW) && (start ==true)) {
          vergangeneZeit = startZeit;
          schritte--;
          Serial.println("Schritte");
          Serial.println(schritte);
      }
    }
          else if ((schritte == 0) && (start == true)){
          start = false;
           Serial.println("Ziel");
          ergebnis = false;
          gleisAlt = wertSpeichern;
       }
}

void best_Richtung(){
 
}

void motor(){
 
}



Beim überprüfen des Codes bekomme ich folgende Fehlermeldung:

Arduino: 1.8.5 (Windows 10), Board: "Arduino/Genuino Uno"

C:\Users\danie\Documents\Arduino\Drehscheibensteuerrung_mit_Funktionen\Drehscheibensteuerrung_mit_Funktionen.ino: In function 'void referenzFahrt()':

Drehscheibensteuerrung_mit_Funktionen:73: error: assignment of read-only variable 'pin_motor_rechts'

     pin_motor_rechts = HIGH;

                      ^

Drehscheibensteuerrung_mit_Funktionen:74: error: assignment of read-only variable 'pin_motor_links'

     pin_motor_links = LOW;

                     ^

Drehscheibensteuerrung_mit_Funktionen:78: error: assignment of read-only variable 'pin_motor_rechts'

     pin_motor_rechts = LOW;

                      ^

Drehscheibensteuerrung_mit_Funktionen:79: error: assignment of read-only variable 'pin_motor_links'

     pin_motor_links = LOW;

                     ^

Drehscheibensteuerrung_mit_Funktionen:92: error: 'encoderwert' was not declared in this scope

     lcd.print(encoderwert);

               ^

exit status 1
assignment of read-only variable 'pin_motor_rechts'

Title: Re: Drehencoder Test
Post by: Tommy56 on Jan 13, 2019, 07:42 pm
Da machst Du jetzt aber ganz gewaltige Rückschritte.

Warum willst Du einem Pin (also einer Konstanten) einen Wert zuweisen?
Du willst doch den Anschluss, der durch diesen Pin bestimmt wird auf HIGH oder LOW setzen!

Grundlagen lernen: digitalWrite

Gruß Tommy
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 13, 2019, 08:58 pm
Stimmt. Habe es geändert. Wie könnte das aussehen wenn ich anstatt der Delay's millis() einsetze? Gibt es eine Möglichkeit eine globale Wartezeit für Anzeige Referenzfahrt gestartet und für Referrenzfahrt beendet?

Code: [Select]


void referenzFahrt(){
  status_sensor_referenz = digitalRead(sensor_referenz);
  if ((nullStellung == false) && (status_sensor_referenz == HIGH)) {
    lcd.clear();
    lcd.begin(16, 2);
    lcd.setCursor(0, 0);
    lcd.print("Referenzfahrt");
    lcd.setCursor(0, 1);
    lcd.print("gestartet");
    digitalWrite (pin_motor_rechts, HIGH);
    digitalWrite (pin_motor_links, LOW);
  delay(2000);
  }
  else {
Serial.println(nullStellung);
Serial.println(status_sensor_referenz);
   
    nullStellung = true;
    digitalWrite(pin_motor_rechts, LOW);
    digitalWrite(pin_motor_links, LOW);
    lcd.clear();
    lcd.begin(16, 2);
    lcd.setCursor(0, 0);
    lcd.print("Referenzfahrt");
    lcd.setCursor(0, 1);
    lcd.print("beendet");
    delay(2000);
    lcd.clear();
    lcd.begin(16, 2);
    lcd.setCursor(0, 0);
    lcd.print("Wert");
    lcd.setCursor(0, 1);
    lcd.print(encoderWert);
  }
 
}

Title: Re: Drehencoder Test
Post by: Tommy56 on Jan 13, 2019, 09:02 pm
Da kann ich Dir nur die Standardantwort geben: Schaue Dir BlinkWithoutDelay an und verstehe es. Lies dazu die Nachtwächtererklärung.
Das kann Dir keiner abnehmen, das musst Du selbst verstehen. Das brauchst Du in vielen Anwendungen.

Gruß Tommy
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 13, 2019, 10:08 pm
Jetzt habe ich es mit millis() geschrieben. Die Zeit läuft auch ab. der Text 2 Sekunden abgelaufen kommt alle 2 Sekunden. Ich habe nur das Gefühl das er die zeit nicht als Wartezeit für die LCD Anzeige nutzt. Es wird so schnell gelöscht und neu geschrieben das man kaum was erkennt. Woran liegt das. Müsste die LCD Anzeige nicht jetzt auch für 2 Sekunden stehen bleiben?

Code: [Select]


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

unsigned long aktuelleZeit;
unsigned long vergangeneZeit_A;
unsigned long interval_1 = 2000;
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
int sensor = LOW;
bool start = false;
bool ergebnis = false;

unsigned long encoderDruckzeit;       // Zeit wann der Encodertaster betätigt wurde
unsigned long entprellZeit = 200;     // Zeit die nach der betätigung eines Tasters gewartet wird
unsigned long startZeit;
unsigned long interval = 2000;
unsigned long vergangeneZeit = 0;
bool nullStellung = false;
int pin_motor_links = A1;      // Richtungspin an H-Brücke für Links
int pin_motor_rechts = A2;     // Richtungspin an H-Brücke für Rechts
const byte sensor_referenz = 2;
int status_sensor_referenz;
void setup() {
  pinMode(sensor_referenz, INPUT);
  pinMode(pin_motor_links, OUTPUT);
  pinMode(pin_motor_rechts, OUTPUT);
  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("Drehscheiben-");
  lcd.setCursor(0, 1);
  lcd.print("steuerrung");
  delay (2000);
  //lcd.clear();
  //lcd.begin(16, 2);
  //lcd.setCursor(0, 0);
  //lcd.print("Wert");
  //lcd.setCursor(0, 1);
  //lcd.print(encoderWert);
}


void loop() {
  referenzFahrt();
 // encoder_lesen();
  //schritt();
  //schritteZaehlen();

}

void referenzFahrt(){
  aktuelleZeit = millis();
  status_sensor_referenz = digitalRead(sensor_referenz);
  if ((nullStellung == false) && (status_sensor_referenz == HIGH)) {
    lcd.clear();
    lcd.begin(16, 2);
    lcd.setCursor(0, 0);
    lcd.print("Referenzfahrt");
    lcd.setCursor(0, 1);
    lcd.print("gestartet");
    digitalWrite (pin_motor_rechts, HIGH);
    digitalWrite (pin_motor_links, LOW);
  if (millis() - vergangeneZeit_A >= interval_1){
    Serial.println("2 Sekunden abgelaufen");
     vergangeneZeit_A = millis();
  }
  }
  else {
Serial.println(nullStellung);
Serial.println(status_sensor_referenz);
Serial.println(vergangeneZeit_A);
   
    nullStellung = true;
    digitalWrite(pin_motor_rechts, LOW);
    digitalWrite(pin_motor_links, LOW);
    lcd.clear();
    lcd.begin(16, 2);
    lcd.setCursor(0, 0);
    lcd.print("Referenzfahrt");
    lcd.setCursor(0, 1);
    lcd.print("beendet");
    delay(2000);
    lcd.clear();
    lcd.begin(16, 2);
    lcd.setCursor(0, 0);
    lcd.print("Wert");
    lcd.setCursor(0, 1);
    lcd.print(encoderWert);
  }
 
}

void encoder_lesen () {
  messungPin1 = digitalRead(encoderPinA);
  if ((messungPin1 == LOW) && (messungPin1Alt == HIGH)) {
    if (digitalRead(encoderPinB) == HIGH) {
      if (encoderWert < 48) 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;
     
    }
    messungPin1Alt = messungPin1;
}

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

void schritteZaehlen () {
  sensor = digitalRead (hal);
   startZeit = millis();
    if ((schritte != 0)&& (ergebnis == true)){
      start = true;
      if ((startZeit - vergangeneZeit >= interval) && (sensor == LOW) && (start ==true)) {
          vergangeneZeit = startZeit;
          schritte--;
          Serial.println("Schritte");
          Serial.println(schritte);
      }
    }
          else if ((schritte == 0) && (start == true)){
          start = false;
           Serial.println("Ziel");
          ergebnis = false;
          gleisAlt = wertSpeichern;
       }
}

void best_Richtung(){
 
}

void motor(){
 
}


Title: Re: Drehencoder Test
Post by: Tommy56 on Jan 13, 2019, 10:17 pm
Du gibst in der 2-Sekunden-Steuerung doch nur die Serielle Ausgabe aus. Wenn Du die Ausgaben auf dem lcd auch in diesem Teitraster haben willst, dann müssen sie in das
Code: [Select]
if (millis() - vergangeneZeit_A >= interval_1){
mit rein. Millis ist kein delay-Ersatz sondern ein "Mache etwas, wenn die Zeit vorbei ist" und das "etwas" muss dan halt in das if mit rein.

Gruß Tommy
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 13, 2019, 10:29 pm
Ah jetzt habe ich es glaube verstanden. Danke Tommy

Jetzt muss ich noch das mit der richtungswahl hinbekommen. Durch den Code bin ich ehrlich gesagt noch nicht wirklich durchgestiegen.
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 13, 2019, 10:54 pm
vielleicht kann mir da noch jemand helfen.

Hab dann noch ein weiteres Problem. Möchte dann auch per Tastendruck um 180 Grad (24 Schritte) drehen können.

Wenn die Scheibe aber zum Beispiel auf Position 3 steht und ich dann 180 Grad linksrum drücke wird ja normaler weise  3-24 gerechnet. das wäre ja dann Pos. -21 und nicht nicht Pos. 27. Wie könnte man das lösen?
Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 13, 2019, 10:59 pm
Hi

Wenn das Ziel negativ ist, einfach 48 dazu zählen.
Wenn das Ziel >48 ist, einfach 48 abziehen.

MfG
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 13, 2019, 11:07 pm
Das sagst du so einfach. Ich verstehe das aber irgendwie nicht. Wie kommst du da drauf?
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 14, 2019, 10:40 pm
Schade keiner ne idee?
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 14, 2019, 11:35 pm
Hab mal versucht die Richtngsbestimmung einzubauen. Wenn ich mir dei Werte im Serial Monitor augeben lasse, nimmt er immer rchtsrum, egal ob ich von Gleis 11 zu Gleis 12 oder von Gleis 12 zu Gleis 11 fahren will.


Ausgabe Serieller Monitor:
Schritte rechts   1       rechtsrum das stimmt
Schritte links    47
benoetigte Schritte  1
11  // gleisAlt
12  // gleisNeu
1   // Schrittzähler
Schritte
0
Ziel  // Ziel erreicht
12
Schritte rechts   1       immer rechtsrum obwohl linksrum gefahren werden soll
Schritte links    47
benoetigte Schritte  1
12  // gleisAlt
11  // gleisNeu

Bei dem Code:
Code: [Select]

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

unsigned long aktuelleZeit;
unsigned long vergangeneZeit_A;
unsigned long interval_1 = 2000;
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
int sensor = LOW;
bool start = false;
bool ergebnis = false;

unsigned long encoderDruckzeit;                   // Zeit wann der Encodertaster betätigt wurde
unsigned long entprellZeit = 200;                 // Zeit die nach der betätigung eines Tasters gewartet wird
unsigned long startZeit;                          // Abfrage begin Sensor an Bühne
unsigned long interval = 2000;                    // Zeitabstand nachdem ein Zustand des Sensors erkannt wird
unsigned long vergangeneZeit = 0;                 // Speichervariable um die Vergangene Zeit zu speichern
bool nullStellung = false;                        // Speichervariable ob Referenzfahrt erfolgt ist
int pin_motor_links = A1;                         // Richtungspin an H-Brücke für Links
int pin_motor_rechts = A2;                        // Richtungspin an H-Brücke für Rechts
const byte sensor_referenz = 2;                   // Pin für Sensor Referenz aussen an der Grube (Nullstellung)
int status_sensor_referenz;                       // Speichervariable für Status von Sensor für Referenzfahrt
byte linksRum = 0;                                // Anzahl Schritte Drehrichtung links
byte rechtsRum = 0;                               // Richtungsflag Drehrichtung rechts


void setup() {
  pinMode(sensor_referenz, INPUT);
  pinMode(pin_motor_links, OUTPUT);
  pinMode(pin_motor_rechts, OUTPUT);
  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("Drehscheiben-");
  lcd.setCursor(0, 1);
  lcd.print("steuerrung");
  delay (2000);
  //lcd.clear();
  //lcd.begin(16, 2);
  //lcd.setCursor(0, 0);
  //lcd.print("Wert");
  //lcd.setCursor(0, 1);
  //lcd.print(encoderWert);
}


void loop() {
  referenzFahrt();
  encoder_lesen();
  schritt();
  schritteZaehlen();
  //Motor();

}

void referenzFahrt() {
  aktuelleZeit = millis();
  status_sensor_referenz = digitalRead(sensor_referenz);
  if ((nullStellung == false) && (status_sensor_referenz == HIGH)) {

    digitalWrite (pin_motor_rechts, HIGH);
    digitalWrite (pin_motor_links, LOW);
    if (millis() - vergangeneZeit_A >= interval_1) {
      Serial.println("2 Sekunden abgelaufen");
      lcd.clear();
      lcd.begin(16, 2);
      lcd.setCursor(0, 0);
      lcd.print("Referenzfahrt");
      lcd.setCursor(0, 1);
      lcd.print("gestartet");
      vergangeneZeit_A = millis();
    }
  }
  else if ((nullStellung == false) && (status_sensor_referenz == LOW)) {
    Serial.println(nullStellung);
    Serial.println(status_sensor_referenz);
    Serial.println(vergangeneZeit_A);

    nullStellung = true;
    digitalWrite(pin_motor_rechts, LOW);
    digitalWrite(pin_motor_links, LOW);
    lcd.clear();
    lcd.begin(16, 2);
    lcd.setCursor(0, 0);
    lcd.print("Referenzfahrt");
    lcd.setCursor(0, 1);
    lcd.print("beendet");
    delay(2000);
    lcd.clear();
    lcd.begin(16, 2);
    lcd.setCursor(0, 0);
    lcd.print("Wert");
    lcd.setCursor(0, 1);
    lcd.print(encoderWert);
  }

}

void encoder_lesen () {
  messungPin1 = digitalRead(encoderPinA);
  if ((messungPin1 == LOW) && (messungPin1Alt == HIGH) && (nullStellung == true)) {
    if (digitalRead(encoderPinB) == HIGH) {
      if (encoderWert < 48) 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;

  }
  messungPin1Alt = messungPin1;
}

void schritt () {
  if (enter == true) {
    gleisNeu = wertSpeichern;
    //schritte = abs (gleisNeu - gleisAlt);
    rechtsRum = abs(gleisAlt - gleisNeu);                //Weg rechts herum
    linksRum = 48 - abs(gleisAlt - gleisNeu); //Weg links herum
    schritte = min(rechtsRum, linksRum);                      //kürzeren Weg nehmen
    Serial.print("Schritte rechts   ");
    Serial.println(rechtsRum);
    Serial.print("Schritte links    ");
    Serial.println(linksRum);
   
    Serial.print ("benoetigte Schritte  ");
    Serial.println(schritte);
    //gleisAlt = wertSpeichern;
    Serial.println(gleisNeu);
    Serial.println(gleisAlt);
    Serial.println(enter);
    enter = false;
    ergebnis = true;
  }
}

void schritteZaehlen () {
  sensor = digitalRead (hal);
  startZeit = millis();
  if ((schritte != 0) && (ergebnis == true)) {
    start = true;
    if ((startZeit - vergangeneZeit >= interval) && (sensor == LOW) && (start == true)) {
      vergangeneZeit = startZeit;
      schritte--;
      Serial.println("Schritte");
      Serial.println(schritte);
    }
  }
  else if ((schritte == 0) && (start == true)) {
    start = false;
    Serial.println("Ziel");
    ergebnis = false;
    gleisAlt = wertSpeichern;
  }
}

void best_Richtung() {

}

void motor() {

}



Woran könnte das liegen?


Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 15, 2019, 06:35 pm
Hi

Probier Mal was in der Richtung:
Gleis_neu < Gleis_alt XOR rechtsrum<linksrum
(wobei in der Berechnung die Namen links/rechtsrum wohl so nicht stimmen)

MfG
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 15, 2019, 10:23 pm
Guten Abend,

aber müsste das nicht auch mit dieser min funktion funktionieren?
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 15, 2019, 10:49 pm
So würde es auch funktionieren.

Code: [Select]

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

unsigned long aktuelleZeit;
unsigned long vergangeneZeit_A;
unsigned long interval_1 = 2000;
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
int sensor = LOW;
bool start = false;
bool ergebnis = false;

unsigned long encoderDruckzeit;                   // Zeit wann der Encodertaster betätigt wurde
unsigned long entprellZeit = 200;                 // Zeit die nach der betätigung eines Tasters gewartet wird
unsigned long startZeit;                          // Abfrage begin Sensor an Bühne
unsigned long interval = 2000;                    // Zeitabstand nachdem ein Zustand des Sensors erkannt wird
unsigned long vergangeneZeit = 0;                 // Speichervariable um die Vergangene Zeit zu speichern
bool nullStellung = false;                        // Speichervariable ob Referenzfahrt erfolgt ist
int pin_motor_links = A1;                         // Richtungspin an H-Brücke für Links
int pin_motor_rechts = A2;                        // Richtungspin an H-Brücke für Rechts
const byte sensor_referenz = 2;                   // Pin für Sensor Referenz aussen an der Grube (Nullstellung)
int status_sensor_referenz;                       // Speichervariable für Status von Sensor für Referenzfahrt
byte linksRum = 0;                                // Anzahl Schritte Drehrichtung links
byte rechtsRum = 0;                               // Richtungsflag Drehrichtung rechts


void setup() {
  pinMode(sensor_referenz, INPUT);
  pinMode(pin_motor_links, OUTPUT);
  pinMode(pin_motor_rechts, OUTPUT);
  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("Drehscheiben-");
  lcd.setCursor(0, 1);
  lcd.print("steuerrung");
  delay (2000);
  //lcd.clear();
  //lcd.begin(16, 2);
  //lcd.setCursor(0, 0);
  //lcd.print("Wert");
  //lcd.setCursor(0, 1);
  //lcd.print(encoderWert);
}


void loop() {
  referenzFahrt();
  encoder_lesen();
  schritt();
  schritteZaehlen();
  //Motor();

}

void referenzFahrt() {
  aktuelleZeit = millis();
  status_sensor_referenz = digitalRead(sensor_referenz);
  if ((nullStellung == false) && (status_sensor_referenz == HIGH)) {

    digitalWrite (pin_motor_rechts, HIGH);
    digitalWrite (pin_motor_links, LOW);
    if (millis() - vergangeneZeit_A >= interval_1) {
      Serial.println("2 Sekunden abgelaufen");
      lcd.clear();
      lcd.begin(16, 2);
      lcd.setCursor(0, 0);
      lcd.print("Referenzfahrt");
      lcd.setCursor(0, 1);
      lcd.print("gestartet");
      vergangeneZeit_A = millis();
    }
  }
  else if ((nullStellung == false) && (status_sensor_referenz == LOW)) {
    Serial.println(nullStellung);
    Serial.println(status_sensor_referenz);
    Serial.println(vergangeneZeit_A);

    nullStellung = true;
    digitalWrite(pin_motor_rechts, LOW);
    digitalWrite(pin_motor_links, LOW);
    lcd.clear();
    lcd.begin(16, 2);
    lcd.setCursor(0, 0);
    lcd.print("Referenzfahrt");
    lcd.setCursor(0, 1);
    lcd.print("beendet");
    delay(2000);
    lcd.clear();
    lcd.begin(16, 2);
    lcd.setCursor(0, 0);
    lcd.print("Wert");
    lcd.setCursor(0, 1);
    lcd.print(encoderWert);
  }

}

void encoder_lesen () {
  messungPin1 = digitalRead(encoderPinA);
  if ((messungPin1 == LOW) && (messungPin1Alt == HIGH) && (nullStellung == true)) {
    if (digitalRead(encoderPinB) == HIGH) {
      if (encoderWert < 48) 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;

  }
  messungPin1Alt = messungPin1;
}

void schritt () {
  if (enter == true) {
    gleisNeu = wertSpeichern;
    schritte = abs (gleisNeu - gleisAlt);
    if (gleisNeu > gleisAlt) {
      Serial.println ("rechts");
    }
    else if (gleisNeu < gleisAlt){
      Serial.println ("links");
    }
    Serial.print ("benoetigte Schritte  ");
    Serial.println(schritte);
    Serial.println(gleisNeu);
    Serial.println(gleisAlt);
    Serial.println(enter);
    enter = false;
    ergebnis = true;
  }
}

void schritteZaehlen () {
  sensor = digitalRead (hal);
  startZeit = millis();
  if ((schritte != 0) && (ergebnis == true)) {
    start = true;
    if ((startZeit - vergangeneZeit >= interval) && (sensor == LOW) && (start == true)) {
      vergangeneZeit = startZeit;
      schritte--;
      Serial.println("Schritte");
      Serial.println(schritte);
    }
  }
  else if ((schritte == 0) && (start == true)) {
    start = false;
    Serial.println("Ziel");
    ergebnis = false;
    gleisAlt = wertSpeichern;
  }
}

void best_Richtung() {

}

void motor() {

}


nur wie bekomme ich das hin, das die Scheibe, wenn ich von Gleis 1 auf Gleis 48 fahren möchte, nur  1 Schritt nach links fährt anstatt 48 Schritte nach rechts fährt?
Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 15, 2019, 11:01 pm
Hi

Was sagt dazu meine neueste Kreation?
Gleis_neu<Gleis_Alt wird wohl hier false sein (48<1 -> false)
rechtsrum müsste abs(48-1) = 47 sein - bleibt in beiden Konstellationen gleich
linksrum müsste 48-rechtsrum=1 sein - hier auch, Namen irreführend!!

Bei 1->48 und bei 48->1 müsste
(Gleis_neu<Gleis_Alt XOR rechtsrum<linksrum) 1x true und 1x false werden

MfG
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 15, 2019, 11:18 pm
Hm... Verstehe leider nicht wie du das mit dem XOR meinst.

Müsste ich in die eine Richtung mit absoluten Werten rechnen und in die andere mit normalen Werten?
Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 16, 2019, 07:14 pm
Hi

Warum versuchst Du's nicht einfach?
Mehr, als daß Dir der Compiler das XOR um die Ohren haut, kann nicht passieren.
Mein Compiler traut Sich Das aber scheinbar nicht:
Code: [Select]
const byte schritte_max = 48;   //Anzahl an möglichen Anschlußpunkten

byte von;                       //Ausgangsgleis
byte nach;                      //Zielgleis

void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:
  von = random(schritte_max) + 1;   //von und bis 'auswürfeln'
  nach = random(schritte_max) + 1;

  Serial.print("Von ");       // Von 1
  Serial.print(von);
  Serial.print(" nach ");     // nach 12
  Serial.println(nach);

  byte schritte_a = abs(von - nach);
  Serial.print("Entfernung ohne 1-");
  Serial.print(schritte_max - 1);
  Serial.print(" Wechsel ");  //Entfernung ohne 1-47 Wechsel 11
  Serial.println(schritte_a);
  byte schritte_b = schritte_max - schritte_a;
  Serial.print("Entfernung mit 1-");
  Serial.print(schritte_max - 1);
  Serial.print(" Wechsel ");   //Entfernung mit 1-47 Wechsel 37
  Serial.println(schritte_b);
  //wenn schritte_a<schritte_b && von<nach, dann 'aufwärts' drehend ... 1->12
  //wenn schritte_a<schritte_b && von>nach, dann 'abwärts' drehend  ... 12->1
  //wenn schritte_a>schritte_b && von<nach, dann 'abwärts' drehend  ... 1->48
  //wenn schritte_a>schritte_b && von>nach, dann 'aufwärts' drehend  ... 48->1
  if (schritte_a) {
    if (schritte_a < schritte_b xor von < nach) { //jedes der Statements kann nur wahr oder falsch sein
      Serial.println("Starte Abwärts");   // wenn nur Eines wahr ist
    } else {
      Serial.println("Starte Aufwärts");  // wenn Keines oder Beide wahr sind
    }
  } else {
    Serial.println("identisches Gleis");
  }
  delay(1000);
}

Ungetestet - das 'xor' lässt sich recht einfach in der Zeile 35 entdecken.

Der Hintergedanke dazu ist, daß sich die Drehrichtung umkehren muß, wenn der Weg 'durch die Null' länger ist, oder (eigentlich exclusives oder) Start und Ziel die Positionen getauscht haben.

KA, ob's so wirklich klappt, sollte aber.

MfG
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 17, 2019, 06:48 pm
Guten abend,

random heißt doch Zufall oder? Wie soll das mit Zufall denn funktionieren?
Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 17, 2019, 07:57 pm
Hi

Das soll Dir zeigen, ob die Berechnung so passt - wenn hier Patzer erscheinen, sollte dieser Code vll. doch nicht in die endgültige Version Einzug erhalten.

Also:
- Auf einen Arduino brutzeln
- Terminal aufmachen und die Zeilen, Die der Arduino ausspuckt, interpretieren

Dazu gehört auch: Wenn Er IMMER die falsche Richtung wählt, passt Das auch - dann statt XOR == oder die Bedingungen 'durchtauschen'.

MfG

PS: Du darfst auch was selber machen, zumindest das Antesten ... so mit fertigem Code, am Besten noch mit Schleifchen drum herum, tun wir uns hier gelegentlich arg schwer!
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 17, 2019, 09:57 pm
Ich möchte auch keinen fertigen Code. Ich will es ja auch lernen. Ich konnte mir nur nicht vorstellen was der Random Befehl soll. Aber ich habe es begriffen. Mit dem Befehl werden Zusatzzahlen erstellt die dann mit durch xor verglichen werden. Ich danke euch :-)
Title: Re: Drehencoder Test
Post by: Tommy56 on Jan 17, 2019, 10:06 pm
Mit dem Befehl werden Zusatzzahlen erstellt
Zufallszahlen.

Gruß Tommy
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 17, 2019, 10:10 pm
Meinte ich natürlich auch. Hab es übrigens gerade getestet. Das sieht gut aus.
Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 17, 2019, 10:13 pm
;)

Sieht nach Autokorrektur aus.

Durch Zufall (... Pseudo! Sind immer die Gleichen, da ich keinen Seed setze) werden die beteiligten Gleise 'ausgewürfelt', die Formeln werden mit diesen Gleisen durchgerechnet und Du bekommst das Ergebnis ins Terminal.
Hier musst Du 'nur noch' entscheiden, ob die Ergebnisse ok sind, wobei 'Alle falsch' ebenfalls ok ist - dann muß man nur die Abfrage oder die Ansteuerung des Motor umdrehen.

Wenn vereinzelt Ausreißer auftreten, müsste man Diesen nachgehen, wer wo was falsch berechnet.

MfG
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 17, 2019, 10:18 pm
Hab den Code etwas abgeändert, in der Hoffnung das ich das richtig interpretiert habe?

Code: [Select]


const byte schritte_max = 48;   //Anzahl an möglichen Anschlußpunkten

byte von;                       //Ausgangsgleis
byte nach;                      //Zielgleis

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
}




void loop() {
  // put your main code here, to run repeatedly:
  von = random(schritte_max) + 1;   //von und bis 'auswürfeln'
  nach = random(schritte_max) + 1;

  Serial.print("Von ");       // Von 1
  Serial.print(von);
  Serial.print(" nach ");     // nach 12
  Serial.println(nach);

  byte schritte_a = abs(von - nach);
  Serial.print("Entfernung links 1-");
  Serial.print(schritte_max - 1);
  Serial.print(" Wechsel ");  //Entfernung ohne 1-47 Wechsel 11
  Serial.println(schritte_a);
  byte schritte_b = schritte_max - schritte_a;
  Serial.print("Entfernung rechts 1-");
  Serial.print(schritte_max - 1);
  Serial.print(" Wechsel ");   //Entfernung mit 1-47 Wechsel 37
  Serial.println(schritte_b);
  //wenn schritte_a<schritte_b && von<nach, dann 'aufwärts' drehend ... 1->12
  //wenn schritte_a<schritte_b && von>nach, dann 'abwärts' drehend  ... 12->1
  //wenn schritte_a>schritte_b && von<nach, dann 'abwärts' drehend  ... 1->48
  //wenn schritte_a>schritte_b && von>nach, dann 'aufwärts' drehend  ... 48->1
  if (schritte_a) {
    if (schritte_a < schritte_b xor von < nach) { //jedes der Statements kann nur wahr oder falsch sein
      Serial.println("Starte links");   // wenn nur Eines wahr ist
    } else {
      Serial.println("Starte rechts");  // wenn Keines oder Beide wahr sind
    }
  } else {
    Serial.println("identisches Gleis");
  }
  delay(1000);
}



Komischerweise kommt dann irgendwann:

Von 4 nach 24
Entfernung links 1-47 Wechsel 20
Entfernung rechts 1-47 Wechsel 28
Starte rechts
?
rechts ist ja richtig aber es sind nur 20 anstatt 28 Schritte??

oder
Von 9 nach 20
Entfernung links 1-47 Wechsel 11
Entfernung rechts 1-47 Wechsel 37
Starte rechts

oder

Von 3 nach 34
Entfernung links 1-47 Wechsel 31
Entfernung rechts 1-47 Wechsel 17
Starte links

oder

Von 37 nach 38
Entfernung links 1-47 Wechsel 1
Entfernung rechts 1-47 Wechsel 47
Starte rechts

Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 17, 2019, 10:41 pm
Ich glaube es ist mein Fehler. Mit Wechsel meinst es geht über 0 zur 47 und ohne Wechsel meinst du es geht nicht über 0. Richtig? Somit ist meine Änderung Käse
Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 17, 2019, 10:44 pm
Hi

Ok, eigentlich sollte 'rechts herum' im Uhrzeigersinn sein - also von 4 nach 24 Rechts:20, Links:28

Störe Dich nicht am eigentlichen Text einer Anzeige, sondern passe Diese so an, daß Die zum Vorhaben stimmt.
Ich habe den Sketch so runtergetippt und geschaut, ob Er kompiliert - on Rechts jetzt wirklich Rechts ist - entscheidest Du.
Hätte auch A und B schreiben können, dann muß man aber IMMER in den Kommentaren schauen, was welche Zeile bedeuten soll.
Passe die Zeilen so an, daß Das bei Dir Sinn ergibt.

Dann bitte drei Beispiele mit von<nach und Drei mit von>nach - wenn in Deiner Ausgabe dann auch noch die Richtung, Die eingeschlagen werden soll, richtig 'geschwätzt' wird, schadet bestimmt auch nicht.

Wenn Er dann immer noch Fehler bringt, Diese bitte auch hier rein mit dem Sketch/der Berechnung, Die Du dann benutzt.

MfG

PS: Ja, Da fehlt klassisch ein 'MIT' und ein 'OHNE' - ist wohl rausgeflogen, als ich von '48' auf 'schritte_max' geändert habe - liest sich SO nämlich äußerst anstrengend!
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 17, 2019, 11:06 pm
Hoffe man kann es jetzt besser lesen.

Von 13 nach 3
Entfernung in Drehrichtung links 1-47 nicht ueber 0 =10 Schritte
Entfernung in Drehrichtung rechts 1-47 ueber 0 =38 Schritte
gewählte Drehrichtung links


Von 3 nach 34
Entfernung in Drehrichtung links 1-47 nicht ueber 0 =31 Schritte
Entfernung in Drehrichtung rechts 1-47 ueber 0 =17 Schritte
gewählte Drehrichtung links


Von 4 nach 22
Entfernung in Drehrichtung links 1-47 nicht ueber 0 =18 Schritte
Entfernung in Drehrichtung rechts 1-47 ueber 0 =30 Schritte
gewählte Drehrichtung rechts


Von 32 nach 33
Entfernung in Drehrichtung links 1-47 nicht ueber 0 =1 Schritte
Entfernung in Drehrichtung rechts 1-47 ueber 0 =47 Schritte
gewählte Drehrichtung rechts


Von 2 nach 25
Entfernung in Drehrichtung links 1-47 nicht ueber 0 =23 Schritte
Entfernung in Drehrichtung rechts 1-47 ueber 0 =25 Schritte
gewählte Drehrichtung rechts


Von 19 nach 38
Entfernung in Drehrichtung links 1-47 nicht ueber 0 =19 Schritte
Entfernung in Drehrichtung rechts 1-47 ueber 0 =29 Schritte
gewählte Drehrichtung rechts


Mit dem Code:

Code: [Select]

const byte schritte_max = 48;   //Anzahl an möglichen Anschlußpunkten

byte von;                       //Ausgangsgleis
byte nach;                      //Zielgleis

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  von = random(schritte_max) + 1;   //von und bis 'auswürfeln'
  nach = random(schritte_max) + 1;

  Serial.print("Von ");       // Von 1
  Serial.print(von);
  Serial.print(" nach ");     // nach 12
  Serial.println(nach);

  byte schritte_a = abs(von - nach);
  Serial.print("Entfernung in Drehrichtung links 1-");
  Serial.print(schritte_max - 1);
  Serial.print(" nicht ueber 0 =");  //Entfernung ohne 1-47 Wechsel 11
  Serial.print(schritte_a);
  Serial.println(" Schritte");
  byte schritte_b = schritte_max - schritte_a;
  Serial.print("Entfernung in Drehrichtung rechts 1-");
  Serial.print(schritte_max - 1);
  Serial.print(" ueber 0 =");   //Entfernung mit 1-47 Wechsel 37
  Serial.print(schritte_b);
  Serial.println(" Schritte");
  //wenn schritte_a<schritte_b && von<nach, dann 'rechts' drehend ... 1->12
  //wenn schritte_a<schritte_b && von>nach, dann 'links' drehend  ... 12->1
  //wenn schritte_a>schritte_b && von<nach, dann 'links' drehend  ... 1->48
  //wenn schritte_a>schritte_b && von>nach, dann 'rechts' drehend  ... 48->1
  if (schritte_a) {
    if (schritte_a < schritte_b xor von < nach) { //jedes der Statements kann nur wahr oder falsch sein
      Serial.println("gewählte Drehrichtung links");   // wenn nur Eines wahr ist
    Serial.println(" ");
    } else {
      Serial.println("gewählte Drehrichtung rechts");  // wenn Keines oder Beide wahr sind
    Serial.println(" ");
    }
  } else {
    Serial.println("identisches Gleis");
    Serial.println(" ");
  }
  delay(1000);
}
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 18, 2019, 09:11 pm
Guten abend,

Kann mir jemand helfen?
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 19, 2019, 03:14 pm
Hallo alle zusammen,

von 4 nach 24 wird immer die Falsche Richtung genommen?
Woran könnte das liegen?

Code: [Select]

const byte schritte_max = 48;   //Anzahl an möglichen Anschlußpunkten

byte von;                       //Ausgangsgleis
byte nach;                      //Zielgleis

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  von = random(schritte_max) + 1;   //von und bis 'auswürfeln'
  nach = random(schritte_max) + 1;

  Serial.print("Von ");       // Von 1
  Serial.print(von);
  Serial.print(" nach ");     // nach 12
  Serial.println(nach);

  byte schritte_a = abs(nach - von);
  Serial.print("Entfernung in Drehrichtung links 1-");
  Serial.print(schritte_max );
  Serial.print(" nicht ueber 0 =");  //Entfernung ohne 1-47 Wechsel 11
  Serial.print(schritte_a);
  Serial.println(" Schritte");
 
  byte schritte_b = schritte_max - schritte_a;
  Serial.print("Entfernung in Drehrichtung rechts 1-");
  Serial.print(schritte_max );
  Serial.print(" ueber 0 =");   //Entfernung mit 1-47 Wechsel 37
  Serial.print(schritte_b);
  Serial.println(" Schritte");
  //wenn schritte_a<schritte_b && von<nach, dann 'rechts' drehend ... 1->12
  //wenn schritte_a<schritte_b && von>nach, dann 'links' drehend  ... 12->1
  //wenn schritte_a>schritte_b && von<nach, dann 'links' drehend  ... 1->48
  //wenn schritte_a>schritte_b && von>nach, dann 'rechts' drehend  ... 48->1
  if (schritte_a) {
    if (schritte_a < schritte_b) { //jedes der Statements kann nur wahr oder falsch sein
      Serial.println("gewählte Drehrichtung links");   // wenn nur Eines wahr ist
    Serial.println(" ");
    } else {
      Serial.println("gewählte Drehrichtung rechts");  // wenn Keines oder Beide wahr sind
    Serial.println(" ");
    }
  } else {
    Serial.println("identisches Gleis");
    Serial.println(" ");
  }
  delay(1000);
}
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 19, 2019, 03:19 pm
verstehe es nicht?

Von 3 nach 34
Entfernung in Drehrichtung links 1-48 nicht ueber 0 =31 Schritte  //falsch
Entfernung in Drehrichtung rechts 1-48 ueber 0 =17 Schritte
gewählte Drehrichtung rechts
 
Von 20 nach 14
Entfernung in Drehrichtung links 1-48 nicht ueber 0 =6 Schritte   //richtig
Entfernung in Drehrichtung rechts 1-48 ueber 0 =42 Schritte
gewählte Drehrichtung links
 
Von 4 nach 22
Entfernung in Drehrichtung links 1-48 nicht ueber 0 =18 Schritte  //falsch
Entfernung in Drehrichtung rechts 1-48 ueber 0 =30 Schritte
gewählte Drehrichtung links
 
Von 32 nach 33
Entfernung in Drehrichtung links 1-48 nicht ueber 0 =1 Schritte  //falsch
Entfernung in Drehrichtung rechts 1-48 ueber 0 =47 Schritte
gewählte Drehrichtung links
 
Von 2 nach 25
Entfernung in Drehrichtung links 1-48 nicht ueber 0 =23 Schritte  //falsch
Entfernung in Drehrichtung rechts 1-48 ueber 0 =25 Schritte
gewählte Drehrichtung links
 
Von 30 nach 18
Entfernung in Drehrichtung links 1-48 nicht ueber 0 =12 Schritte  //richtig
Entfernung in Drehrichtung rechts 1-48 ueber 0 =36 Schritte
gewählte Drehrichtung links
 
Von 45 nach 44
Entfernung in Drehrichtung links 1-48 nicht ueber 0 =1 Schritte  //richtig
Entfernung in Drehrichtung rechts 1-48 ueber 0 =47 Schritte
gewählte Drehrichtung links
 
Von 19 nach 38
Entfernung in Drehrichtung links 1-48 nicht ueber 0 =19 Schritte  //falsch
Entfernung in Drehrichtung rechts 1-48 ueber 0 =29 Schritte
gewählte Drehrichtung links
 
Von 42 nach 18
Entfernung in Drehrichtung links 1-48 nicht ueber 0 =24 Schritte  //richtig
Entfernung in Drehrichtung rechts 1-48 ueber 0 =24 Schritte
gewählte Drehrichtung rechts
 
Von 5 nach 41
Entfernung in Drehrichtung links 1-48 nicht ueber 0 =36 Schritte  / /richtig
Entfernung in Drehrichtung rechts 1-48 ueber 0 =12 Schritte
gewählte Drehrichtung rechts
 
Von 5 nach 3
Entfernung in Drehrichtung links 1-48 nicht ueber 0 =2 Schritte   //richtig
Entfernung in Drehrichtung rechts 1-48 ueber 0 =46 Schritte
gewählte Drehrichtung links
 
Von 13 nach 21
Entfernung in Drehrichtung links 1-48 nicht ueber 0 =8 Schritte  //falsch
Entfernung in Drehrichtung rechts 1-48 ueber 0 =40 Schritte
gewählte Drehrichtung links
Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 19, 2019, 07:14 pm
Hi

Schade, daß Du einen 'Ausreißer' drin hast
Quote
Von 5 nach 41
Entfernung in Drehrichtung links 1-48 nicht ueber 0 =36 Schritte  / /richtig
Entfernung in Drehrichtung rechts 1-48 ueber 0 =12 Schritte
gewählte Drehrichtung rechts
Ohne diesen 'Richtig', wären alle Fälle falsch gewesen, in Denen das Start-Gleis kleiner als das Ziel-Gleis war - durch den Ausreißer ist diese Theorie aber wieder Müll.

Sorry, daß Du mit meinem Versuch jetzt doch so viel Zeit unnütz verballert hast.
Leider sehe ich gerade aber auch keine Gemeinsamkeit - der XOR-Ansatz hätte eigentlich passen sollen ... eigentlich.

MfG
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 20, 2019, 11:26 am
Hallo alle zusammen,

das mit dem richtig habe ich manuell dazu geschrieben. Überall wo richtig dahinter steht, stimmen die Schritte und die Richtung und bei denen wo falsch dahinter steht stimmen Ricchtung und Schritte nicht.

Hat noch wer ne Idee, wie man es lösen könnte?
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 20, 2019, 01:00 pm
Keiner ne Idee? Es muss doch irgendwie möglich sein. Ich denke das das Problem daran liegt, dass man über Null dreht.
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 20, 2019, 02:38 pm
Man könnte doch auch die Richtung über die drhrichtung des encoders wählen. Dazu müsste man aber den Encoder über 0 zählen lassen können. Geht sowas und wenn ja wie könnte man das machen?
Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 20, 2019, 08:09 pm
Hi

Über Null zählen ist nicht so schwer:
- wenn über 47 (Maximal-Wert -1), einfach 48 (Maximal-Wert) abziehen
- wenn unter 0 (dafür signed Typ notwendig) 48 (Maximal-Wert) addieren

Oder, ohne signed-Typ, beim Hochzählen prüfen, ob wir damit auf 48 (Maximal-Wert) kämen, ja->0, nein ->+1, beim Runterzählen, ob wir jetzt noch auf NULL sind, ja ->Maximal-Wert-1, nein -> -1.

Trotzdem muß Es gehen, daß der Arduino die richtige Richtung errechnet.
Wenn mir akut aber auch eine direkte Idee fehlt und die Zeit - da bekommen dann doch eher eigene Projekte den Vorrang.

MfG
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 20, 2019, 08:32 pm
* gelöscht mein Fehler*
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 20, 2019, 09:51 pm
Habe einen Weg gefunden. :-)


Code: [Select]


const byte schritte_max = 48;   //Anzahl an möglichen Anschlußpunkten

byte von;                       //Ausgangsgleis
byte nach;                      //Zielgleis

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  von = random(schritte_max) + 1;   //von und bis 'auswürfeln'
  nach = random(schritte_max) + 1;
  //  von = 19;
    //nach = 38;
  Serial.print("Von ");       // Von 1
  Serial.print(von);
  Serial.print(" nach ");     // nach 12
  Serial.println(nach);
if (von > nach){
  int schritte_links = (von - nach);
  Serial.println("Entfernung in Drehrichtung links");
  Serial.println(schritte_links);
  Serial.println(" ");
 
  int schritte_rechts = nach - von;
  Serial.println("Entfernung in Drehrichtung rechts");
  Serial.println(schritte_rechts);
  int schritte_rechts_erg = schritte_rechts + 48;
  Serial.println(schritte_rechts_erg);
  Serial.println(" ");
  if (schritte_links > schritte_rechts_erg) {
    Serial.println("Drehrichtung rechts");
   
  }
  else if (schritte_links < schritte_rechts_erg) {
    Serial.println("Drehrichtung links");
  }
}
if (von < nach) {
    int schritte_links = abs ((nach - von) -48);
    Serial.println("Entfernung in Drehrichtung links");
    Serial.println(schritte_links);
    Serial.println(" ");
    int schritte_rechts = (nach - von);
    Serial.println("Entfernung in Drehrichtung rechts");
    Serial.println(schritte_rechts);
    Serial.println(" ");
    if (schritte_links > schritte_rechts) {
      Serial.println("Drehrichtung rechts");
    }
    else if (schritte_links < schritte_rechts) {
      Serial.println("Drehrichtung links");
    }
  }

 
 
  Serial.println("-------------------------------------------------------------------------");

  delay(1000);
}



Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 20, 2019, 10:35 pm
geht auch nicht. Schade

das kommt bei:

Von 42 nach 18
Entfernung in Drehrichtung links
24
 
Entfernung in Drehrichtung rechts
-24
24

raus.  ::)
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 20, 2019, 11:05 pm
Hab es rausbekommen. Er wusste nicht in welche Richtung er fahren soll, da bei Richtungen die gleiche Anzahl an Schritten hatte.

Jetzt funktioniert es.  :)

Code: [Select]



const byte schritte_max = 48;   //Anzahl an möglichen Anschlußpunkten

byte von;                       //Ausgangsgleis
byte nach;                      //Zielgleis

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
 von = random(schritte_max) + 1;   //von und bis 'auswürfeln'
 nach = random(schritte_max) + 1;
  //von = 25;
  //nach = 1;
  Serial.print("Von ");       // Von 1
  Serial.print(von);
  Serial.print(" nach ");     // nach 12
  Serial.println(nach);
if (von > nach){
  int schritte_links = (von - nach);
  Serial.println("Entfernung in Drehrichtung links");
  Serial.println(schritte_links);
  Serial.println(" ");
 
  int schritte_rechts = nach - von;
  Serial.println("Entfernung in Drehrichtung rechts");
  Serial.println(schritte_rechts);
  int schritte_rechts_erg = schritte_rechts + 48;
  Serial.println(schritte_rechts_erg);
  Serial.println(" ");
  if (schritte_links >= schritte_rechts_erg) {
    Serial.println("Drehrichtung rechts");
   
  }
  else if (schritte_links < schritte_rechts_erg) {
    Serial.println("Drehrichtung links");
  }
}
if (von < nach) {
    int schritte_links = abs ((nach - von) -48);
    Serial.println("Entfernung in Drehrichtung links");
    Serial.println(schritte_links);
    Serial.println(" ");
    int schritte_rechts = (nach - von);
    Serial.println("Entfernung in Drehrichtung rechts");
    Serial.println(schritte_rechts);
    Serial.println(" ");
    if (schritte_links >= schritte_rechts) {
      Serial.println("Drehrichtung rechts");
    }
    else if (schritte_links < schritte_rechts) {
      Serial.println("Drehrichtung links");
    }
  }

 
 
  Serial.println("-------------------------------------------------------------------------");
 
 
  delay(1000);
}



Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 22, 2019, 10:53 pm
Guten Abend,

Wie bekomme ich hin, dass man den Encoderwert überdrehen kann. Ich meine, das ich wenn ich den Encoder bei 48 weiter drehe dann als nächstes der Wert 1 kommt und wenn ich ihn zurück drehe der Wert 48?

Code: [Select]

void encoder_lesen () {
  messungPin1 = digitalRead(encoderPinA);
  if ((messungPin1 == LOW) && (messungPin1Alt == HIGH) && (nullStellung == true)) {
    if (digitalRead(encoderPinB) == HIGH) {
      if (encoderWert < 48) encoderWert++ ;
    } else {
      if (encoderWert > 1) encoderWert-- ;

Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 23, 2019, 07:13 pm
Hi
Code: [Select]
if (encoderWert < 48) encoderWert++ ;
Hier bist Du im Bereich 'Aufwärts' - Du hast also wohl rechts herum gedreht.
Deine jetzige Abfrage fragt, ob der Wert kleiner 48 ist, wenn Das gegeben ist, zählst Du 1 hinzu.
Da Das bei 48 nicht mehr gegeben ist, kannst Du entweder einen else-Zweig machen, um dort encoderWert auf 1 zu setzen, oder Du rechnest 'mit Überlauf'.

48+1->49
49%48->1 (Modulo, Rest der Division, 49:48=1, Rest 1)

Damit Das auch 'rückwärts' klappt, musst Du '-1' addieren - dabei kannst Du aber einen Unterlauf erzeugen - dann wird Dir Modulo 48 wohl keine 47 zurück geben.
Deshalb addierst Du '48-1'.

Beim 'Hochdrehen' stur +1
Beim Runterdrehen stur +47 (=48-1)
Ein +48 wäre das Gleiche, wie ein +0, somit bekommst Du durch +47 Dein '-1', aber in die Richtung 'nach Oben'.
Nach der Addition (also +1 oder +47) erzeugst Du das Modulo:
Code: [Select]
encoderWert=encoderWert%48+1;
Hier fällt Dir wohl die +1 auf - Die brauchen wir hier, weil Dein Sketch von 1-48 'zählt', Modulo aber Ergebnisse von 0-47 liefert (eben der Rest, wenn wir keine 48 mehr abziehen können).
Richtung, von, über (Addition), nach (Modulo)
+> 1 -> 2 -> 2
+> 2 -> 3 -> 3
-> 3 -> 49 -> 2
-> 2 -> 48 -> 1
-> 1 -> 47 -> 48
-> 48 -> 95 -> 47

MfG
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 23, 2019, 10:12 pm
Ich danke dir. Oh kannst mir das genauer erklären wie ich das machen muss. Versteh das leider nicht.
Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 23, 2019, 10:35 pm
Da, wo Du um 1 erhöhst, erhöhst Du auch weiterhin um 1.
Da, Wo Du um 1 verminderst, erhöhst Du um 47 (einen weniger als MAX-Positionen).
BEIDE, ohne die IF-Abfrage davor, wir wollen ja bei 1 auch runter und bei 48 auch hoch zählen.
Hinter der Zählerei kommt dann die Korrektur des gezählten Wert, die Modulo-Berechnung.

Etwas Spieltrieb darfst Du gerne auch zeigen - wenn's wider Erwarten doch nicht klappt, hast Du die Vorversion (Die Du Dir UNBEDINGT Exportieren/Archivieren solltest).

Zur größten Not schreibe Dir einen Testsketch und lasse eine Variable von 0 bis 32000 hoch zählen (int geht dafür).
Diese Variable verrechnest Du mit %48 (Modulo 48) und lässt Dir dieses Ergebnis anzeigen.

MfG
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 24, 2019, 07:03 pm
Aber wen ich die If Abfragen für den Encoderwert wegnehme, mach das doch keinen Sinn mehr oder?


if (encoderWert < 48) encoderWert++ ;
    } else {
      if (encoderWert > 1) encoderWert-- ;

Ich begreif das einfach nicht. Gibt es da eventuell irgendwo ein Beispiel?
Title: Re: Drehencoder Test
Post by: postmaster-ino on Jan 24, 2019, 07:37 pm
Hi

Code: [Select]
if ((messungPin1 == LOW) && (messungPin1Alt == HIGH) && (nullStellung == true)) {
    if (digitalRead(encoderPinB) == HIGH) {
      if (encoderWert < 48) encoderWert++ ;
    } else {
      if (encoderWert > 1) encoderWert-- ;

1. Zeile: Abfrage, ob der Encoder gedreht wurde, wenn JA, geht's weiter
2. Zeile, Abfrage, ob der Encoder HOCH gedreht wurde, wenn JA, geht's direkt weiter, sonst beim ELSE
3. Zeile - HIER begrenzt Du den Wert auf 48 - DIESE IF raus und NUR encoderwert++; dahin
4. Zeile ... ein ELSE, ab hier, wenn 'RUNTER' gedreht wurde
5. Zeile - HIER begrenzt Du auf den Wert 1 - DIESES IF raus und statt -- machst Du hier encoderwert+=47; (oder +(maxiwert-1) )
DAHINTER - quasi Zeile 5 1/2
encoderwert=encoderwert%48; (oder maxwert)

... fertig ...

Die 3.te und die 5.te Zeile haben NICHTS mit der Abfrage des Encoder zu tun - DIE verhindern nur, daß der Wert <1 oder >48 werden kann.

Wenn man mit der IF-Verschachtelung nicht klar kommt, sollte man STUR ALLE Klammern setzen.
Das hier:
if (encoderWert < 48) encoderWert++ ;
ist eine komplette und gültige IF-Abfrage mit einer Anweisung, wenn Diese erfüllt ist.
if (encoderWert < 48) {
   //hier, wenn Bedingung erfüllt
  encoderWert++ ;
}else{
  //hier, wenn Bedingung NICHT erfüllt
}
Ohne die Klammern (Block-Bildung), kannst Du auch nur EINEN Befehl bedingt ausführen lassen.
Im Block beliebig Viele.

MfG
Title: Re: Drehencoder Test
Post by: Acki1985 on Jan 26, 2019, 03:33 pm
Hallo alle zusammen. So hab es jetzt mit eurer Hilfe bis hier her Geschafft. Das Programm läuft so wie es soll. Ok hab den Motor noch nicht angeschlossen.

Jetzt müsste ich aber zwei Arduinos verwenden, welche über eine Funkverbindung miteinander reden und die Befehle ausführen. Habt ihr da einen link, wo die Datenübertragung mittels NRF24 beschrieben ist?
Oder wie man das hinbekommt, das wenn am sender ein Pin high ist am Empfänger eine LED angeht und wenn am Sender der Pin wieder LOW ist am Empfänger die LED wieder aus geht?

Hier ist übrigens das Programm was mit eurer Hilfe entstanden ist:

https://pastebin.com/WM9ZZTdt
Title: Re: Drehencoder Test
Post by: Acki1985 on Feb 10, 2019, 10:47 am
Hallo alle zusammen,

habe es mit eurer Hilfe geschaft und es soweit hinbekommen das es funktioniert. Nun möcht ich die Befehle per Funk übertragen und zurückgesendet bekommen wieviele Schritte nach jeder Sensor Betätigung noch übrig sind. Das Senden zur Scheibe funktioniert, nur bekomme ich keine restlichen Schritte zurückgesendet.
Der Sendecode ist nur ein Beispiel um es zu testen.

Sender:
Code: [Select]

#include  <SPI.h>
#include  "RF24.h"
byte data[1];
byte data_e[1];
//const uint64_t pipe = 0xF0F0F0F0A1LL;
const byte addresses[][6] = {"00001", "00002"};
RF24 radio(8, 9);
 
 
const int ledpin =  6;      // the number of the LED pin
 
void setup()
{
  Serial.begin(9600);
  pinMode(ledpin, OUTPUT);
 
  pinMode(0, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
  radio.begin();
  //radio.openWritingPipe(pipe);
  radio.openWritingPipe(addresses[0]); // 00002
  radio.openReadingPipe(1, addresses[1]); // 00001
  }
 
void loop()
{
  if (digitalRead(0) == HIGH ||
      digitalRead(7) == HIGH ||
      digitalRead(2) == HIGH ||
      digitalRead(3) == HIGH ||
      digitalRead(4) == HIGH ||
      digitalRead(5) == HIGH)
  {
    data[0] = 0;
    while (radio.available())
{
Serial.println("Data there");
radio.read(data_e, 1);
Serial.println(data_e[0]);
  }
  if (digitalRead(0) == LOW)
  {
    data[0] = 1;
    digitalWrite(LED_BUILTIN, HIGH);
 
  }
  if (digitalRead(7) == LOW)
  {
    data[0] = 2;
    digitalWrite(LED_BUILTIN, HIGH);
  }
  if (digitalRead(2) == LOW)
  {
    data[0] = 3;
    digitalWrite(LED_BUILTIN, HIGH);
  }
  if (digitalRead(3) == LOW)
  {
    data[0] = 4;
    digitalWrite(LED_BUILTIN, HIGH);
  }
  if (digitalRead(4) == LOW)
  {
    data[0] = 254;
    digitalWrite(LED_BUILTIN, HIGH);
  }
   if (digitalRead(5) == LOW)
  {
    data[0] = 255;
    digitalWrite(LED_BUILTIN, HIGH);
  }
  if (data [0] != 0) {
    radio.stopListening();
  radio.write(data, 1);
  digitalWrite(LED_BUILTIN, LOW);
  Serial.println(data[0]);
  radio.startListening();
}
}
}



Empfänger (Bühne):
Code: [Select]

#include <SPI.h>
#include "RF24.h"

int data[1];
boolean var = true;
const byte addresses[][6] = {"00001", "00002"};
//const uint64_t pipe = 0xF0F0F0F0A1LL;
RF24 radio (8, 9);
byte rever_start = false;
const byte hal = 3;
byte schritte = 0;                                 // Schritte die deer Motor (Hallsensor betätigt) zurücklegen muss
int sensor = LOW;
unsigned long startZeit;                          // Abfrage begin Sensor an Bühne
unsigned long interval = 2000;                    // Zeitabstand nachdem ein Zustand des Sensors erkannt wird
unsigned long vergangeneZeit = 0;                 // Speichervariable um die Vergangene Zeit zu speichern
/*int pin_motor_links = A1;                         // Richtungspin an H-Brücke für Links
int pin_motor_rechts = A2;                        // Richtungspin an H-Brücke für Rechts
*/
// Statusvariablen
bool nullStellung = false;                      // Speichervariable ob Referenzfahrt erfolgt ist
bool ergebnis = false;                          // Berechnung der Schritte und Richtung beendet/gestartet
bool start = false;                           // Schritte Zaehlen beendet/gestartet

void setup() {
  radio.begin();
  //radio.openReadingPipe(1, pipe);
  radio.openWritingPipe(addresses[1]); // 00001
  radio.openReadingPipe(1, addresses[0]); // 00002
  radio.startListening();
  pinMode(hal, INPUT);
  Serial.begin(9600);
  //delay (2000);
  }

void loop() {
 
  referenzFahrt();
  encoder_lesen();
  schritteZaehlen();
  }

void referenzFahrt() {
  while (radio.available())
{
Serial.println("Data there");
radio.read(data, 1);
Serial.println(data[0]);
}

      // Reverenzfahrt

      if ((data[0] == 255) && (rever_start == false) && (nullStellung == false)) {
        rever_start = true;
        Serial.println("Reverenzfahrt gestartet");
    //    digitalWrite (pin_motor_rechts, HIGH);
      //  digitalWrite (pin_motor_links, LOW);
      }
      else if ((data[0] == 254) && (rever_start == true)) {
        nullStellung = true;
        rever_start = false;
        Serial.println("Reverenzfahrt beendet");
        Serial.println (" "); 
  //      digitalWrite (pin_motor_rechts, LOW);
//        digitalWrite (pin_motor_links, LOW);
      }
    }
 
  void encoder_lesen () {
   if ((data[0] <= 48) && (data[0] > 0) && (nullStellung == true) && (ergebnis == false)) {
    //rechtsrum data[0] Schritte
    schritte = data[0];
    ergebnis = true;
    // Motor
    Serial.println (schritte);
    Serial.print ("  Schritte nach Rechts");
    Serial.println (" ");   
   }
  else if ((data[0] >=100) && (data[0] <= 149) && (nullStellung == true) && (ergebnis == false)) {
    //linksrum data[0] - 100 Schritte
    schritte = data[0] - 100;
    ergebnis = true;
    // Motor
    Serial.println (schritte);
    Serial.print ("  Schritte nach links");
    Serial.println (" ");
   }
  }
 
void schritteZaehlen () {

  sensor = digitalRead (hal);
  startZeit = millis();
  if ((schritte != 0) && (ergebnis == true)) {
    start = true;
    if ((startZeit - vergangeneZeit >= interval) && (sensor == LOW) && (start == true)) {
      vergangeneZeit = startZeit;
      schritte--;
      Serial.println("Drehung start");
      Serial.println("Restl. Pos.");
      Serial.println(schritte);
      radio.stopListening();
      radio.write (schritte, 3);
      radio.startListening();
      }
  }
  else if ((schritte == 0) && (start == true)) {
    start = false;
    ergebnis = false;
    data[0] = 0;
    Serial.println("Ziel");
    Serial.println("Drehung");
    Serial.println("beendet");
    Serial.print("daten");
    Serial.println(schritte);
    radio.stopListening();
    radio.write (schritte, 1);
    radio.startListening();
    delay(2000);
    Serial.println(ergebnis);
    }
}


Warum bekomme ich von der Bühne nichts zurück?

P.S. Ich weis nicht ob ich einen neuen Fred aufmachen soll?

Gruß Acki
Title: Re: Drehencoder Test
Post by: agmue on Feb 10, 2019, 11:11 am
P.S. Ich weis nicht ob ich einen neuen Fred aufmachen soll?
Hatte ich auch gerade überlegt, da ich beispielsweise einen Drehencoder habe aber keinen Funk.

Alternativ kannst Du auch Beitrag #0 editieren und dort die Überschrift verändern, in dem Du "RF24" erwähnst.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 10, 2019, 12:13 pm
Danke dir. Hab es geändert.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 10, 2019, 10:03 pm
Hat denn wirklich keiner ne Idee?
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: HotSystems on Feb 10, 2019, 10:15 pm
Hat denn wirklich keiner ne Idee?
Ich kann nur vermuten, da der Sketch schlecht zu lesen ist.
Es fehlen einfach Kommentare, was an welcher Stelle passieren soll.

Ich vermute die Signale (Sender und Empfänger) überschneiden sich und damit bekommst der Empfänger nichts mit.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 11, 2019, 07:17 am
Hast du sicher gestellt, dass die Kommunikation zu den NRFs funktioniert?
Am einfachsten machst du das mit printDetails() (http://tmrh20.github.io/RF24/classRF24.html#adc95213ed4c8569a90eb33122e16cea6).

Welche Art von Modulen benutzt du?

Wie versorgst du die NRFs mit 3.3V?

Warum benutzt du hier ein while?
Code: [Select]
    while (radio.available())
{
Serial.println("Data there");
radio.read(data_e, 1);
Serial.println(data_e[0]);
  }


Warum benutzt du falsche Kommentare?
Code: [Select]
const byte addresses[][6] = {"00001", "00002"};

  radio.openWritingPipe(addresses[0]); // 00002
  radio.openReadingPipe(1, addresses[1]); // 00001

const byte addresses[][6] = {"00001", "00002"};

  radio.openWritingPipe(addresses[1]); // 00001
  radio.openReadingPipe(1, addresses[0]); // 00002


Benutze bitte mal Ctrl-T in der IDE um deinen Sketch zu formatieren.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 11, 2019, 11:35 pm
Guten Abend,

danke für deine Antwort.

zu 1. es sind diese Module      https://www.amazon.de/SainSmart-NRF24L01-drahtlos-Transceiver-2-4GHz/dp/B006CHFPFU

zu 2. Versorgt werden sie momentan über den Arduino NANO am 3,3Volt Ausgang mit Kondensator zur Masse

zu 3. Mit dem While das ist durch das testen entstanden. In manchen Codes steht while in anderen if.

zu 4. Das mit Kommentaren ist auch durch brobieren zu Stande gekommen.

Habe den Code nochmal geändert. Das Empfangen funktioniert super nur das zurück Senden nicht.

Wie gesagt der Sender ist nur zum testen. Ich habe die Variable Schritte immer händisch abgeändert.
Mit den Orginal Scetches von https://www.instructables.com/id/Arduino-and-NRF24L01/ hat das gegenseitige Senden und Empfangen funktioniert.


Hier meine Codes:
Sender (Provisorisch)

Code: [Select]

/*
  Arduino NRF24L01 simple transmit and receive - Created October 2017
    by DonX Developer
  *** This code was created for an Arduino UNO using the Arduino IDE v1.8.4. ***

  Parts:
  2 X Arduinos
  2 X Breadboards
  2 X NRF24L01
  [optional] 2 X YL-105 breakout boards for the NRF24L01. This allows for 5v connection and easier wiring
  2 X Momentary switches
  2 X Red LEDs
  2 X Yellow LEDs
  4 X 220 ohm resistors
  Jumper wires


  NRF24L01  Arduino pin
  VCC       3.3 V
  GND       GND
  CS        8
  CE        7
  MOSI      11 or ICSP-4
  MISO      12 or ICSP-1
  SCK       13 or ICSP-3

  If you use the YL-105 breakout board, the Vcc lead can go to the 5v Arduino pin

  Arduino pin 2 to Yellow LED long lead - anode
  Yellow short lead - cathode to 220ohm resistor, then second resistor lead to GND

  Arduino pin 3 to Red LED long lead - anode
  Red short lead - cathode to 220ohm resistor, then second resistor lead to GND

  Arduino pin 4 to switch, other side of switch to GND

  The physical build of the two boards are identical
  There are minor software differences for the reading and writing pipes for the respective boards.

*/

#include <SPI.h>
#include "RF24.h"

#define button 4
#define confirmLed 2
#define led 3

RF24 NRF24L01 (8, 9);//create object called NRF24L01. specifying the CE and CSN pins to be used on the Arduino

byte address[] [6] = {"pipe1", "pipe2"};//set addresses of the 2 pipes for read and write
boolean buttonState = false;//used for both transmission and receive
byte schritte[1];
void setup() {
  Serial.begin(9600);
  pinMode(button, INPUT_PULLUP);
  pinMode(confirmLed, OUTPUT);//yellow LED
  pinMode(led, OUTPUT);//red LED

  NRF24L01.begin();
  //open the pipes to read and write from board 1
  NRF24L01.openWritingPipe(address[0]);//open writing pipe to address pipe 1
  NRF24L01.openReadingPipe(1, address[1]);//open reading pipe from address pipe 2

  NRF24L01.setPALevel(RF24_PA_MAX);//set RF power output to minimum, RF24_PA_MIN (change to RF24_PA_MAX if required)
  NRF24L01.setDataRate(RF24_250KBPS);//set data rate to 250kbps
  NRF24L01.setChannel(110);//set frequency to channel 110
}

void loop() {
  schritte[0] = 105;
  //Transmit button change to the other Arduino
  delay(10);
  NRF24L01.stopListening();
  buttonState = digitalRead(button);//test for button press on this board
  if (buttonState == LOW)//button is pulled up so test for LOW
  {
    Serial.println("1");
   
    NRF24L01.write(&schritte, sizeof(schritte));//send LOW state to other Arduino board
    //flash the yellow LED to show progress
    digitalWrite(confirmLed, HIGH);
    Serial.println(schritte[0]);
    delay(100);
    digitalWrite(confirmLed, LOW);
  }

  buttonState = HIGH;//reset the button state variable

  //Receive button change from the other Arduino
  delay(10);
  NRF24L01.startListening();
  if (NRF24L01.available())//do we have transmission from other Arduino board
  {
    Serial.println("2");
   
    NRF24L01.read(&buttonState, sizeof(buttonState));//update the variable with new state
    NRF24L01.stopListening();
    Serial.println(buttonState);
  }
  if (buttonState == HIGH)//test the other Arduino's button state
  {
    digitalWrite(led, LOW);
  }
  else
  {
    flashLed();//indicate that the button was pressed on the other board
  }
  buttonState = HIGH;//reset the button state variable
}

//flash the red LED five times
void flashLed()
{
  for (int i = 0; i < 1; i++)
  {
    digitalWrite(led, HIGH);
    delay(200);
    digitalWrite(led, LOW);
    delay(200);
  }

}




Empfänger (Bühne)

Code: [Select]

#include <SPI.h>
#include "RF24.h"

int data[1];
boolean var = true;
//const byte addresses[][6] = {"00001", "00002"};
//const uint64_t pipe = 0xF0F0F0F0A1LL;
RF24 radio (8, 9);
byte address[] [6] = {"pipe1", "pipe2"}; // Adressen der beiden Pipes
byte rever_start = false;
const byte hal = 3;
byte schritte[1];                                 // Schritte die deer Motor (Hallsensor betätigt) zurücklegen muss
int sensor = LOW;
unsigned long startZeit;                          // Abfrage begin Sensor an Bühne
unsigned long interval = 2000;                    // Zeitabstand nachdem ein Zustand des Sensors erkannt wird
unsigned long vergangeneZeit = 0;                 // Speichervariable um die Vergangene Zeit zu speichern
/*int pin_motor_links = A1;                         // Richtungspin an H-Brücke für Links
  int pin_motor_rechts = A2;                        // Richtungspin an H-Brücke für Rechts
*/
// Statusvariablen
bool nullStellung = false;                      // Speichervariable ob Referenzfahrt erfolgt ist
bool ergebnis = false;                          // Berechnung der Schritte und Richtung beendet/gestartet
bool start = false;                           // Schritte Zaehlen beendet/gestartet

void setup() {
  radio.begin();
  //radio.openReadingPipe(1, pipe);
  radio.openWritingPipe(address[1]); // 00002
  radio.openReadingPipe(1, address[0]); // 00001
  radio.setPALevel(RF24_PA_MAX);
  radio.setDataRate (RF24_250KBPS);
  radio.setChannel(110);

  radio.startListening();
  pinMode(hal, INPUT);
  Serial.begin(9600);
  //delay (2000);
}

void loop() {

  referenzFahrt();
  encoder_lesen();
  schritteZaehlen();
}

void referenzFahrt() {
  if (radio.available())
  {
    Serial.println("Data there");
    radio.read(data, 1);
    Serial.println(data[0]);
  }

  // Reverenzfahrt

  if ((data[0] == 255) && (rever_start == false) && (nullStellung == false)) {
    rever_start = true;
    Serial.println("Reverenzfahrt gestartet");
    //    digitalWrite (pin_motor_rechts, HIGH);
    //  digitalWrite (pin_motor_links, LOW);
  }
  else if ((data[0] == 254) && (rever_start == true)) {
    nullStellung = true;
    rever_start = false;
    Serial.println("Reverenzfahrt beendet");
    Serial.println (" ");
    //      digitalWrite (pin_motor_rechts, LOW);
    //        digitalWrite (pin_motor_links, LOW);
  }
}

void encoder_lesen () {
  if ((data[0] <= 48) && (data[0] > 0) && (nullStellung == true) && (ergebnis == false)) {
    //rechtsrum data[0] Schritte
    schritte[0] = data[0];
    ergebnis = true;
    // Motor
    Serial.println (schritte[0]);
    Serial.print ("  Schritte nach Rechts");
    Serial.println (" ");
  }
  else if ((data[0] >= 100) && (data[0] <= 149) && (nullStellung == true) && (ergebnis == false)) {
    //linksrum data[0] - 100 Schritte
    schritte[0] = data[0] - 100;
    ergebnis = true;
    // Motor
    Serial.println (schritte[0]);
    Serial.print ("  Schritte nach links");
    Serial.println (" ");
  }
}

void schritteZaehlen () {

  sensor = digitalRead (hal);
  startZeit = millis();
  if ((schritte[0] != 0) && (ergebnis == true)) {
    start = true;
    if ((startZeit - vergangeneZeit >= interval) && (sensor == LOW) && (start == true)) {
      vergangeneZeit = startZeit;
      schritte[0]--;
      Serial.println("Drehung start");
      Serial.println("Restl. Pos.");
      Serial.println(schritte[0]);
      radio.stopListening();
      radio.write (&schritte, sizeof (schritte));
      radio.startListening();
    }
  }
  else if ((schritte[0] == 0) && (start == true)) {
    start = false;
    ergebnis = false;
    data[0] = 0;
    Serial.println("Ziel");
    Serial.println("Drehung");
    Serial.println("beendet");
    Serial.print("daten");
    Serial.println(schritte[0]);
    radio.stopListening();
    radio.write (&schritte, sizeof (schritte));
    radio.startListening();
    delay(2000);
    Serial.println(ergebnis);
  }
}
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 11, 2019, 11:53 pm
Mit dem verwendeten Modul kann es mit nur einem Kondensator funktionieren,
eine eigene vernünftige Stromversorgung ist betriebssicherer.

Dass dein delay-Gestolper im Sender keine Antworten empfängt wundert mich nicht.
Das Fenster in dem ein Empfang möglich ist, ist viel zu klein.
Delay gehört IMHO nicht in ein Programm das asynchrone Kommunikation versucht.

Code: [Select]
 for (int i = 0; i < 1; i++)

Wozu dient diese optische Kodebereicherung?
Der Kompiler entfernt sie völlig (zum Glück).
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 12, 2019, 06:55 pm
Hallo,

Stimmt das mit dem Delay mag ich auch nicht. Der Beispielcode war halt so.

Eigentlich soll es so ablaufen:

- benötigte Schritte werden zur Scheibe gesendet
- Scheibe sendet immer wenn ein Schritt runter gezählt wurde, die verbleibenden Schritte zurück
- Wenn Scheibe die benötigten Schritte zurückgelegt hat, soll die Aktuelle Position an den Sender gesendet
   werden
- Zwischenzeitlich (während die Schritte abgearbeitet werden) soll über den Sender ein Nothalt der Bühne
  ausgelöst werden können.

Das sind so die Vorstellungen.

Gruß Acki
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 12, 2019, 07:32 pm
Stimmt das mit dem Delay mag ich auch nicht. Der Beispielcode war halt so.
Und dein Editor ist so beschädigt dass du keinen Kode ändern kannst?

Du hast mein Mitleid.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 12, 2019, 08:27 pm
Klar kann ich den Code ändern. Mich hat nur gewundert das der Beispielcode (aus dem Link) ohne Probleme funktioniert hat. Meinst du das Delay im Sendecode?
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 12, 2019, 08:38 pm
Ich meine alle delay() Aufrufe, oder versuchen deine Sketches nicht miteinander zu kommunizieren?

In der Regel reicht es nicht delay Aufrufe einfach zu löschen oder auszukommentieren.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 12, 2019, 08:46 pm
Ich müsste sie durch eine Millis Abfrage ersetzen. Oder?
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 12, 2019, 09:04 pm
Na ja, du solltest deinen Kode so blockierungsfrei wie möglich machen.
For und while solltest nicht für Abläufe nutzen
und möglichst keine (länger) blockierenden Funktionen aufrufen.

radio.write() blockiert auch, ist aber (spätestens) nach ca. 18 ms fertig.
Manchmal lässt sich ein kurzes Anhalten nur mit Kopfständen vermeiden,
beim NRF lohnt sich das IMHO nicht.

Deine Knoten sollten grundsätzlich lauschen und auf eingehende Pakete reagieren,
wenn sie was zu senden haben, schalten sie kurz den Empfänger ab,
senden und schalten ihn danach sofort wieder ein.

Deinen Stepper wirst du ja vielleicht auch zeitgesteuert bewegen wollen,
der Teil darf natürlich genauso wenig blockieren, sonst geht das mit der Anhalte-Anfrage in die Hose.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 12, 2019, 09:11 pm
Der Motor ist nur ein ganz normaler DC Motor, welcher über einen Treiber angesteuert wird. Die Positionen (Schritte) werden über einen Sensor eingelesen. Die genaue Positionierung, sowie das Ausschalten erledigt der Orginale Raststift. So hatte ich es zumindest vor.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 12, 2019, 09:20 pm
Aber die Bühne hört ja auch permanent. Das hören wird doch nur unterbrochen, wenn die restlichen Schritte gesendet werden. Oder lieg ich da falsch?
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: postmaster-ino on Feb 12, 2019, 09:32 pm
Hi

Ein oder zwei Kleinigkeiten wird 'die Bühne' wohl drum herum noch machen müssen - gucken, ob der Endschalter betätigt wurde, um 1 runter zu zählen, den Motor anhalten, wenn wir auf Null sind und so Kram.
Du kannst, wie sonst auch immer, entweder bei jedem (möglichst schnellem) loop()-Durchlauf nachschauen, ob's was Neues gibt, oder, wenn der Funk-Empfänger Das bietet, einen Interrupt aktivieren, in Dem Du auf den eingehenden Datenstrom reagierst.
Normal wird dort aber auch nur 'gemerkt', daß was Neues gesendet wird - das Auslesen muß dann so schnell wie möglich in der loop() erledigt werden - und dann das darauf reagieren.

Wie bereits geschrieben: MALE Dir auf, was wann wie passieren soll.
Dort wirst Du schnell sehen, daß Du eine ganze Menge Kram zu erledigen hast und Du so auch eine ganze Zeit NICHT schaust, ob's was Neues gibt.
Damit Du trotzdem Nichts verpasst, muß loop() rasend schnell sein, um in jedem Durchlauf die 1/2 angefallenen Zeichen abzugrasen.

MfG
MfG
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 12, 2019, 09:33 pm
Der Kommunikationsablauf in der Bühne sollte so in Ordnung sein, du hast aber noch keinen Anhaltebefehl.

Der Ablauf im Sender ist dein Problem.
Wenn du den Sender änderst, bitte entferne alle Kommentare die Offensichtlichkeiten kommentieren.

Ich durchschaue deine verschachtelten Funktionen nicht,
die Positionserkennung kommt mir komisch an die Zeit gebunden vor,
teilweise gibt es komplizierte Bedingungen,
der halbe Kode ist auskommentiert.
Warum nutzt du einelementige Arrays?

Wie wäre es mit aktualisierten Versionen in einem neuen Post?
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 12, 2019, 10:06 pm
Hier ist der Aktuelle Code vom Sender:

Code: [Select]

#include <SPI.h>
#include "RF24.h"

#define button 4
#define confirmLed 2
#define led 3

RF24 NRF24L01 (8, 9);//create object called NRF24L01. specifying the CE and CSN pins to be used on the Arduino

byte address[] [6] = {"pipe1", "pipe2"};//set addresses of the 2 pipes for read and write
boolean buttonState = false;//used for both transmission and receive
byte schritte[1];
void setup() {
  Serial.begin(9600);
  pinMode(button, INPUT_PULLUP);
  pinMode(confirmLed, OUTPUT);//yellow LED
  pinMode(led, OUTPUT);//red LED

  NRF24L01.begin();
  //open the pipes to read and write from board 1
  NRF24L01.openWritingPipe(address[0]);//open writing pipe to address pipe 1
  NRF24L01.openReadingPipe(1, address[1]);//open reading pipe from address pipe 2

  NRF24L01.setPALevel(RF24_PA_MAX);//set RF power output to minimum, RF24_PA_MIN (change to RF24_PA_MAX if required)
  NRF24L01.setDataRate(RF24_250KBPS);//set data rate to 250kbps
  NRF24L01.setChannel(110);//set frequency to channel 110
}

void loop() {
  schritte[0] = 120;

  buttonState = digitalRead(button);
  if (buttonState == LOW)
  {
    NRF24L01.stopListening();
    Serial.println("1");
    NRF24L01.write(&schritte, sizeof(schritte));
    Serial.println(schritte[0]);

    NRF24L01.startListening();
  }

  buttonState = HIGH;//reset the button state variable


  if (NRF24L01.available())
  {
    Serial.println("2");
    NRF24L01.read(&buttonState, sizeof(buttonState));
    Serial.println(buttonState);
  }
}


Und die Bühne:

Code: [Select]

#include <SPI.h>
#include "RF24.h"

unsigned long warteZeit;
int data[1];
boolean var = true;
//const byte addresses[][6] = {"00001", "00002"};
//const uint64_t pipe = 0xF0F0F0F0A1LL;
RF24 radio (8, 9);
byte address[] [6] = {"pipe1", "pipe2"}; // Adressen der beiden Pipes
byte rever_start = false;
const byte hal = 3;
byte schritte[1];                                 // Schritte die deer Motor (Hallsensor betätigt) zurücklegen muss
int sensor = LOW;
unsigned long startZeit;                          // Abfrage begin Sensor an Bühne
unsigned long interval = 2000;                    // Zeitabstand nachdem ein Zustand des Sensors erkannt wird
unsigned long vergangeneZeit = 0;                 // Speichervariable um die Vergangene Zeit zu speichern
/*int pin_motor_links = A1;                         // Richtungspin an H-Brücke für Links
int pin_motor_rechts = A2;                        // Richtungspin an H-Brücke für Rechts
*/
// Statusvariablen
bool nullStellung = false;                      // Speichervariable ob Referenzfahrt erfolgt ist
bool ergebnis = false;                          // Berechnung der Schritte und Richtung beendet/gestartet
bool start = false;                           // Schritte Zaehlen beendet/gestartet

void setup() {
  radio.begin();
  //radio.openReadingPipe(1, pipe);
  radio.openWritingPipe(address[1]); // 00001
  radio.openReadingPipe(1, address[0]); // 00002
  radio.setPALevel(RF24_PA_MAX);
  radio.setDataRate (RF24_250KBPS);
  radio.setChannel(110);
 
  radio.startListening();
  pinMode(hal, INPUT);
  Serial.begin(9600);
  //delay (2000);
  }

void loop() {
 
  referenzFahrt();
  encoder_lesen();
  schritteZaehlen();
  }

void referenzFahrt() {
  if (radio.available())
{
Serial.println("Data there");
radio.read(data, 1);
Serial.println(data[0]);
}

      // Reverenzfahrt

      if ((data[0] == 255) && (rever_start == false) && (nullStellung == false)) {
        rever_start = true;
        Serial.println("Reverenzfahrt gestartet");
    //    digitalWrite (pin_motor_rechts, HIGH);
      //  digitalWrite (pin_motor_links, LOW);
      }
      else if ((data[0] == 254) && (rever_start == true)) {
        nullStellung = true;
        rever_start = false;
        Serial.println("Reverenzfahrt beendet");
        Serial.println (" "); 
  //      digitalWrite (pin_motor_rechts, LOW);
//        digitalWrite (pin_motor_links, LOW);
      }
    }
 
  void encoder_lesen () {
   if ((data[0] <= 48) && (data[0] > 0) && (nullStellung == true) && (ergebnis == false)) {
    //rechtsrum data[0] Schritte
    schritte[0] = data[0];
    ergebnis = true;
    // Motor
    Serial.println (schritte[0]);
    Serial.print ("  Schritte nach Rechts");
    Serial.println (" ");   
   }
  else if ((data[0] >=100) && (data[0] <= 149) && (nullStellung == true) && (ergebnis == false)) {
    //linksrum data[0] - 100 Schritte
    schritte[0] = data[0] - 100;
    ergebnis = true;
    // Motor
    Serial.println (schritte[0]);
    Serial.print ("  Schritte nach links");
    Serial.println (" ");
   }
  }
 
void schritteZaehlen () {

  sensor = digitalRead (hal);
  startZeit = millis();
  if ((schritte[0] != 0) && (ergebnis == true)) {
    start = true;
    if ((startZeit - vergangeneZeit >= interval) && (sensor == LOW) && (start == true)) {
      vergangeneZeit = startZeit;
      schritte[0]--;
      Serial.println("Drehung start");
      Serial.println("Restl. Pos.");
      Serial.println(schritte[0]);
      radio.stopListening();
      radio.write (&schritte, sizeof (schritte));
      radio.startListening();
      }
  }
  else if ((schritte[0] == 0) && (start == true)) {
    start = false;
    ergebnis = false;
    data[0] = 0;
    Serial.println("Ziel");
    Serial.println("Drehung");
    Serial.println("beendet");
    Serial.print("daten");
    Serial.println(schritte[0]);
    radio.stopListening();
    radio.write (&schritte, sizeof (schritte));
    radio.startListening();
    //schritte[0]=0;
   
    Serial.println(ergebnis);
    }
}


- Stimmt der Stopbefehl ist noch nicht drin. Diesen würde ich wieder in eine Funktion packen, die dann augeführt wird, wenn eine 0 vom Sender kommt.

- Die Positionserkennung (Zeit) ist dazu da um ein Erneutes auslesen den Sensors zu vermeiden.

- Was meinst du mit den Verschachtelten Funktionen? Der Ablauf ist im Moment folgender:
   - die Bühne empfängt vom Sender eine 255 (die Reverenzfahrt wird gestartet) Bühne beginnt zu
     drehen
   - dann sendet der Sender eine 254 (wenn der Referenzpunkrt erreicht ist) Bühne stoppt
   - wenn jetzt vom Sender eine Zahl (Schritte) <48 kommt, dreht die Bühne rechtsrum
   - wenn eine Zahl > 100 kommt wird Zahl - 100 = Schritte linksrum
   - Jetzt wird bei jeder Sensor Betätigung die Variable schritte um 1 verringert bis sie 0 ist
   - dann hält die Bühne an und wartet auf neue Befehle
 
   - Während der Ganzen Zeit wo die Bühne dreht, lauscht sie ob eine 0 vom Sender kommt.
     Kommt diese soll die Bühne anhalten (Das ist Zukunft).

Ich hoffe ich konnte es etwas erklären.

Vielen Dank das ihr mir helft.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 12, 2019, 10:32 pm
Dem Sender fehlt ein startListening in setup.

Der Receiver wird nicht so kurz wie möglich abgeschaltet.

Du sendest solange der Knopf gedrückt ist, nicht wenn er gedrückt wird.

Code: [Select]
 buttonState = HIGH;//reset the button state variable

Reines Wunschdenken.

Dein Ablauf ist IMHO unausgegoren und viel zu verschränkt.

Quote
- Die Positionserkennung (Zeit) ist dazu da um ein Erneutes auslesen den Sensors zu vermeiden.
Warum in Gottes Names würde man einen Sensor nicht lesen wollen?
Könnte aber das gleiche Problem wie mit deiner Taste sein, du hast keine State-Change-Detection.

Und weiterhin: Warum nutzt du einelementige Arrays?
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 12, 2019, 10:50 pm
Was meinst du damit? Ich stoppe doch das Hören und starte es gleich nach dem Schreiben wieder?
Quote
Der Receiver wird nicht so kurz wie möglich abgeschaltet.
Die Array`s stammen auch aus dem Beispielcode. Ich dachte es funktioniert nur mit Array`s


Bei dem Sensor müsste ich vielleicht mit Flanke arbeiten?

Ich merke schon das ich den Beispielcode genommen und etwas umgeändert habe, war großer Mist.

Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 12, 2019, 10:53 pm
Was meinst du damit? Ich stoppe doch das Hören und starte es gleich nach dem Schreiben wieder?
Code: [Select]
  if (buttonState == LOW)
  {
    NRF24L01.stopListening();
    Serial.println("1");
    NRF24L01.write(&schritte, sizeof(schritte));
    Serial.println(schritte[0]);

    NRF24L01.startListening();
  }

Lüge.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 12, 2019, 10:59 pm
Code: [Select]
  if (buttonState == LOW)
  {
    NRF24L01.stopListening();
    Serial.println("1");
    NRF24L01.write(&schritte, sizeof(schritte));
    Serial.println(schritte[0]);

    NRF24L01.startListening();
  }

Lüge.

Meinst du weil da da noch die Serial.print("1") und die Serial.println (schritte[0]) dazwischen sind?
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 12, 2019, 11:03 pm
Was ist an 'so kurz wie möglich' so schwer zu verstehen?

Schieb die Druckerei hinter das startListening.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 12, 2019, 11:04 pm
Nur mal zum Verständnis. Frisst das Serielle Drucken so viel Zeit?

Hab es geändert:

Code: [Select]

 if (buttonState == LOW)//button is pulled up so test for LOW
  {
    NRF24L01.stopListening();
    NRF24L01.write(&schritte, sizeof(schritte));//send LOW state to other Arduino board
    NRF24L01.startListening();
    Serial.println("1");
    Serial.println(schritte[0]);
  }
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 12, 2019, 11:07 pm
Normalerweise nicht, bei vollem Puffer und deiner Baudrate aber 1 ms pro Zeichen, also 8 ms.

Das ist ungefähr 128000 Instruktionen lang.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 12, 2019, 11:12 pm
Ah ok. Der Code vom Sender sieht jetzt so aus:

Code: [Select]

#include <SPI.h>
#include "RF24.h"

#define button 4
#define confirmLed 2
#define led 3

RF24 NRF24L01 (8, 9);//create object called NRF24L01. specifying the CE and CSN pins to be used on the Arduino

byte address[] [6] = {"pipe1", "pipe2"};//set addresses of the 2 pipes for read and write
boolean buttonState = false;//used for both transmission and receive
byte schritte[1];
void setup() {
  Serial.begin(9600);
  pinMode(button, INPUT_PULLUP);
  pinMode(confirmLed, OUTPUT);//yellow LED
  pinMode(led, OUTPUT);//red LED

  NRF24L01.begin();
  //open the pipes to read and write from board 1
  NRF24L01.openWritingPipe(address[0]);//open writing pipe to address pipe 1
  NRF24L01.openReadingPipe(1, address[1]);//open reading pipe from address pipe 2

  NRF24L01.setPALevel(RF24_PA_MAX);//set RF power output to minimum, RF24_PA_MIN (change to RF24_PA_MAX if required)
  NRF24L01.setDataRate(RF24_250KBPS);//set data rate to 250kbps
  NRF24L01.setChannel(110);//set frequency to channel 110
  NRF24L01.startListening();
}

void loop() {
  schritte[0] = 120;

  buttonState = digitalRead(button);//test for button press on this board
  if (buttonState == LOW)//button is pulled up so test for LOW
  {
    NRF24L01.stopListening();
    NRF24L01.write(&schritte, sizeof(schritte));//send LOW state to other Arduino board
    NRF24L01.startListening();
    Serial.println("1");
    Serial.println(schritte[0]);
  }
 
  buttonState = HIGH;//reset the button state variable


  if (NRF24L01.available())//do we have transmission from other Arduino board
  {
    Serial.println("2");
    NRF24L01.read(&buttonState, sizeof(buttonState));//update the variable with new state
    Serial.println(buttonState);
  }
}
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 12, 2019, 11:18 pm
Code: [Select]
 {
    Serial.println("2");
    NRF24L01.read(&buttonState, sizeof(buttonState));//update the variable with new state
    Serial.println(buttonState);
  }

Erst von der Hardware lesen, dann Ausgeben.
Du willst den Puffer so schnell wie möglich leeren, er ist nur 3 Elemente tief.

Was ist das für ein komischer Kommentar?

Ich dachte die Bühne gäbe irgendwelche Schritte zurück, keinen Tastenzustand.
Zusätzlich schreibst du einen int, liest aber nur ein byte.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 12, 2019, 11:28 pm
Code: [Select]
RF24 NRF24L01 (8, 9);//create object called NRF24L01. specifying the CE and CSN pins to be used on the Arduino

Hätten die Pins vernünftige const byte Definitionen wäre der Kommentar überflüssig.

Code: [Select]
byte address[] [6] = {"pipe1", "pipe2"};//set addresses of the 2 pipes for read and write

Offensichtlich.

Code: [Select]
boolean buttonState = false;//used for both transmission and receive

Falscher Kommentar.

Code: [Select]
  pinMode(confirmLed, OUTPUT);//yellow LED
  pinMode(led, OUTPUT);//red LED

Hätten die Pins vernünftige const byte Definitionen wäre der Kommentar überflüssig.

Code: [Select]
  //open the pipes to read and write from board 1
  NRF24L01.openWritingPipe(address[0]);//open writing pipe to address pipe 1
  NRF24L01.openReadingPipe(1, address[1]);//open reading pipe from address pipe 2

  NRF24L01.setPALevel(RF24_PA_MAX);//set RF power output to minimum, RF24_PA_MIN (change to RF24_PA_MAX if required)
  NRF24L01.setDataRate(RF24_250KBPS);//set data rate to 250kbps
  NRF24L01.setChannel(110);//set frequency to channel 110

Alles offensichtlich.

Code: [Select]
  if (NRF24L01.available())//do we have transmission from other Arduino board

Offensichtlichkeit und unter Umständen auch noch falsch (falls mein Raspi sendet z.B.)
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 12, 2019, 11:33 pm
Stimmt werde ich gleich alles ändern. Danke dir übrigens für deine Geduld.

Jetzt weis ich wieder warum ich mit Array`s gearbeitet habe. Wenn ich mit Int arbeite bekomme ich immer den Fehler beim Kompilieren : no matching function for call to 'RF24::read(int*)'

Kannst du mir sagen woran das liegt und wie ich das beheben kann?
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 12, 2019, 11:47 pm
Stimmt werde ich gleich alles ändern. Danke dir übrigens für deine Geduld.

Jetzt weis ich wieder warum ich mit Array`s gearbeitet habe. Wenn ich mit Int arbeite bekomme ich immer den Fehler beim Kompilieren : no matching function for call to 'RF24::read(int*)'

Kannst du mir sagen woran das liegt und wie ich das beheben kann?
Hab es rausgefunden.

Der Code sieht jetzt so aus:

Code: [Select]

#include <SPI.h>
#include "RF24.h"

#define button 4
#define confirmLed 2
#define led 3

RF24 NRF24L01 (8, 9);

byte address[] [6] = {"pipe1", "pipe2"};
boolean buttonState = false;                  // Status Taster
int schritte;
int rest_schritte = 0;
void setup() {
  Serial.begin(9600);
  pinMode(button, INPUT_PULLUP);
  NRF24L01.begin();
  NRF24L01.openWritingPipe(address[0]);
  NRF24L01.openReadingPipe(1, address[1]);
  NRF24L01.setPALevel(RF24_PA_MAX);
  NRF24L01.setDataRate(RF24_250KBPS);
  NRF24L01.setChannel(110);
  NRF24L01.startListening();
}

void loop() {
  schritte = 120;

  buttonState = digitalRead(button);
  if (buttonState == LOW)
  {
    NRF24L01.stopListening();
    NRF24L01.write(&schritte, sizeof(int));// Sende zu fahrende Schritte zur Bühne
    NRF24L01.startListening();
    Serial.println("1");
    Serial.println(schritte);
  }

  buttonState = HIGH;//reset the button state variable


  if (NRF24L01.available())// wenn Daten von Bühne empfangen werden
  {
    NRF24L01.read(&rest_schritte, sizeof (int));//restliche Schritte die von Bühne gesendet wurden
    Serial.println("2");
    Serial.println(rest_schritte);
  }
}

Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 13, 2019, 12:04 am
Ich bau dir mal die eine Taste ein.  ;) Die Library gibts in der IDE.

Code: [Select]
#include <RF24.h>
#include <Bounce2.h>

const byte buttonPin = 4;
const byte nrfCE = 8;
const byte nrfCSN = 9;
const byte address[] = "pipe1" "pipe2";

RF24 nrf(nrfCE, nrfCSN);
Bounce button;

int schritte;
int restSchritte;

void setup() {
  Serial.begin(250000);
  button.attach(buttonPin, INPUT_PULLUP);
  nrf.begin();
  nrf.openWritingPipe(address);
  nrf.openReadingPipe(1, address + 5);
  nrf.setPALevel(RF24_PA_MAX);
  nrf.setDataRate(RF24_250KBPS);
  nrf.setChannel(110);
  nrf.startListening();
}

void loop() {
  schritte = 120;
  if (button.update()) {
    if (button.fell()) {
      nrf.stopListening();
      nrf.write(&schritte, sizeof(schritte));
      nrf.startListening();
      Serial.print(F("> mach "));
      Serial.print(schritte);
      Serial.println(F(" Schritte"));
    }
  }
  if (nrf.available()) {
    nrf.read(&restSchritte, sizeof(restSchritte));
    Serial.print(F("< noch "));
    Serial.print(restSchritte);
    Serial.println(F(" Schritte"));
  }
}

Der einzelne int ist noch unglücklich, oder was soll der Wert für STOP sein?

Vielleicht in der Art?

Code: [Select]
#include <RF24.h>
#include <Bounce2.h>

const byte buttonPin = 4;
const byte stopPin = 5;
const byte nrfCE = 8;
const byte nrfCSN = 9;
const byte address[] = "pipe1" "pipe2";

enum Typen {
  machSchritte,
  stop,
};

struct Packet {
  byte type;
  int daten;
  Packet() : type(stop), daten(0) {}
  Packet* befehl(byte welchen, int info = 0) {
    type = welchen;
    daten = info;
    return this;
  }
} data;

RF24 nrf(nrfCE, nrfCSN);
Bounce button, stopButton;

int schritte = 120;
int restSchritte;

void setup() {
  Serial.begin(250000);
  button.attach(buttonPin, INPUT_PULLUP);
  stopButton.attach(stopPin, INPUT_PULLUP);
  nrf.begin();
  nrf.openWritingPipe(address);
  nrf.openReadingPipe(1, address + 5);
  nrf.setPALevel(RF24_PA_MAX);
  nrf.setDataRate(RF24_250KBPS);
  nrf.setChannel(110);
  nrf.startListening();
}

void loop() {
  if (button.update()) {
    if (button.fell()) {
      nrf.stopListening();
      nrf.write(data.befehl(machSchritte, schritte), sizeof(data));
      nrf.startListening();
      Serial.print(F("> mach "));
      Serial.print(schritte);
      Serial.println(F(" Schritte"));
    }
  }
  if (stopButton.update()) {
    if (stopButton.fell()) {
      nrf.stopListening();
      nrf.write(data.befehl(stop), sizeof(data));
      nrf.startListening();
      Serial.println(F("> STOP"));
    }
  }
  if (nrf.available()) {
    nrf.read(&restSchritte, sizeof(restSchritte));
    Serial.print(F("< noch "));
    Serial.print(restSchritte);
    Serial.println(F(" Schritte"));
  }
}
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 13, 2019, 09:06 pm
Guten Abend,

so jetzt sitze ich wieder am Projekt. Die Bounce libery kenn ich noch nicht. Die ansteuerung der Drehscheibe wird Später mittels eines Drehencoder`s zum einstellen des jeweiligen Abganges (die benötigten Schritte und die Richtung wird in der Bühne errechnet).

Ich stelle mir das so vor, dass über den Encoder und ein LCD-Display das Zielgleis eingestellt wird. Beim drücken des Encoders soll die Zielposition an die Bühne gesendet werden, in welcher dann die Richtung und die benötigten Schritte berechnet und ausgeführt werden. Bei erneutem drücken des Encoders während die Bühne läuft, soll die Bühne sofort anhalten (das könnte man bestimmt mit der Bounce.h machen). Während der drehung sollen die restlichen Schritte af dem LCD der Bedienung angezeigt werden. Wenn das Ziel erreicht ist soll die Aktuelle Position auf das Display übertragen werden. Die aktuelle Position ist dann Ausgangspunkt für die nächste Drehung. Den Sendecode habe ich hauptsächlich hergenommen um zu verstehen wie die Funkübertragung arbeitet. Ich hatte ja am Anfang den Code so geschrieben das, dass Ganze über einen Ardino läuft (bis auf die Ansteuerung Motor und die Stopfunktion). Ich muss aber auf Grund von Mangel an Schleifringen, zwischen Grube und Bühne, die Befehle per Funk übertragen.

Ich hoffe es ist einigermaßen verständlich.

Gruß Acki
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: agmue on Feb 13, 2019, 09:14 pm
Die Bounce libery kenn ich noch nicht.
Die dient zum Entprellen mechanischer Kontakte.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 13, 2019, 09:28 pm
Danke dir agmue.


Übrigens:

Bei der Zahl für Stop dachte ich an 0. Oder ist das ungünstig?

Gruß Acki
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 13, 2019, 09:38 pm
Hallo Whandall,

Was bedeudet diese Zeile:

nrf.openReadingPipe(1, address + 5);

Gruß Daniel
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 13, 2019, 09:58 pm
Nimm die zweiten 5 Bytes aus dem Addressarray als Addresse für die Pipe 1.

Die Pipeaddressen sind keine Strings, es ist nur bequem die als solche anzugeben.

Code: [Select]
const byte address[] = "pipe1" "pipe2";

Ich stehe nicht so auf die mehrdimensionale Notation für diese Konstanten, die nur sehr selten benutzt werden.

Ansonsten ist das Zeiger-Arithmetik. address zeigt auf den ersten Character, address + 5 auf den sechsten.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 13, 2019, 10:06 pm
Ich werde mal den tatsächlichen Sendercode versuchen zu schreiben. Alles andere hat glaube ich wenig Sinn. Sonst fangen wir ja nochmal von vorne an.

Gruß Acki
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 13, 2019, 10:09 pm
Ein Beispiel für einen nicht blockierenden Sender hast du ja,
da brauchst du 'nur noch' die nicht-blockierende  Encoder und Anzeige Funktionalität einbauen,
Oder den Sendekode in das Programm, wie auch immer.

Keine Delays, kein for/while zur Ablaufsteuerung.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 13, 2019, 10:13 pm
Whandall verstehe die Zeilen nur nicht wirklich.


enum Typen {
  machSchritte,
  stop,
};

struct Packet {
  byte type;
  int daten;
  Packet() : type(stop), daten(0) {}
  Packet* befehl(byte welchen, int info = 0) {
    type = welchen;
    daten = info;
    return this;
  }
} data;
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 13, 2019, 10:19 pm
Das Beispiel benutzt ein Paket aus Befehl und Wert.

Es gibt bisher zwei Befehle, machSchritte (könnte auch fahre Position an sein) und stop.

Das Paket hat einen Konstruktor der type und daten sinnvolle Startwerte verpasst,
sowie eine Funktion befehl die einen typ/Befehl und (optional) einen Wert in das Paket einträgt
und die Adresse des Pakets zurückgibt.

Ein Objekt Paket mit dem Namen data wird definiert.

Ich glaube du bist flexibler wenn du nicht nur einen einzelnen int überträgst.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 13, 2019, 10:27 pm
Der Rückkanal benutzt in dem Beispiel das alte Format,
eine Erweiterung der Typen um z.B. restSchritte könnte auch das abdecken.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 13, 2019, 10:28 pm
Whandall was meinst du mit flexiebler, kann nicht wirklich folgen. Die Bühne reagiert ja auf Zahlen die an sie gesendet werden. Na gut man könnte vielleicht die Anzahl der Schritte und die Richtung mit einmal übertragen. Dadurch würde man sich die zusäzliche Berechung in der Bühne sparen. Meinst du das so in der Art?
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 13, 2019, 10:38 pm
Du musst keine Werte mit magischen Nebenwirkungen versehen.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 13, 2019, 10:40 pm
Was meins du mit "magischen Nebenwirkungen"?
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 13, 2019, 10:43 pm
Bei der Zahl für Stop dachte ich an 0. Oder ist das ungünstig?
Ja magische Nebenwirkungen sind ungünstig.

Was nimmst du für 'weiter geht's' nach einem Stop?
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 13, 2019, 10:51 pm
Was nimmst du für 'weiter geht's' nach einem Stop?
Da wollte ich einfach die nächste Anzahl an Schritten senden. Also 1 bis 48 für rechtsrum und 101 bis 148 für links rum.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 13, 2019, 10:52 pm
Wen du keinen Rat haben willst, dann halt nicht.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 13, 2019, 10:58 pm
Doch ich bin Froh wenn ich Tip`s bekomme. Das Problem ist nur das ich nicht so recht verstehe was sie bedeuten. Verstehe diese Zusammengefassten Sachen leider nicht. :-(

Ich danke dir Whandall das du mir hilfst.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 13, 2019, 11:01 pm
Jetzt weis ich was du mit weiter gehts nach einem Stop meinst.

Wenn die Bühne per Nothalt gestoppt wurde und wieder losfahren soll muss sie ja einen Befehl erhalten. Dazu müsste sie sich aber die aktuelle Position merken und die restlichen Schritte nachdem sie wieder angefahren ist, weiter runter zählen. Oder?
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 13, 2019, 11:12 pm
Doch ich bin Froh wenn ich Tip`s bekomme. Das Problem ist nur das ich nicht so recht verstehe was sie bedeuten. Verstehe diese Zusammengefassten Sachen leider nicht. :-(
Ich verstehe nicht was du mit "zusammengefasste Sachen" meinst.

struct kannst du nachschlagen, die Funktionen sind nur bequem,
könnten genauso normale Funktionen mit einem Zeiger auf die struct sein.
(Was sie ja auch sind, der erste Parameter wird nur versteckt und mit this angesprochen,
zusätzlich wird der Zugriff auf die Attribute der struct ermöglicht.)

Jetzt weis ich was du mit weiter gehts nach einem Stop meinst.

Wenn die Bühne per Nothalt gestoppt wurde und wieder losfahren soll muss sie ja einen Befehl erhalten. Dazu müsste sie sich aber die aktuelle Position merken und die restlichen Schritte nachdem sie wieder angefahren ist, weiter runter zählen. Oder?
Ich würde nicht die Schritte als Kommando schicken, sondern die Zielposition und ja,
die Bühne sollte ihren gesamten Zustand alleine verwalten (wieviele Schritte wohin, aktuelle Position, ...)

Befehl mit diesem Kontext könnte z.B. sein 'gib mir die aktuelle Position' oder
'gib mir den Zustand'  (steht, gestoppt, läuft, ...)

Sowas ist leicht mit den zwei (oder mehr) Feldern zu implementieren, siehst du den Vorteil?
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 13, 2019, 11:22 pm
Das würde ja quasi bedeuten das der Sender nur den Encoder auswertet, den aktuellen wert auf dem Display anzeigt und den Encodertaster abfragt. Und natürlich die entsprechenden Befehle (neue Position, Anhalten, Weiter fahren an die Bühne Sendet? Und die aktuelle Position und die Restlichen Positionen empfängt. Sehe ich das richtig?
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 13, 2019, 11:27 pm
So ungefähr würde ich mir das vorstellen, ja.

Den aktuellen Zustand könnte der Sender abfragen, während der Bewegung könnte er von der Bühne
die Restschritte, vielleicht zusätzlich noch wann er eine Abfahrtsmöglichkeit erreicht hat, erhalten.

Insofern würde ich für beide Richtungen mehr als einen Wert verschicken,
vielleicht ist das typ/wert Paar ja auch für beide Richtungen einsetzbar.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 13, 2019, 11:33 pm
Mir erschlißt nur nicht was du mit "Insofern würde ich für beide Richtungen mehr als einen Wert verschicken," meinst. Da komm ich nicht mit. Kannst du versuchen mir das etwas ausführlicher zu erklären?
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 13, 2019, 11:37 pm
Die Antworten sollten ebenso nicht nur einen Wert übertragen,
sondern z.B. restschritte(10), position(1), Zustand(5), ... was auch immer.

Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 16, 2019, 07:28 pm
Guten abend alle zusammen,

also sollte ich nicht nur Werte sondern auch Worte übertragen? Meinst du das so?

Controller  sendet zu Bühne -->  rechts, fahren, 25 Schritte.

Bühne sendet zu Controller --> fahre, rechts, noch 24 Schritte.


Meinst du das so Whandall?
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 16, 2019, 07:30 pm
Ja, so etwas in der Art.

Wäre doch viel einfacher auszuwerten als einzelne Zahlen, und viel erweiterungsfähiger.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 16, 2019, 07:33 pm
Also würde man text und Zahlen übertragen und das alles mit einmal?

Man bräuchte so zu sagen nur einmal senden und es wären alle Informationen enthalten, egal ob sie benötigt werden oder nicht?
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 16, 2019, 07:37 pm
Wer redet von Texten?

Du könntest in beide Richtungen das gleiche Format benutzen, ein Kode und ein Wert.

Wenn du mehr als zwei Knoten betreiben willst (und auch grundsätzlich) ist ein Feld für den Absender praktisch,
um Paketverluste zu erkennen ein laufender Zähler (beide Felder könnten Bytes sein).
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 16, 2019, 07:39 pm
Aber rechts und fahren sind doch Wörter?? Irgendwie begreife ich das alles nicht :o
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 16, 2019, 07:44 pm
Code: [Select]
enum DrehscheibenZustaende {
  ok,
  fehler,
  stoerung,
  stehe,
  fahreNachRechts,
  fahreNachLinks,
};

ok
Kommando verstanden, Position im Wert, oder nichts

fehler
nee, das mach/kann/verstehe ich nicht, genauerer Grund im Wert, oder nichts

stoerung
Betrieb wegen Stoerung nicht moeglich, welche Störung im Wert, oder nichts

stehe
Drehscheibe in Ruhe,  Position im Wert, oder nichts

fahreNachRechts
auf dem Weg nach rechts (ClockWise), Restschritte im Wert

fahreNachLinks,
auf dem Weg nach links (CounterClockWise), Restschritte im Wert

Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 16, 2019, 08:38 pm
Ich begreife einfach nicht wie das funktioniert. Was steht dann in den Zuständen drin? Zahlen?
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 16, 2019, 08:44 pm
Ich begreife einfach nicht wie das funktioniert.
Was ist 'das'?

Was steht dann in den Zuständen drin? Zahlen?
In den Zuständen steht nichts drin, es sind Zahlen, schlag mal enum nach.

Das entspricht einer Latte von const int name = wert;.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 16, 2019, 08:59 pm
Verstehe ich das richtig, das für jeden Bestandteil der Aufzählung ein Wert steht?

So zu sagen:

OK = 0
fehler = 1
stoerung = 2
stehe = 3
fahreNach rechts = 4
fahreNachlinks = 5
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: postmaster-ino on Feb 16, 2019, 09:11 pm
Hi

Wenn die Reihenfolge so war, dann sogar recht genau so.
Wenn Du in enum den Namen aber einen Wert zuweist, dann können darin auch Sprünge vorkommen - ist aber im Normalfall nur für Dich (dem Programmierer), damit Du 'if DrehscheibenZustaende==ok' - Du musst hier nicht mit kryptischen Zahlen hantieren sondern kannst sprechende Texte nehmen.
Für den Kompiler werden das wieder Zahlen, für den Arduino erst recht.

MfG
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 16, 2019, 09:11 pm
Ja. Eine Zahl nimmt viel weniger Platz weg als der Text (hier reicht locker ein Byte)
und man muss nicht immer Texte vergleichen um herauszubekommen was es bedeuten soll.

Ich würde etwas in dieser Art als Nachrichten zwischen den Knoten verwenden,
kann man natürlich noch weiter ausbauen wenn man will.

Code: [Select]
struct Packet {
  byte to;
  byte from;
  byte count;
  byte type;  // Kommandos, Zustand,
  int16_t wert;
};

Mit so einem Paketaufbau könnten auch weiterere Knoten leicht die Kommunikation zwischen Steuerung(en) und Drehbühne(n) mitlesen und sinnvoll interpretieren.

Das ist sehr praktisch um solche Kommunikationen zu debuggen oder zu dokumentieren.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 16, 2019, 09:16 pm
Vom Prinzip schicke ich also eine Nachricht mit dem Inhalt:

Drehscheibenstatus = ok, fahre von Gleis 1, fahre zu Gleis 12, rechtrum, 11 Schritte

Oder?
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 16, 2019, 09:26 pm
Nein, eher die folgende Sequenz von Paketen.

Code: [Select]
B: stehe         - Gleis 2
S: fahreZu       - Gleis 4
B: OK            - 3000 Steps
B: nachRechts    - 3000 Steps
B: nachRechts    - 2000 Steps
B: GleisErreicht - Gleis 3
B: nachRechts    - 1000 Steps
B: nachRechts    - 500 Steps
B: GleisErreicht - Gleis 4
B: stehe         - Gleis 4
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 16, 2019, 09:40 pm
Ich werd da einfach nicht schlau draus. Irgendwie ist das zu kompliziert für mich. Kann damit einfach nix anfangen. Hab auch scho nach einer erklärung für enum gesucht und habe dabei gelesen das den Zuständen automatisch diese Werte zugeordnet werden (normal von 1 bis 5 zum Beispiel) und das man die Werte verändern kann (springen) indem man einen Zustand einen Wert gibt. Der nächste Zustand hat dann einen Wert höher des vorherigen Zustands. Aber was und wie soll mir das ganze bei meinem Projekt helfen?
Die Werte zum Beispiel für stehe ändern sich und sind nicht konstant. Eigentlich ist das das doch nichts anderes als eine Aneinanderreihung von einzelnen Variablen. Oder?

Komm da echt nicht wirklich klar damit. Gibt es da nicht irgendwo ein (richtig) einfaches Beispiel was auch ich verstehe?
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Tommy56 on Feb 16, 2019, 10:00 pm
Der Sinn ist, dass Du Dir in der Programmierung nicht merken musst, was 0, 1, 2, ... bedeuten, sondern dafür Worte benutzen kannst, die Du verstehst. Wie ok, fehler, störung, ...

Nicht mehr, aber auch nicht weniger.

Gruß Tommy
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 16, 2019, 10:00 pm
Du hast es einfacher wenn du einzelne Knoten selbstständig machst.
Anweisung geben und Ergebnisse betrachten/darstellen.

Nicht "Drehscheibenstatus = ok, fahre von Gleis 1, fahre zu Gleis 12, rechtrum, 11 Schritte",
das versucht für den eigentlichen Aktor zu denken,
wo doch aber eigentlich nur der wirklich weiss wo er steht und wie er am Besten zum gewünschten Gleis kommt.

Was verstehst du an dem Kommunikationsablauf in meiner Beispielsequenz nicht?

Ok, a sind Luxusmeldungen drin, aber die sind einfach zu implementieren, bieten aber viele Möglichkeiten.
Alles basierend auf einem extrem simplen Paket.

Man muss empfangene Paket nicht verarbeiten, man muss sie nur aus dem Chip holen.

Die Paket struct/class kann man mit Funktionen erweitern, die die Intialisierung fester Werte und das
Weiterzählen des count Felds erledigen und dir eine Schnittstelle der Art
Code: [Select]
paket.send(steheAn, aktuellesGleis);bietet.

Das klingt alles viel komplizierter als es wirklich ist.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 16, 2019, 10:06 pm
Wahrscheinlich ist das alles ganz einfach, aber es will nicht in meinen Kopf. B steht für Bühne und S steht für Sender richtig?

Aber da würde ich aber doch auch nur einen Wert (4) senden. Oder?
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 16, 2019, 10:13 pm
B: ist ein Paket der Drehbühne
S: ist ein Paket für die Steuerung

Im übertragenen Paket stehen nur Bytes, ja.
In deinem Sketch benutzt du die sprechenden Namen.

Code: [Select]
#include "dieEnumsDefsUndSo.h"

int16_t aktuellesGleis = 42;

  ...
  paket.send(steheAn, aktuellesGleis);
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 16, 2019, 10:25 pm
Und niemand zwingt dich aufeinanderfolgende und bei 0 startende Zahlen zu benutzen.

Bei Bytes z.B. bietet es sich an druckbare Zeichen zu verwenden,
dann kannst du den konstanten Header (alles vor dem Wert) einfach ausdrucken.

from könnte für die Drehbühne ein 'D' sein, die Sterung bekommt ein 'S',
der count könnte sich über 0-9A-Za-z bewegen,
's' stehe,
'o' OK
'!' fahreZu
'r' rechts
'l' links
...
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 16, 2019, 10:29 pm
Irgendwie finde ich die Variante so wie ich mir das gedacht habe für mich verständlicher.

Indem ich eine Zahl senden lasse und die je nach Größe auswerte:

von Sender zu Bühne
eine 0 für anhlten
von 1 bis 48 = Anzahl Schritte rechtsrum
101 bis 148 = Anzahl Schritte linksrum, z.B. 126-100 = 26 Schritte linksrum
255 = referenzfahrt starten
254 = reverenzfahrt beendet

von Bühne zu Sender
0 = Ziel erreicht
1 - 47 = restliche Schritte

So hatte ich es mir gedacht.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 16, 2019, 10:30 pm
Dann mach es so.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 16, 2019, 10:34 pm
Ich wollte dich nicht verärgern. Vielleicht begreife ich es irgendwan. Ich (denke) ich verstehe worauf du/ ihr hinaus wollt. Es geht darum das man das übertragene in meiner Variante nicht einfach lesen kann, da man ja nur mit Zahlen arbeitet. Bei eurer Variante würde man alles im Klartext übertragen. Oder denke ich falsch?
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Whandall on Feb 16, 2019, 10:48 pm
Es geht darum das man das übertragene in meiner Variante nicht einfach lesen kann, da man ja nur mit Zahlen arbeitet. Bei eurer Variante würde man alles im Klartext übertragen. Oder denke ich falsch?
Offensichtlich hast du #193 vom Today at 22:25:28 entweder nicht gelesen, oder nicht verstanden.
Man kann beides haben, sprechende Namen und (nahezu) druckbare Pakete,
mit fast minimaler konstanter Größe.

Und niemand zwingt dich irgendetwas wie vorgeschlagen zu machen.

Die eigentliche Kommunikation solltest du ja jetzt hinbekommen, was du hin und her schickst
ist ja völlig wurscht und muss nur dir passen.

Dass ich anscheinend nicht in der Lage bin zu vermitteln wie man simpel, bequem, robust und
nicht-blockierend Kommunikationen zwischen Netztwerkknoten implementieren kann, ist nur etwas irritierend.

Vielleicht hat ja der ein oder andere Mitleser etwas damit anfangen können.

Ich habe zwar keine Eisenbahn, aber ein paar NRF Knoten.  ;)
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: postmaster-ino on Feb 16, 2019, 11:09 pm
Hi

Mir fehlt Beides - wobei so NRF-Dinger hier zwei rumliegen müssten ...

@Whandall
Ich bin der Überzeugung, daß Deine Erklärungen schon noch zünden werden, zumindest ich fand Sie durchaus eingängig.

@Acki
Wenn Deine Kommunikation funktioniert, dann soll Das doch auch ok sein!
Mehr muß nicht - für spätere Wartung oder Erweiterbarkeit wären halt sprechende Namen oder übertragbare weitere Informationen einfacher - wobei, eigentlich unabdingbar.
Wenn es jetzt noch nicht so weit sein soll, dann eben noch nicht - Dir reißt hier Keiner den Kopf ab, wenn Deine Drehbühne nach Deinen Vorstellungen fährt und eben genau so mit Dir via Funk schwätzt.

MfG
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 17, 2019, 11:23 am
Guten morgen alle zusammen,

ich habe mir das mit dem enum noch mal durch den Kopf gehen lassen und noch mal danach gesucht und bin auf volgende Seite gestoßen : https://www.proggen.org/doku.php?id=c:type:enum (https://www.proggen.org/doku.php?id=c:type:enum)

Hab mir diese Seite durchgelesen. Wenn ich das richtig verstanden habe, kann ich am Anfang den Bestandteilen der Aufzählung je einen Wert zuweisen: Z.B.

Code: [Select]
enum zustaende
{
  rev_start = 255,
  rev_ende = 254,
  nothalt = 0,
  alte_pos = 1,
  neue_pos = 1,
  restl_schritte = 0,
  rechts = 0,
  links = 0
};


Habe ich das so richtig verstanden?

Dann kann ich in den Abfragen mit den bezeichnungen direkt arbeiten Z.B.
neue_pos = 10

Kann man dieses enum dann auch direkt versenden?
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: postmaster-ino on Feb 17, 2019, 11:59 am
Hi

Nein

Das ist kein struct, sondern NUR eine Aufzählung verschiedener Zustände.
Eigentlich dürfte Das So auch nicht kompilieren?!?
Habe Es noch nicht probiert, aber müssen die Zahlen nicht unterschiedlich sein?

Aber ein struct nimmst Du eh, um die ganzen Informationen aufzunehmen, unter Anderem auch den Zustand (und davon KANN Es immer nur Einen geben - und Deine 0 wäre links, rechts, restl_schritte und nothalt - ich sehe dort eine Mehrdeutigkeit.

MfG
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 17, 2019, 12:04 pm
Hm dachte ich habe es verstanden... Nagut dann werde ich es mit der Zahlenmethode machen.
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 17, 2019, 08:36 pm
So habe mal wieder ein Bisschen was gemacht. Hab mal im Sender versucht das Programm für die Referenzfahrt zu programmieren. Aber leider empfängt die Bühne nichts...

Hier mal der Code vom Sender:

Code: [Select]

#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
#include <SPI.h>
#include "RF24.h"
RF24 radio (A4, A5);
byte address[] [6] = {"pipe1", "pipe2"};
const byte sensor_referenz = 2;                   // Pin für Sensor Referenz aussen an der Grube (Nullstellung)
int status_sensor_referenz;                       // Speichervariable für Status von Sensor für Referenzfahrt
byte befehl [8];

// Statusvariablen
bool nullStellung = false;                      // Speichervariable ob Referenzfahrt erfolgt ist
bool referenzFahrt_b = true;                      // Speichervariable ob Referenzfahrt gestartet oder beendet wurde
void setup() {
  pinMode(sensor_referenz, INPUT);
  /Serial.begin(9600);
  radio.begin();
  radio.openReadingPipe(1, address[0]);
  radio.openWritingPipe(address[1]);
  radio.setPALevel (RF24_PA_MAX);
  radio.setDataRate (RF24_250KBPS);
  radio.setChannel (110);
  radio.startListening();
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("Drehscheiben-");
  lcd.setCursor(0, 1);
  lcd.print("steuerrung");
  delay (2000);
 
}

void loop() {
//  daten_empfangen();
  referenzFahrt();
  //encoder_lesen();
  //schritte_berechnen();
  //wenden();
  //nothalt();
}

void referenzFahrt() {
  //Serial.println(nullStellung);
  //Serial.println(status_sensor_referenz);
  //Serial.println(referenzFahrt);
 
  status_sensor_referenz = digitalRead (sensor_referenz);
  if ((nullStellung == false) && (status_sensor_referenz == HIGH) && (referenzFahrt_b == true)) {
    referenzFahrt_b = false;
    befehl[0] = 255;
    radio.stopListening();
    radio.write(&befehl[0], sizeof(byte));
    radio.startListening();
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Referenzfahrt");
    lcd.setCursor(0, 1);
    lcd.print("gestartet");
    Serial.println(befehl[0]);
    }
  else if ((nullStellung == false) && (status_sensor_referenz == LOW)) {
    referenzFahrt_b = true;
    nullStellung = true;
    befehl[0] = 254;
    radio.stopListening();
    radio.write(&befehl[0], sizeof(byte));
    radio.startListening();
    lcd.setCursor(0, 1);
    lcd.print("beendet   ");
    Serial.println(befehl[0]);
  }
}


und der Code von der Bühne:

Code: [Select]

#include <SPI.h>
#include "RF24.h"

unsigned long warteZeit;
int data[1];
boolean var = true;
//const byte addresses[][6] = {"00001", "00002"};
//const uint64_t pipe = 0xF0F0F0F0A1LL;
RF24 radio (8, 9);
byte address[] [6] = {"pipe1", "pipe2"}; // Adressen der beiden Pipes
byte rever_start = false;
const byte hal = 3;
byte schritte[1];                                 // Schritte die deer Motor (Hallsensor betätigt) zurücklegen muss
int sensor = LOW;
unsigned long startZeit;                          // Abfrage begin Sensor an Bühne
unsigned long interval = 2000;                    // Zeitabstand nachdem ein Zustand des Sensors erkannt wird
unsigned long vergangeneZeit = 0;                 // Speichervariable um die Vergangene Zeit zu speichern
/*int pin_motor_links = A1;                         // Richtungspin an H-Brücke für Links
int pin_motor_rechts = A2;                        // Richtungspin an H-Brücke für Rechts
*/
// Statusvariablen
bool nullStellung = false;                      // Speichervariable ob Referenzfahrt erfolgt ist
bool ergebnis = false;                          // Berechnung der Schritte und Richtung beendet/gestartet
bool start = false;                           // Schritte Zaehlen beendet/gestartet

void setup() {
  radio.begin();
  //radio.openReadingPipe(1, pipe);
  radio.openWritingPipe(address[1]); // 00001
  radio.openReadingPipe(1, address[0]); // 00002
  radio.setPALevel(RF24_PA_MAX);
  radio.setDataRate (RF24_250KBPS);
  radio.setChannel(110);
 
  radio.startListening();
  pinMode(hal, INPUT);
  Serial.begin(9600);
  //delay (2000);
  }

void loop() {
 
  referenzFahrt();
  encoder_lesen();
  schritteZaehlen();
  }

void referenzFahrt() {
  if (radio.available())
{
Serial.println("Data there");
radio.read(data, 1);
Serial.println(data[0]);
}

      // Reverenzfahrt

      if ((data[0] == 255) && (rever_start == false) && (nullStellung == false)) {
        rever_start = true;
        Serial.println("Reverenzfahrt gestartet");
    //    digitalWrite (pin_motor_rechts, HIGH);
      //  digitalWrite (pin_motor_links, LOW);
      }
      else if ((data[0] == 254) && (rever_start == true)) {
        nullStellung = true;
        rever_start = false;
        Serial.println("Reverenzfahrt beendet");
        Serial.println (" "); 
  //      digitalWrite (pin_motor_rechts, LOW);
//        digitalWrite (pin_motor_links, LOW);
      }
    }
 
  void encoder_lesen () {
   if ((data[0] <= 48) && (data[0] > 0) && (nullStellung == true) && (ergebnis == false)) {
    //rechtsrum data[0] Schritte
    schritte[0] = data[0];
    ergebnis = true;
    // Motor
    Serial.println (schritte[0]);
    Serial.print ("  Schritte nach Rechts");
    Serial.println (" ");   
   }
  else if ((data[0] >=100) && (data[0] <= 149) && (nullStellung == true) && (ergebnis == false)) {
    //linksrum data[0] - 100 Schritte
    schritte[0] = data[0] - 100;
    ergebnis = true;
    // Motor
    Serial.println (schritte[0]);
    Serial.print ("  Schritte nach links");
    Serial.println (" ");
   }
  }
 
void schritteZaehlen () {

  sensor = digitalRead (hal);
  startZeit = millis();
  if ((schritte[0] != 0) && (ergebnis == true)) {
    start = true;
    if ((startZeit - vergangeneZeit >= interval) && (sensor == LOW) && (start == true)) {
      vergangeneZeit = startZeit;
      schritte[0]--;
      Serial.println("Drehung start");
      Serial.println("Restl. Pos.");
      Serial.println(schritte[0]);
      radio.stopListening();
      radio.write (&schritte, sizeof (schritte));
      radio.startListening();
      }
  }
  else if ((schritte[0] == 0) && (start == true)) {
    start = false;
    ergebnis = false;
    data[0] = 0;
    Serial.println("Ziel");
    Serial.println("Drehung");
    Serial.println("beendet");
    Serial.print("daten");
    Serial.println(schritte[0]);
    radio.stopListening();
    radio.write (&schritte, sizeof (schritte));
    radio.startListening();
    //schritte[0]=0;
   
    Serial.println(ergebnis);
    }
}

Die Bühne empfängt nichts vom Sender. Kann mir jemand helfen woran es liegt?

Gruß Acki

Title: Re: Drehscheibe Modellbahn mit RF24
Post by: postmaster-ino on Feb 17, 2019, 09:23 pm
Hi

Warum machst Du Dir Dein Leben so schwer?
Du hattest einen funktionierenden Code - ohne Funk.
Nun willst Du Funk dazu 'bauen' - aber warum packst Du Alles nur Denkbare in den funktionierenden Sketch?
Du willst, daß die Bühne auf Funk reagiert - dann baue EINE Funktion dafür.
Wenn von Der als Rückgabe 'Ja, habe was empfangen' kommt, kannst Du damit Dein schon bestehendes Programm triggern.
Auch sollte Dein Sketch so ausgesehen haben, daß loop() möglichst schnell durchlaufen wird.
Bei JEDEM Durchlauf rufst Du auch eine Funktion auf, Die den Status via Funk sendet.
In dieser Funktion entscheidest Du JEDES MAL NEU, ob jetzt wirklich gesendet werden soll/muss.

Du bekommst also zwei zusätzliche Funktions-Aufrufe in loop() - mehr nicht.
Wenn Deine vorherige Steuerung feste Pins abgefragt hat, ob eben ein neues Ziel angefahren werden soll, musst Du Das um die Möglichkeit erweitern, Das auch von Deiner Funk-Funktion auslosen zu können - mir schwebt dort ein 'funkstatus' vor.
Also eine Status-Variable, Die gerne auch mit enum-Begriffen beschickt werden darf.

MfG
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 17, 2019, 09:48 pm
Du meinst also ich soll den Sketch so lassen wie er ist und Parallel dazu die Funkfunktion (senden, empfangen) einbauen? Habe ich das so richtig verstanden? Also auf den Sender und die Bühne den gleichen Sketch und dann eben den Funk dazu?
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: postmaster-ino on Feb 17, 2019, 10:11 pm
Hi

Der Sender wird wohl keine Bühnen-Komponenten brauchen.
Die Bühne braucht aber neben der schon vorhandenen Funktionalität 'nur' die zusätzlichen Möglichkeiten.
Das Senden und Empfangen geht 'nebenher' - sofern der Bühnensketch nicht auf WHILE und delay() basiert ;) .
Du musst 'nur' im Bühnen-Sketch diese zusätzlichen Eingaben mit verarbeiten.
Wenn Du vorher das neue Zielgleis via Terminal eingegeben hast, kommt jetzt das Ziel eben via Terminal ODER via Funk.
Nach Beiden ist dann, auf magische Art und Weise, die Zielgleis-Nummer eine Andere.
Der Bühnen-Sketch erkennt Das, berechnet die Drehrichtung, startet den Motor, ... also den ganzen Kram, Den Er vorher auch schon gemacht hat.

Zusätzlich wird halt bei jedem loop()-Durchlauf geprüft, ob man Status-Daten senden muss/kann.
Du wirst nicht 1000 Mal die Sekunde 'Bin auf Gleich 1, drehe rechts rum' senden müssen.
Das reicht 1x die Sekunde (millis() ist Dein Freund) oder, wenn sich was geändert hat.
Bei Stillstand z.B. muß die Bühne gar nicht schwätzen, wenn auch hier die Sende-Funktion 1000x die Sekunde aufgerufen wird.

Was löst bisher eine Drehung aus?
Genau DA solltest Du ansetzen, DAS sollte auch der Funk verändern.
Wie stoppst Du die Bühne aktuell? DA greift auch der Funk für den Nothalt mit zu.

MfG
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Feb 17, 2019, 10:39 pm
Aber das hatte ich doch versucht. Wollte das wenn ich den Sender einschalte eine 255 Senden das die Bühne die Referenzfahrt startet. Wenn der Referenzpunkt erreicht ist wollte ich eine 254 Senden. Aber bei der Bühne kommt nix an. Der Bühnencode ist ja noch genau so wie wie ich es mit Test Sendesketch versucht habe. Mit dem hat es auch funktioniert. Nur mit dem jetzigen Sender Sketch funktioniert es nicht.
Nur warum?

Gruß Acki
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Apr 28, 2019, 06:26 pm
Guten Abend,

ich möchte an der Steuerung weiter bauen.
Könnt ihr mir sagen warum der Arduino in der Bühne nur die meistens nur einmal die 255 empfängt obwohl ich sie dauerhaft sende?

Code: [Select]

#include <SPI.h>
#include "RF24.h"

unsigned long warteZeit;
int data[1];
boolean var = true;
//const byte addresses[][6] = {"00001", "00002"};
//const uint64_t pipe = 0xF0F0F0F0A1LL;
RF24 radio (8, 9);
byte address[] [6] = {"pipe1", "pipe2"}; // Adressen der beiden Pipes
byte rever_start = false;
const byte hal = 3;
byte schritte[1];                                 // Schritte die deer Motor (Hallsensor betätigt) zurücklegen muss
int sensor = LOW;
unsigned long startZeit;                          // Abfrage begin Sensor an Bühne
unsigned long interval = 2000;                    // Zeitabstand nachdem ein Zustand des Sensors erkannt wird
unsigned long vergangeneZeit = 0;                 // Speichervariable um die Vergangene Zeit zu speichern
/*int pin_motor_links = A1;                         // Richtungspin an H-Brücke für Links
int pin_motor_rechts = A2;                        // Richtungspin an H-Brücke für Rechts
*/
// Statusvariablen
bool nullStellung = false;                      // Speichervariable ob Referenzfahrt erfolgt ist
bool ergebnis = false;                          // Berechnung der Schritte und Richtung beendet/gestartet
bool start = false;                           // Schritte Zaehlen beendet/gestartet

void setup() {
  radio.begin();
 
  radio.startListening();
  pinMode(hal, INPUT);
  //radio.openReadingPipe(1, pipe);
  radio.openWritingPipe(address[1]); // 00001
  radio.openReadingPipe(1, address[0]); // 00002
  radio.setPALevel(RF24_PA_MAX);
  radio.setDataRate (RF24_250KBPS);
  radio.setChannel(110);
  Serial.begin(9600);
  //delay (2000);
  }

void loop() {
 
  referenzFahrt();
  encoder_lesen();
  schritteZaehlen();
  }

void referenzFahrt() {
  if (radio.available())
{
Serial.println("Data there");
radio.read(data, 1);
Serial.println(data[0]);
}

      // Reverenzfahrt

      if ((data[0] == 255) && (rever_start == false) && (nullStellung == false)) {
        rever_start = true;
        Serial.println("Reverenzfahrt gestartet");
    //    digitalWrite (pin_motor_rechts, HIGH);
      //  digitalWrite (pin_motor_links, LOW);
      }
      else if ((data[0] == 254) && (rever_start == true)) {
        nullStellung = true;
        rever_start = false;
        Serial.println("Reverenzfahrt beendet");
        Serial.println (" ");
        //data [0] = 0; 
  //      digitalWrite (pin_motor_rechts, LOW);
//        digitalWrite (pin_motor_links, LOW);
      }
    }
 
  void encoder_lesen () {
   if ((data[0] <= 48) && (data[0] > 0) && (nullStellung == true) && (ergebnis == false)) {
    //rechtsrum data[0] Schritte
    schritte[0] = data[0];
    ergebnis = true;
    // Motor
    Serial.println (schritte[0]);
    Serial.print ("  Schritte nach Rechts");
    Serial.println (" ");   
   }
  else if ((data[0] >=100) && (data[0] <= 149) && (nullStellung == true) && (ergebnis == false)) {
    //linksrum data[0] - 100 Schritte
    schritte[0] = data[0] - 100;
    ergebnis = true;
    // Motor
    Serial.println (schritte[0]);
    Serial.print ("  Schritte nach links");
    Serial.println (" ");
   }
  }
 
void schritteZaehlen () {

  sensor = digitalRead (hal);
  startZeit = millis();
  if ((schritte[0] != 0) && (ergebnis == true)) {
    start = true;
    if ((startZeit - vergangeneZeit >= interval) && (sensor == LOW) && (start == true)) {
      vergangeneZeit = startZeit;
      schritte[0]--;
      Serial.println("Drehung start");
      Serial.println("Restl. Pos.");
      Serial.println(schritte[0]);
      radio.stopListening();
      radio.write (&schritte, sizeof (schritte));
      radio.startListening();
      }
  }
  else if ((schritte[0] == 0) && (start == true)) {
    start = false;
    ergebnis = false;
    data[0] = 0;
    Serial.println("Ziel");
    Serial.println("Drehung");
    Serial.println("beendet");
    Serial.print("daten");
    Serial.println(schritte[0]);
    radio.stopListening();
    radio.write (&schritte, sizeof (schritte));
    radio.startListening();
    //schritte[0]=0;
   
    Serial.println(ergebnis);
    }
}
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Apr 28, 2019, 06:46 pm
Hier noch der Code vom Sender:

Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Tommy56 on Apr 28, 2019, 06:52 pm
Warum fügst Du den nicht hier ein? Wenn er zu lang ist, hänge ihn als Attachment ran.

Gruß Tommy
Title: Re: Drehscheibe Modellbahn mit RF24
Post by: Acki1985 on Apr 28, 2019, 07:00 pm
Hallo Tommy,

danke dir für den Tip. hab es geändert.