Forum: Mikrocontroller und Digitale Elektronik Drehencoder-Funktion partiell deaktivieren?


von Michael (Gast)


Lesenswert?

Hallo zusammen,

ich verwende für eine einfache Menüstruktur die untenstehende 
Standardfunktion zur Auslesung eines Drehencoders.
Funktioniert grundsätzlich alles super, allerdings habe ich das Problem, 
dass die Drehencoderfunktion in einem Untermenü deaktiviert sein müsste.
Da gibt es nämlich nichts mehr zum Auswählen. Wenn man das Drehrad aber 
weiter dreht, dann zählt der Code die Ausgabe weiter hoch oder zurück, 
und wenn ich aus dem Untermenü wieder rausgehe, hat sich dann der Wert 
verändert, was ich nicht will.

Wie "deaktiviert" man denn denn diese Funktion für einen gewissen 
Codeabschnitt?
Ich dachte, das geht mit "cli" und "sei", das ändert aber nichts.

Weiß hier vielleicht jmd. Bescheid, wie das funktionieren könnte?

Danke schon mal!

Michael

1
int8_t encode_read4( void )      // read four step encoders
2
{
3
  int8_t val;
4
5
  cli();
6
  val = enc_delta;
7
  enc_delta &= 3;
8
  sei();
9
  return val >> 2;
10
}
11
12
int main( void )
13
{
14
  int32_t val = 0;
15
16
  LEDS_DDR = 0xFF;
17
  encode_init();
18
  sei();
19
20
  for(;;){
21
    val += encode_read1();      // read a single step encoder
22
    LEDS = val;
23
  }
24
}

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Du könntest enc_delta auf 0 setzen, denn hier werden die Drehgeberwerte 
akkumuliert.
Aber du kannst im Untermenü auch auslesen und das Ergebnis verwerfen.

von Falk B. (falk)


Lesenswert?

Michael schrieb:
> Problem,
> dass die Drehencoderfunktion in einem Untermenü deaktiviert sein müsste.
> Da gibt es nämlich nichts mehr zum Auswählen. Wenn man das Drehrad aber
> weiter dreht, dann zählt der Code die Ausgabe weiter hoch oder zurück,
> und wenn ich aus dem Untermenü wieder rausgehe, hat sich dann der Wert
> verändert, was ich nicht will.

Na dann muss man es halt so programmieren, daß das nicht passiert. Da 
macht man NICHT, indem man Interrupts sperrt oder an der Ausleseroutine 
rumfummelt, sondern indem man die Auswertung der Drehbewegung 
menugesteuert vornimmt.

Stark vereinfacht
1
if (!menu_sub) {
2
  // Encoder auswerten
3
}

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Michael schrieb:
> Wenn man das Drehrad aber weiter dreht, dann zählt der Code die Ausgabe
> weiter hoch oder zurück, und wenn ich aus dem Untermenü wieder rausgehe,
> hat sich dann der Wert verändert, was ich nicht will.
Es ist eigentlich voll einfach: du musst diesen Programmfehler eben 
noch beheben. Diesen Vorgang nennt man "Programmieren".

> Weiß hier vielleicht jmd. Bescheid, wie das funktionieren könnte?
In diesem Code ist kein Menü oder soanstwas.
Aber hier könntest du sowas machen:
Du könntest da sowas "probieren":
1
   if (Menue != InDiesemMenueDarfNichtGezaehltWerden) val += encode_read1(); // read a single step encoder

BTW:
Bitte den Text über jeder Eingabebox beachten!
1
Antwort schreiben
2
Wichtige Regeln - erst lesen, dann posten!
3
    :
4
    :
5
Formatierung (mehr Informationen...)
6
    [c]C-Code[/c]

von Michael (Gast)


Lesenswert?

Danke für die schnelle Antworten.

Im entsprechenden Untermenü lese ich den Wert aber gar nicht aus, also 
im Codebeispiel überschreibe ich "val" gar nicht, d.h. ich kann ichn ja 
auch nicht verwerfen. Sobald ich aus der Untermenüschleife rausgeh, hat 
sich dann der Wert aber schon ggf.verändert.

von Michael (Gast)


Lesenswert?

Lothar M. schrieb:
> BTW:
> Bitte den Text über jeder Eingabebox beachten!

Entschuldige, das nächste mal achte ich drauf.

von Michael B. (laberkopp)


Lesenswert?

Michael schrieb:
> Wenn man das Drehrad aber
> weiter dreht, dann zählt der Code die Ausgabe weiter hoch oder zurück,
> und wenn ich aus dem Untermenü wieder rausgehe, hat sich dann der Wert
> verändert, was ich nicht will.

Eintritt ins Untermenü: oldval=val;

Austritt aus dem Untermenü, wieder ins Hauptmenü: val=oldval;

Michael schrieb:
> Ich dachte, das geht mit "cli" und "sei", das ändert aber nichts.

Immer eine doofe Idee, denn damit sperrst du alle Interrupts, nicht nur 
die, die den Drehencoder auswerten (hoffentlich ein Timerinterrupt).

von Axel S. (a-za-z0-9)


Lesenswert?

Michael schrieb:

> Im entsprechenden Untermenü lese ich den Wert aber gar nicht aus

Ja. Und das ist der Fehler. Lies den Encoder-Wert aus und verwirf ihn. 
Spätestens beim Verlassen dieses Menüs.

