Hallo Leute,
ich habe ein Problem mit dem internen AD_Wandler des Atmega32. Und zwar
liegt an dem Wandler an Pin1 (ADC0) ein Abstandsensor, welcher
Spannungen zw. 0,4 V und 2,56 V liefert. Abhängig von diesen Spannungen
möchte ich ein Servo üner pwm mit dem Timer/Counter 2 steuern. Da die
maximal gelieferte Spannung des Sensors 2,56 V ist, dachte ich mir, das
ist optimal um die interne Referenzspannung des Wandlers zu verwenden.
Das Problem ist bloß, das das pwm-signal nicht auf die Werte des
Ad-Wandlers reagiert, sie werden einfach ignoriert. Ich weiß nicht woran
das liegen könnte, ich habe das Datenblatt mehrmals durchgelesen und
auch hier im Forum gibt es ja genug Quelltext-beispiele.
ich hoffe hier kann mir jemand unter die Arme greifen, vielleicht es es
ja nur ein dummer Anfängerfehler.
Hier mein Quelltext:
1
#include<avr/io.h>
2
3
// Initialisierung des AD-Wandlers
4
voidadc_initial(void){
5
6
//interne Referenzspannung, AD-Wandler- kanal 0 (ADC0)
DDRD|=(1<<PD7);//OC2 (Pin 21) als PWM-Ausgang setzen
20
21
intmain(void){
22
23
while(1){
24
25
timer2_initial();//Timer 2 initialisieren
26
27
adc_initial();//AD-Wandler initialisieren
28
intDWert=0;
29
ADCSRA|=(1<<ADSC);//AD-Wandlung starten
30
while(!(ADCSRA&(1<<ADIF)));//Warten bis Wandlung beendet ist
31
DWert=ADC;
32
33
if(DWert>320)//320 entspricht 0,8 V
34
OCR2=0xC4;
35
else
36
OCR2=0x71;
37
}
38
}
Vielleicht sollte ich noch was zur Hardware sagen: zwischen AVCC des
Wandlers und Masse habe ich einen 100nF-Kondensator angebracht, ebenso
zw. AREFF des Wandlers und der Masse. Außerdem befindet sich ze. Vcc
(Versorgungsspannung des µC) und Avcc (Versorgungsspannung des Wandlers)
noch eine 22 µH -Spule. Im Datenblatt steht zwar was von 10 µH aber mir
wurde gesagt ich sollte es mit den 22 µH versuchen.
Vielen Dank schon für jede Hilfe, wenn och etwas unklar sein sollte
beantworte ich gerne alle Fragen
Grüße,
Bach001
Danke für die schnelle Antwort, aber trotzdem funktioniert es noch nicht
ganz wie ich will.
das pwm-signal reagiert immernoch nicht wirklich auf die vom Wandler
gelieferten Werte. Also der Wandler soll ohne unterbrechung ständig die
Werte des sensors wandeln und sobalt die grenze, also die 320
unterschritten wird, soll sich das pwm-signal ändern. Das tut es bis
jetzt nch nicht....
aber noch mal danke für die Hilfe..
Ich seh grad, dass du den Free Running Mode nutzt. Das vorhin ist mir
nur sofort ins Auge gesprungen.
Beim Free Running Mode muss man nur einmal starten mit
1
ADCSRA |= (1<<ADSC);
. Weiß jetzt nicht genau, ob in dem Modus das Bit jemals gelöscht wird.
Müsstest im Datenblatt nachsehen.
Ich würde jedoch den ADC Interrupt aktivieren und das Setzen vom Compare
Wert fürn Timer2 in der ADC ISR machen. Auto Trigger brauchst dann gar
nicht aktivieren, kannst einfach in den Idle oder ADC Noise Reduction
Sleep Modus gehen, da wird automatisch eine Wandlung gestartet.
Hallo,
@Tim: also wegoptimiert ist wohl nichts, habe deinen Vorschlag getestet,
aber ilft immernch nicht.
@Christopher G.:
1
ADCSRA|=(1<<ADSC);
habe ich auch ausprobiert, geht auch nicht. Allerdings wird das bit im
free running mode nie gelöscht, heißt das ich muss deshalb noch was
beachten?
dein zweiter vorschlag hört sih interessant an, allerdings ist mir noch
nicht alles ganz klar: in welchen register stelle ich den einen von den
beiden modes ein? im Register SFIOR wüsste ich nicht, was ich da
auswählen sollte.
zu den Interrupts steht im Datenblatt bei ADCSRA: "Bit 3 : when this bit
is written to one and the I-Bit in SREG is set, the ADC conversion
Complete Interrupt is activated"
Da schalte ich den interrupt doch ein, oder? aber was ist mit "I-Bit in
SREG" gemeint?
danke für alle antworten,
gruß Bach001
hmm...ich versteh das nicht..hab nch ein bisschen experimentiert, und
dabei rausgefunden, dass:
1
adc_initial();//AD-Wandler initialisieren
2
intDWert=0;
3
ADCSRA|=(1<<ADSC);//AD-Wandlung starten
4
5
DWert=ADC;
6
7
if(DWert>320)//320 entspricht 0,8 V
8
OCR2=0xC4;
9
else
10
OCR2=0x71
hier wird immer die else-Anweisung gestartet, unabhängig davon was DWert
liefert. Wnn ich (DWert > 320) zu (DWert < 320) mache, wird allerdings
die if-Anweisung aufgerufen. D.h. es wird immer die Anweisung < 320
aufgerufen.
Und das ohne den Wert des AD-Wandlers zu beachten.
könnte es sein, dass irgendwie ne while-schleife falsch gesetzt habe,
dass der AD-wert nicht aktualisiert wird ? oder das bei der Deklaration
der Variablen DWert etwas falsch gelaufen ist? Oder habe ich beim
Free-running mode etwas nicht beachten?
Bin langsam am verzweifeln...danke für alle Antworten...
Gruß
habe es jetzt ausprobiert, aber das ergebnis ist wie oben...hat sich
nichts verbessert, aber auch nicht falscher geworden :-)
mal ne andere (doofe)frage: also ich benutze den internen takt, 8 Mhz.
Kann ich da überhaupt im register ADCSRA den prescaler einstellen? weil
im datenblatt steht: "ADPS2:0 these bits determine the division factor
between the XTAL frequenzy and the input clock to the ADC" . aber an
XTAL hab ich ja garnichts hängen...
Und die Hardware stimmt? also nichts vergessen und die
spule/Kondensatoren richtig dimensioniert?
Grüße und vielen dank für die mühe
Zieh dir bitte das Datenblatt vom AtMega32 und lies dir die
entsprechenden Kapitel durch. Das Datenblatt ist sehr informativ, wenn
man es liest.
Dir fehlt eindeutig das Grundwissen.
Hi
>aber an XTAL hab ich ja garnichts hängen...
Mit der Aussage ist der Controllertakt gemeint.
Im Übrigen solltest du die ADC-Initialisierung aus der Schleife in der
main herausnehmen. Das macht man nur ein mal.
MfG Spess
So, es funktioniert jetzt....sage lieber nicht woran es lag...
Vielen Dank an alle für die Antworten, haben mir sehr geholfen, den
Ad-Wandler wirklich zu verstehen...super....
Grüße Bach001
Bach001 schrieb:
> So, es funktioniert jetzt....sage lieber nicht woran es lag...
Das ist der Falsche Ansatz. Wenn jetzt einer den Thread findet, weil er
einen ähnlichen Fehler hat, so steht er jetzt vor geschlossenen Türen.
Selbst wenn es nichts mit dem geposteten Code zu tun hat, weil der
Fehler sich wo anders eingeschlichen hat, poste es einfach. So kann man
schaun, ob man nicht denselben Fehler gemacht hat.
Selbst wenn der Fehler noch so blöd ist, keiner ist Perfekt.
Was ich schon an Fehlern gesucht - und auch gefunden - hab...
Ok, Christopher, hast wohl recht...
also sage ich den fehler: Die verbindung vom sensor zum µC- Pin, also
ADC0, war schlecht gelötet, so dass nichts am AD-Wandler ankam,also
hatte er auch nicht zu tun, und das pwm konnte natürlich auch nicht
funktionieren.
Also hier men tipp: Auch mal ab und zu direkt am µC-pin nachmessen, ob
überhaupt nen signal ankommt.
Mit den oben genannten Hinweisen funktioniert der Code also.
Nochmal danke an alle, dadurch habe ich auch das datenblatt nochmals
intensiever und mit mehr Verständnis gelesen als vorher...
viele Grüße
Manchmal ist es auch hilfreich, die Werte auf UART auszugeben
(debuggen).
Oder bei Binärgeschichten eine LED an einem Ausgang zur Überwachung
eines Bits zu benutzen.