Hallo,
Ich möchte mittels LM35 die Temp messen und habe den LM35 am ADC0.
Dieser liefert eine Spannung von ca. 2,31 V.
Leider zeigt das LCD immer 1023 an, egal ob das Kabel dran ist oder
nicht. DIe Spannung steht eigentlich auf interne Ref, aber selbst wenn
ich sie extern schalte und dort +5V dran habe passiert nix.
Das komische ist, dass es funktioniert hat, ich das ganze aber eine
Weile hab ruhen lassen und jetzt geht nix mehr.
Hier die zwei Routinen, die ich probiert habe. Beide werden ausgewertet
und zeigen 1023 an.
1. Routine
uint16_t ReadChannel(uint8_t mux)
{
uint8_t i;
uint16_t result;
ADMUX = mux; // Kanal waehlen
ADMUX |= (0<<REFS1) | (0<<REFS0); // interne Referenzspannung nutzen
ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler
// setzen auf 8 (1) und ADC aktivieren
(1)
/* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man
liest
also einen Wert und verwirft diesen, um den ADC "warmlaufen zu
lassen" */
ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
while ( ADCSRA & (1<<ADSC) ) {
; // auf Abschluss der Konvertierung warten
}
result = ADCW; // ADCW muss einmal gelesen werden,
// sonst wird Ergebnis der nächsten Wandlung
// nicht übernommen.
/* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden
Wandlungen */
result = 0;
for( i=0; i<4; i++ )
{
ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
while ( ADCSRA & (1<<ADSC) ) {
; // auf Abschluss der Konvertierung warten
}
result += ADCW; // Wandlungsergebnisse aufaddieren
}
ADCSRA &= ~(1<<ADEN); // ADC deaktivieren (2)
result /= 4; // Summe durch vier teilen = arithm.
Mittelwert
return result;
}
2. Routine
int MESSWERT (int kanal){
int i=512,j=512;
long int analogwert=0, analogwert1=0, analogwert2=0 ;
while(j){
while(i){
ADCSRA=0x80; // ADC eingeschaltet, kein Prescale
ADMUX=kanal; // ADC Ref auf Avcc, PC0 gewaehlt, normale
Formatierung
ADCSRA |=_BV(ADSC); // single conversion mode ein
while (ADCSRA & (1<<ADSC)) {;} // auf Abschluss der Konvertierung
warten
analogwert+=ADCW;
i--;
}
analogwert1 = analogwert/512;
analogwert2 += analogwert1;
j--;
}
analogwert=(analogwert2/512);
return (analogwert);
}
Andreas Schneider wrote:
> nicht. DIe Spannung steht eigentlich auf interne Ref, aber selbst wenn
dann hast du ein anderes Datenblatt als ich
> ADMUX |= (0<<REFS1) | (0<<REFS0); // interne Referenzspannung nutzen
was soll diese Zeile deiner Meinung nach machen?
Ich verstehe nichts von "C" aber m.E. bedeuten die Bits REFS0 und REFS1
auf Null, daß AREF verwendet wird und die interne Referenzspannung
abgeschaltet wird. (Datenblatt von 11/04)
Vielleicht hilft Dir das.
MfG Paul
Hi
>Ich verstehe nichts von "C" aber m.E. bedeuten die Bits REFS0 und REFS1>auf Null, daß AREF verwendet wird und die interne Referenzspannung>abgeschaltet wird. (Datenblatt von 11/04)
Ich auch nicht. Aber, da das eine ODER-Verknüpfung ist gilt das nur,
wenn vorher schon 0 drin stand. Also sinnlos.
MfG Spess
Es gibt auch so was wie for-Schleifen. while ist nicht alles auf der
Welt. Und es gibt hier im Forum eine ganz tolle Funktion, mit der man
C-Code schön formatiert darstellen kann, so dass man ihn lesen kann,
ohne dabei Augenkrebs zu bekommen. Bitte benutze diese Funktion!
Und ja: Eine beliebige Zahl mit 0 verODERt ergibt wieder die beliebige
Zahl, so dass man die Operation auch weglassen kann. Schau Dir mal den
Artikel zum Thema Bitmanipulation an.
Ein Funktionsname in Großbuchstaben ist auch keine gute Idee. Gewöhne
Dir besser gleich eindeutige Schreibweisen an: Makros in
GROSSBUCHSTABEN, Variablen und Funktionen in kleinbuchstaben. Dann weiß
man immer sofort, was was ist.
Ehrlich gesagt keine Ahnung was die Zeile macht, ich hab den Code aus
einem Beispiel übernommen und hatte ja wie gesagt auch funktioniert.
den Formatier-flag kannte ich nicht aber hier nochmals formatiert.
1. Routine
Andreas Schneider wrote:
> Ehrlich gesagt keine Ahnung was die Zeile macht, ich hab den Code aus> einem Beispiel übernommen und hatte ja wie gesagt auch funktioniert.
Glückssache... Und auch toll: Einfach Code irgendwo her kopieren, ohne
ihn auch nur ansatzweise zu verstehen...
> den Formatier-flag kannte ich nicht aber hier nochmals formatiert.
und mit den selben "Fehlern" drin...
Andreas Schneider wrote:
> return (analogwert);
BTW: return ist keine Funktion. Die Klammern gehören da nicht hin
(auch wenn es nicht direkt falsch ist...)
Abgesehen davon gehe ich davon aus, dass der eigentliche Fehler in dem
Teil des Programms liegt, den Du nicht zeigst. Es fehlt z.B. die
Port-Initialisierung, und mein Gefühl sagt mir, dass da vielleicht ein
Pull-Up aktiviert sein könnte...
Hallo,
das hat bei mir funktioniert mit der gleiche Routine, aber in der
Routine steckt ein Fehler.
Du addierst 5 X den Meßwert und dann result /= 4 da muß /= 5 stehen.
Gruß
Jochen
Jochen wrote:
> Du addierst 5 X den Meßwert und dann result /= 4 da muß /= 5 stehen.
Wo addiert er fünfmal den Messwert? Da steht
> for( i=0; i<4; i++ )
Die Schleife wird viermal durchlaufen.
Übrigens: In dem zweiten "Beispiel" werden 512*512 = ca. 262000
Wandlungen pro Durchlauf durchgeführt. Das dauert bei 15 kSPS schon mehr
als 17 Sekunden, bis das erste Ergebnis da ist...
@Johannes M. ; Wow du schreibst soviel aber sagst so wenig zur Sache.
Ich habe eigentlich nicht nach einer Lehrstunde in C-Syntax gefragt,
sondern eine Lösung des Problems erhofft. Trotzdem vielen Dank, deine
Tipps sind echt hilfreich.
Das erste Beispiel ist übrigens das GCC Tutorial, deshalb gehe ich davon
aus, dass es genau so sein muss. Ich werde den Fehler mal im Rest
suchen.
Okay das Problem lag tatsächlich woanders. Offensichtlich hatte ich den
falschen Port geschaltet. grmpf :-) Nun geht die erste Variante
zumindest soweit, dass sie bei 0V auch fast 0 und bei +5 V 1023 anzeigt.
Der interne Ref ist ja auf 2,xx gestellt, so dass auch bei anschluß des
LM35 1023 angezeigt wird, da dieser ca. 2,9 V bringt. Klingt irgendwie
logisch :-) Werde also morgen mal versuchen den internen auf VCC zu
stellen.
Andreas Schneider wrote:
> Das erste Beispiel ist übrigens das GCC Tutorial, deshalb gehe ich davon> aus, dass es genau so sein muss.
nein ist es nicht...
bei dir
1
ADMUX|=(0<<REFS1)|(0<<REFS0);
im Tutorial
1
ADMUX|=(1<<REFS1)|(1<<REFS0);
Deine Variante funktioniert wenn nur zufällig, weil REFS1 und REFS0
beide als default Null sind, aber deine Code würde sie nicht wieder auf
0 stellen, wenn sie vorher mal auf 1 gestanden hätten
Andreas Schneider wrote:
> Ja stimmt, leider kann man hier nix editieren.
Doch, kann man. Aber nicht bis in alle Ewigkeit. Ne Viertelstunde nach
Absenden geht es glaub ich...
Andreas Schneider wrote:
> @Johannes M. ; Wow du schreibst soviel aber sagst so wenig zur Sache.> Ich habe eigentlich nicht nach einer Lehrstunde in C-Syntax gefragt,> sondern eine Lösung des Problems erhofft.
Naj, wenn schon, dann richtig. Wenn ich mir den Code schon anschaue,
dann kriegste auch alles, was mir auffällt, um die Ohren gehauen...;-)
Johannes M. wrote:
> Naj, wenn schon, dann richtig. Wenn ich mir den Code schon anschaue,> dann kriegste auch alles, was mir auffällt, um die Ohren gehauen...;-)
Okay hast ja recht :-)
Funktioniert nun übrigens endlich. Problem war die Kombination aus
Port-Fehler und Ref-Spannung falsch gesetzt. Nachdem diese auf VCC ist,
gehts so wie es sollte.
1
ADMUX=(0<<REFS1)|(1<<REFS0);// interne Ref auf VCC
>ADMUX=(0<<REFS1)|(1<<REFS0);// interne Ref auf VCC
OK, das geht zwar, und es gibt auch Leute, die sagen, dass sie das so
übersichtlicher finden, wenn alle Bits da stehen, aber: Die Operation
"(0<<REFS1)" macht rein gar nichts, und sinnlose Operationen sollte man
besser ganz weglassen. Eine Null kann man schieben, so lange man will,
es bleibt eine Null. Und 0 | IRGENDWAS ist einfach nur IRGENDWAS...