Hallo zusammen. Ich habe die Frage schonmal bei Mikrocontroller.net gestellt, aber ich bin nicht wirklich weitergekommen. Darum versuche ich es mal hier, da ich hier nicht der einzige mit RN-Control bin.
Also ich habe am RN-Control eine Temperatursensor an Kanal 6 des ADC's dran. Über den Kanal 7 lese ich aus wie die Referenzspannung eingestellt ist (einfach nur so, damit ich beim Betrieb den Referenzjumper umstecken kann).
Ich lese die Temperatur mit folgender Funktion aus:
Code:
int get_temp(){
int value;
if(read_adc(7) < 500){ //REF = 5V
value = read_adc(6);
value -= 265; // 0°C
return (value*30)/5;
}
else{ //REF = 2,5V
value = read_adc(6);
value -= 536; // 0°C
return (value*190)/64;
}
}
Soweit so gut.
Nun ist mit aufgefallen, dass wenn ich die Referenz auf 2,5V habe der ADC Wert sich MEHR als nur verdoppelt. Angenommen ich messe vorher bei AREF=5V einen Wert von 300, dann messe ich bei AREF=2,5V einen Wert von 610 (also 1,49V anstatt 1,46V). Gut könnte man meinen, ist halt der Spannungsteiler ungenau oder so... denkste, denn wenn ich den Kanal 6 manuell auslese dann stimmt der Wert. Sprich, das schnelle auslesen von Kanal 7 und Kanal 6 hintereinander hat Auswirkungen auf den Messwert. Dies habe ich bestätigt bekommen als ich die Funktion mit einem Delay versehen habe:
Code:
int get_temp(){
int value;
if(read_adc(7) < 500){ //REF = 5V
value = read_adc(6);
value -= 265; // 0°C
return (value*30)/5;
}
else{ //REF = 2,5V
_delay_ms(15);
_delay_ms(15);
_delay_ms(15);
_delay_ms(15);
value = read_adc(6);
value -= 536; // 0°C
return (value*190)/64;
}
}
Mit dem obigen Code wird in beiden Fällen richtig ausgelesen. Kann sich jemand erklären wie das zustande kommt?
Ich hatte später gedacht, dass der Schaltplan falsch ist, da der 100nF von AREF an VCC geschaltet ist, darum habe ich mal versucht den Kondensator von VCC auf GND zu legen. Das Resultat ist, dass der Wert bei 2,5V jetzt immer zu hoch ist, es jedoch keinen Unterschied mehr macht ob ich ein Delay einbaue oder nicht.
Der Vollständigkeit halber hier nochmal meine read_adc-Funktion:
Code:
unsigned int read_adc(unsigned char channel)
{
unsigned char i;
unsigned int result = 0;
ADCSRA = (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler = 128
ADCSRA |= (1<<ADEN); //Enable ADC
ADMUX = channel; // Kanal waehlen
ADMUX &= ~((1<<REFS1) | (1<<REFS0)); // externe Referenzspannung nutzen
ADCSRA |= (1<<ADSC); // Dummy-Wandlung
while ( ADCSRA & (1<<ADSC) ); // auf Abschluss der Konvertierung warten
/* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
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;
}
Lesezeichen