Schritte vor und zurück zählen mit Inkrementalgeber

Erst einmal Hallo
Bin ziemlich neu hier und habe bis jetzt immer direkt meine Antworten zu meinen Problemen gefunden !
Aber jetzt bin ich am verzweifeln !

Zu Thema:
Ich habe ein Tintenstrahldrucker so weit zerlegt das ich nur noch die Druckerkopfaufnahme und die Achse auf der der Druckerkopf läuft, mit dem DC-Motor und den Zahnriemen.
Jetzt möchte ich den Druckerkopf auf der Achse in meine Gewünschte Position bewegen ( die Position soll sich erst einmal mit einem Poti verändern lassen)
Um das erst einmal Technisch aufzubauen habe ich einen optischen Inkrementalgeber aus anderen teilen des Druckers und “Strichrasterband” mit gröberer Auflösung zur Position Erkennung eingebaut!

Zum Problem:
Ich schaffe es nicht die Position des Druckerkopfs genau auszulesen.
Er verzählt sich immer wieder und das schon nach der ersten links-rechts fahrt um 10-30 Schritte !

Ein paar Fakten:
-habe ein Arduino UNO Board mit einem ATmega328
-Der Inkrementalgeber liest mit großer Sicherheit jeden Impuls vom “Strichrasterband”
-Besonders langsame Fahrten 1m/h werden zum teil über Haupt nicht gezählt!
-Der Inkrementalgeber hat 2 digitale Ausgänge: Wenn ich eine Karte von links nach rechts durchzieh bleibt er auf A1=HIGH A2=LOW. Ziehe ich die Karte von rechts nach links bleibt er auf A1=LOW A2=HIGH.
-Ich habe sehr wenig Erfahrung in C/C++ und habe das meiste an Programmen mir zusammen gefummelt und verändert bis es läuft !

Mein Programm:
Ich weiß das hier vieles nicht gebraucht wird aber gehe jetzt einfach mal davon aus das Geschwindigkeit nicht mein Problem ist !
Wie gesagt das Programm gibt mir zwar einen Zählerstand wieder und erkennt auch die Richtung (zählt rauf und runter) aber lässt viele Schritte aus und das meist bei langsamen !

int Refahrt = LOW;
int fahrtR;
int fahrtL;
int soll;
int sollmax;
int sollmin;
int ES =6;
int reset;
int SensorL =3;
int SensorR =2;
int val;
int val0;
int SensorRst;
int SensorLst;
int StreckeR = 0;
const int LEDR =4;
const int LEDL =5;
 const int led = 9  ;
 const int led1 = 10  ; 
void setup(){
  pinMode(SensorR, INPUT);
  pinMode(SensorL, INPUT);
  pinMode(ES, INPUT);
  Serial.begin(9600);
 SensorRst = digitalRead(SensorR);
 SensorLst = digitalRead(SensorL);
  pinMode(LEDR, OUTPUT);
  pinMode(LEDL, OUTPUT);
   pinMode(led, OUTPUT);
   pinMode(led1, OUTPUT);
    
 
}
int sollAnalog ()
{
  int v;
  v = analogRead(A0);
  v -=500;
  v  /=4;
  return v;
}

void loop() {
  val = digitalRead(SensorR);  
  val0 = digitalRead(SensorL);
  digitalRead(ES);
  fahrtL = digitalRead(SensorR)== LOW & digitalRead(SensorL)== HIGH ;
  fahrtR = digitalRead(SensorR)== HIGH & digitalRead(SensorL)== LOW ;
  
if (val != SensorRst){
    if(fahrtR == LOW) {
      if(fahrtL == HIGH){
      StreckeR--;      
      }           
     }
     SensorRst = val ;
    }         
if (val0 != SensorLst){
    if( val0 == LOW) {
     if(fahrtR == HIGH){
      StreckeR++;
       
      }
     Serial.println(StreckeR);
     }
     SensorLst = val0 ;
  }

 
  
if (digitalRead(ES) == HIGH){ // Positionsangabe durch Enschalter reseten
  StreckeR = 0;
}
if (Refahrt == LOW){
  while(digitalRead(ES) == LOW ){
    analogWrite(led, 0);  // turn the LED on (HIGH is the voltage level)
    analogWrite(led1, 130);
  }
  Refahrt = HIGH;
}

 soll =  sollAnalog();
sollmin = soll - 1 ;
sollmax = soll + 1 ;
if (soll != StreckeR){
  if (sollmax <  StreckeR){
  analogWrite(led, 0);  // turn the LED on (HIGH is the voltage level)
  analogWrite(led1, 130);
 // fahrtR = LOW;
//  fahrtL = HIGH;
  }else {
    analogWrite(led1,0);
  }
  if (sollmin > StreckeR){
  analogWrite(led1, 0);    // turn the LED off by making the voltage LOW
  analogWrite(led, 130);
 // fahrtL = LOW;
 // fahrtR = HIGH;
  } else {
    analogWrite(led,0);}
                 // wait for a second
}

 // Schritt überwachung  
    if (val == HIGH) {     
    // turn LED on:    
    digitalWrite(LEDR, HIGH);  
  } 
  else {
    // turn LED off:
    digitalWrite(LEDR, LOW); 
  }
    if (val0 == HIGH) {     
    // turn LED on:    
    digitalWrite(LEDL, HIGH);  
  } 
  else {
    // turn LED off:
    digitalWrite(LEDL, LOW); 
  }
}

