Coundown Timer

OP #6801590
Lesenswert?


Guten Abend,

Ich versuche einen Countdown Timer mit einer 4 x 7 Segment Anzeige zu 
machen. Nachfolgend ist auch meine C datei und meine H datei.

Nach dem Code soll auf meiner Segment anzeige von 1min 23sec. herunter 
gezählt werden.

allerdings leuchten alle Ziffern der Segmentanzeige kontinuierlich und 
ich komme nicht drauf warum.

könnte mir bitte jemand mal meinen Code anschauen und mir sagen was ich 
hier falsch mache ?

hier main.c
1
// Count down timer with 4 x 7 digit LED display
2

3
#define F_CPU    8000000
4

5
#include <avr/io.h>
6
#include <util/delay.h>
7
#include <avr/interrupt.h>
8
#include "LED_display.h"
9

10
int main()
11
{  initialize_LED_display();
12
  uint8_t minutes = 1;
13
  uint8_t seconds = 23;
14
  
15
  while ((minutes > 0) | (seconds > 0))      // Countdown until 00:00
16
  {  number_output (minutes*100+seconds);
17
    _delay_ms (1000);
18
    if (seconds == 0)
19
    {  seconds = 60; minutes--;
20
    }
21
    seconds--;
22
  }
23

24
  number_output (0);    // display 00:00 for 5 seconds
25
  _delay_ms (5000);
26

27
  while (1)      // display blinking 00:00 for ever
28
  {  number_output (0);
29
    cli();          // switch off interrupts for blank display
30
    PORTC = 0b00001111; _delay_ms (500);
31
    sei(); _delay_ms (200);      // switch on interrupts for 00:00 display
32
  }
33

34
  return 0;
35
}

hier LED_display.h
1
 // 4 x 7 digit LED display control
2

3
// seven segment codes
4
const int8_t numbers [10] = {20, 215, 76, 69, 135, 37, 36, 87, 4, 5}; 
5

6
volatile uint8_t Digit_X000, Digit_0X00, Digit_00X0, Digit_000X;  // store single digits
7
volatile uint8_t active_digit = 0;                  // active digit
8

9
void initialize_LED_display()
10
{  DDRD = 0b11111111;  
11
  DDRC = 0b00001111;  
12
  OCR1A = 8;        // load compare value for 1 ms repetition time
13
  TIMSK |= (1 << OCIE1A);             // interrupt if compare match
14
  TCCR1B = (1<<CS12) | (1<<CS10) | (1<<WGM12);  // div 1024 & clear counter on compare match
15
  sei();
16
}
17

18
// Write number at indicated position to display
19
void digit (uint8_t value, uint8_t pin)
20
{  PORTD = numbers[value];  // send number to output
21
  PORTC &= ~(1 << pin);  // PinLow => current digit on
22
}
23

24
// distribute number to digits
25
void number_output (uint16_t number)       
26
{  Digit_X000 = number/1000; number %= 1000;
27
  Digit_0X00 = number/100;  number %= 100;
28
  Digit_00X0 = number/10;    number %= 10;
29
  Digit_000X = number;    
30
}
31

32
ISR (SIG_OUTPUT_COMPARE1A)  
33
{  PORTC = 0b00001111;     // Digits off
34
  if(active_digit == 0) digit (Digit_000X, PC0);
35
  if(active_digit == 1) digit (Digit_00X0, PC1);
36
  if(active_digit == 2) digit (Digit_0X00, PC2);
37
  if(active_digit == 3) digit (Digit_X000, PC3);
38
  
39
  active_digit ++; if (active_digit == 4) active_digit = 0;
40
  
41
}
Gast #6801615
Lesenswert?

Michael H. schrieb:
> könnte mir bitte jemand mal meinen Code anschauen und mir sagen was ich
> hier falsch mache ?

- Auf jeden Fall plenkst du
- und du verwendet Programmcode in einer *.h-Datei

beides ist scheisse. Das ist noch nicht das eigentliche
Problem.

Und vermutlich ist der Code irgendwo hergeholt und du hast
selbst keine Ahnung vom Programmieren, sonst wüsstest du wo
du zu suchen hast.

Grübel ....
Ach jetzt seh ich es. Michael Huber .... da gab es schon vor
einigen Monaten skurrile Threads wo jemand sehr schwer von
Begriff war.

Kommt immer wieder. Und täglich grüsst das Murmeltier.
Gast #6801629
Lesenswert?

Natürlich ist der Code irgendwo hergeholt.

Die Suche nach Programminhalten ergibt z.B.

https://www.edv-buchversand.de/suse/productinfo.php?cnt=productinfo&id=fr-65019&index=2&type=2&mode=2&nr=0&preload=false&page=1&view=fit&Toolbar=1&pagemode=none

