Forum: Mikrocontroller und Digitale Elektronik Controllerprobleme / Programm Atmega 8, WTV020


von Philipp (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Zusammen,

ich habe ein Programm geschrieben, welches eine Stoppuhr in Verbindung 
mit dem WTV020 Sound Modul umsetzten soll. (zum Teil aus dem Internet 
zusammenkopiert und angepasst)
Durch drücken des Start Tasters soll auf dem WTV020 eine Sounddatei 
abgespielt werden. Nach einer bestimmten Zeit (wenn in der Sounddatei 
der Startbefehl ertönt) soll die Stoppuhr wieder auf 0 gesetzt werden, 
da erst ab dem Zeitpunkt gezählt werden soll.
Durch einen Stopptaster soll die Zeitnahme gestoppt werden.
Die Zeit wird ständig über multiplexen auf einer 4x7 Segment Anzeige 
dargestellt.

Mein Problem ist, dass die Zeitnahme, sowie das zurücksetzten nach der 
Zeit x und auch die Anzeige nicht immer funktionieren.
Manchmal funktioniert alles. Manchmal kommt es aber auch vor, dass die 
angezeigte Zeit hin und her springt oder manchmal nur noch ein Ziffer 
auf den 4 Anzeigen zu sehen ist. Außerdem startet der Timer manchmal, 
ohne dass ich auf einen Taster gedrückt habe oder der Stopptaster 
reagiert nicht, obwohl ich vorher auf Start gedrückt habe und den 
Stopptaster auch lange genug gedrückt habe.

Mein Programm habe ich in den Anhang gepackt.

Ich hoffe mir kann irgendwer weiter helfen, da ich hier aktuell sehr am 
verzweifeln bin.

: Verschoben durch User
von void (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Philipp.

Das ist spannend. Du hast nur 5 Anforderungen und doch 9 beschriebene 
Fehler. Wo soll man da anfangen... Na vielleicht mit einem Code Review.

  >1) Durch drücken des Start Tasters soll Sounddatei abgespielt werden.
  >4) Durch einen Stoptaster soll die Zeitnahme gestoppt werden.

Bei beiden Taster-Drücken (start und stop) entprellst du den Taster 
nicht.
  zeile 122: if(!(PINB & (1<<PINB2)) && lauf == 0)    //Start
  zeile 144: if(!(PINB & (1<<PINB1))  && lauf == 1)    // Stopp

Das ergibt beispielhaft dieses Problem: "Außerdem (...), ohne dass ich 
auf einen Taster gedrückt habe."


  > 2) Nach einer bestimmten Zeit (wenn in der Sounddatei der 
Startbefehl ertönt)
  > soll die Stoppuhr wieder auf 0 gesetzt werden,

Warum läuft die Stoppuhr überhaupt? Sie sollte bis hierher noch gar 
nicht gestartet sein.
Sprich: Warum startest du das zählen der Stoppuhr nicht erst hier indem 
du den Timer2 erst hier einschaltest und wenn stopp gedrückt wurde 
wieder Timer2 abschaltest?
Die Antwort findet sich wohl in der bestimmten Zeit; Du möchtest zwei 
mal zählen. (Das erste Mal bis 18800.)

Später stoppst du dann den Timer2 doch. Wie wäre es zwecks Lesbarkeit 
zwei Funktionen zur Timer2 Stoppuhr einzuführen?
Wie wäre es mit:
- Timer2_Stopuhr_Start() und
- Timer2_Stopuhr_Stop()
Und dann noch Timer2_Stopuhr_Init() weils so schön ist. Und gleich 
sinnvoller Klingt als interrupt_init().


  > 3) da erst ab dem Zeitpunkt gezählt werden soll.

In der Timer2 ISR hast du eine korrekte Zählerlogik gebaut. (Wenn auch 
du zaehler[0] nicht verwendet hast.)
Später rechnest du dann aber von zaehler[] auf zeiger[] für die Anzeige 
um, indem du die ganzen Werte einfach umkopierst. 
(zeiger[1]=zaehler[1]; usw.)

Hier wäre es aber angebracht zwischen der Abstraktion der Darstellung 
für die Anzeige (zeiger[]) und der Darstellung des eigentlichen Zählens 
[zaehler[]) zu unterscheiden.
Dann muss man auch nicht so umständlich die Zeit des startbefehls 
(18800) abfragen, wie du es machst:

  zeile 8: if(zaehler[5] >= 1 && zaehler[4] >= 8 && zaehler[3] >= 8 && 
sound == 1){

So sähe das doch gleich viel einfacher aus:
  if (zaehler >=18800)

Dafür müsstest du dann zaehler passend für die Anzeige (zeiger[]) 
umrechnen.
Kleine Hilfe:
  zeiger[5] = zaehler / 10000;
  usw.


  >5) Die Zeit wird ständig über multiplexen auf einer 4x7 Segment 
Anzeige dargestellt.

Das Multiplexing sieht sauber aus.
Außer: sei(), cli() mitten im Program-Lauf (start taster). Das 
unterbricht dein Multiplexing für eine ganze Weile, weil du dazwischen 
mal eben _delay_ms() aufrufst.


  int Nummer;
Dann noch "Nummer". Diese Variable veränderst du in einer ISR. Sollte 
also auch volatile sein. Genau genommen benötigst du die Variable nur in 
der ISR. Dann kann sie auch direkt da rein. (static int Nummer = 5; 
Damit sie nur einmal initialisiert wird.)

  int adresse[6];
adresse[] wird garnicht verwendet. Hinfort damit.


Sieht gleich viel aufgeräumter aus. Die editierte main.c ist im Anhang. 
(ungetestet)
Nächste Schritte für dich: Funktion sendCommand() aufräumen, 
systematisch die nächsten Probleme angehen und nicht verzweifeln. ;-)

von Philipp (Gast)


Lesenswert?

Vielen Dank für deine schnelle Antwort,

ich habe deine Anpassungen mal getestet. Leider treten die Probleme 
immer noch auf.

Ich habe mir jetzt aber mal die Hardware angeschaut. Es scheint so als 
ob der Quarz nicht richtig funktioniert hat. Nachdem ich den 
ausgetauscht habe hat alles funktioniert.

von void (Gast)


Lesenswert?

Philipp schrieb:
> Vielen Dank für deine schnelle Antwort,

Gerne.

Nach deiner Problembeschreibung hätte ich nicht einen Fehler des Quarzes 
vermutet. Aber wenn es jetzt geht ist doch toll.

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.