Forum: PC-Programmierung ESP32-Variable in ihrem Wertebereich beschränken


von Alex (suda_721)


Lesenswert?

Moin,
ich weiß, dass es verschiedene Datentypen gibt. Ich möchte auf meinem 
i2c-Display eine Variable ausgeben und diese mit zwei Buttons hoch und 
runter einstellen. Buttoon-Programmierung alles kein Problem.
Ich möchte das meine Variable x nur von 0 bis z.B. 5 geht und wenn ich 
+1 oder -1 gehe, diese nur von o bis 5 geht.

Wie kann ich in Arduino diese Variable durchgängig überprüfen lassen, 
sodass bspw. bei "unsigned char x" (Wertebereich bekannt von 0 bis 255) 
und x=0 ist, die Anzeige auf dem Display beim Schritt von x=0 nach x=5 
(also -1 gehe) nicht auf dem Display dann 255 kurz anzeigt.
Danke!

von cppbert (Gast)


Lesenswert?

Alex schrieb:
> Moin,
> ich weiß, dass es verschiedene Datentypen gibt. Ich möchte auf meinem
> i2c-Display eine Variable ausgeben und diese mit zwei Buttons hoch und
> runter einstellen. Buttoon-Programmierung alles kein Problem.
> Ich möchte das meine Variable x nur von 0 bis z.B. 5 geht und wenn ich
> +1 oder -1 gehe, diese nur von o bis 5 geht.
>
> Wie kann ich in Arduino diese Variable durchgängig überprüfen lassen,
> sodass bspw. bei "unsigned char x" (Wertebereich bekannt von 0 bis 255)
> und x=0 ist, die Anzeige auf dem Display beim Schritt von x=0 nach x=5
> (also -1 gehe) nicht auf dem Display dann 255 kurz anzeigt.
> Danke!

du machst eine funktion für rauf() und eine für runter() in der du das 
prüft und die Variable sonst nicht direkt angreifst - das ist der 
korrekte Weg

von Alex (suda_721)


Lesenswert?

hättest du ein beispiel.Ich bin da etwas neu und möchte es verstehen und 
lernen

von Helmut -. (dc3yc)


Lesenswert?

Dazu gibt es die Modulo-Funktion. Google weiß da mehr darüber!

von Dieter (Gast)


Lesenswert?

```
counter = 2;
counter_min = 0;
counter_max = 5;

hochzaehlen(){
  counter++;
  if (counter > counter_max)
    counter = counter_max;
}

runterzaehlen(){
  counter--;
  if (counter < counter_min)
    counter = counter_min;
}

...

if (btn_pressed){
  hochzaehlen()
}

```

von Dieter (Gast)


Lesenswert?

Helmut -. schrieb:
> Modulo-Funktion

Bring mal ein Beispiel bitte, damit ist m.E. die Anforderung nicht 
umsetzbar...

von Rolf M. (rmagnus)


Lesenswert?

Helmut -. schrieb:
> Dazu gibt es die Modulo-Funktion. Google weiß da mehr darüber!

Das wird hier nicht funktionieren.

Dieter schrieb:
> runterzaehlen(){
>   counter--;
>   if (counter < counter_min)
>     counter = counter_min;
> }

Dazu muss für ein Minimum von 0 die Variable allerdings 
vorzeichenbehaftet sein. Außerdem fehlt der wrap-around. Wenn man es so 
schreibt, geht's auch vorzeichenlos und mit wrap-around:
1
runterzaehlen()
2
{
3
    if (counter > counter_min)
4
        counter--;
5
    else
6
        counter = counter_max;
7
}

: Bearbeitet durch User
von Stefan S. (chiefeinherjar)


Lesenswert?

Dieter schrieb:
> runterzaehlen(){
>   counter--;
>   if (counter < counter_min)
>     counter = counter_min;
> }

Würde das nicht einen Überlauf verursachen?

Wenn die Funktion aufgerufen wird und Counter bereits 0 ist, wird 
trotzdem weiter munter dekrementiert. Das heißt aus 0 wird 255.

Ich würde es so lösen:
Erst prüfen, welche Taste gedrückt wurde. Wenn die Taste für 'runter' 
gedrückt wurde, prüfen, ob counter > 0 ist. Wenn ja, counter 
dekrementieren. Wenn nicht, dann counter auf 5 setzen.

Beim hochzählen genau umgekehrt: Ist counter < 5? Wenn ja, dann 
inkrementiere counter ansonsten setze Counter auf 0.