von Michael (Gast)


Lesenswert?

Axel S. schrieb:
> Ja. Und das ist der Fehler. Lies den Encoder-Wert aus und verwirf ihn.
> Spätestens beim Verlassen dieses Menüs.

Ich muss den veränderten Wert mit Ursprungswert verrechnen, oder?
Ob ich ihn verwerfe oder gar nicht auslese, ist doch das selbe, oder?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Michael schrieb:
> Ob ich ihn verwerfe oder gar nicht auslese, ist doch das selbe, oder?
Kommt auf den Code an.

Übrigens ist der von dir gepostete Code zur Fehlersuche nicht hilfreich:
1
int8_t encode_read4( void )      // read four step encoders
2
3
int main( void )
4
{
5
:
6
    val += encode_read1();      // read a single step encoder

Und falls der Code, den du tatsächlich verwendest, so aussieht:
1
int8_t encode_read1( void )         // read single step encoders
2
{
3
  int8_t val;
4
 
5
  cli();
6
  val = enc_delta;
7
  enc_delta = 0;
8
  sei();
9
  return val;                   // counts since last call
10
}
dann stell dir mal vor, was bei enc_delta=0; passieren könnte.

> Ob ich ihn verwerfe oder gar nicht auslese, ist doch das selbe, oder?
Ich würde es einfach mal ausprobieren, wenn ich es nicht kapieren kann 
oder will.

Beitrag #6460860 wurde von einem Moderator gelöscht.
von Axel S. (a-za-z0-9)


Lesenswert?

Michael schrieb:
> Axel S. schrieb:
>> Ja. Und das ist der Fehler. Lies den Encoder-Wert aus und verwirf ihn.
>> Spätestens beim Verlassen dieses Menüs.
>
> Ich muss den veränderten Wert mit Ursprungswert verrechnen, oder?

Kommt auf den Code an. Aber gezeigt hast du
1
  //...
2
  val += encode_read1();
3
  //...

Hier liest du den Encoder-Wert durch den Aufruf von encode_read1() aus. 
Und gleichzeitig verwendest du den Wert, um die Variable val 
hochzuzählen. Was du in diesem speziellen Untermenü tun sollst, ist die 
Funktion aufzurufen und den Rückgabewert einfach nicht zu verwenden.

> Ob ich ihn verwerfe oder gar nicht auslese, ist doch das selbe, oder?

Natürlich nicht. Der Encoder wird ja im Interrupt ausgelesen und der 
Wert in der Variable enc_delta abgelegt. Beim Auslesen wird enc_delta 
zurück auf 0 gesetzt (zumindest bei 1-Schritt Auswertung). Und genau 
dieses auf-Null-setzen willst du haben. Spätestens wenn das Menü 
verlassen wird (weil innerhalb des Menüs ist es ja egal, ob und wieviel 
am Encoder gedreht wird). Jetzt könntest du theoretisch eine extra 
Funktion dafür schreiben. Einfacher ist es, die schon vorhandene 
Funktion zu benutzen.

von W.S. (Gast)


Lesenswert?

Michael schrieb:
> ich verwende für eine einfache Menüstruktur die untenstehende
> Standardfunktion zur Auslesung eines Drehencoders.
> Funktioniert grundsätzlich alles super, allerdings habe ich das Problem,
> dass...

..es eben doch nicht "super" funktioniert.
Das kommt davon, daß du dir beim Erfinden deines Menüs eben nicht 
wirklich genug Gedanken gemacht hast.

Du solltest die Dinge trennen: den Treiber für den Drehgeber einerseits 
und das Menü andererseits. Aus dem Treiber sollten schlichtweg 
Botschaften sprich "events" herauskommen. Also etwa so: event_links, 
event_rechts, event_Taste. Und die landen in einer Event-Warteschlange, 
von wo aus sie in der Grundschleife herausgeholt und dem Menü in den 
Rachen geworfen werden.

So ein simples Menü seinerseits hat üblicherweise ja im Grunde 2 
Zustände: Manövrieren und Editieren (das sieht bei anspruchsvolleren 
Menüs anders aus). Also wenn es im Zustand Manövrieren ist, dann sollte 
das Drehen einen Wechsel des aktuell fokussierten Menü-Eintrages 
bewirken.
Also z.B. UHR-DATUM-SPRACHE-ORT-UNTERMENÜ-DIES-DAS-JENES hin und zurück 
oder Karussell. Und im Untermenü gibt es dann 
ZURÜCK-UNTERPUNKT1-UNTERPUNKT2 und so weiter.

Im Zustand Editieren bleibt es beim fokussierten Eintrag, aber dieser 
ändert dann den Wert, zu dem er gehört.

Du brauchst in deinem Untermenü ja bloß die zugehörigen Handler 
entsprechend zu schreiben, so daß die Uhr nicht höher als 23.59 und 
nicht tiefer als 00.00 gestellt werden kann.

Und das gilt entsprechend für alle Menüpunkte. Dein Problem ist nicht 
der Drehgeber, sondern das Fehlen einer wohldurchdachten Funktionalität 
in deinem Menü.

W.S.

von Peter D. (peda)


Lesenswert?

Die Lesefunktion wird einfach beim Verlassen der Unterfunktion oder bei 
Rückkehr daraus aufgerufen. Nur wird der Rückgabewert nicht verarbeitet, 
sondern weggeschmissen.

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.