Forum: Mikrocontroller und Digitale Elektronik Coundown Timer


von Michael H. (h_m)


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
}

von huberdetektor (Gast)


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.

von Erich (Gast)


Lesenswert?

Die Aufgabe ist nur lösbar zusammen mit dem Schaltplan.

von huberdetektor (Gast)


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.

von Michael H. (h_m)


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 ;-)

von huberdetektor (Gast)


Lesenswert?

Michael H. schrieb:
> es ist immer noch das gleiche Buch

Und warum hast du es noch nicht weggeschmissen?

Erich schrieb:
> Die Aufgabe ist nur lösbar zusammen mit dem Schaltplan.

von Michael H. (h_m)


Angehängte Dateien:

Lesenswert?

Oben ein Bild vom Schaltplan und eines von der Anzeige

von huberdetektor (Gast)


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.

von Michael H. (h_m)


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

von Erich (Gast)


Lesenswert?

Du solltest mal mit einem Scope messen, ob überhaupt "wechselnde" 
Signale an den uC Pins rauskommen. Evtl. "läuft" der uC gar nicht.

von huberdetektor (Gast)


Lesenswert?

Michael H. schrieb:
> reicht kein 100uf

Nein, und wir haben das damals bereits klar beschrieben.
So viel kann ich mich in meiner Erinnerung nicht irren,
aber ich bin auch zu faul dir das jetzt nochmal auf dem
Silbertablett zu servieren.

oh my god

von Michael H. (h_m)


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
}

von HildeK (Gast)


Lesenswert?

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.

von Michael H. (h_m)


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.

: Bearbeitet durch User
von Eberhard H. (sepic) Benutzerseite


Lesenswert?

Michael H. schrieb:
> Kann das vielleicht sein das die Bezeichnung der isr nicht mehr stimmt ?

Das müsste der Compiler reklamieren.

Statt

ISR (SIG_OUTPUT_COMPARE1A)

für den ATmega8A

ISR (TIMER1_COMPA_vect)

nehmen und neu kompilieren, dann aber gleich für den ATmega8A (letzteres 
könnte dennoch für beide funktionieren).

von huberdetektor (Gast)


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!

von huberdetektor (Gast)


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 ...).

von Ozvald K. (Gast)


Angehängte Dateien:

Lesenswert?

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

Funktioniert aber auch ohne. Wozu sonst die Power-on Reset?
Und weil die Abblock-Kondensator fehlt, ist auch nicht der Hauptgrund 
dafür, dass alle Segmente leuchten.

von HildeK (Gast)


Angehängte Dateien:

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.

von huberdetektor (Gast)


Lesenswert?

HildeK schrieb:
> hat jedenfalls PU und 100nF am Reseteingang.

Papier ist geduldig. Der Schaltplan überträgt sich nicht
automatisch auf den Aufbau.

HildeK schrieb:
> Welches Bild schaust du denn an?

Schaust du nochmal genauer hin ....

von huberdetektor (Gast)


Lesenswert?

Ozvald K. schrieb:
> Funktioniert aber auch ohne.

Natürlich. Aber die lange Leitung zum Programmierer lässt
leicht Störungen einfangen, lässt den Reset-Pin leichter
wackeln und macht damit die Funktionssicherheit fragwürdig.
Daher: R/C Beschaltung.

von Michael H. (h_m)


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
}

: Bearbeitet durch User
von H. (Gast)


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.

von huberdetektor (Gast)


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.

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

HildeK schrieb:
> Ich habe was ähnliches gebaut für eine dreistellige Anzeige eines Bytes

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' viel heller  leuchtet als z.B die '8'.

: Bearbeitet durch User
von HildeK (Gast)


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.

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

HildeK schrieb:
> 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.

Ok, alles klar. Nur in der Variante mit ein R pro Digit läßt sich dann 
via SW die Helligkeit angleichen.

von roehrenvorheizer (Gast)


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

von MaWin (Gast)


Lesenswert?

Michael H. schrieb:
> PORTC &= ~(1 << pin);

PORTC = ~(1<<pin);

von Martin V. (oldmax)


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.

von Stefan F. (Gast)


Lesenswert?

Michael H. schrieb:
> reicht kein 100uf der ist bei der Spannungsversorgung mit dran

Elkos sind zu träge für hochfrequente Störungen.

von Patrick L. (Firma: S-C-I DATA GbR) (pali64)


Lesenswert?

Martin V. schrieb:
> 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.
Ja gehen sogar par mehr G zum beispiel ;-)

Wobei bei Billigst Geräten mit irgend welchen murks auch noch T mit 
halbem dach usw darstellbar sind ;-)

von huberdetektor (Gast)


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.

von Michael H. (h_m)


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.

von Erich (Gast)


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

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.