Forum: Compiler & IDEs Tasterabfrage mit Problemen


von Robert (Gast)


Angehängte Dateien:

Lesenswert?

Hallo an alle!!

Ich bin gerade bei der Implementierung der Eingabe bei benem
Belichtungsgerättimer. Ich hab 3 Taster zu Verfügung: Start, Cursor,
Set. Mit Start strate ich und schalte das Relay ein. Mit Set erhöhe ich
den Timerwert an der aktuellen Cursorposition. Mit Cursor schalte ich
zur nächsten Cursorposition. Doch so weit bin ich noch gar nicht mit
dem Implementieren gg

Als Anhang hab ich meinen aktuellen Softwarestand.

Das Problem ist so. Ich hab eine Interruptroutine. Alle 1s wird der
time Wert decrmentiert wenn diese Timerfunktion aktiviert ist.

Alle 5ms frage ich derzeit mit meiner TAsterabfrage einen Taster ab.
Wenn der Taster gedrückt ist, soll die Zeit wieder auf 10min (= 600s)
zurückgestellt werden.

Doch wenn ich wenn ich auf den Taster drücke, und gedrückt bleibe,
zählt er kurz nach unten und und zeigt dann 10.00 an, die er dann im 1s
takt wieder dekremntiert. Wenn ich den Taster los lasse, dann zeigt er
mir am Display auf einmal 8,34 an die dann bis 8,33 dekremntiert
werden. Danach fängt er wieder bei 10 Minuten an zu dekrementieren.
Wenn ich in der Phase an der 8,34 - 8,33 den Taster drücke und gedrückt
halte, fängt er bei ca 12,50 an sehr sehr schnell zu dekremntiern bis 10
min. Ab dann dekrementiert er wieder im 1sec Takt. Wenn ich den ATster
wieder los lasse, bin ich wieder bei 8,34 und so gehts weiter.

