Forum: Mikrocontroller und Digitale Elektronik Selbstlaufende Uhr mit AVR Atmega8


von Mike32 (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich versuche gerdade über einen Atmega8 Mikrocontroller eine Uhrzeit
über eine Lichtskulptur auszugeben.
Der Mikrokontroller steuert 8 LED Treiber (Allegro 6276 Schieberegister) 
an.
Das Programm soll später natürlich noch erweitert werden.
Nun wollte ich die Ausgabe aber schon mal testen, nur leider 
funktioniert mein Programm bis hier hin nicht richtig, bzw. es gibt 
nichts aus.

Der Interrupt soll eigentlich jede 1ms kommen. Hierbei werde ich mich 
wohl verechnet haben, jedoch sollte ja trozdem eine Ausgabe erfolgen.

An den Mikrokontroller habe ich einen 8 Megaherz Quarz angeschlossen.

Vieleicht erkennt ja jemand auf anhieb einen Fehler.

Gruß, Mike

von Klaus D. (kolisson)


Lesenswert?

Mike32 schrieb:
> An den Mikrokontroller habe ich einen 8 Megaherz Quarz angeschlossen.

... und hoffentlich auch aktiviert.

Gruss Klaus

von holger (Gast)


Lesenswert?

>#include <avr/io.h>
>#include <avr/interrupt.h>
>//#define TIMER2_COMP_vect  _VECTOR(3)      // Zeile löschen
>#include <util/delay.h>
>#define F_CPU 8000000UL   // Ist hier falsch


#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 8000000UL     // besser in die Projektoptionen aufnehmen
#include <util/delay.h>

Übernimm das erst mal und dann noch mal melden.

von holger (Gast)


Lesenswert?

Auf PIND schreibt man nicht;) Nimm PORTD.
      PIND &=~(1<<PIND0);    //0 an PD0 Ausgeben   //0 an Data
      PIND |=(1<<PIND1);    //1 an PD1 Ausgeben    //1 an Clock

von Mike32 (Gast)


Lesenswert?

Wow,
das geht ja schnell.
Danke! Ich ändere das mal eben und melde mich dann nochmal.

von Mike32 (Gast)


Angehängte Dateien:

Lesenswert?

So, habe das Programm jetzt soweit geändert.

#define F_CPU 8000000UL     // besser in die Projektoptionen aufnehmen

diese Zeile habe ich nun gelöscht und im Programm (ich benutze AVR 
Studio)
unter Project Options bei Frequency 8000000 eingetragen.

Habe ich das so richtig verstanden?

von Karl H. (kbuchegg)


Lesenswert?