Bist du dir sicher das der Inkrementalgeber nicht zwei Spuren hat normalerweise sind es zwei Kanäle die um 90° Versetzt zueinander stehen.
Solche Encoder musst du über einen Interrupt auslesen da du sonst schnell “Schritte” verlierst. Digital Pin2 und 3 sind Interrupt eingänge.
Es sind beide Pullups aktiviert.
Hier mal ein kleinen Code von mir.
Kanal A ist an Pin2 und Kanal B an Pin3

int B=3;
int A=2;

void setup (){
  attachInterrupt(0,CHAInt,CHANGE);        // Call Channel A of ENCODER Function while on CH1 Signal Changing
  pinMode(2,INPUT);
  pinMode(3,INPUT);
  digitalWrite(2,HIGH);
  digitalWrite(3,HIGH);
}

void loop(){
  // Hier kannst du dann mit der Variabeln Wert machen was du willst

}

void CHAInt (){
  boolean Aread=false;
  boolean Bread=false;
  Aread=digitalRead(A);
  Bread=digitalRead(B);
  if (Aread==true && Bread==false||Aread==false && Bread==true){
    Wert++;
  }
  if (Aread==false && Bread==false ||Aread==true&& Bread==true){
    Wert--;
  }
}

In Wert stehen dann deine Schritte drinnen. Pack mal deinen Code auch in eine Codebox (doppelkreuz über den Smilies).
Gruß
Der Dani

Wenn der Inkrementalgeber bei langsamer Fahrt nicht richtig zählt, liegt es vielleicht an dem zu geringen Kontrast zwischen Strich und Band. Versuch mal den Geber besser gegen Tageslicht zu schützen.

Erst einmal danke für die Schnellen Antworten : -Ich habe das mit dem Interrupt ausprobiert und leider immer noch Schritt Verlust! -Auch den Sensor komplett verdunkeln hat nicht geholfen!

Wie ist das mit dem entprellen ? Muss ich ein Inkrementalgeber entprellen und wie mach ich das wenn die Impuls abstände nicht kenne bzw. ungleichmäßig sind ?

Bei der Softwareentprellung bekomme ich kein besseren Wert !

Wenn der Geber prellen würde, hättest du mehr Impulse und nicht weniger. Aber mehr fällt mir dazu auch nicht ein. Kann es sein, dass der Schrittmotor zu stark ruckelt? Oder läuft er schön gleichmässig?

Die Sache läuft mit einem einfachen DC-Motor ! Es kann auch sein das zu viele Schritte bei der rückfahrt gezählt werden. Zumidestens habe ich immer zu wenig schritte wenn ich wieder am Startpunkt bin von dem ich den Zähler resete! Der Geber hat auch keine 4 Zustände > A1&B1 , A0&B1 , A1&B0 , A0&B0. also die 90C Regel. Sondern 3 Zustände:

A0&B0 wenn der Sensor komplet beleget ist A1&B0 wenn durch den Sensor von links nach rechts ein Unterbrecher z.b. Karte gezogen [u]wurde[/u] A0&B1 wenn durch den Sensor von rechts nach links ein Unterbrecher z.b. Karte gezogen [u]wurde[/u] Nach einer Unterbrechenung hät der Sensor einen der beiden Kontakte bis er wieder unterbrochen wird! Die Simpelste möglichkeit das auszulesen ist mit dem Code

int B = 2 ;
int A = 3 ;
int Wert;
int Null;


void setup() {
  pinMode(A, INPUT);
  pinMode(B, INPUT);
  Serial.begin(9600);
}
void loop() {
//Null;
if  (digitalRead(A)== LOW & digitalRead(B)== LOW) 
{
  Null=HIGH;
}

 if(Null == HIGH)
 {
   if(digitalRead(A)== HIGH)
   {
     Wert++;
     Null=LOW;
   }
   if(digitalRead(B)==HIGH)
   {
     Wert--;
     Null=LOW;
   }
 }


   
Serial.println(Wert);
}

Das klapt auch ist aber viel zu langsam ! Leider habe ich das nicht auf den InterruptCode übertragen können (falls möglich) Ich werde die Lösung weiter suchen und berichten ! :cold_sweat:

Hast du es noch hingekommen? Bin grad auch dabei die Positionierung über diesen Druckerstreifen zu realisieren.
Gruß