Hallo,
bisher konnte ich alle auftretenden Fehler und Probleme selber lösen,
indem ich einfach mal die Weiten des Internets genutzt habe um zu
gewissen Problematiken zu recherchieren. Doch jetzt habe ich schon eine
Woche vergeblich versucht dieses Problem zu lösen.
Zunächst einmal eine kleine Projektbeschreibung:
Ich habe einen Weihnachtsstern gebaut, welcher aus 5*8 LEDs besteht.
Diese LEDs hängen an 5 in Reihe geschalteten Schieberegistern (74HC595,
in welche ich das aktuelle Leuchtbild seriell reinschiebe und dann auf
dessen Ausgänge übertrage. Das ganze wird mit einem ATTiny45 gesteuert.
Dazu gibt es noch einen Eingang als Interrupt, um zwischen verschiedenen
Blinkmustern zu wechseln. Deweiteren gibt es noch einen Spannungsteiler
mit einem lichtabhängigen Widerstand, der erkennt, ob es Hell oder
Dunkel ist. Um somit die LEDs ausschalten zu können.
Jetzt tritt folgendes Phänomen auf: Immer wenn alle LEDs ausgeschaltet
werden sollen, dann stürzt der ATTiny45 ab und das Programm startet sich
von vorne.
Soweit konnte ich es jedenfalls schon einschränken, denn wenn ich das
Programm so umschreibe, dass niemals alle LEDs ausgeschaltet sind, dann
funktioniert es einwandfrei.
Den Code der einzelnen Modi (Blinkmuster) habe ich mal bewusst entfernt,
da dieser meiner Einschätzung und Tests nichts mit dem Problem zu tun
hat.
Meiner Meinung nach arbeit die Funktion LEDout() nicht richtig, wenn
diese nur Nullen an die Schieberegister schicken soll, doch ich kann mir
überhaupt nicht erklären warum.#
Ich habe zwar noch bis Weihnachten Zeit, aber ich hoffe echt, dass mir
hier jemand bei meinem Problem helfen kann.
Hier nun der dazugehörige Code:
1
/*
2
* ChristmasStar.c
3
*
4
* Created: 19.07.2012
5
* Latest Modification: 17.10.2012
6
*
7
* Author: Christian Schoknecht
8
*/
9
10
#include<avr/io.h>
11
#include<util/delay.h>
12
#include<avr/interrupt.h>
13
14
#define F_CPU 8000000UL
15
#define modicounter 8
16
#define SI 0
17
#define RCK 3
18
#define SCK 4
19
20
volatilecharinterrupt_counter=0;
21
volatilecharflag=0;
22
volatileuint8_tLED0=0x00;
23
volatileuint8_tLED1=0x00;
24
volatileuint8_tLED2=0x00;
25
volatileuint8_tLED3=0x00;
26
volatileuint8_tLED4=0x00;
27
volatileuint8_tcounter=9;
28
volatileuint8_tday=0;
29
volatileuint8_tcache=0x00;
30
volatileuint8_tsteps=0;
31
volatileuint8_trandom_mode=0;
32
33
/* function prototypes */
34
voidsetBit(uint8_tbit);
35
voidresetBit(uint8_tbit);
36
voidLEDout()__attribute__((optimize(0)));
37
voidresetLEDs();
38
voidrandom_();
39
voidrunning();
40
voidcircle();
41
voidcircle2();
42
voidsnail();
43
voidrider();
44
voidblinking();
45
voidfilling();
46
47
/* function to set a single bit */
48
voidsetBit(uint8_tbit)
49
{
50
PORTB|=(1<<bit);
51
}
52
53
/* function to reset a single bit */
54
voidresetBit(uint8_tbit)
55
{
56
PORTB&=~(1<<bit);
57
}
58
59
/* function for serial output */
60
/* output of the current content of the LED-Array */
Könnte auch ein Hardware Problem sein?
>Jetzt tritt folgendes Phänomen auf: Immer wenn alle LEDs ausgeschaltet>werden sollen, dann stürzt der ATTiny45 ab und das Programm startet sich>von vorne.>Soweit konnte ich es jedenfalls schon einschränken, denn wenn ich das>Programm so umschreibe, dass niemals alle LEDs ausgeschaltet sind, dann>funktioniert es einwandfrei.
Wie sieht der Schaltplan aus, sind genug Blockkondensatoren
an den IC's speziell an den 74HC595 ?
--
[offtopic]
Irgentwie klingt der Titel nach "Ende der Welt" ;-)
rggre schrieb:> 1,5s delay in der ISR? Nix gut. Flag setzen und ab in die main damit.
Das dient derzeit nur zum Testen und direktem erkennen, ob übe
bko schrieb:> Könnte auch ein Hardware Problem sein?> Wie sieht der Schaltplan aus, sind genug Blockkondensatoren> an den IC's speziell an den 74HC595 ?
Das würde ich erstmal bezweifeln, denn wenn ich in der
ResetLED()-Funktion zwei der LED-Warte auf 0x01 setze, egal welche
davon, dann stürzt das Programm nicht ab, dann erst wieder wenn in einem
Leuchtmuster mal alles aus muss.
Mit 16 LEDs und einem ATMega8 sowie einem 89C51 hatte es bereits
funktioniert und die Steuerung habe ich jetzt halt nur auf 5
Schieberegister erweitert und dann einen µController gewählt, der
günstig ist und mir alle Funktionen liefert, die ich brauche (Also auch
einen ADC).
Schaltplan müsste ich mal zeichnen, aber bei den 16 LEDs hat es wie
gesagt auch ohne Blockkondensatoren wunderbar funktioniert.
bko schrieb:> Wie sieht der Schaltplan aus, sind genug Blockkondensatoren> an den IC's speziell an den 74HC595 ?
Da würde ich die Probleme aber beim Einschalten aller LEDs erwarten,
nicht beim Ausschalten.
@ Christian Schoknecht
Es werden also 40-LEDs auf einmal abgeschaltet?
Dies könnte auch einen kurzen Überschwinger in der
Versorgung verursachen welche den UC stören...
Ohne Bild von Layout oder Schaltplan ist das Rätselraten...
Aber 100nF an jedem HC-MOS IC sind eigtl. üblich:
Beitrag "74hct595 100nF Kondensator"
Teste dies: Schalte nicht alle auf einmal ab,
sondern kurz (alle 100 usec oder so)
nacheinander jeweils z.B. 8 Stück
und siehe was passiert.
Wenn dies geht, ists doch recht Wahrscheinlich die Versorgung
Da Dieter schrieb:>> [offtopic]>> Irgentwie klingt der Titel nach "Ende der Welt" ;-)>> Ich dachte bei dem Titel eher an eine zu schmale Fensterbank ;-)
Ein Fall für das Astronomie-Forum von http://www.raumfahrer.net ? ;-)
bko schrieb:> Es werden also 40-LEDs auf einmal abgeschaltet?> Dies könnte auch einen kurzen Überschwinger in der> Versorgung verursachen welche den UC stören...
Nicht in jedem Fall, manchmal werden auch nur zwei oder drei einzeln
ausgeschaltet, das hängt ja vom Blink-Modus ab. Oder momentan nach
Verlassen der ISR werden immer 5 abgeschaltet und da hängt es sich auf.
Schaltplan liefere ich aber gleich nach.
bko schrieb:> Teste dies: Schalte nicht alle auf einmal ab,> sondern kurz (alle 100 usec oder so)> nacheinander jeweils z.B. 8 Stück> und siehe was passiert.>> Wenn dies geht, ists doch recht Wahrscheinlich die Versorgung
Das bringt zumindest nach dem ersten Test Besserung, muss das Programm
jetzt nur mal umschreiben, um zu sehen, ob dies überall der Fall ist.
Edit: Jap, damit funktioniert es. Okay, vielen Dank, dann kann komme ich
jetzt weiter.
Okay, dann muss ich jetzt mal auf meiner Platine noch Platz suchen, bei
den weiteren Exemplaren kann ich das Layout dann ja anpassen, so dass es
auch gleich funktioniert.
Ich sehe gerade, dass es ja auch Sockel mit Abbklockkondensator gleich
gibt. Okay, ich werde dann berichten, ob das ganze das Problem löst.
Das ist mir beim Übertragen wohl ein Fehler passiert.
Ich hatte nämlich noch paar unnötige Zeilen und Kommentare rausgelöscht
und dabei alles in eine Zeile geschrieben. LEDcache soll natürlich
LEDcache1 sein.
So Kondensatoren sind bestellt, in der größe, die noch auf meine Platine
passt waren die nämlich bei Conrad nicht vorrätig. Ergebnisse folgen.
Christian Schoknecht schrieb:> Das ist mir beim Übertragen wohl ein Fehler passiert.>> Ich hatte nämlich noch paar unnötige Zeilen und Kommentare rausgelöscht
Da geht noch einiges mehr. Hast du den Kopf frei für
Programmvereinfachungen?
Karl Heinz Buchegger schrieb:> Da geht noch einiges mehr. Hast du den Kopf frei für> Programmvereinfachungen?
Prinzipiell ja, wollte bisher nur erstmal ein Programm erzeugen, dass
auch funktioniert und das auch noch übersichtlich ist, bevor ich da
irgendwelche Vereinfachungen reinbaue.
Christian Schoknecht schrieb:> Karl Heinz Buchegger schrieb:>> Da geht noch einiges mehr. Hast du den Kopf frei für>> Programmvereinfachungen?>> Prinzipiell ja, wollte bisher nur erstmal ein Programm erzeugen, dass> auch funktioniert und das auch noch übersichtlich ist, bevor ich da> irgendwelche Vereinfachungen reinbaue.
Genau darum gehts :-)
Die Vereinfachungen sind nicht von der Kategorie 'möglichst viel
tricksen', sondern von der Kategorie:
Eine 5-zeilige Funktion ist leichter zu überblicken, zu verstehen und im
Fehlerfall zu analysieren, als derselbe Sachverhalt auf 2
Bildschirmseiten :-)
welche Variante gefällt dir besser?
Was mir an deiner nicht gefällt: das sie extrem in die Länge gezogen
ist, ohne das es dafür einen guten Grund gibt.
switch-case ist nicht immer in der Lesbarkeit besser.
(Und ja: manchmal darf man sich auch über Formatiervorschriften
hinwegsetzen, WENN es dafür einen extrem guten Grund gibt. Hier ist es
mir wichtig, dass die gedankliche Zuordnung von 0, 1, 2, 3, ... zur
aufgerufenen Funktion schnell, leicht und einfach herzustellen ist. Denn
im Prinzip hast du es ja hier mit einer 'Tabelle' zu tun. In der einen
Tabellenspalte steht 'Indexnummer', in der anderen Spalte die
aufzurufende Funktion. Genau das spiegelt aber auch diese auf den ersten
Blick seltsame Struktur wieder. WEnn man sich die Formatierung aber mal
genau ansieht, dann macht sie absolut Sinn.)
Was allerdings nicht funktioniert hatte: Ich hatte erst LED0-4 als Array
deklariert und dann eine Schleife in LEDout(), die LED[0] bis LED[4]
nacheinander abarbeiten soll, und das hat nicht funktioniert, nehme an,
dass es falsch optimiert worden ist vom Compiler.
Christian Schoknecht schrieb:> Wobei das ja auch so funktionieren würde:
Ja - Genau.
Nicht falsch verstehen.
Ich bin ein absoluter Verfechter von Formatierungsvorschriften.
Aber - es gibt auch Fälle, in denen man sie 'etwas zurecht biegt' und
dafür einen Zusatznutzen bekommt.
Ich verstehe was du meinst.
Wenn man mit einem großen Monitor arbeitet, dann stört es einen weniger,
wenn man da ein paar Zeilen scrollen muss bzw. in Editoren die gerade
nicht benötigten Funktionen einklappt.
Deshalb fällt es ja kaum auf. Hier ist es natürlich klar, wenn das
jemand liest und das so lang ist, obwohl es kürzer sein könnte, dann ist
das eventuell ärgerlich.
Christian Schoknecht schrieb:> Ich verstehe was du meinst.>> Wenn man mit einem großen Monitor arbeitet, dann stört es einen weniger,> wenn man da ein paar Zeilen scrollen muss bzw. in Editoren die gerade> nicht benötigten Funktionen einklappt.>> Deshalb fällt es ja kaum auf. Hier ist es natürlich klar, wenn das> jemand liest und das so lang ist, obwohl es kürzer sein könnte, dann ist> das eventuell ärgerlich.
Nicht nur. Es wird auch dir irgendwann sauer aufstossen, warum deine
LEDout Funktion so dermassen in die Länge gezogen ist. Und es wird der
Tag kommen, an dem du dich fragst, ob eigentlich alle 5 'Ausgabestufen'
in dieser Funktion tatsächlich Buchstabe für Buchstabe identisch sind
(abgesehen von dem einen Variablennamen) oder nicht. (Spätestens dann,
wenn du beobachtest, dass sich SR Nummero 3 aus irgendeinem Grund anders
verhält)
Dabei hättest du dir mit einer Funktion, die die Ausgabe für 1 SR macht,
die dann 5 mal aufgerufen wird, von vorne herein gleich mal Zeit
gespart. Und diese Frage wird auch nie aufgekommen.
Es ist ein Trugschluss zu glauben: "Och, das räum ich später dann schon
irgendwann mal auf." Denn, Hand aufs Herz, ... es passiert nicht.
Wobei man ja auch noch die Frage aufwerfen kann:
Müssen das eigentlich eigene Funktionen sein?
Ist es nicht möglich die einzelnen Muster (mit Ausnahme des
Zufallsmusters in random) nicht in einer gemeinsamen Basis darzustellen?
(Ich will wieder mal auf ein Array raus, in dem die Abfolge der zu
leuchtenden LEDs festgelegt ist)
Denn: dann wird auch das Hinzufügen eines neuen Musters trivial und
beschränkt sich einfach nur auf das Hinzufügen von ein paar Einträgen in
einem Array und dem Anpassen von ein paar #define.
:-)
Und wenn man R. Max-es Vorschlag und meine zusammennimmt, dann könnte
man daraus auch einen gemeinsamen Nenner ziehen: Es ist oft gar nicht so
verkehrt, anstelle von immer gleichen Sequenzen Arrays einzusetzen, wenn
man eine einfache Möglichkeit hat, die Unterschiede einfach nur in den
Daten festzunageln.
Christian Schoknecht schrieb:> void SRout(uint8_t SR)> {> uint8_t LEDcache, i;> LEDcache = LED[SR];
Ah,
Ich sehe, du bist auf ein Array übergegangen anstelle der LED0, LED1,
etc.
gute Entscheidung :-)
PS: Gefällt mir, das du da mitmachst.
Das hatte ich auch vorher überlegt, weil das mit einem zweidimensionalen
Array gut machbar wäre, Zeilen für das Muster, Spalte für die einzelnen
Schieberegister, aber allein der Modus snail() hätte dann schon 5*40
Einträge. Von der Geschwindigkeit mag das ein enormer Vorteil sein. Der
ist aber durch die vielen Verzögerungen in diesem Fall nicht so wichtig.
Aber bei Interesse kann ich auch gerne noch mal die Blink-Modi posten.
Habe diese gerade auch schon der Übersichtlichkeit etwas umformatiert.
Denn mein Code ist inzwischen fast nur noch halb so lang.
Karl Heinz Buchegger schrieb:> Ah,> Ich sehe, du bist auf ein Array übergegangen anstelle der LED0, LED1,> etc.>> gute Entscheidung :-)
Hatte ich vorher auch schon mal. Bei der Fehlersuche, warum die
verschachtelten Schleifen nicht funktionierten, habe ich dann einzelne
Werte daraus gemacht. Was keine Besserung brachte und hatte es bisher
nur noch nicht zurückgeändert.
In dem Fall mit dem Array ist das Programm natürlich leichter zu
modifzieren, wenn man irgendwann einen sechszackigen oder 4 zackigen
Stern bauen will.
R. Max schrieb:> Hier noch der Code zu meinem letzten Vorschlag. Er wirft beim> Compilieren keine Warnungen, weiter getestet habe ich ihn aber nicht.typedef
void (bfunc)(void);
> bfunc *bfuncs[] = {> resetLEDs, random_, running, circle,> snail, rider, blinking, filling> };>> // ...>> if (day == 0)> {> bfuncs[interrupt_counter]();> }
Das ist auch eine nette Idee, aber das wird mir dann gänzlich
unübersichtlich.
Christian Schoknecht schrieb:> Das hatte ich auch vorher überlegt, weil das mit einem zweidimensionalen> Array gut machbar wäre, Zeilen für das Muster, Spalte für die einzelnen> Schieberegister, aber allein der Modus snail() hätte dann schon 5*40> Einträge.
OK. Ich gesth dir natürlich zu, dass wenn es eine einfache Möglichkeit
gibt ein Muster algorithmisch zu generieren, dann ist das sicherlich
einfacher, als so was.
> Von der Geschwindigkeit mag das ein enormer Vorteil sein.
Gar nichtg mal so sehr.
Wenn du dir das Beispiel ansiehst, dann sieht man auf einen Blick sehr
schnell, wie das Muster eigentlich aussieht, weil man die 1-en in der
Initialisierung gut verfolgen kann.
D.h. das Musterdesign ist viel einfacher, weil ich einfach in diesen
(zugegebenen) Datenwust, die 1-en da hin setzte, wo ich sie haben will
ohne lang rumwurschteln zu müssen. Im Beispiel läuft einer 4er Schlange
eine einzelne LED nach. Algorithmisch ist das gar nicht mehr so einfach.
Will ich dann vielleicht von der Gegenseite auch noch eine Schlange
einlaufen lassen, dann ist das im Array einfach. Ich schreib einfach die
1-en dort hin, wo ich sie brauche :-)
Karl Heinz Buchegger schrieb:> Es ist oft gar nicht so verkehrt, anstelle von immer gleichen> Sequenzen Arrays einzusetzen, wenn man eine einfache Möglichkeit> hat, die Unterschiede einfach nur in den Daten festzunageln.
Tja, und der nächste Schritt wäre dann, die Arrays nicht mehr im Code
unterzubringen, sondern im EEPROM, so daß man sie ändern kann, ohne den
ganzen Controller neu zu flashen.
Karl Heinz Buchegger schrieb:> OK. Ich gesth dir natürlich zu, dass wenn es eine einfache Möglichkeit> gibt ein Muster algorithmisch zu generieren, dann ist das sicherlich> einfacher, als so was.
Für die snail()-Funktion in diesem Fall schon:
Noch der PlayIt Funktion zu gegebener Zeit einen Pointer auf blink4
übergeben und fertig ist ein neues Muster.
Und da fängt jetzt die zugegebenermassen etwas kompliziertere
Infrastruktur für dich zu arbeiten an - neue Muster hinzufügen ist
plötzlich einfach geworden.
Christian Schoknecht schrieb:> Karl Heinz Buchegger schrieb:>> OK. Ich gesth dir natürlich zu, dass wenn es eine einfache Möglichkeit>> gibt ein Muster algorithmisch zu generieren, dann ist das sicherlich>> einfacher, als so was.>> Für die snail()-Funktion in diesem Fall schon:
Ah. du hast das anders aufgebaut.
Pro Aufruf ein Musterschritt - sehr vernünftig.
Dann eben
Ich frage mich gerade nur, warum du nicht gleich ein zweidimensionales
Array statt einer Struktur benutzt. Ich sehe darin jetzt keinen Vorteil.
1
Muster[4][5]={
2
{0x03,0x03,0x03,0x03,0x03},
3
{0x0C,0x0C,0x0C,0x0C,0x0C},
4
{0x30,0x30,0x30,0x30,0x30},
5
{0xC0,0xC0,0xC0,0xC0,0xC0}};
Beziehungsweise dann auch in der Bitdarstellung.
Denn so kann man nun in Abhängigkeit von static Laufvariablen auch in
der Funktion durchlaufen lassen.
Karl Heinz Buchegger schrieb:>> Für die snail()-Funktion in diesem Fall schon:> Ah. du hast das anders aufgebaut.> Pro Aufruf ein Musterschritt - sehr vernünftig.
Ja klar, damit nach einem Interrupt sofort in den nächsten Modus
gewechselt wird, ohne dieses Muster zu Ende laufen lassen zu müssen.
Allerdings funktioniert das mit festen Werten auch. Allerdings braucht
man dann eventuell noch zwei Laufvariablen.
In dem Fall, dass alle 5 SR gleiche Inhalte bekommen, reicht natürlich
auch ein 1-Dimensionales Array und die Werte werden nur kopiert.
Christian Schoknecht schrieb:> Ich frage mich gerade nur, warum du nicht gleich ein zweidimensionales> Array statt einer Struktur benutzt. Ich sehe darin jetzt keinen Vorteil.
Weil ich gerne das Array zusammen mit der Arraygröße in einer STruktur
haben möchte. Dann hab ich alles beisammen, was für ein Muster relevant
ist. Da könnte zb noch für jedes Muster eine spezifische
Verzögerungszeit dazukommen oder wie in der letzten Modifikation die
Schrittnummer des gerade aktuellen Schrittes.
Meine Sicht der Dinge ist eben die, dass zu der vollständigen
Beschreibung eines Musters nicht nur die auszugebenden Bytewerte
gehören, sondern noch mehr.
> Denn so kann man nun in Abhängigkeit von Laufvariablen auch in der> Funktion durchlaufen lassen.
Überleg dir nochmal, was das bedeutet, wenn du mehr als ein Muster hast.
Du hast ein
uint8_t Blink1[3][5] = { ... };
uint8_t Clockwise[8][5] = { ... };
uint8_t AntiClockWise[8][5] = { ... };
uint8_t Race[12][5] = { ... };
...
jedes Muster besteht aus einer unterschiedlichen Anzahl von Schritten.
Diese Information muss irgendwo herkommen, damit die 'Schleifen' richtig
arbeiten können.
So, mit der Struktur, übergebe ich einen Pointer auf so ein Muster an
die Funktion, und die Funktion hat alles was sie braucht.
Geht ja dann noch weiter.
Denn ich will ja auch in weiterer Folge, deinen 'interrupt_counter' mit
einem Muster verheiraten. D.h. da wird es noch ein Array geben, welches
diesen interrupt_counter in ein Muster übersetzt.
struct Muster* alleMuster[] =
{
&snail,
&blink4,
...
};
und der Aufruf lautet dann
1
intmain()
2
{
3
...
4
sei();// enable global interrupt
5
6
while(1)
7
{
8
if(day==0)
9
// spiele einen Schritt vom momentan eingestellten aktiven Muster ab.
10
playIt(alleMuster[interrupt_counter]);
11
12
else
13
{
14
resetLEDs();
15
_delay_ms(250);
16
}
17
}
18
19
return1;
20
}
Wir nähern uns immer mehr einer allgmeinen 'Maschine', deren Fähigkeiten
einzig und alleine durch ein paar Einträge in Arrays geregelt werden :-)
Karl Heinz Buchegger schrieb:> Da könnte zb noch für jedes Muster eine spezifische> Verzögerungszeit dazukommen
... oder sogar verschiedene Verzögerungszeiten für die einzelnen
Schritte eines Musters (wie bei animierten GIFs für die einzelnen
Frames).
> oder wie in der letzten Modifikation die> Schrittnummer des gerade aktuellen Schrittes.
Das leutchtet mir jetzt nicht ein, denn es ist ja immer nur ein Muster
aktiv. Warum also den aktuellen Schritt in den Mustern speichern und
nicht in einer globalen oder statischen Variablen? Nur damit die Muster
beim Umschalten dort weiter machen, wo man sie zuletzt weggeschaltet
hat?
Karl Heinz Buchegger schrieb:> Da könnte zb noch für jedes Muster eine spezifische> Verzögerungszeit dazukommen.
Welche bei mir nicht immer konstant ist. Die ist teilweise abhängig von
der Anzahl der Funktionsaufrufe.
Aber über deinen Vorschlag müsste ich noch mal etwas genauer nachdenken.
Bei dir wird das Muster (mit Schrittzahl, Blinkmuster und
Verzögerungszeit) ja quasi zu einem Objekt. Auch wenn man diese in C
nicht hat, aber du würdest alle Eigenschaften in der Struktur abbilden,
wenn ich das richtig verstehe.
R. Max schrieb:>> oder wie in der letzten Modifikation die>> Schrittnummer des gerade aktuellen Schrittes.>> Das leutchtet mir jetzt nicht ein, denn es ist ja immer nur ein Muster> aktiv. Warum also den aktuellen Schritt in den Mustern speichern und> nicht in einer globalen oder statischen Variablen? Nur damit die Muster> beim Umschalten dort weiter machen, wo man sie zuletzt weggeschaltet> hat?
Ist nur ein Vorschlag.
Kann jeder machen wie er will :-)
Christian Schoknecht schrieb:> Aber über deinen Vorschlag müsste ich noch mal etwas genauer nachdenken.> Bei dir wird das Muster (mit Schrittzahl, Blinkmuster und> Verzögerungszeit) ja quasi zu einem Objekt.
Bingo!
(Na ja. Fast)
> Auch wenn man diese in C> nicht hat, aber du würdest alle Eigenschaften in der Struktur abbilden,> wenn ich das richtig verstehe.
Jep. Das brauch ich, damit ich in der Hauptschleife dann schreiben kann
1
while(1)
2
{
3
if(day==0)
4
// spiele einen Schritt vom momentan eingestellten aktiven Muster ab.
5
playIt(alleMuster[interrupt_counter]);
6
7
else
8
{
9
resetLEDs();
10
_delay_ms(250);
11
}
12
}
und es passiert immer das richtige. Warum? Weil das Muster-Objekt selbst
alles mithat, was die Funktion benötigt um es abspielen zu können. Ich
hab quasi eine 2-teilung. Die Funktion stellt den Mechanismus - das
Muster Objekt die Details.
Und ich hatte mir überlegt, dass die Blinkmuster-Funktion immer den
nächsten "Blink-Schritt" aufgrund des vorherigen berechnet/zuweist.
Wobei ich deine Überlegungen gut nachvollziehen kann. Ich es aber
durchaus herausfordernd fand einen Algorithmus für die Leuchtmuster zu
suchen. Es gibt sicher auch bei mir Fälle, in denen es einfacher ist,
wenn es fest codiert ist. Nur sehe ich in der algorithmischen Berechnung
den Vorteil, wenn der Stern auf weitere Register erweitert werden
sollte. Denn der Speicheraufwand für die festcodierten Werte steigt dann
ja enorm an.
Allein für meine jetzigen Blinkmuster bräuchte ich schon 5*137 Byte an
Speicher, was in etwa einem Drittel des jetzigen Programms entspricht.
Bei Erweiterung um weitere SR wächst der Bedarf allein an Speicher für
jedes SR dann um 137 Byte und das nur bei der jetzigen Anzahl an
Mustern. Algorithmisch sind das ein paar Speicherplätze in dem
LED[]-Array und ein paar mehr Codezeilen, weil es ein paar mehr
Zuweisungen geben muss.
Aber schon einmal vielen Dank für das Interesse an dem Projekt und den
zahlreichen Hinweisen zur Optimierung.
Sobald die Kondensatoren eingetroffen sind, ich diese angelötet habe und
der Stern tut, was er soll, werde ich dann mal ein Video erstellen und
das hierher verlinken. Vielleicht regt das dann ja den einen oder
anderen zum Nachbau an und dem Ausprobieren deiner Idee mit der
konsequent umgesetzten Zustandsmaschine. Immerhin ist bald Weihnachten
und mein Stern soll ein Geschenk werden.
Christian Schoknecht schrieb:> Nur sehe ich in der algorithmischen Berechnung den Vorteil,> wenn der Stern auf weitere Register erweitert werden> sollte. Denn der Speicheraufwand für die festcodierten> Werte steigt dann ja enorm an.
Nur dann, wenn jede LED einzeln ansteuerbar sein soll (z.B. bei einem
umlaufenden Lauflicht). Falls es aber innerhalb des Sterns bei jedem
Schritt eines Musters periodische Wiederholungen gibt (z.B. alle Zacken
machen das gleiche), muß nur jeweils eine Periode gespeichert und dann
entsprechend oft in die Register geschoben werden.
Okay, es sind definitiv die Abblockkondensatoren gewesen, denn jetzt
läuft es wie am Schnürchen. Vielen Dank für den Hinweis.
Deshalb hier mal ein Video, wie das ganze dann im Dunkeln aussieht.
http://www.youtube.com/watch?v=wExSOsv7RWU
Sieht nett aus! :)
Hier noch ein Mustervorschlag: Alle LEDs sind an und es wird zufällig
immer mal wieder eine kurz (<1s) ausgeschaltet. Mit dem richtigen Timing
wirkt das wie ein glitzern oder funkeln.
Am besten sieht es aus, wenn die jeweilige LED nicht schlagartig
ausgeht, sondern aus- und wieder eingeblendet wird, aber ich weiß nicht,
ob Deine Schieberegister-Kette schnell genug ist, um auf einzelnen LEDs
auch noch PWM zu machen.