>   if (neuse==altse)
>   {

Wieso "gleich"?


Der Update muss erfolgen, wenn sich was verändert hat, wenn die Werte 
also ungleich sind!

von Karl H. (kbuchegg)


Lesenswert?

>     for(a=0;a==9;a++)      //Schieberegister auf 0 setzten


Schau bitte in ein C Buch deiner Wahl, wie die Einzelteile einer 
for-Schleife funktionieren.

Das ist

  for( initial; Schleifenbedingung; Inkrement )

Solange die Schleifenbedingung wahr ergibt (also ungleich 0) wird die 
Schleife weiter ausgeführt. Bei dir wäre das: solange a den Wert 9 hat, 
wird die Schleife ausgeführt. a wird aber nie 9 sein, denn du 
initialisierst a mit 0. 0 ist aber nicht gleich 9 und damit kommt die 
Schleife nie zur Ausführung.

von Karl H. (kbuchegg)


Lesenswert?

Vergiss momentan mal die Zehener und Einer, Minuten und Stunden. Sieh 
zu, dass du EIN Schieberegister in Betrieb nimmst. In deinem Code 
wimmelt es nur so von lächerlichen C-Fehlern.

von Peter D. (peda)


Lesenswert?

Volatile schüttet man nicht mit der Gießkanne aus.
Volatile sind ausschließlich die Variablen, die sowohl im Interrupt, als 
auch im Main verwendet werden.
Und Konstanten schonmal garnicht.


Peter

von Mike32 (Gast)


Lesenswert?

Oh man,
das mit der for-Schleife ist natürlich ein Fehler!

Werde das heute Abend änderen sowie das Volatile vor allen Variablen
die nicht im Interrupt und Main genutzt werden weg nehmen.

Werde mich dann nochmal melden!

von Mike32 (Gast)


Angehängte Dateien:

Lesenswert?

So, ich habe nun mal ein paar Sachen geändert.
Leider funktioniert es alles immer noch nicht.

Könnte ich evtl mit dem Timer bzw Interrupt etwas falsch gemacht haben?

Ich wollte eigentlich ereichen, dass der Interrupt jede 1ms ausgelöst 
wird.

Oder evtl bei der sonstigen Ausgabe?

von spess53 (Gast)


Lesenswert?

Hi

>if(second==9)

10 Sekunden dauern bei dir nur 9?

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

Mike32 schrieb:
> So, ich habe nun mal ein paar Sachen geändert.

Wo?

Ich sehe immer noch die alten Fehler.

>   if (neuse==altse)
>     for(a=0;a==b;a++)      //Schieberegister weiter "schieben"
>   if (neusz==altsz)

usw. usw.

Soll ich dir jetzt wirklich jede einzelne Zeile raussuchen, damit du die 
immer gleichen Fehler auch wirklich alle korrigierst?

von Mike32 (Gast)


Lesenswert?

Habe dort nur 9 Led's. Danach soll in den Zehner Sekunden Block eine LED 
angehen.

von Karl H. (kbuchegg)


Lesenswert?

Mike32 schrieb:
> Habe dort nur 9 Led's. Danach soll in den Zehner Sekunden Block eine LED
> angehen.

Wenn du meinst.
Dann zählt deine Uhr eben schon auf 10, wenn in der Realität nur 9 
Sekunden vergangen sind. Tipp: Auch 0, wenn also keine LED brennt, ist 
ein anzeigenswerte Zahl.

Aber das ist momentan noch nicht so wichtig. (Bei Minuten und Stunden 
hast du denselben Quatsch. Deine Minute zb hat nur 49 Sekunden, sogar 
weniger, weil ja pro 10 Sekunden 1 fehlt).

Erst mal kriegst du das jetzt zum Laufen. Um die korrekte Zählweise 
kannst du dich später kümmern.

von Karl H. (kbuchegg)


Lesenswert?

Was hast du da eigentlich mit deinem
"Schieberegister auf 0 setzen"?

Braucht doch kein Mensch. Du hast doch an einem Schieberegisterstrang, 
so wie ich das im Code sehe, sowieso immer nur die Leds einer 'Spalte' 
(also Zehner oder Einer). Schieb deine Zahlen raus und gut ists.
Du musst 9 LED für die Einer setzen: Wenn die Schleifenvariable kleiner 
als die aktuelle Sekundenzahl ist, dann schiebst du ein 0 Bit raus und 
ansonsten ein 1 Bit.
Und das ganze machst du nur, wenn du musst. Sprich, wenn sich die Einer 
der Sekunden verändert haben.

von Karl H. (kbuchegg)


Lesenswert?

Ich seh auch nicht, wo du in deinem Programm die Latch Enable bzw. 
Output Enable Leitungen der SR bedienst.


Hast du denn ein paar Vorversuche mit EINEM Schieberegister gemacht, um 
dich erst mal mit der prinzipiellen Vorgehensweise vertraut zu machen, 
ehe du dich gleich auf eine Uhr gestürzt hast?

von Mike32 (Gast)


Lesenswert?

Es sind leider 16 bit Schieberegister, da diese vorhanden waren.

Das Programm war eigentlich so gedacht, dass ich 9x1 Bit hinein schiebe.

Wenn nun 9 Leds leuchten, wollte ich dort 9x eine "0" rein schieben und 
dies schnell hintereinander damit alle neun leds wieder aus sind.

Schieberegister auf 0 setzen ist hier auch bestimmt eher unglücklich von 
mir ausgedrückt.

von Karl H. (kbuchegg)


Lesenswert?

Mike32 schrieb:

> Wenn nun 9 Leds leuchten, wollte ich dort 9x eine "0" rein schieben und
> dies schnell hintereinander damit alle neun leds wieder aus sind.

Ist doch viel zu kompliziert.
Du musst IMMER 9 Bits ins Schieberegister laden.
Die entscheidende Frage bei jedem Bit ist nur: muss es ein 0 Bit oder 
ein 1 Bit sein

1
  if (second != altse)
2
  {
3
   for( i = 0; i < 9; ++i )
4
   {
5
     if( i < second )
6
       PORTD &=~(1<<PORTD0);
7
     else
8
       PORTD |= (1<<PORTD0);
9
10
      PORTD |=(1<<PORTD1);
11
      _delay_ms(1);
12
      PORTD &=~(1<<PORTD1);
13
    }
14
15
    altse = second;
16
  }

von Mike32 (Gast)


Lesenswert?

Den Latch Enable habe ich in der Schaltung dauerhaft auf High, den 
Output Anable dauerhaft auf Low gelegt.

Bei dem manuellen probieren ohne Mikrokontroller sah man wie geschoben 
wurde.

von Karl H. (kbuchegg)


Lesenswert?

Mike32 schrieb:
> Den Latch Enable habe ich in der Schaltung dauerhaft auf High, den
> Output Anable dauerhaft auf Low gelegt.

Das heisst man sieht, wie du die Schieberegister befüllst :-)
Keine gute Idee.
Zumindest die Output Enable Leitung willst du steuern können!
Du willst die LED gezielt abschalten, dann die Schieberegister befüllen 
und danach die LED wieder einschalten. Damit man eben nicht sieht, wie 
du die Daten reintaktest.

