Guten Abend
ich habe ein Problem und bin wohl auf eure Hilfe angewiesen.
Ich beschäftige mich gerade mit einem Temperatursensor.
Benutzt wird ein AD22100.
Ich möchte eine Temperatur auf meinem LCD-Display ausgeben, jedoch
klappt dies noch nicht so gut. Der Sensor arbeitet jedoch -> gemessen!
Hier mal mein für euch abgespeckter Code, alle anderen #includes etc.
sind natürlich vorhanden:
/* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
16
also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
17
18
ADCSRA|=(1<<ADSC);// eine ADC-Wandlung
19
while(ADCSRA&(1<<ADSC)){}// auf Abschluss der Konvertierung warten
20
/* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten
21
Wandlung nicht übernommen. */
22
result=ADCW;
23
}
24
25
26
/* ADC Einzelmessung */
27
uint16_tADC_Read(uint8_tchannel)
28
{
29
// Kanal waehlen, ohne andere Bits zu beeinflußen
30
ADMUX=(ADMUX&~(0x1F))|(channel&0x1F);
31
ADCSRA|=(1<<ADSC);// eine Wandlung "single conversion"
32
while(ADCSRA&(1<<ADSC)){}// auf Abschluss der Konvertierung warten
33
returnADCW;// ADC auslesen und zurückgeben
34
}
35
36
intmain(void)
37
{
38
while(1)
39
{
40
ADC_Init();
41
42
x=5/(1023*0.0225)*(ADC_Read(5)-1.375)/0.0225;
43
44
sprintf(buffer,"%d",temperatur/1000);
45
lcd_setcursor(1,2);
46
lcd_string(buffer);
47
}
48
}
Auf dem Display erscheint jedoch nur ein -12°C.
Vielleicht sehe ich vor lauter Bäumen den Wald auch schon nicht mehr,
aber ich hoffe jemand kann mir helfen!
schönen Abend
wie wäre es mit eine mathematische trennung punkt vor strich?
x=(5/(1023*0.0225))*((ADC_Read(5)-1.375)/0.0225);
dann den fehler liegt das die initializierung in der while schleife ist
man man..... du machst immer wieder eine initialisierung
Ciao
fang damit an, dir den Wert für
ADC_Read(5)
ausgeben zu lassen
Dann würde ich mal die Formel etwas umstellen um sie besser lesbar zu
machen.
Der Faktor 0.0225 ist da schon etwas seltsam in der Verwendung, das
sieht gefühlsmässig nicht richtig aus.
Die Formel sieht aus, als ob du falsch substituiert hättest. Die nackten
5 bei 5/.... machen mich stutzig.
Aber erst mal solltest du checken, ob deine ADC Werte plausibel sind.
Dann die ADC Werte in eine Spannung umrechnen (damit du mit einem
Voltmeter vergleichen kannst)
und erst dann die Volt in eine Temperatur umrechnen.
Hallo Fausto, erstmal danke für deine Hilfe!
Also die init ist nicht in der While(1), das ist mir eben beim
zusammenkopieren passiert, ebenfalls habe ich ausversehen die
temperatur-Ausgabe nochmal durch 1000 geteilt, was auch nicht sein
sollte.
Habe mal deine punkt vor strich trennung befolgt, bekomme nun einen Wert
von
9863 ausgegeben.
Hier nochmal der untere Code, wie gesagt die ADC_init(); ist natürlich
nicht in der while!
Hallo Karl Heinz,
wenn ich ADC_Read(5) ausgeben lasse, erscheint eine 1023 auf dem
Display, welche sich nicht ändert. Wenn ich den Sensor erhitze oder
abkühle, passiert rein garnichts? Mit dem Voltmeter gemessen, ändert
sich die Sp. jedoch...?
Vll. liegt der Fehler sogar vor der Main?
Wenn ich das richtig sehe, hast du den ADC auf interne Spannungsreferenz
von 2,56V gestellt, ist das gewollt? Jede Spannung über 2,56V wird somit
zu 1023 gewandelt. Das würde zu deiner Erklärung passen, dass sich der
Wert nicht ändert bei Veränderung der Temperatur, falls der
Spannungswert immer über 2,56V liegt.
Hallo Thorsten,
der Spannungswert liegt um und bei 2,47V.
Wo genau habe ich die interne Spannungsreferenz beim ADC auf 2,56V
gestellt?
Die Funktionen habe ich von mikrocontroller.net
> Wo genau habe ich die interne Spannungsreferenz beim ADC auf 2,56V> gestellt?
hier, an der Stelle bei der der Kommentar zur Referenzspannung steht
>> ADMUX = (1<<REFS1) | (1<<REFS0); // interne Referenzspannung nutzen
Beim Atmega8 (Table 74. Voltage Reference Selections for ADC in
Datenblatt Revision 2486T–AVR–05/08) ist diese Bitkombination
REFS1 REFS0 Voltage Reference Selection
1 1 Internal 2.56V Voltage Reference with external capacitor at AREF pin
AVcc = Vcc intern wäre
0 1 AVCC with external capacitor at AREF pin
Im AVR-GCC-Tutorial hatte jemand das Beispiel von AVCC als Referenz
auf 2,56V als Referenz umgestellt. Die Originalzeile mit der 01
Bitkombination war auskommentiert. IMHO ist die AVCC Referenz sinnvoller
für den Lernenden.
Hallo Leute,
ich habe mein Programm nun soweit zum laufen, es lag erstens an der
Formel und zweitens an meinem ATmega328P.
Sobald ich einen mega8 mit dem Code bespiele zeigt er mir nun die genaue
Temperatur an und verändert sich auch.
Woran kann das liegen? hat das was mit dem ADC zu tun, dass es mit dem
mega328P nicht funktioniert?
Habe schon mal im Datenblass nachgesehen, kann auf anhieb aber nichts
finden, was dort anders sein könnte!
Auch mit einer Referenzsp. von 1,1V bekomme ich keinen vernünftigen Wert
auf mein Display. Da muss doch irgend etwas Grundlegendes am 328P anders
sein als am mega8?
Obacht: Bei einer Referenzspannung von 1.1V und einer Signalspannung von
2,47V kannst du keinen vernünftigen ADC Wert bekommen!
Der Atmega328P unterscheidet sich vom Atmega8 in der genau dieser
internen, genauen Referenzspannung, die mit (1<<REFS1) | (1<<REFS0)
gewählt wird: Atmega8 2,56V und Atemag328P 1,1V.
Leider hat Martin Thomas im AVR-GCC-Tutorial wieder die vermaledeite
"Interne Referenzspannung" als Voreinstellung für das adc_init()
Beispiel gewählt. Statt dass man im allerersten (!) Beispiel Genauigkeit
mal aussen vor lässt und den vollen ADC Eingangsbereich 0..AVcc
auszunutzt...
Wir werden diese Problematik "Mein ADC misst nur Mist" noch häufiger
sehen. Ich habe keinen Bock das jedes Mal zu erklären, wenn ich den ADC
Einsteigern erkläre "Benutzt für eure ersten ADC Versuche doch die
bewährten Routinen aus dem AVR-GCC-Tutorial, aber mit der
Referenzspannung müsst ihr..."
Krapao schrieb:> Statt dass man im allerersten (!) Beispiel Genauigkeit> mal aussen vor lässt und den vollen ADC Eingangsbereich 0..AVcc> auszunutzt...
Die sowieso ein Trugschluss ist.
Denn die interne Referenzspannung ist vor allen Dingen eines:
Sie ist zwar stabil, aber keinesfalls immer und bei jedem µC exakt 1.1
oder 2.5V.
Ich würds auch besser finden, wenn man Anfänger da erst mal nicht
durchjagt, sondern sie mit der Versorgungsspannung arbeiten lässt.
Zumindest die einzelnen Varianten als auskommentierte Versionen (so wie
das früher mal war) in den Source Code mit aufnimmt.
Hallo ihr beiden,
danke erstmal, dass ihr nochmals Stellung zu meinem Problem nimmt.
Die Spannung von 2,47V(Vout) ist Geschichte, da muss ich wohl irgendwie
mist gemacht haben.
Ich habe Sie nochmals gemessen und Sie liegt bei Zimmertemperatur
ungefähr bei 1,86V!
Ich habe meine Formel im C-Code schon auf die 1,1 V umgestellt.
Hier mal die Formel:
1
result=ADC_Read(5);
2
A=2560L*result/1023L;
3
temperatur=(u-1375)/0.0225;
4
sprintf(buffer,"Temp=%d",temperatur/1000);
Diese Formel umgeschrieben für den 328P
1
result=ADC_Read(5);
2
A=1100L*result/1023L;
3
B=(u-1375)/0.0225;
4
sprintf(buffer,"Temp=%d",B/1000);
Wie gesagt beim mega8 funktioniert alles beim 328 nicht.
Die Routinen sind ja aus dem GCC-Tutorial, aber irgend einen Unterschied
zwischen den genannten megas muss es ja geben!
Die weitere Suche im Forum ergab auch keine Treffer...
Daniel F. schrieb:> Ich habe Sie nochmals gemessen und Sie liegt bei Zimmertemperatur> ungefähr bei 1,86V!> ...> Ich habe meine Formel im C-Code schon auf die 1,1 V umgestellt.> ...> Wie gesagt beim mega8 funktioniert alles beim 328 nicht.
Kann es eventuell sein, dass dir nicht klar ist, dass die
Referenzspannung die obere Grenze der messbaren Spannung darstellt? Bei
einer Referenzspannung von 1,1V hast du bei jeder Spannung >= 1,1V (also
auch bei 1,86V) 1023 als Ergebnis.
Daniel F. schrieb:> Ich habe Sie nochmals gemessen und Sie liegt bei Zimmertemperatur> ungefähr bei 1,86V!>>> Ich habe meine Formel im C-Code schon auf die 1,1 V umgestellt.
Der ADC misst deine Spannung im Prinzip als Prozentwert in Bezug auf die
Referenzspannung. D.h. der ADC Wert sagt dir, wo im Bereich 0 bis
Referenzspannung sich deine zu messende Spannung bewegt. Ist die
Spannung kleiner 0, liefert der ADC auch 0. Ist die Spannung größer als
die Referenzspannung, kriegst du immer 100%
Das bedeutet aber auch:
Dein Messwert darf den durch die Referenzspannung vorgegebenen
Messbereich nicht verlassen, sonst kriegst du IMMER die Endwerte 0 bzw.
100%. Denn mehr als 100% kann der ADC nun mal nicht als Ergebnis
liefern.
Nur dass der ADC die 100% eben als die Zahl 1023 ausdrückt.
> Die weitere Suche im Forum ergab auch keine Treffer...
Nicht für alles gibt es vorgefertigte Antworten. Du musst schon auch
mitdenken und dein Wissen darüber wie die Einzelsysteme funktionieren
zum Einsatz bringen.
Wenn du einen Meterstab hast, der 1 Meter lang ist (der "Referenzwert"),
dann kannst du durch anlegen an ein Objekt nur dann seine Länge messen,
wenn das Objekt nicht länger als 1 Meter ist. Darüber kannst du nur noch
die Aussage treffen: Ist länger. Aber Zahlenwert kannst du keinen mehr
angeben.
Tu dir selbst einen Gefallen und stell beim ADC die Referenzspannung auf
die Verwendung von Vcc (also deine 5V Versorgungsspannung) um und
vergiss die interne Referenzspannung fürs erste. Denn die ist sowieso
nicht 1.1V oder 2.56V oder .... Schau ins Datenblatt, die hat ganz
schön große Toleranzen von µC zu µC! Der Zweck der Referenzspannung ist
es nicht, auf allen µC die immer gleiche Spannung zur Verfügung zu
stellen, sondern eine Spannung zur Verfügung zu stellen, die sich auf
einem µC möglichst wenig ändert! Ob die 1.2V hat oder 1.0V spielt nicht
so sehr die Rolle (das kann man softwaretechnisch kalibrieren), wichtig
ist dass die 1.2V sich unter Last, unter wechselnden
Temperaturbedingungen nicht ändern und bei -20°C bzw +60°C immer noch
1.2V sind.
Hi Karl Heinz,
wie von dir beschrieben habe ich es gemacht.
ADMUX = (0<<REFS1) | (0<<REFS0);
Zum probieren habe ich erstmal die 5V ohne schnickschnack auf Vref
gelegt.
Nun bekomme ich jedenfalls schonmal einen Wert heraus der sich ändert.
Dennoch wird mir nun ein zu kleiner Wert vom ADC ausgegeben.
Bei 20°C habe ich an Vout des AD22100 1,86V.
Wenn ich nun 1023/5V rechne, bekomme ich einen Wert von 204,6.
204,6 * 1,86V = 380<- Wert der aus dem ADC kommen sollte.
Wenn ich ADC_Read auslesen lasse, wird mir aber bei 20°C ein Wert von
ca. 250 ausgegeben. Wo liegt denn nun schon wieder der Hund begraben?
Das hat ja mit der Umrechnung für die Temperatur nichts zu tun.
Ich habs,
keine Ahnung wie aber auf einmal scheints zu klappen. Habe AVR-Studio
mal neu gestartet und danach ging es. Da hatte sich wohl irgendwie ein
Fehler im Programm eingeschlichen, aber egal, Hauptsache es
funktioniert!
Vielen herzlichen Dank an alle Helfer!!!
schönes Wochenende!