Guten Abend,
ich versuch nun schon seit einigen Stunden eine Spannung mit hilfe des
ADC's des Atmega8 einzulesen, aber leider ohne Erfolg.
Das Internet hab ich auch schon wundgesucht, aber nichts passendes
gefunden.
Ich will eine kleine LED, welche an Pin0 von Port C angeschlossen ist,
in verschiedenen Frequenzen blinken lassen.
Dazu wollte ich die 8 höherwertigen Bits auslesen und damit eine
Zeitschleife "steuern" (0-255 Durchläufe * ca.10ms ).
Das Speichern des "Spannungswertes" erfolgt in der Interruptroutine des
ADC
Erstmal der Ausschnitt des Codes:
1
.include "m8def.inc" ;Definitionsdatei fuer den ATmega8 dazuladen
2
3
.dseg
4
5
COUNT: .BYTE 1
6
.cseg ;Beginn eines Code-Segmentes
7
8
.org 0x00 ;Startadresse=0x0000 (Anfang des Flash)
9
10
rjmp start
11
12
.org OVF1addr
13
rjmp OVF1
14
.org ADCCaddr ; ADC Interrupt Vector Address
15
rjmp ADCRUPT
16
17
18
start: ldi r16, 0b11111111
19
out ddrd,r16
20
out ddrb,r16
21
out ddrc,r16 ;Alle Ports auf output
22
23
ldi r16,high(RAMEND) ;
24
out SPH,r16 ; Set Stack Pointer to top of RAM
25
ldi r16,low(RAMEND)
26
out SPL,r16
27
28
LDI r16, 91
29
sts COUNT, r16 ;COUNT Variable auf 1s initialisieren
30
31
32
33
rcall ADCINI ;ADC initialisieren
34
sei ;Interrupts zulassen
35
main:
36
37
38
39
40
SBI portc, 1
41
rcall wait
42
CBI portc, 1
43
rcall wait
44
45
46
ldi r18, 0b11001111
47
out ADCSRA, r18 ;ADC conversion start
48
49
50
51
rjmp main ;Schleife neu beginnen
52
53
54
55
56
TMR1: ldi r18, 0b00000100
57
out TIMSK, r18 ;Interrupt enable
58
ldi r16,0x01
59
out TCCR1B,r16 ;Timer Start(kein prescaler)
60
ret
61
62
OVF1: inc r19
63
reti
64
65
66
67
wait11ms: clr r19 ;Warteschleife 11ms
68
rcall TMR1
69
loop1: ldi r20, 0x02
70
SUB r20, r19
71
BRNE loop1
72
ret
73
74
75
wait: lds r21, COUNT ;Variable COUNT laden
76
loop2: rcall wait11ms ;11ms warten
77
dec r21 ;COUNT bis 0 dekrementieren
78
BRNE loop2
79
ret
80
81
;***********ADC Initialisierung****
82
ADCINI: ldi r16, 0b01100000
83
out ADMUX, r16 ;Pin PortC0, left adjust,AVCC + AREF Capacitor
84
ldi r16, 0b10001111
85
out ADCSRA, r16 ;ADC enable,Interrupt enable, Prescaler 128
86
ret
87
88
;***********ADC Interrupt**********
89
ADCRUPT: in r0, ADCH ;"Spannungswert" aus ADCH Register lesen
90
sts COUNT, r0 ;und in Variable COUNT schreiben
91
92
reti
In der Simulation läuft das alles Einwandfrei. Die Zeitschleife
funktioniert auch wenn ich die Werte für COUNT manuell im Code zuweise.
Wenn ich das Programm nun übertrage und im Schaltungsaufbau teste, dann
scheint es so, als würde der Wert von COUNT ständig bei 255 liegen, egal
wie ich das Poti drehe.
Bin schon am Verzweifeln, ich hoffe hier kann mir jemand helfen :-)
Den Schaltplan hab ich acuh noch angehängt.
Gruß, Arood
Bin jetzt zu faul ins Datenblat zu schauen, aber
ldi r16, 0b11111111
out ddrd,r16
out ddrb,r16
out ddrc,r16 ;Alle Ports auf output
port C ist ausgang. so dass Du dein hier den Port samplest?
Wie gesagt, zu faul, aber wenn man man ADCH ausliest, muss man nicht
auch ADCL auslesen?
Versuche, eine Debug-Ausgabe zu realisieren, entweder eine Serielle zum
PC oder zumindest die ADC-Daten am PortD auszugeben, damit Du siehst, an
welcher Stelle es hakt.
Im DDRC ist alles auf Ausgang, PortC0 ist Dein ADC-Eingang.
@Robert:
Für diese simple Schaltung ist es doch nicht essentiell, das Poti an
AREF anzuschließen, oder?
Was meinst du mit Stellspannung?
@Tobi
Ob input oder output dürfte egal sein wenn der ADC aktiviert ist, hab
acuh beides ausprobiert, so isses net :-)
Das Datenblatt sagt, ADCH auszulesen reicht wenn es links ausgerichtet
ist.
GND und AGND sind verbunden, ja
Wenn der eingelesene Wert nicht verändert werden kann, kann es sein,
dass das Poti keine veränderlichen Werte liefert. Ein Nachmessen mit dem
Multimeter ist daher sinnvoll.
Die Frage von tobi ist IMHO noch nicht befriedigend beantwortet.
Laut Schaltplan.png hat AGND keine Verbindung zu GND und bambelt in der
Luft, wenn der ISP-Programmieradapter nicht eingesteckt ist.
Versuchsweise würde ich den Test mit einer zusätzlichen Brücke von GND
nach AGND wiederholen.
NB: Welchen Zweck hat R2?
AVcc o-----###-----o Vcc
R2 47R
Das Poti liefert veränderliche Werte, das hab ich schon gemessen.
GND und AGND sind verbunden, da ist im Schaltplan nur irgendwie die
Junction verschwunden (oberhalb rechts von C6)
R2 hatte ich ursprünglich nicht drin, den hab ich auf ner Beschaltung
hier in den Infos gesehen, statt einer Spule. Dann hab ich ihn halt mal
reingelötet
Arood schrieb:>> R2 hatte ich ursprünglich nicht drin, den hab ich auf ner Beschaltung> hier in den Infos gesehen, statt einer Spule. Dann hab ich ihn halt mal> reingelötet
Du hast 47 Ohm in der Stromversorgung von PortC und ADC und wunderst
Dich, dass der ADC nicht funktioniert?
...
Nö, wenn der Port Ausgang ist, is er Ausgang.
Wär mir neu, dass die ADC-Unit da von sich aus umschaltet. Kannst mich
natürlich mit Datenblatt-Seiten-Angabe geren überzeugen ;-)
Du startest die Conversion, wartest aber nicht bis die fertig ist. Hier
ist in dem Code eine Race-Condition.
(Kann es sein, dass der ADC eine Conversion abbricht und neu startet,
wenn man bei einer laufenden Conversion nochmal SC schreibt?)
Aber bring mal erstmal deine Schaltung in Ordnung:
- AGND muss angeschlossen sein (verbinde es einfach mit GND, das passt
schon)
- Hinweis: Der C am VREF muss streng genommen auch mit AGND verbunden
werden, nicht mit GND -- wenn man es exakt machen möchte
- die 47Ohm werden zwar nix machen (da in AVCC nicht viel Strom reingeht
und der nicht getaktet ist) jedoch ist hier 0Ohm besser (normalerweise
werden in ner Schaltung die Analogen versorgunen und massen extra
geroutet und dann an einem Sternpunkt zusammengeschlossens.)
Atmel empfiehlt eine Spule + C um Störungen zu filtern. Steht in jeden
Datenblatt und auch in ein paar ANs, braucht man aber meistens nicht.
PS: Sample mal Kanal 0b1110 (VBG). Dann kannst Du das Problem eingrenzen
ob SW oder HW. (nat. muss auch hier AREF,AVCC,ABGND richtig sein....)
PPS: Dein Schaltplan ist recht unübesichtlich und schwer zu lesen...
Arbeite mehr mit Netznamen und Symbolen (z.B für +5V, GND, ...)
z.B wie hier: Beitrag "Re: DTMF AVR314 nach mega8"
@Arood: Nein, AREF darf nicht belastet werden. An AREF hat ein C und
sonst nix was verloren.
Ich habe die Schaltung kurz aufgebaut (leicht verändert, da M32 statt
M8) und es funktioniert einigermaßen.
Das Problem liegt an der Warteschleife, da sie sowohl bei 0 als auch bei
FF lange wartet.
Von 0,00 bis 0,027V blinkt die LED langsam, bei 0,03V so schnell, dass
man es nicht mehr sieht (halbe Helligkeit). Ab 0,06V merkt man, dass sie
sehr schnell blinkt.
Vielleicht willst Du nicht die Periodendauer, sondern die Frequenz
proportional zur Eingangsspannung machen?
Manchmal "blinzelt / verschluckt" sie einmal kurz. Liegt daran, was
"Entwickler" gerade schrieb.
Das Blinken würde ich direkt in der Timer-ISR machen.
Das Konstrukt mit wait11ms ... ist alles verworren.
47 Ohm als RC-Filter statt einer L in Verbindung mit einem C sollte in
Ordnung sein, es können auch weniger Ohm (oder mehrere 47er parallel)
sein, falls vorhanden. Allerdings sollten dann keine
PullDown-Verbraucher dranhängen. Du hast nicht geschrieben, ob Deine LED
an +5V oder Gnd geht.
sooo, nabend!
Danke erstmal für die zahlreichen Antworten :-)
Im Anhang hab ich mal den aktuellen Schaltplan.
Ich versuch jetzt mal den Code zu überarbeiten, dann meld ich mich
wieder :-)
>Von 0,00 bis 0,027V blinkt die LED langsam, bei 0,03V so schnell, dass>man es nicht mehr sieht (halbe Helligkeit). Ab 0,06V merkt man, dass sie>sehr schnell blinkt.
Das versteh ich jetzt absolut nicht, warum sind hier die änderungen nur
bei <0,06V zu sehen?
Ich warte doch in der Zeitschleife länger, wenn die Spannung sich
erhöht.
Ob nun die Frequenz oder die Periodendauer proportional zur Spannung
ist, das ist mir eigentlich egal, programmiert ist es aber auf die
Periodendauer.
...aber naja, wie gesagt, ich versuch mich erstmal an nem sauberen Code
Gruß
soo, hab jetz mal was neues geschrieben. Ich hab die Interrupts jetz
komplett weggelassen und arbeite mit dem overflow-flag vom Timer1 und
dem SC Bit vom ADC.
Mit dem SREG Register sollte es jetzt auch keine Probleme geben
eigentlich.
Das Problem ist leider nach wie vor, irgendein fester Wert füttert meine
Warteschleife. Das Poti am ADC zeigt keinerlei Wirkung :-(
1
.include "m8def.inc" ;Definitionsdatei fuer den ATmega8 dazuladen
2
3
.dseg
4
5
COUNT: .BYTE 1
6
.cseg ;Beginn eines Code-Segmentes
7
8
.org 0x00 ;Startadresse=0x0000 (Anfang des Flash)
9
10
11
12
13
ldi r16, 0b11111111
14
out ddrd,r16
15
out ddrb,r16 ;PortB/PortD auf Output
16
ldi r16, 0b11111110
17
out ddrc,r16 ;PortC Pin0 auf input, Rest output
18
19
ldi r16,high(RAMEND) ;
20
out SPH,r16 ; Set Stack Pointer to top of RAM
21
ldi r16,low(RAMEND)
22
out SPL,r16
23
24
LDI r16, 255
25
sts COUNT, r16 ;COUNT Variable auf 0,5s initialisieren
Arood,
könnte daran liegen, dass Du nur den Wert von TCNT1L setzt (direkt vor
Label "null"). Guck' doch mal im Datenblatt “Accessing 16-bit Registers”
on page 77. Meiner Meinung nach musst Du IMMER zuerst TCNT1H und TCNT1L
setzen, und zwar ZUERST TCNT1H und direkt DANACH TCNT1L sonst funzt's
nicht.
mare_crisium
Nein, daran liegt es leider nicht. Die Warteschleife funktioniert ja
soweit wunderbar, sofern ich die Werte für COUNT nicht mit Hilfe des ADC
festlege sondern "per Hand" direkt im Programm eingebe.
Hi
>Die Warteschleife funktioniert ja>soweit wunderbar, sofern ich die Werte für COUNT nicht mit Hilfe des ADC>festlege sondern "per Hand" direkt im Programm eingebe.
Dein Programm ist zwar nicht sehr schön, aber es funktioniert.
Kontrolliere mal deine Schaltung. Kannst du am ADC-Eingang (PC0) eine
von der Poti-Stellung abhängige Spannung messen?
MfG Spess
Hi
Ergänzung:
Ich schrieb:
>Dein Programm ist zwar nicht sehr schön, aber es funktioniert.
allerdings nur wenn man diese Zeile:
> lds r19, COUNT ;ADC-Wert aus COUNT laden und> dec ;dekrementieren <-------> sts COUNT, r19 ;und wieder abspeichern
in 'dec r19' ändert.
MfG Spess
das 'dec r19' ist wohl beim posten kaputt gegangen, da hätte AVR Studio
ja gemeckert!
aaaaaaaaaber ich hab das Problem gefunden, des kann ich kaum erzählen
:-)
Als ich die Spannung am PinC0 gemessen hab, hab ich immer an meiner
eingelöteten Stiftleiste gemessen, nicht direkt am IC.
Kaum mess ich am IC, merk ich, dass da nichts anliegt.
Der Pin vom IC-Sockel ist irgendwie nicht vorhanden, allerdings siehts
an der Lötseite so aus, als wäre er da....naja...dumm gelaufen.
In Zukunft mess ich wohl lieber immer direkt am IC...
Danke an alle die geholfen haben!
Gruß