Hallo,
zunächstmal ein dickes Lob für die wirklich guten Tutorials, sie haben
mir den Einstieg in die AVR Prorgammierung sehr erleichtert.
Dennoch habe ich eine Frage:
Ich habe mir aus den Codebeispielen der Tutorials ADC, PWM und
LED-Fading ein Programmzusammengebastelt das eine LED dimmen sollte.
Soweit so gut, ich bin der Meinung das Programm tut, also übertrage ich
es auf meinen ATmega8.
Ich beschalte ihn wie in der Skizze angegeben zu Testzwecken mit
Labornetzteil, deshalb keine Kondensatoren zur Spannungsglättung.
VCC auf+5V, GND auf 0V
Reset mit einem 100M Widerstand auf +5V
die LED mit -Pol auf 0V mit +Pol an den Timerausgang von Timer1
(selbstverständlich mit passendem Vorwiderstand).
AREF auf +5V, die Masse auf der "rechten Seite" auf die 0V der anderen
kurzgeschlossen und ein Poti (1MOhm linar) zwischen AREF und 0V mit
Mittenabgriff auf ADC0 der vom ADC eingelesen werden sollte...
Meines erachtens nach sollte die LED dann mit dem Poti zwischen ganz aus
und immer an dimmbar sein. Leider bleibt die dunkel egal in welche
Stellung ich den Poti drehe.
Was habe ich falsch gemacht/welche Stelle des Tutorials habe ich falsch
verstanden? vielen Dank für eure Hilfe
Christoph Müller
Im Anhang das Pinout aus dem Datenblatt...
> Reset mit einem 100M Widerstand auf +5V
Aussergewöhnlich. Normalerweise nimmt man da so 10 KOhm.
> AREF auf +5V,
Externe Spannung auf AREF ist keine gute Idee. Eine Fehlkonfiguration
der Referenz des ADC und das wars.
Verbinde AREF nur über einen 100nF Kondensator mit AGND. Die +5V für
AREF kannst du prima über die interne Referenz auf den ADC schalten. Wie
steht im Tutorial.
> und ein Poti (1MOhm linar) zwischen AREF und 0V mit> Mittenabgriff auf ADC0 der vom ADC eingelesen werden sollte...
Ähm. Wenn du eine Spannung gegen AREF messen willst, dann sollte die
Schaltung nicht AREF beeinflussen. Ich würde das Potentiometer nicht an
AREF hängen.
Das 1 MOhm ist viel zu hochohmig. Nimm ein 10 oder 22 kOhm Poti.
100 nF Abblockkondensatoren zwischen Vcc/GND und AVCC/GND und AREF/GND
sind sehr zu empfehlen.
AVCC (pin 20) muss auch Saft bekommen!
Quellcode habe ich nicht groß angesehen, weil mich die exotische
Schaltung "gefesselt" hat. Mich wundert aber, dass die LED an OCR1B (Pin
16) hängt im Programm aber mehrfach ...A (OCR1AH/L, COM1A1) benutzt
wird.
Welche Teile deines Programms hast du unabhängig von allen anderen
getestet?
Wenn du jetzt sagst: keine
dann hast du IMHO den Kardinalfehler schlechthin gemacht. Du hast zuviel
Code auf einmal geschrieben ohne dir zu überlegen in welcher Reihenfolge
du die Dinge einzeln während der Entwicklung in Betrieb nehmen kannst.
Leg in dem Fall dein Programm beiseite und fang noch einmal mit einem
neuen an.
Aber: arbeite diesmal in Etappen.
Ein guter Einstieg ist es zb immer, wenn man zunächst sicherstellt, dass
"Ausgaben" klappen, was auch immer dann "Ausgaben" konkret sein mögen.
Bei dir ist das eine LED.
Also soll dein erstes Programm einfach nur die LED einschalten.
Gegentest: LED ausschalten.
Dann weist du schon mal: Der Pin funktioniert, die LED funktioniert, der
Prozessor funktioniert, ich kann Programme übertragen.
Dann gehts weiter mit der PWM.
Aber bitte nicht mit Tabelle und allem Drum und Drann. Einfach nur Timer
konfigurieren, einen fixen Wert ins OCR Register und die LED muss eine
bestimmte Helligkeit einnehmen. Den Wert variieren und die Helligkeit
muss sich verändern.
Dann kommt der ADC ins Spiel
In einem ersten Schritt reicht es völlig aus, den ADC Wert auszulesen
und wenn der über 512 ist (oder was die Grenze sein soll) eine LED
einschalten. Ist der Wert unter der Grenze die LED ausschalten.
Den Schritt könnte man überspringen, indem man den ADC Wert geeignet
skaliert direkt ins OCR Register schreibt. Gegebenenfalls die PWM
Obergrenze auf 1024 setzen (also 10 Bit PWM) oder den ADC Wert
entsprechend zurechschieben, damit Der ADC Wert die PWM auch voll
aussteuern kann.
Und dann kannst du deine Tabelle zur optischen Linearisierung einbauen.
Wichtig: Den nächsten Schritt, das nächste Zwischenziel erst dann in
Angriff nehmen, wenn das vorhergehende zur Zufriedenheit funktioniert.
Sonst gehts dir nämlich so wie jetzt: Du stehst mit einem Haufen Code da
der nicht funktioniert und hast keine Ahnung wo du mit Suchen anfangen
sollst.
Und den meisten hier wirds so ähnlich gehen wie mir: Wir haben keine
Lust, da jetzt 5 Subsysteme auf mögliche Fehler abzuklopfen, wenn wir
uns auf nichts Getestetes stützen können und einzig die Fehlermeldung
"Geht nicht" haben. Der Fehler kann etwas ganz einfaches sein (wird es
wahrscheinlich auch sein), aber er kann überall sein, weil nichts in
seiner einfachsten Form getestet wurde.
Das schlimmste was du tun kannst, ist von der Annahme auszugehen, dass
du ein fehlerfreies Programm auf Anhieb abliefern kannst. Das kann
niemand. Daher arbeitet man in Etappen, damit man möglichst schnell und
möglichst oft testen kann.
Hi
> ldi ZL, LOW(pwm_tabelle)> ldi ZH, HIGH(pwm_tabelle)
Das ist falsch. Die Adresse 'pwm_tabelle' muss als Byte-Adresse
angegeben werden:
ldi ZL, LOW(pwm_tabelle<<1)
ldi ZH, HIGH(pwm_tabelle<<1)
Das ist auch etwas umständlich:
> clc> adc ZL, PWMValue> brcc 1> inc ZH> clc> adc ZL, PWMValue> ....
clr temp
lsl PWMValue ; PWMValue x 2
rol temp
add ZL, PWMValue
adc ZH, temp
und das Laden aus dem Flash funktioniert auch anders:
lpm temp, Z+
;läd timer wert für PWM in Timer1
out OCR1AH, temp
lpm temp, Z
out OCR1AL, temp
MfG Spess