Edit: Ich sehe gerade, Rolf war schneller :)

: Bearbeitet durch User
von Helmut -. (dc3yc)


Lesenswert?

Mit Modulo gehts immer, bis auf den Sonderfall, wenn die Variable 0 ist 
und "runter" gedrückt wird. Dann müsste auf den Modulowert-1 gesetzt 
werden. Die Variable muss dann aber auch unsigned sein.
Bei signed geht's immer, denn -1 mod 6 ist 5. Und 6 mod 6 ist 0.

von Rolf M. (rmagnus)


Lesenswert?

Allerdings ist auf einem µC in aller Regel ein Modulo deutlich 
aufwändiger als eine Verzweigung.

von Helmut -. (dc3yc)


Lesenswert?

Rolf M. schrieb:
> Allerdings ist auf einem µC in aller Regel ein Modulo deutlich
> aufwändiger als eine Verzweigung.

Also in C ist Modulo nur "%".

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

... so z.B.
1
#define mMax(a, b) ({typeof(a) _a= (a); typeof(_b)= (b); (_a > _b)? _a : _b;}) 
2
#define mMin(a, b) ({typeof(a) _a= (a); typeof(_b)= (b); (_a > _b)? _b : _a;})
3
#define mClamp(x, hi, lo) mMin(hi, mMax(lo, x))
4
#define mConstrain mClamp
ODER simple vom Arduino Framework
https://www.arduino.cc/reference/en/language/functions/math/constrain/

Alex schrieb:
> ich weiß, dass es verschiedene Datentypen gibt

Lern mal lesen, selbständig arbeiten und nicht nur immer doof rumfragen!
Und das reflexartig Ahnungslose hier dann rumsülzen ist fast noch 
schlimmer!

: Bearbeitet durch User
von Εrnst B. (ernst)


Lesenswert?

Wenn's wg. Arduino eh schon C++ ist:
1
template <typename T, T Tmin, T Tmax> class LimitierterWert {
2
  public:
3
    typedef T value_type;
4
    operator T const& () const { return myValue; }
5
    LimitierterWert& operator= (T const& val) {
6
         if (val<Tmin) myValue=Tmin;
7
         else if (val>Tmax) myValue=Tmax;
8
         else myValue=val;
9
         return *this;
10
    }
11
    ... operator++, operator--, Konstruktor usw.
12
  private:
13
    value_type myValue;
14
};
15
16
LimitierterWert<int8_t, -5, 5> counter;
17
18
...

usw.
Schaut erstmal schlimm aus, der Compiler optimiert das aber alles gut 
zusammen.

von Da Baby [reformed] (Gast)


Lesenswert?

Warum muss man jeden scheiss in eine klasse döddeln?

von Εrnst B. (ernst)


Lesenswert?

Da Baby [reformed] schrieb:
> Warum muss man jeden scheiss in eine klasse döddeln?

Es ist nicht nur eine Klasse, es sind fast beliebig viele, für jeden 
Basis-Datentyp und jede mögliche Limit-Konfiguration ist's eine.

Warum? Weil's schön wiederverwendbar ist. Die Template-Definition 
wandert in ein Header-File und muss dich später nicht mehr stören.

Es braucht auch nicht mehr RAM als die nackte Variable die dahinter 
steckt, und die Range-Checks übersetzt der Compiler auch nicht anders 
als in der Makro-Variante.

von Rolf M. (rmagnus)


Lesenswert?

Da Baby [reformed] schrieb:
> Warum muss man jeden scheiss in eine klasse döddeln?

Warum nicht? Wie würdest du in C++ sowas wie einen Integertyp mit 
vorgegebenem Wertebereich umsetzen, wenn nicht als Klasse?

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Du machst eine eigene Funktion, z.B. mit den Namen "limit". Dieser 
übergibst du den Eingangswert und den oberen und unteren Grenzwert.

integer limit(integer inp, integer upper, integer under)
{
   integer intern = inp;
   if intern > upper then intern = upper;
   if intern < under then intern = under;
   return intern;
}

von Rolf M. (rmagnus)


Lesenswert?

Frank E. schrieb:
> Du machst eine eigene Funktion, z.B. mit den Namen "limit". Dieser
> übergibst du den Eingangswert und den oberen und unteren Grenzwert.

Die musst du dann aber nach jeder Operation, die den Wert ändert, 
explizit aufrufen. Die Klasse kannst du einfach wie einen normalen 
Integer verwenden, und sie kümmert sich automatisch darum.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.