Diese "Literatur" gibt einem auch noch vor den Programmcode
in *.h-Dateien zu legen. Und offensichtlich funktioniert nicht
mal dieser C&P Code beim User .... was für eine Literatur.
OP #6801639
Lesenswert?

huberdetektor schrieb:
> Natürlich ist der Code irgendwo hergeholt.
>
> Die Suche nach Programminhalten ergibt z.B.
>
> 
https://www.edv-buchversand.de/suse/productinfo.php?cnt=productinfo&id=fr-65019&index=2&type=2&mode=2&nr=0&preload=false&page=1&view=fit&Toolbar=1&pagemode=none
>
> Diese "Literatur" gibt einem auch noch vor den Programmcode
> in *.h-Dateien zu legen. Und offensichtlich funktioniert nicht
> mal dieser C&P Code beim User .... was für eine Literatur.

Er ist nicht irgendwo hergeholt sondern es ist immer noch das gleiche 
Buch und es liegt bei mir auf dem Tisch ;-)
Gast #6801653
Lesenswert?

Michael H. schrieb:
> ....... und eines von der Anzeige

So so, ein Schaltplan von der Anzeige.

Und wo sind die Abblock-Kondensatoren die wir schon vor Monaten
bemängelt haben? Braucht's nicht gell, denn dein schönes Buch
ist ja so gut und allwissend dass es diese einfach weglassen
kann.
OP #6801657
Lesenswert?

huberdetektor schrieb:
> Michael H. schrieb:
>> ....... und eines von der Anzeige
>
> So so, ein Schaltplan von der Anzeige.
>
> Und wo sind die Abblock-Kondensatoren die wir schon vor Monaten
> bemängelt haben? Braucht's nicht gell, denn dein schönes Buch
> ist ja so gut und allwissend dass es diese einfach weglassen
> kann.

reicht kein 100uf der ist bei der Spannungsversorgung mit dran. und ich 
ich hatte nie behauptet das das buch super allwissend oder ähnliches ist
OP #6801673
Lesenswert?

Das habe ich auch schon vermutet denn wenn ich in der nachfolgenden 
Funktion in der H Datei DDRD = 0b11111111; nach zb. DDRD = 0b00000000; 
ändere dann bleiben alle aus. Und mit dem Scope kann ich an Port D jetzt 
auch keine änderung feststellen

1
void initialize_LED_display()
2
{  DDRD = 0b11111111;  
3
  DDRC = 0b00001111;  
4
  OCR1A = 8;        // load compare value for 1 ms repetition time
5
  TIMSK |= (1 << OCIE1A);             // interrupt if compare match
6
  TCCR1B = (1<<CS12) | (1<<CS10) | (1<<WGM12);  // div 1024 & clear counter on compare match
7
  sei();
8
}
OP #6801916
Lesenswert?

HildeK schrieb:
> Michael H. schrieb:
>> wenn ich in der nachfolgenden
>> Funktion in der H Datei DDRD = 0b11111111; nach zb. DDRD = 0b00000000;
>> ändere dann bleiben alle aus.
>
> Klar, der Port D ist jetzt auch komplett als Eingang definiert. Dann
> leuchtet nichts.

Ja das stimmt hab vor lauter Verzweiflung übersehen das hier die ein und 
Ausgänge Gesetz werden.

Kann das vielleicht sein das die Bezeichnung der isr nicht mehr stimmt ?

ISR (SIG_OUTPUT_COMPARE1A)

Ich nutzte erst einen atmega8 und dann einen atmega8a  der aktuell jetzt 
auch verbaut ist.
Gast #6802039
Lesenswert?

Eberhard H. schrieb:
> Das müsste der Compiler reklamieren.

Nein. Das alte AVR Studio übernimmt das klaglos. Dort sind
die alten Definitionen enthalten. Üblicherweise werden die
für alle Ewigkeit mitgeschleppt.

- Die Reset-Beschaltung des Controllers fehlt.

- Wie wird der Controller programmiert? In der Schaltung kann es
nicht funktionieren, dazu braucht es die Reset-Leitung.

- die Fuses müssen korrekt stehen, speziell für internen Clock!
Gast #6802122
Lesenswert?

huberdetektor schrieb:
> - Die Reset-Beschaltung des Controllers fehlt.

Kaum schaut man das Foto drei Stunden lang an schon sieht man
eine Reset-Leitung zu einem (vermuteten) Programmier-Port
gehen.

Aber der übliche Pullup und der Kondensator dazu fehlt trotzdem.
Und die Abblock-Kondensatoren natürlich ebenfalls (ich wieder-
hole mich ...).
Gast #6802143
Lesenswert?

huberdetektor schrieb:
> Kaum schaut man das Foto drei Stunden lang an schon sieht man
> eine Reset-Leitung zu einem (vermuteten) Programmier-Port
> gehen.

