Rechnen via Rotary/Encoder

Hallo Gemeinde,

ich steh etwas auf dem Schlauch und brauche mal eure Hilfe. Ich möchte ene Kommazahl addieren bzw. subtrahieren wenn ich meinen Rotary/Encoder drehe.

Bei der Ganzahl (int) scheint es zu gehen. Die Kommazahl (double) macht da probleme. Als Beispiel ein Demosketch.

#include <Rotary.h>

Rotary r = Rotary(2, 3);
int x;
double y;


void setup()
{
  Serial.begin(9600); 
  x = 1;
  y = 438.8500;

  // Interrupt fuer Drehgeber konfigurieren
  PCICR |= (1 << PCIE2);
  PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
  sei();
}


void loop() {

}

ISR(PCINT2_vect) {
 unsigned char result = r.process();
 if (result) {
   if (result == DIR_CW) {
          x++;
          y = y + 0.0250;
          Serial.print("X ");Serial.println(x); 
          Serial.print("Y ");Serial.println(y, 4); 
   } else {
          x--;  
          y = y - 0.0250; 
          Serial.print("X ");Serial.println(x); 
          Serial.print("Y ");Serial.println(y, 4); 
   }  
 }
}

Am Anfang läuft es normal, doch dann kommt plötzlich der Fehler …

Serial ausschnitt:
X 10
Y 439.0750
X 11
Y 439.1000
X 12
Y 439.1250
X 13
Y 439.1499 <---- Fehler

Hat jemand eine Idee an was das liegen kann ?

Gruß Wolfi

Keine Ahnung wo der Fehler liegt. Vermutlich an "double".

Aber warum rechnest du nicht mit der Ganzzahl (Long) und teilst dann durch 1000 ?

Hmmm ... Ich werde das mal versuchen. Double und float liefern das selbe falsche Ergebnis. Ich werde dann informieren sobald getestet.

Gruß Wolfi

Also ich hab das nun mal so versucht …

#include <Rotary.h>

Rotary r = Rotary(2, 3);
long y;
double ftx;

void setup()
{
  Serial.begin(9600); 
  y = 4388500;

  // Interrupt fuer Drehgeber konfigurieren
  PCICR |= (1 << PCIE2);
  PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
  sei();
}


void loop() {

}

ISR(PCINT2_vect) {
 unsigned char result = r.process();
 if (result) {
   if (result == DIR_CW) {
          y = y + 250;
          ftx = y / 10000;
          Serial.print("y ");Serial.println(y); 
          Serial.print("ftx ");Serial.println(ftx, 4); 
   } else {
          y = y - 250; 
          ftx = y / 10000;
          Serial.print("y ");Serial.println(y); 
          Serial.print("ftx ");Serial.println(ftx, 4); 
   }  
 }
}

Die Ganzzahl wird dann ja richtig gemacht, aber beim anschließenden teilen passiert dann folgendes …

y 4397750
ftx 439.0000
y 4398000
ftx 439.0000
y 4398250
ftx 439.0000
y 4398500
ftx 439.0000
y 4398750
ftx 439.0000
y 4399000
ftx 439.0000

Warum das?

Gruß Wolfi

Hat jemand eine Idee an was das liegen kann ?

0.025 ist eine ganz krumme Zahl.

Während 0.25 prima als Zweierpotenz (2-2)geschrieben werden kann (und daher erst viel später Rundungsfehler produziert), geht das für 0.1 nicht so gut.

double und float ist beim Arduino dasselbe (float32).
Und erheblich ungenauer als long.

Da ein RotaryEncoder zählt, sind Ganzzahl-Datentypen erheblich passender als Gleitkomma-Variable.

10000000 + 1  geht prima mit long, aber überhaupt nicht mit float32.

meinst du evtl.

ftx = y / 10000.0 ;

oder sonst eine Art, wie du klarmachen kannst, dass eine float-Division gewünscht wird.

float ftx = float(y) / 10000 ; alternative Möglichkeit

michael_x:
meinst du evtl.

ftx = y / 10000.0 ;

oder sonst eine Art, wie du klarmachen kannst, dass eine float-Division gewünscht wird.

float ftx = float(y) / 10000 ; alternative Möglichkeit

Oh vielen Dank michael_x für die Info … Was ein .0 doch alles ausmachen kann. Da sieht man wieder das ich noch viel zu lernen habe … Funktioniert nun wunderbar!

Gruß Wolfi