Variablen verändern ( Begrenzen)

Hallo Gemeinde
Ich suche nach einer Möglichkeit Variablen in ihrem Wertebereich zu begrenzen mit Überlauf.
Also int. 0-65535 in--> z.b 0-5000

Es geht um Zählimpulse aus einem Drehencoder /255/PPU welcher zur Positionsbestimmung von Drehtischen dienen soll.
Der Encoder misst am Außendurchmesser, welcher sich von Tisch zu Tisch ändert.
Also ändern sich auch die Anzahl der Impulse für einen Vollkreis.
Mappen der Zählwerte auf 0-3600 geht,

constrain begrenzt nur den Wert und ignoriert die nächsten Impulse.
Ist also nicht nützlich.

Da ja bei einen Vollkreis nach 360° wieder die Position 0 beginnt brauche ich also einen überlauf nach 0 oder Höchstwert

Ich steh da Momentan auf dem Schlauch
Hat jemand eine Idee

Grüße Brömmel

if(x>359) x=0;
if(x<0) x=359;
anstatt 359 eben den gewünschten Überlauf
x muss muss Vorzeichen haben

Danke für die Antwort
Hmm.
Macht mir aber keinen Überlauf in meiner Variable, sondern begrenzt auch nur wie constrain.

Meine Variabel "Winkel"

unsigned short Winkel= encoder1Pos;
if(Winkel>4000)Winkel=0 ;

"encoder1Pos" ist volatile unsigned short und wird in der ISR sowie in einer weiteren Funktion benötigt.

Grüße Brömmel

die Variable muss signed sein und wenn in beide Richtungen bewegt wird, musst du auch beide if Anweisungen rein machen

Du musst auch die encoder1pos ändern, nicht Winkel

Deine Variable darf nicht unsigned sein. Dann hast du sowohl Überlauf als auch Unterlauf, weil auch negative Zahlen dargestellt werden können. Bei unsigned int springst du wenn es "kleiner als 0" wird wieder an den oberen Rand des Wertebereichs.

Ansonsten solltest du genauer erklären was du genau meinst. Das ist nicht 100%ig klar

Broemmel:
Danke für die Antwort
Hmm.
Macht mir aber keinen Überlauf in meiner Variable, sondern begrenzt auch nur wie constrain.

Natürlich kannst Du auch
x++;
if(x>359) x=359;
schreiben, und so keine größeren Werte zulassen.
Grüße Uwe

Danke für die Antworten

ein bisschen verwirrt ihr mich gerade.
meine Annahme für int : singed Werte -32.767 bis 32.768 und unsigned Werte 0-65.535 .
Ich möchte keine negativen Werte.

in meiner ISR:

void Encoder() {
 IndexState = bitRead(PIND,4);   // hoffentlich schneller
 //IndexState = digitalRead(4);    // Arduino
    if (IndexState == HIGH){
     lastIndexState = IndexState;
     //Serial.println("Runde");         
    }
 if (bitRead(PIND,2) == bitRead(PIND,3))           // Ich hoffe schneller
 //if (digitalRead(encoder1PinA) == digitalRead(encoder1PinB))   //  Arduino
 {
   encoder1Pos++; 
 } else {
   encoder1Pos--;
 }

 Serial.println (encoder1Pos, DEC);

}

ermittle ich die Encoder Impulse.
die Variable “encoder1Pos” ist global und wird in weiteren Funktionen benötigt.

zur Anzeige Am Display brauche ich Werte entsprechend der Scheibengröße( Impulszahlen)
deshalb benutze ich zusätzlich die Variable “Winkel”
da der Tisch mehrere Umdrehungen machen kann in beider Richtungen muss ich einen Überlauf/ Unterlauf machen das er bei >360,0 wider 0 anzeigt. dies in beide Richtungen.
mache ich mit

 unsigned short Winkel= encoder1Pos; 
 if(Winkel>4000)Winkel=0;
 if(Winkel<0)Winkel=3599;
 module.setDisplayToDecNumber(Winkel,4,false);    // Inhalt ,Pos.DP,keine Nullen)
 module.setDisplayDigit('4',1,true);

