Hallo,
ich befinde mich so mitten im Einstieg in die µC-Welt.
Nachdem ich mich ein wenig mit C probiert habe
(Beitrag "[AVR|C] Codeschloss Projekt - wie den Code verbessern"), habe ich gemerkt das mir
ein besseres Verständnis der Hardware wichtig ist.
Ich habe hier 4 ATtiny12 rumliegen, die ich gerne als LED-Controller
verwenden möchte.
Der Controller soll über eine 4-Bit Einstellmöglichkeit (z.B.
DIP-Switches) verschiedene Modi für den Betrieb einer LED realisieren.
Zum Beispiel:
Dimmen in 10%-Schritten
Strobe (versch. Geschwindigkeiten) (wollte ich den Timer nutzen)
Ich habe nach einem kurzen Blick ins Tutorial hier mir gestern einfach
mal die AVR-Befehlsreferenz (und Google) geschnappt und drauf los
programmiert.
Das es nicht gleich 100% geklappt hat, war zu erwarten ;)
In meinem angehängten Beispielcode wird sich ein Fehler finden lassen.
Meine Vermutung ist, dass es mit den Flags im SREG zu tun hat, da ich
mehrfach hintereinander cpi ausführe. (nach der Marke 'inLoop')
Was kann ich nun tun, um diesen Fehler zu vermeiden?
Da ich mit 0-Ahnung eingestiegen bin, danke ich auch für jeden
anderweitigen Verbesserungsvorschlag.
LG:
Jan W.
>In meinem angehängten Beispielcode wird sich ein Fehler finden lassen.
vllt., aber besser du beschreibst den fehler mal. gibt es eine
fehlermeldung? welche?
Viel Erfolg
MeinFehleer
Oh, sorry.
Klar, so könnt ihr ja auch nichts damit anfangen.
Das Listing habe ich ja auch angehängt. Fehler werden nicht ausgegeben.
PB0-PB3 dienen zur Eingabe des Modus (die besagten 4-bit). PB4 ist der
Ausgabepin, an dem die LED z.B. über einen ULN2803A oder 2x BC547 in
Darlingtonschaltung angeschlossen ist.
Die Verwendung der Register habe ich am Anfang kommentiert.
1
loop: cpi r20, 0x00 ; compare with 0
2
brne setHigh ; jump and set output high if r20 is not 0
3
inLoop: in r17, PINB ; load i/o
4
;[...]
5
6
setHigh: sbi PORTB, 5 ; set output to high
7
rjmp inLoop ; jump back
loop bis zu 'rjmp loop' ist der Teil, in dem ich den Modus abfrage und
auf die entsprechenden Unterabschnitte verzweige.
Da ich über die Dip-Switches die LED auch vollständig aus schalten
können möchte, muss ich das Einschalten bedingen.
Dazu prüfe ich r20. steht in r20 ein Wert anders 0, soll der PB4 high
gesetzt werden.
Dazu verzweige ich zu setHigh und springe danach wieder zurück (inLoop)
1
inLoop: in r17, PINB ; load i/o
2
andi r17, 0x0F ; delete high nibble (bit 7-4)
3
cpi r17, 0x01 ; compare with one
4
breq one ; jump if one (to 'one')
5
cpi r17, 0x02 ; compare with two
6
breq two ; jump if two (to 'two')
7
cpi r17, 0x03 ; compare with three
8
breq three ; jump if three (to 'three')
9
10
ldi r20, 0xFF ; set output high next time
11
rjmp loop ; jump back to the beginning
Hier lade ich PINB und eleminiere die oberen 4 Bit mit 'andi r17, 0x0F'.
Somit bleibt jetzt eine Zahl zwischen 0 und 31 über, die den jeweiligen
Modus repräsentiert.
Mit den 3 Blöcken (cpi ... breq ...) frage ich die Modi 1-3 ab und
springe ggf. Bei diesen 3 Blöcken vermute ich das Problem, vllt
beeinflussen die Flags, die beim vorhergehenden cpi gesetzt/gelöscht
wurden die danach kommenden cpi-breq Blöcke ja auch noch.
1
one: cbi PORTB, 5 ; set output to low
2
ldi r19, 0x05 ; 5 times nop (30 cyles)
3
ldi r20, 0xFF ; set high after nop
4
rjmp doNop ; jump to nopRoutine
Hier lösche ich erst den Output, lege dann in r19 die Anzahl der NOP
fest, die bis zum zurücksetzen auf high gewartet wird, setze r20 auf
0xFF damit (dar größer 0) im kommenden Durchlauf von loop der Pin wieder
high gesetzt wird, und springe dann zum Unterpunkt, in dem die NOPs
ausgeführt werden. Jedes Mal durchlaufen dauert 6 Taktzyklen.
two ist das selbe, nur mit der doppelten Anzahl NOP-Durchläufe
1
three: cbi PORTB, 5 ; set low
2
ldi r20, 0x00 ; DO NOT set output high in loop
3
rjmp loop ; jump to the beginning
Hier schalte ich die LED aus, und bestimme in r20, dass sie ausbleiben
soll. Dann springe ich gleich zurück. setHigh wird jetzt übersprungen
(da r20 equal 0)
1
doNop: cpi r19, 0x00 ; compare with 0 (1 cycle)
2
breq loop ; jump back if 0 (1 cycle)
3
nop ; (1 cycle)
4
dec r19 ; r19 minus 1 (1 cycle)
5
rjmp doNop ; and over (2 cycles)
6
; Sum: 6 cycles
Hier wird in einer Schleife die Anzahl Durchläufe gewartet bis zu loop
zurückgesprungen (und PB4 high gesetzt) wird, die in r19 definiert
wurden.
Ist eigentlich selbsterklärend.
LG
Hi
>setHigh: sbi PORTB, 5 ; set output to high>one: cbi PORTB, 5 ; set output to low
....
Gibt es nur, wenn du das Resetpin disabled hast.
>Hier lade ich PINB und eleminiere die oberen 4 Bit mit 'andi r17, 0x0F'.>Somit bleibt jetzt eine Zahl zwischen 0 und 31 über, die den jeweiligen>Modus repräsentiert.
Nein. 0...15.
MfG Spess
Jedoch habe ich bei nur 1 NOP-Durchlauf im Mittel nur 0.6V am Output.
Wie bekomme ich die Spannung höher (den Code kürzer)?
spess53 schrieb:
> Gibt es nur, wenn du das Resetpin disabled hast.
Habe ich gerade schon selbst gemerkt.
spess53 schrieb:
> Nein. 0...15
Hast du natürlich recht. 0-31 wäre es bei 5-Bit ;)
Ich mache euch einen Schaltplan.
Es sind 2 Transistoren BC547B oder BC547C in Darlington-Schaltung vor
der LED.
Eine LED an einem ULN2803A leuchtet übrigens ;)
So, ich habe es gemeistert
Nachdem die 0,6V gestern zu wenig waren, leuchtet meine weiße (!) LED
heute schon bei 0,01V :|
(Ja, ich habe mit 2 Multimetern nachgemessen, an der LED liegen 0,01V,
und sie glimmt)
Im Anhang Schaltplan und Code.
Ich habe statt high setzen, das low setzen in die loop Routine (hätte
ich main nennen sollen) geschrieben.
Dann habe ich eine zusätzliche Wartezeit für den low-Zustand eingebaut.
Ich kann nun beide Parameter (low und high Time) bestimmen.
Den Strobe habe ich mit dem Timer realisiert bekommen.
Und jetzt freue ich mich über Kommentare, Verbesserungsvorschläge und
Rückfragen ;)
LG:
jan
Hi
EinBC547 ist eigentlich in der Lage eine Led anzusteuern. Weshalb du
eine Darlington-Schaltung mit Led von Emitter nach Masse benutzt kann
ich nicht nachvollziehen. Die einfache Schaltung sieht so aus:
GND-Emitter
µC-Basiswiderstand-Basis
VCC-Vorwiderstand-LED-Kollektor oder VCC-LED-Vorwiderstand-Kollektor
MfG Spess
Da hast du recht!
ich hatte das während der Entwicklungszeit so aufgebaut, um ein
möglichst vergleichbares Bild mit den LEDs auf dem Addon-Board von
pollin zu bekommen. Die LEDs dort werden über einen ULN2803A
angesteuert, welcher auch eine Darlingtonschaltung beinhaltet.
Nur ging es in diesem Fall um eine weiße LED.
Das Ganze ist dann als "Altlast" auf'm Steckboard geblieben, und ich
habe den Schaltplan von dort abgeguckt.
Mittlerweile habe ich auch einen 3W-LED Driver dazu entworfen. Zusammen
mit dem Strobeeffekt eine schöne Sache :p
Den erneuerten Schaltplan habe ich wieder angehängt.
Bei der Software denke ich gerade darüber nach, wie man manche Sachen
verbessert programmieren kann:
Ich kann bspw. den Strobemodus nicht mit unterschiedlichen Helligkeiten
kombinieren, und ein Strobezyklus (an...aus) muss erst zu Ende
durchlaufen werden, bis der Modus gewechselt wird, auch wenn die
Einstellungen früher vorgenommen werden.
Jemand einen Ansatz, wie ich das umschreiben kann?
Desweiteren erarbeite ich gerade eine RGB-Version
(PB4-2: RGB, PB1: Programm (oder besser Tempo??), PB0: Hold/Run)
LG:
jan