Hallo zusammen,
ich habe zwar gehofft das Problem alleine lösen zu können, komme aber
einfach nicht weiter.
Mein ADC des Atmega328P gibt immer den Höchstwert (1023) aus.
Zum Testen hatte ich zunächst eine "komplexere" Schaltung, die ich jetzt
aber verworfen habe. Nun lese ich die Spannung an einem
Potentiometerabgriff ein und möchte ab einem bestimmten Grenzwert eine
LED leuchten lassen.
Mein Code sieht momentan so aus:
1
#include<avr/io.h>
2
3
voidADC_init(void){
4
ADMUX|=(1<<REFS0);//reference voltage on AVCC mit externen Kondensator 100nF an GND
5
6
ADMUX&=~(1<<MUX0);// Einstellen Kanal 0
7
ADMUX&=~(1<<MUX1);
8
ADMUX&=~(1<<MUX2);
9
ADMUX&=~(1<<MUX3);
10
11
ADCSRA=(1<<ADEN);// ADC enablen
12
ADCSRA|=(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);// Prescaler auf 128 da 16MHz Takt
13
14
ADCSRA|=(1<<ADSC);// Dummy
15
while(ADCSRA&(1<<ADSC)){// auf Abschluss der Konvertierung warten
16
}
17
(void)ADCW;
18
}
19
20
21
22
intmain(void){
23
24
uint16_tPotentiometerWert;
25
uint16_tGrenzwert;
26
27
Grenzwert=0b10000000;
28
29
30
DDRD|=(1<<DDD2);
31
32
PRR&=~(1<<PRADC);// Datenblatt sagt dieses Bit muss auf 0 gesetzt werden, obwohl kein Beispiel im Internet dies tut...
33
34
ADC_init();
35
36
while(1){
37
38
ADCSRA|=(1<<ADSC);// Start Conversion
39
while(ADCSRA&(1<<ADSC)){// auf Abschluss der Konvertierung warten
40
}
41
42
PotentiometerWert=ADCW;
43
44
if(PotentiometerWert>=Grenzwert)
45
{
46
PORTD|=(1<<PORTD2);
47
}
48
49
else
50
{
51
PORTD&=~(1<<PORTD2);
52
}
53
54
return(0);
55
}
56
}
Den Atmega328P verwende ich mit einem Arduino Uno Board, daher müsste an
AVcc bereits Vcc anliegen. Zusätzlich habe ich an den ARef Pin einen
100nF Kondensator auf GND gelegt. Dass ich den Höchstwert erhalte, habe
ich getestet, indem ich die IF-Bedingung auf 1023 gesetzt habe und die
LED immer noch leuchtete.
Ich habe auch gelesen, dass meine Input-Pins einen internen PULLUP
geschaltet haben könnten. Deshalb habe ich es mit "MCUCR |= (1<<PUD);"
probiert, um alle Pull-Ups von vorneherein abzuschalten, ohne Erfolg.
Leider weiß ich nun wirklich nicht mehr, woran es liegen könnte, habe
schon einiges versucht. Eine Idee war noch, dass AVcc wohl doch nicht
auf 5V liegt und ich deshalb den Höchstwert auslese, aber die Arduino
Pinbelegung bestätigt dies nicht. Die Suchfunktion hat mir auch keine
passende Lösung gegeben.
Kann mir vielleicht jemand einen Tipp oder Anhaltspunkt geben?
Ich hoffe meine Formatierung ist in Ordnung, dies ist mein erster Post.
Für Stilverbesserungen bin ich auch dankbar.
Mit freundlichen Grüßen
Neuling schrieb:> Ja, das kann man einfach ignorieren.
Nein. Das gehört da nicht hin, denn der Compiler ignoriert das nicht.
Also, was soll der Sch...?
S. Landolt schrieb:> Also, wenn ich das bei mir auskommentiere, dann läuft es.> (Allerdings nicht auf einem Arduino
auskommentiert würde es auch auf dem Arduino laufen!
Entweder Arduino stile
setup()
loop()
oder
AVR
while(1)
und never return!
> Allerdings nicht auf einem Arduino, sondern, festhalten, auf einem> STK200
Du hast auch den Atmega328P verwendet? Das ist interessant,
normalerweise sollte das return 0 keine Rolle spielen. Es liegt also an
meiner Hardware, wenn ich das richtig deute. Oder kann doch irgendwie
mein Eingang auf 5V gezogen sein und ich muss das auf andere Weise
umstellen?
Neuling schrieb:> normalerweise sollte das return 0 keine Rolle spielen.
das erkläre bitte mal!
while(1) hast du ja, aber was passiert wohl bei return?
Das darf da nicht sein!
Neuling schrieb:> normalerweise sollte das return 0 keine Rolle spielen
Oh doch. Das return(0) springt wieder zu main(). Das hört sich zwar
unproblematisch an, aber nach der Initialisierung hat der ADC beim
ersten Auslesen erstmal Murks raus. Ersten ausgelesenen Wert verwerfen
und dann in einer while(1) ohne return weiter machen
>das erkläre bitte mal!
Jetzt sehe ich, dass das return innerhalb der while-Schleife war. Das
ist natürlich blöd! Ihr habt vollkommen Recht.
Leider will es dennoch nicht funktionieren. Kann es sein, dass irgendein
Bit beim Arduino gesetzt ist, dass ich clearen muss?
Der springende Punkt ist der, dass dein Return INNERHALB der
While-Schleife steht. Wäre es außerhalb - eine Instanz tiefer - dann
wäre es tatsächlich wirkungslos.
Neuling schrieb:>>Was soll das tun?>> Das habe ich aus dem ADC Tutorial -> https://www.mikrocontroller.net/articles/AVR-GCC-T...> aus Verzweiflung übernommen, da es nicht funktionierte.
Also wenn man das Beispiel aus dem Tutorial 1:1 übernimmt, funzt es bei
mir auf dem 328p. Solltest du vielleicht auch mal machen
>Also wenn man das Beispiel aus dem Tutorial 1:1 übernimmt, funzt es bei>mir auf dem 328p. Solltest du vielleicht auch mal machen
Habe ich eben auch mal probiert, ohne Erfolg. Ich schätze mal irgendeine
Eigenheit vom Arduino verhindert das Funktionieren. Ich meine es ist
schon verdächtig, dass ich immer den Höchstwert einlese.
Neuling schrieb:> Ich meine es ist> schon verdächtig, dass ich immer den Höchstwert einlese.
Vielleicht hast du auch nur das Poti falsch angeschlossen.
Wie hoch ist denn deine Referenzspannug tatsächlich? Kannst du mit nem
Multimeter an Aref messen.
> Kannst du mit nem Multimeter an Aref messen.
Ich werde morgen einmal nachmessen.
Außerdem will ich noch einmal ein Standardprojekt mit Arduino-Code
(analogRead()) testen, ob da das gleiche Problem besteht, da ich mich
nicht mehr richtig erinnern kann. (Ich wollte mich von
Arduino-Programmierung entfernen, habe ansonsten nur mit STM32 (Cortex
M3) Erfahrung)
Neuling schrieb:>>Also wenn man das Beispiel aus dem Tutorial 1:1 übernimmt, funzt> es bei>>mir auf dem 328p. Solltest du vielleicht auch mal machen>> Habe ich eben auch mal probiert, ohne Erfolg. Ich schätze mal irgendeine> Eigenheit vom Arduino verhindert das Funktionieren. Ich meine es ist> schon verdächtig, dass ich immer den Höchstwert einlese.
Habs auch auf einen Arduino geschossen
Arduino Fanboy D. schrieb:> Schöner geht immer, soll allerdings nicht meine Baustelle sein.
Wenn nur andere Leute auch solch "unschöne" Listings
liefern würden (das ist Ordnung pur gegenüber dem
Chaos von Anderen!).
while(ADCSRA&1<<ADSC){}// Warten bis die Dummy-Wandlung abgeschlossen ist
11
(void)ADC;// Dummy-Ergebnis verwerfen
12
13
DDRB|=(1<<5);// Onboard-LED ist an PB5 High-Active
14
DDRB|=(1<<1);// Hier schalte ich PORTB1 auf HIGH als Ausgang
15
PORTB|=(1<<1);// Hier schalte ich PORTB1 auf HIGH als Spannungsversorgung für das Poti
16
17
uint16_tGrenzwert=0;
18
19
while(1){
20
21
Grenzwert=500;
22
23
ADCSRA|=(1<<ADSC);// ADC starten
24
while(ADCSRA&1<<ADSC){}// Warten bis die Wandlung abgeschlossen ist
25
26
if(ADC>Grenzwert){
27
PORTB|=(1<<5);
28
}
29
else{
30
PORTB&=~(1<<5);
31
}
32
33
}// Ende while (1)
34
}// Ende int main(void)
Ich habe dir mal ein paar Zeilen getippt.
Läuft auf einem Pro Mini - Klon von Pollin (810366) mit ATmega168PA oder
ATmega328PA.
Ich erinnere mich noch an meine ersten Gehversuche mit den Atmels und
wäre auch heilfroh über ein paar einfache Zeilen Code gewesen.
Das Poti hängt an GND und über PB2 an Vcc. Der Abgriff geht auf ADC0.
Hoffe ich konnte dir helfen.
Gruß Daniel
Guten Tag zusammen,
erstmal vielen Dank and Daniel und Arduino Fanboy, dass ihr euch die
Zeit genommen habt. Auch ein Danke an Thomas. Das Nachmessen hat
wirklich ergeben, dass an ARef 0V lagen (wobei mein DMM schrecklich
ist). Tja woran lags? Ich habe mit meiner tollen Noise Reduction den
ARef Pin auf Masse gezogen, da ich auf dem Breadboard den Kondensator
kurzgeschlossen habe. Dämlich ich weiß. Jedenfalls bin ich froh, dass es
nicht der Code war (das return war doof kopiert und hätte ich niemals an
diese Stelle geschrieben).
>Kann es sein, dass die LED auf Masse geschaltet wird?
Was wäre daran verwerflich?
Neuling schrieb:> Was wäre daran verwerflich?
Überhaupt nichts :-)
Aber du würdest den Fehler dann vielleicht an der falschen Stelle
suchen.
Freut mich, dass es jetzt klappt.
Gruß Daniel