Da encoder1Pos weiter werte über (hier 4000) zählt funktioniert dies nicht.

ich brauche eine Lösung wie z.b. 2 verschieden große Zahnräder als Getriebe mit jeweils einem Nullpunkt.
das große ist" encoder1Pos ", das kleine “Winkel” mit unterschiedlichen Größen.
Also wie ein Ringzähler :

  1. 0- 65535
  2. 0-xxx
    Grüße Brösel

Serial darfst du in ISRs nicht machen!

unsigned short Winkel= encoder1Pos;
 if(Winkel>4000)Winkel=0;
 if(Winkel<0)Winkel=3599;

Winkel kann nie < 0 sein, da unsigned

@Serenifly

genau das möchte ich ja.
wenn der Tisch über 360,0° dreht sind es wieder0° und umgekehrt.

Grüße Brömmel

Die Abfrage kann aber niemals wahr sein. Dazu müsste die Variable short oder int sein. Dann kann sie dirch die Dekrementierung negativ sein und man macht sie per Hand positiv.

@Serenifly
Serial in der ISR ist nur zum Debuggen, da mir im Loop sonst ständig gleiche Werte geschrieben werden.
fliegt dann raus.

Grüße Brömmel

Das Zauberwort heißt: Modulo

Grad = (X % 360)

Wenn X größer als 360 ist, beginnt X wieder bei Null :))

Gegebenenfalls noch:
If (Grad == 360) Grad = 0;

Grüße, Robert

Danke an Alle

Ich hab mir "Winkel" als volatile short deklariert und lasse diese in der ISR zusammen mit encoder1Pos counten.
nach rausschmiss von Serial ist diese hoffentlich schnell genug. Werde ich bei realen Geschwindigkeiten sehen.

Nun zählt mein Display brav bis 360,0 tastet 1x dunkel und fängt dann wieder bei 0,1 an.

Grüße Brömmel

@Roki

Ich kannte Modulo nur in Verbindung mit float, werde mir dies aber mal anschauen.

Die jetzige Lösung hat den Vorteil das ich mir für die maximale Pulszahl eine Variable generiere und
für verschiedene Scheibengrößen Werte hinterlege.
Diese werden dann auf 0-3600 gemappt
Bei ganz großen Scheiben gern auch auf 0-36000.

Grüße Brömmel

Modulo und float hat nicht den geringsten Sinn. Modulo ist der Rest einer Division. Dabei geht es immer um ganze Zahlen

@Roki:
Du meinst bei float sicher sowas

  if (Grad >= 360.0) Grad -= 360.0;
  if (Grad < 0.0) Grad += 360.0;

// “in beide Richtungen”

Aber auf float zu verzichten und stattdessen in einem Wertebereich 0 … 3599
(oder sogar [b]uint16_t[/b] x; // 0 .. 35999 ) zu bleiben, ist sicher besser.

Eine uint16_t Modulo-Division ist übrigens “teurer” als zwei if - Abfragen.

@michael_x

Ja, so in der Art..

Grad = x - ganzzahl(x / 360) * 360

..Also einfach ausgedrückt, Modulo! Der Vorteil ist, dass der Tisch auch 20 x drehen kann und noch immer den richtigen Winkel angezeigt

Ps.: Du hast mit uint16_t natürlich recht!! In allen meinen Berechnungen versuche ich bei uint8_t bis uint32_t zu bleiben und verwende gar kein float. Aber das ist eine andere Baustelle :))
Grüße Robert

Der Vorteil ist, dass der Tisch auch 20 x drehen kann und noch immer den richtigen Winkel angezeigt

Stimmt schon, bei sehr sehr großen Überläufen wird irgendwann while (x > 360) x-=360;
zwar nicht von der Code-Größe aber evtl. von der Ausführungszeit langsamer als eine Modulo-Division.
Das sehe ich zwar hier bei diesem Drehtisch-Encoder nicht, aber hier ist es ja eigentlich sowieso egal;)