Ich hab echt keinen Plan mehr was da los ist :(

Ich hoffe es kann mir wer helfen

Gruß Robert

von Karl H. (kbuchegg)


Lesenswert?

Wenn ich mir dein Programm mal oberflächlich
anschaue, fällt mir auf:

volatile uint8_t taster_pressed[3] = {NO_TASTER};

Das Array ist mit einer Größe von 3 definiert.

    if(taster_is_set(PINB, PB4, 4) == 1)

Beachte den letzten Parameter im Aufruf: eine 4

int taster_is_set(uint8_t port, uint8_t pin, uint8_t tasterflag)

Was passiert mit tasterflag in dieser Funktion:

  if(taster_pressed[tasterflag]

Oha: tasterflag == 4, aber das Array taster_pressed hat nur 3
Einträge. Du fragst Dinge ab, die gar nicht zu taster_pressed
gehören.

Selbiges hier:

    debounce[tasterflag]--;

Das Array debounce ist so definiert:

volatile uint8_t debounce[3] = {DEBOUNCEWERT};

Also auch wieder nur 3 Elemente. Nur Gott alleine und gcc wissen,
welche Variablen du dir bei einer Zuweisung an debounce[4]
zerschiest.

von Robert (Gast)


Lesenswert?

Hallo Karl

Danke für den Hinweiß. Das funktioniert jetz so halbwegs. NUr mit der
Tasterabfragerotine klappt es leider noch nicht wie es soll. :(

Die Taster sind auf GND geschalten und die interen Pullups des ATTiny
26 sind aktiv.

Mit
1
if(taster_is_set(PINB, PB4, 2) == 5)
2
  time += 10;

frage ich den Taster ab.

Die Abfrageroutine habe ich jetzt noch ein wenig geändert.
1
int taster_is_set(uint8_t port, uint8_t pin, uint8_t tasterflag)
2
{
3
  if(taster_pressed[tasterflag] == TASTER_PRESSED && bit_is_set(port,
4
pin))
5
  {
6
    taster_pressed[tasterflag] = NO_TASTER;
7
    return 1;
8
  }
9
10
  if(bit_is_clear(tasterstatus, tasterflag) && bit_is_clear(port, pin)
11
&& taster_pressed[tasterflag] == NO_TASTER && debounce[tasterflag] !=
12
0)
13
  {
14
    tasterstatus |= (1 << tasterflag);
15
    debounce[tasterflag]--;
16
    return 2;
17
  }
18
  
19
  if(bit_is_set(tasterstatus, tasterflag) && bit_is_clear(port, pin) &&
20
taster_pressed[tasterflag] == NO_TASTER && debounce[tasterflag] != 0)
21
  {
22
    debounce[tasterflag]--;
23
    return 3;
24
  }
25
26
  if(bit_is_set(tasterstatus, tasterflag) && bit_is_set(port, pin) &&
27
taster_pressed[tasterflag] == NO_TASTER && debounce[tasterflag] != 0)
28
  {
29
    tasterstatus &= ~(1 << tasterflag);
30
    debounce[tasterflag] = DEBOUNCEWERT;
31
    return 4;
32
  }
33
  
34
  if(debounce[tasterflag] == 0 && taster_pressed[tasterflag] ==
35
NO_TASTER && bit_is_set(port,pin))
36
  {
37
    taster_pressed[tasterflag] = TASTER_PRESSED;
38
    return 5;
39
  }
40
  return 0;
41
}

In einer ISR (Alle 5ms ein Interrupt) führe frage ich das ganze ab.
Doch leider wenn ich das kompiliere und flashe, zählt er autmatisch
immer die 10 dazu (Ohne Tastendruck). wenn ich auf den TAster drücke,
bleibt der Counter stehen.

Doch nur warum ist denn das so??

HAb jetzt schon seit 2 Stunden an der Funktion herumgespielt, finde
aber nicht die Lösung.

Ich hoffe es kann mir wer helfen

Danke im Voraus

Gruß Robert

von Peter D. (peda)


Lesenswert?

Für mich sieht das nur höllisch kompliziert aus.

Ich würde das Ganze einfach mit ner Statemaschine machen.

Ein Beispiel dafür findest Du hier, wobei noch zwischen kurz und lang
Drücken unterschieden wird:

http://www.mikrocontroller.net/forum/read-4-405548.html#new


Die Haupt-States sind für 2 Tasten + kurz/lang immer in 5-er Abständen,
bei 3 Tasten müßten sie dann um 7 auseinander liegen.

Da unter AVR-GCC Statemachines eh 16-Bittig sind, könnte man auch 256
Haupt-States + 6 Tastenevents (0..6) nehmen, wenns umfangreicher wird.


Peter

von Karl H. (kbuchegg)


Lesenswert?

> Für mich sieht das nur höllisch kompliziert aus.

Sehe ich auch so.

> Ich hoffe es kann mir wer helfen

Warum spielst du das ganze nicht mal im Debugger durch?

von Robert Schilling (Gast)


Lesenswert?

Hallo an alle

Ja das ist wirklich ein bisschen kompliziert ;)

ICh hab nun einmal deine Tastenroutine genommen Peter.

Doch leider funktioniert noch nicht alles ganz zuverlässig. Am Auslesen
des EEproms happerts noch einbisschen.

Und was mir noch aufgefallen ist, wenn ich KEY0 gedrückt halte, dann
zählt er viel langsamer die Variable time herunter als wenn ich KEY1
gedrückt halte und er nach oben zählt.

Warum ist denn das so??

Ich hoffe es kann mir helfen

Gruß Robert

von Robert Schilling (Gast)


Angehängte Dateien:

Lesenswert?

Hab den Anhang vergessen

von Peter D. (peda)


Lesenswert?

Ich würd noch mehr aus dem Interrupt rausnehmen.

Du hast allein schon 12 Divisionen drin und nur 1ms Zeit (Divisionen
sind das teuerste).

Du machst viel zu viel, viel zu oft.

Sachen, die nicht oft gemacht werden müssen, lieber im Main.
Wenn Du mal mein Programm ansiehst, ich setze nur ein 1-Sekunden-Flag
und zähle dann im Main die Zeit.


Es könnte sogar sein, daß dann im Main Sachen noch öfter gemacht
werden, aber dort hast du alle Zeit der Welt dazu, d.h. es wird nichts
behindert.


Peter

von Robert Schilling (Gast)


Lesenswert?

Hallo Peter

Ich hab mal eine Frage zu Ansi C:
1
  if( --sec_timer == 0 ){
2
    one_second = 1;
3
    sec_timer = INTTIME;
4
    if( --corrector == 0 ){    // correction n / 256
5
      sec_timer = (XTAL - 255UL * 8 * INTTIME + 4) / 8;
6
    }
7
  }

BEim dekremntien im if Statement, wird da geprüft ob sec_timer - 1 == 0
oder dekremntiert er und prüft dann. Beim nächsten mal dekremntiert er
wieder um eins und prüft dann??

Was würdest du aus der ISR rausschmeissen??

Gruß Robert

von Robert Schilling (Gast)


Lesenswert?

So hab nun die ganzen time2display() Funktionen in die main verlagert.

Eigentlich läuft alles jetzt sehr zuverlässig.

Einen Schönheitsfehler hat das Programm aber noch. Das Inkrementieren
bei gedrückter Taste geht viel schneller als das Dekrementieren.

Woran kann das liegen???

Gruß Robert

von Karl heinz B. (kbucheg)


Lesenswert?

j = ++i;   // j ist identisch zu i + 1
  j = i++;   // j ist identisch zu i

In beiden Fällen ist aber nach der kompletten Anweisung:
  i = i + 1
Wann diese Änderung an i allerdings tatsächlich durchgeführt
wird, ist undefiniert. Sie muss erst bei 'Abarbeitung des ;'
durchgeführt worden sein. (In C-speak: ; markiert einen
Sequenz-Punkt, engl. sequence point. Und erst wenn dieser
erreicht wird, muss dieser Nebeneffekt des Erhöhens abgeschlossen
sein.)

  ++i    : erhöhe i, das Ergebnis mit dem weitergerechnet wird
           ist i + 1

  i++    : erhöhe i, das Ergebnis mit dem weitergerechnet wird
           ist i.

Sinngemäs gilt gleiches für --

von Robert Schilling (Gast)


Lesenswert?

Danke.

Jetzt funktionioniert fast alles.

Ein Problem hab ich noch.

Das inkrementieren geht viel schneller als das dekrementieren.

Warum ist das so???

Gruß Robert

von Karl heinz B. (kbucheg)


Lesenswert?

Das kann ich dir nicht sagen.
So beim drüberlesen ist mir eigentlich nichts aufgefallen.
Da wirst du wohl oder übel selbst mit einem Debugger
reinschauen müssen was da passiert.

von Robert Schilling (Gast)


Lesenswert?

Meinst du den Debugger von AvrStudio??? Das funktioniert bei mir leider
nicht. Das versteh ich nicht. Projekt kann ich ein neues erstellen,
aber beim kompilieren hängt er sich auf. Er hängt sich auch auf, wenn
ich ein erstellt Projekt öffne. Was ist den da los?? (Hab WinXP Prof +
SP1).

Wie funktioniert eigenlich der Debugger?? Gibts da ein Tutorial?

Gruß Robert

von Karl H. (kbuchegg)


Lesenswert?

> Das funktioniert bei mir leider nicht.

Das ist schlecht. Das solltest du unbedingt in den Griff
kriegen. Du verzichtest sonst auf ein mächtiges Werkzeug.

> Was ist den da los??
Hast auch sicher die letzten Versionen + Avr-Studio Service Packs
installiert?

> Wie funktioniert eigenlich der Debugger??
Dein Programm läuft unter der Kontrolle des Debuggers.
Du kannst das Programm Schritt für Schritt durchgehen lassen
oder du kannst Breakpoints setzen (der Programmablauf wird
dann angehalten, wenn diese Anweisung abgearbeitet wird), du
kannst Variablen anschauen, neue Werte zuweisen, du kannst
den Speicher direkt überwachen, die kannst Port-Stati life
anschauen (und auch ändern), siehst wie der Timer hochzählt
usw.

Die Bedienung ist eigentlich ziemlich einfach: Ist alles in
einem Menü zusammengefasst, bzw. die I/O Ansicht ist als
Tree organisiert.

Wie gesagt: Du verzichtest auf ein mächtiges Werkzeug.
Auf einem PC war das Fehlen eines Debuggers zu verschmerzen, da
konnte man sich mit printf() behelfen, aber auf einem µC geht
das meist nicht.

von Robert S. (razer6)


Lesenswert?

So ich hab es jetzt hin bekommen. Ich hab mir noch das SP3
heruntergeladen und installiert :)

Ein bisschen verstehe ich das schon mit dem Debugger. Wie die I/O
Register und die Timer Register gesetzt werden sehe ich schon. Jedoch
das hilft mir ja nichts.

Die Werte der von mir angelegten Variablen she ich jar nicht.

Wie kann ich das sinnvoll beobachten was da passiert??

Gruß Robert

von Karl heinz B. (kbucheg)


Lesenswert?

Mittels F10 oder F11 gehst du immer einen Schritt weiter.
F10: Ist der Schritt ein Funktionsaufruf so wird die Funktion
     ausgeführt, und der Debugger meldet sich wieder wenn
     die Funktion returned
F11: Ist der Schritt ein Funktionsaufruf, denn erfolgt der Schritt
     in die Funktion hinein und du kannst auch durch die Funktion
     reinschreiten

F9:  Setzt einen Breakpoint in die Zeile, in die der Cursor ist.
     Wenn du das Programm für sich laufen lässt, so meldet sich
     der Debugger wieder, wenn diese Zeile erreicht wird.
     Das ist besonders bei ISR interessant: Sobald aus irgendeinem
     Grund die ISR aufgerufen wird, wird der Breakpoint ausgelöst.
     Auch dann wenn du eigentlich an einer ganz anderen Stelle
     mittels F10 oder F11 durchstepst.

Um den Inhalt einer Variablen zu sehen, fahr einfach mit der
Maus auf den Variablennamen (egal wo). Im Tooltip wird dir
dann der Wert der Variablen angezeigt. Bei Strukturen oder
wenn du eine Variable öfter anschauen willst, ist es oft
besser so zu verfahren: Maus auf den Variablenname.
Rechte Maustaste. Im Kontextmenue den Punkt 'Add Watch' auswählen.
Im AVR-Studio sollte unten ein Fenster sein, dass den Titel 'Watch'
trägt. Dort taucht jetzt die Variable mitsamt ihrem Wert auf.
Steppst du weiter durch den Code, so wird dieses Fenster mit
den sich verändernden Werten der Variable upgedated.

Soweit das Wichtigste in Kürze.

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.