Welches Bild schaust du denn an? Das vom TO 
(https://www.mikrocontroller.net/attachment/528566/20210826_220254_1_.jpg) 
hat jedenfalls PU und 100nF am Reseteingang.
Ja, die Blockkondensatoren fehlen. Das wird aber nicht sein Problem 
sein.

Michael H. schrieb:
> Ich nutzte erst einen atmega8 und dann einen atmega8a  der aktuell jetzt
> auch verbaut ist.
Muss/wird mit beiden gehen.
Ich habe was ähnliches gebaut für eine dreistellige Anzeige eines Bytes 
in DEZ oder BCD/HEX. Kann man leicht auf vier Stellen anpassen, du musst 
aber vermutlich die Segmente in anderer Reihenfolge anschließen oder 
eine Tabelle anpassen und die auch die Spalten umverdrahten.
Ich lese Daten vom PortB ein, um die anzuzeigen. Du kannst ja an der 
entsprechenden Stelle deinen Countdown einfügen.
Ich hänge dir das mal an, bevor ich mich durch deinen Code durcharbeite 
😀. Läuft derzeit mit einem Mega8.
Angehängte Dateien:
OP #6802194
Lesenswert?

huberdetektor schrieb:
> Eberhard H. schrieb:
>> Das müsste der Compiler reklamieren.
>
> Nein. Das alte AVR Studio übernimmt das klaglos. Dort sind
> die alten Definitionen enthalten. Üblicherweise werden die
> für alle Ewigkeit mitgeschleppt.
>
> - Die Reset-Beschaltung des Controllers fehlt.
>
> - Wie wird der Controller programmiert? In der Schaltung kann es
> nicht funktionieren, dazu braucht es die Reset-Leitung.
>
> - die Fuses müssen korrekt stehen, speziell für internen Clock!

Also jetzt funktioniert es. Ich habe einfach die ISR in " 
(TIMER1_COMPA_vect)" geändert. Dann hat es gleich zu zählen begonnen, 
allerdings musste ich dann noch die Tausender, Hunderter, Zehner und 
Einserstellen etwas anders als auf dem Schlatplan Stecken. Die habe 
warscheinlich ich beim Aufbau vertauscht.

Danke an diejenigen die versucht haben mir zu Helfen.

Achso ich hatte das Microchip Studio und einen Originalen MK2 Programmer
1
ISR (TIMER1_COMPA_vect)  
2
{  PORTC = 0b00001111;     // Digits off
3
  if(active_digit == 0) digit (Digit_000X, PC0);
4
  if(active_digit == 1) digit (Digit_00X0, PC1);
5
  if(active_digit == 2) digit (Digit_0X00, PC2);
6
  if(active_digit == 3) digit (Digit_X000, PC3);
7
  
8
  active_digit ++; if (active_digit == 4) active_digit = 0;
9
  
10
}
Gast #6802210
Lesenswert?

Boah, mein Gott, was für eine Hassentladung hier Fragestellern 
entgegenschlägt… Und dann hätte ich nochmal die Frage, was hier bei 
manchen Leuten im Kopf passiert, wenn man ein Leerzeichen vor einem 
Satzzeichen sieht ?   Hm, wie isses  ? Schlimmer   ? Und nun      ?


Zur Sache: Der Transistor für die Spalten wird gleichzeitig mit dem 
Symbol umgeschaltet. Das kann zu Ghosting führen, d.h. man sieht die 
neue Ziffer noch im vorher geschalteten Symbol, da der Transistor zum 
Sperren etwas Zeit braucht. Könnte bei schwachen Licht sichtbar werden. 
Besser wenn etwas man den Ausgangsport auf Null schaltet, Transistor 
wechseln, etwas warten (vlt. so 50usec) und dann das neue Symbol 
anlegen.
Gast #6802221
Lesenswert?

Michael H. schrieb:
> Also jetzt funktioniert es. Ich habe einfach die ISR in "
> (TIMER1_COMPA_vect)" geändert.

Mit welcher IDE / welchem Compiler?

AVR Studio 4.18 baut jedenfalls mit beiden Tokens, also
TIMER1_COMPA_vect  oder   SIG_OUTPUT_COMPARE1A
den gleichen Maschinencode. Ohne Fehermeldung oder Warning.
Gast #6802329
Lesenswert?

Apollo M. schrieb:
> Was bei dir und dem TO fehlt ist eine Brightness Steuerung z.B. über den
> ISR Timer Interval, der die Abzahl der aktiven Segmente berücksichtigt!
> Weil sonst eine '1' oder '7'sonst viel heller  leuchtet als z.B die '8'.

Nein, wieso? Braucht man nicht.
Die gemeinsame Anode wird ein-/ausgeschaltet, die Kathoden der 
Segment-LEDs bekommen immer über einen LED-Vorwiderstand den selben 
Strom, wenn sie an sind. Ob ein Segment oder alle sieben leuchten ändert 
nichts.

Nur generell die Helligkeit verändern (Tag-/Nachtanpassung) habe ich in 
der SW nicht eingebracht. Könnte man aber über eine variable 
Puls-/Pausenzeit beim Mulitplexen implementieren.
Gast #6802605
Lesenswert?

Hallo,

so wie die Anzeige ins Steckbrett gesteckt ist, könnte es in den beiden 
äußeren Zeilen zu unerwünschten Verbindungen kommen. Ich gebe dies nur 
zum Bedenken, geprüft habe ich die Anschlüsse nicht.

Mfg
#6802971
Lesenswert?

Hi
In C kann ich leider nicht helfen, dennoch zum Verständnis Multiplexer 
beitragen.
Meine Vorgehensweise
Array mit der Decodierung Zahl nach 7-Segment
Puffer mit den decodierten Wertebytes für die Anzeige
Puffer für die Werte
Multiplexer:
Anzeigeansteuerung aus
Passend zum Digit Anzeigemuster aus Puffer auf die Segmente schalten
Nächstes Digit ansteuern

Dieser Vorgang wird durch einen 1ms Interrupt  aufgerufen

Im Polling:
Wert laden
Damit Array der Zahlenmuster adressieren und Zahlenmuster in den 
Ausgabepuffer übertragen.

Der CountDown oder was auch immer angezeigt werden soll wird über den 
Wertepuffer gemacht
 Zum probieren kannst du auch die Multiplexerroutine mit einem größeren 
Zeitraster aufrufen und so auch verfolgen, ob die Werte richtig 
zugeordnet sind. Da ich ein Masochist bin und auf Controllern nur mit 
Assembler unterwegs bin, mußte du mal selbst versuchen, die einzelnen 
Schritte entsprechend in kleine C-Routinen zu packen.
Gruß oldmax
PS. Mit einer 7-Segmentanzeige lassen sich auch Buchstaben wie A, b, 
c,C,d,E,F,H,h,i,J,L,N,n,r,u,U darstellen.Einfach im Array der 
Zahlenmuster anhängen und mit Werten >9 abrufen.
Gast #6803109
Lesenswert?

huberdetektor schrieb:
> Kommt immer wieder. Und täglich grüsst das Murmeltier.

Typischer Verlauf eines Threads von Michael H. Der Thread verläuft
nach einer gewissen Zeit im Sand ohne eine weitere Rückmeldung
und ohne dass der TO eigentlich was verstanden hat.

Stefan ⛄ F. schrieb:
> Elkos sind zu träge für hochfrequente Störungen.

Typischer Verlauf eines Threads von Michael H. Wenn es so
einigermassen funktioniert kann er ja mit dem Brustton der
Überzeugung sagen:
"Wieso Abblock-Kondensatoren? Geht doch auch ohne!"
Ausserdem wird er auch "hochfrequente Störungen" nicht
verstanden haben. Und er braucht sich ja auch nicht mehr
melden.

So wird sich Michael H. (oder eine Abwandlung seines
Benutzernamens) beim nächsten Projekt/Versuch aus besagtem
glorreichen Buch wieder melden und fragen warum sein neues
C&P-Programm nicht funktioniert.

Martin V. schrieb:
> Meine Vorgehensweise ....

Dein Fachwissen in Ehren, aber du hast umsonst geschrieben da
du trotz deines Fachwissens es nicht geschafft hast die
(vorsichtig ausgedrückt) Möglichkeiten des TO richtig einzu-
schätzen. Das gilt aber mehr oder weniger für alle Beitragende
ab dem 27.08.2021 14:18.
OP #6803559
Lesenswert?

Ich hatte geschrieben das es funktioniert. Und ich hatte auch 
geschrieben welche IDE und welchen programmer. Und was mein Problem 
gelöst hast

Und diejenigen die sich als Gast Anmelden um nicht so einfach gesperrt 
werden zu können. Brauchen das nicht kritisieren das jemand richtig 
angemeldet hat.
Gast #6803698
Lesenswert?

Ich bin der Meinung, das Michael soweit gut kommuniziert hat.
Die Feinheiten mit Abblockkondensatoren, Resetbeschaltung etc. wird er 
schon noch lernen. Daß Code nur in .C Dateien gehört auch noch, da hat 
sein Lehrbuch offensichtlich Mängel.
Das Projekt arbeitet, und aufbauend daran kann er gut weiterkommen.
Die Kritik bzw. der Tonfall des nicht angemeldeten Teilnehmers sind 
eindeutig überzogen.
Gruss

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren