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_tencode_read4(void)// read four step encoders
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.
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
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!
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.
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).
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.
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?
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_tencode_read4(void)// read four step encoders
2
3
intmain(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_tencode_read1(void)// read single step encoders
2
{
3
int8_tval;
4
5
cli();
6
val=enc_delta;
7
enc_delta=0;
8
sei();
9
returnval;// 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.
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.
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.
Die Lesefunktion wird einfach beim Verlassen der Unterfunktion oder bei
Rückkehr daraus aufgerufen. Nur wird der Rückgabewert nicht verarbeitet,
sondern weggeschmissen.