Man könnte jetzt höchstens aus der Not eien Tugend machen, weil man ja 
weiß dass die LED nicht in beliebiger Reihenfolge angehen, sondern immer 
eine nach der anderen. Das verkompliziert aber das Programm ein wenig.

von Mike32 (Gast)


Lesenswert?

Also es war so gedacht, dass jede Sekunde eine Led mehr angeht und bei 
der zehnten Sekunde alle neun "Einer Sekunden" Leds aus gehen und die 
erste der 5 "Zehner Sekunden" Leds an geht.
Ab der elften Sekunde sollte wieder die erste "Einer Sekunden" Led an 
gehen und dann nach 20 Sekunden die zweite "Zehner Sekunden" Led usw.

Habe das am Anfang glaube ich nicht so gut erklärt.
Oder habe ich hier einen Denkfehler?

von Karl H. (kbuchegg)


Lesenswert?

Mike32 schrieb:

> Oder habe ich hier einen Denkfehler?

Nein. Man kann das so machen.
Aber dein Programm geht noch nicht einmal ansatzweise in diese Richtung.

Es ist zwar nicht wahnsinnig schwer mit dieser Strategie die Uhr zu 
befüllen, aber so wie ich das sehe ist das für dich noch schwer genug.

Daher: machs erst mal konventionell
Bei jeder Änderung die entsprechende Anzahl an leuchtenden LED neu 
einstellen.

Und konzentrier dich für erste nur auf die Einsterstelle/Sekunden. Alles 
andere löscht du jetzt erst mal raus.

Wenn du die korrekt laufen hast, dann baust du die Zehnerstelle ein. Und 
wenn die dann geht, baust du die Minuten ein etc. etc.

Nicht zu viel auf einmal.

von Mike32 (Gast)


Lesenswert?

Ja, dann vielen Dank erstmal.

Werde mal ein wenig rum probieren.

Wenn ich nochmal Fragen habe (und die habe ich bestimmt ;)  ) melde ich 
mich nochmal.

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.