Hallo zusammen,
habe eine Frage bezüglich des ADC.
Und zwar möchte ich eine Temperaturregelung mit einem Lüfter
realisieren.
In der Endversion soll ein ATTiny24 zum Einsatz kommen, doch zuerst wird
die Schaltung Testweise mit einem ATMega16 aufgebaut.
Dabei ist halt nur der AREF-Pin woanders...
Die Register beim ATMega16 habe ich wie folgt eingestellt:
//ADMUX |= 0x00; //Alles auf 0, also Init-Werte
ADCSRA |= 0x88;
Jetzt wird alle 5 Sekunden das Bit ADSC aus dem ADCSRA Register auf High
gesetzt, das bedeutet, alle 5 Sekunden startet eine Conversion und ADSC
wird am Ende automatisch auf 0 zurück gesetzt.
Aber ich muss doch noch eine Referenz haben, mit der ich dann die
tatsächliche Temp berechnen kann, oder ?
Also messe ich mit dem Temperaturfühler KTY 83-110 einmal bei 20°C und
einmal bei 100°C. So da hab ich meine Bezugswerte, die ich in beliebigen
Variablen, sagen wir RefTemp1 und RefTemp2 speicher.
So jetzt weiß ich weiter, das das Ergebnis in ADCL und ADCH zu finden
ist.
Wie genau muss ich diese jetzt auslesen (ich habs auf right adjusted)
und mit den Werten aus RefTempN verrechnen ?
Danke schonmal im Vorraus für Ratschläge
Hallo nochmal,
ahbe noch selber einen Fehler gefunden !
Und zwar beim Prescaling des ADCs, da habe ich gelesen, das der Takt für
den ADC zwischen 50kHz und 200kHz liegen sollte, ode drunter je nachdem
welche Samplerate ich will!
Also da mein Mega16 mit 8MHz rennt hab ich den Scalingfaktor auf 64
gesetzt, so komm ich auf 125kHz !
Also
ADCSRA |= 0x8E;
Anstatt
ADCSRA |= 0x88;
Aber wie komme ich jetzt z.B. an meine Referenzvalues ?
Display hab ich am laufen, könnte theor. die Werte darauf ausgeben,
müste halt nur wissen wie ich die ADCL und ADCH auslese....
Danke
Hi Hannes Lux,
also ich hab noch einen Fehler bei mir gefunden und zwar hatte ich Kanal
0 ausgewählt, aber Sensor ist an Kanal 1 (also ADC1, PortA1).
Daher ADMUX |= 0x01;
so und das Auslesen habe ich jetzt mal so angenommen (weiß nicht obs
richtig ist)
========================================================================
====
int adc_read()
{
int Temp = 0x00;
/*
switch(channel)
{
case 1: ADMUX |= 0b00000001; break; //Kanal waehlen
case 2: ADMUX |= 0b00000010; break; //Kanal waehlen
}
*/
ADCSRA |=(1<<ADSC); // Start Conversion
//ADCSRA |=(1<<ADEN); // Enable ADC
while ( (ADCSRA & (1<<ADSC)) != 0)//Warten bis konvertierung beendet
{
//Mal ne Runde nix tun (ca. 15 Clk-Cycles)
}
Temp= ADCL;
Temp+=(ADCH <<8); // Ergebnis zusammenbauen
return Temp;
}
========================================================================
====
den switsch hab ich direkt mit eingebaut, falls ich mal mehrere Sensoren
abfragen möchte, da an ADC0 (PORTA0) beim ATTiny24 AREF liegt, hab ich
beim Programm für den ATMega16 auch diesen Port direkt freigelassen...
Wenn das alles so richtig ist, müsste ich nur noch das Ergebnis des
Auslesens aufs Display ausgeben, vorher vielleciht noch eine itoa
Anweisung mit den Werten machen...
Ist denn die Abfrage soweit in Ordnung, oder hat sich da noch ein Fehler
eingeschlichen ?
Nur weil Du mich direkt angesprochen hast:
Ich kann Dir da nicht helfen, denn ich kann kein C. Ich schreibe meine
bescheidenen Progrämmchen in Assembler.
Jedenfalls solltest Du dem ADC genügend Zeit zur Wandlung lassen. Wenn
ich mehrere Kanäle einlesen muss, dann mach' ich das meist in einem
Timer-Interrupt neben der eigentlichen Arbeit oder im
ADC-Complete-Interrupt. Dabei lese ich den Wert aus (mir reichen meist 8
Bit linksbündig), schaffe ihn in Sicherheit und schalte dann auf die
zunächst auszulesende Quelle um. Danach wird bis zum nächsten Int das
gemacht, was sonst noch so ansteht. Es muss nicht unbedingt ein
Interrupt sein, es geht auch eine andere zyklisch aufgerufene Routine,
z.B. Tastenentprellung, LCD-Update oder ähnliches.
...
Guten morgen zusammen,
also zur Zeit läuft es folgendermaßen in meinem Programm:
Es laufen Timer/Counter0 und Timer/Counter1
Der T/C0 ist nur ist für eine spätere Uhr vorgesehen.
T/C1 steuert ca. alle 5s die Funktion adc_read(); an, wo dann die
Werte ausgelesen werden sollen. In dieser Schleife wird das ADSC Bit
auf ein gesetzt (also conversion gestartet) und mittels einer schleife
wird
solange nichts getan, bis dieses Bit wieder auf 0 ist, also die
conversion beendet ist.
Könnte jemand mit C-Erfahrung bitte kurz drüber schauen ?
-Danke-
while(!(ADCSRA&0x10));// auf Ende der Wandlung warten, ADIF flag '1'
13
ADC_temp=ADCL;// ADCL Register lesen
14
ADC_temp+=(ADCH<<8);// ADCH Register lesen
15
Messwert+=ADC_temp;// Ergebnisse der Messungen addieren
16
i++;// Schleifenzähler erhöhen
17
}
18
while(i<=MW);// MW Messungen für bessere Genauigkeit
19
Messwert=Messwert/MW;// Mittelwert der Messungen der globalen Variable zuweisen
20
21
return(Messwert);
22
}
Die Pause von 40µs habe ich deshalb 'reingemacht, weil ich feststellte,
dass nach dem Umschalten des MUX die Werte nicht stimmten. Der
Analogschalter braucht wohl auch seine Zeit.
Aufgerufen wird die Funktion z.B. für ADC0 und 32 Mittelwerte:
Hallo nochmal,
also ich hab es jetzt folgendermaßen gelöst mit der Funktion
ADC_conversion(1, 32) vom Sonic.
char Buffer_ADC[4];
...
DDRA &= 0xFD; //PortA1 ist Eingang
...
if(...) //Wenn 5s vorbei sind
{
Buffer_ADC[4] = ADC_conversion(1, 32);
lcd_gotoxy(0,0);
lcd_puts(Buffer_ADC);
}
kommt leider nix ausser dem "Ready" in der zweiten Zeile des Displays
(wird bei der Displayinitialisierung geschrieben)...
Im Anhang befindet sich die ganze *.c Datei
@Sonic:
Gibts du deine ADC Werte irgenwie aufm Display aus ?
Ich hab leider keinerlei Kontrolle, ob die ADC wirklich funktioniert....
Hat jemand ne Idee ?
> also zur Zeit läuft es folgendermaßen in meinem Programm:> Es laufen Timer/Counter0 und Timer/Counter1> Der T/C0 ist nur ist für eine spätere Uhr vorgesehen.
Jeder Interrupt benötigt neben der Rechenzeit für die Arbeit in der ISR
auch etwas Rechenzeit für den Aufruf und Rücksprung (und
Registersicherung usw.). Das ist zwar nicht die Welt, kann sich aber bei
häufig aufgerufenen ISRs schon summieren.
Wenn Du aber schon einen Interrupt für eine Uhr einplanst, dann kannst
Du diesen doch auch zum Synchronisieren anderer zyklisch laufender Jobs
verwenden. Lass den Uhren-Interrupt z.B. alle 10ms zuschlagen. In dessen
ISR setzt Du ein Flag für die Mainloop (eine Boolsche Variable) und
zählst die Hundertstelsekunden hoch. Bei Erreichen von 100 setzt Du sie
auf 0 zurück und setzt ein weiteres Flag für die Mainloop.
Die Mainloop wertet die Flags aus. Bei gesetztem Sekundenflag zählt sie
die Sekunden (und den ganzen Kalender) hoch, löscht das Sekundenflag
(Job wird ja gemacht), vergleicht vielleicht noch irgendwelche
Schaltzeiten und löst Schaltvorgänge aus usw...
Bei gesetztem Hundertstel-Flag wird in eine Routine verzweigt (oder eine
Funktion aufgerufen, wenn man in C denkt), die alle Jobs erledigt, die
zyklisch fällig sind. Z.B. Tastenentprellung, ADC-Abfrage usw. Wenn der
ADC-Vorteiler (Free-Run-Betrieb) so eingestellt ist, dass bei jeder
Abfrage mindestens zwei neue Werte ermittelt (aber nicht abgeholt)
wurden, dann kann man (wie oben beschrieben) ohne Weiteres den Wert
auslesen (und gemäß der zuletzt eingestellten Quelle sichern und dann
ADMUX auf die demnächst benötigte Quelle umschalten. Der erste Messwert
geht ins Leere, da erst wieder abgefragt wird, wenn bereits mehrere
Wandlungen erfolgt sind. Das erschlägt z.B. auch Sonic's Problem, ohne
dafür Rechenzeit durch eine Warteschleife vernichten zu müssen.
> T/C1 steuert ca. alle 5s die Funktion adc_read(); an, wo dann die> Werte ausgelesen werden sollen. In dieser Schleife wird das ADSC Bit> auf ein gesetzt (also conversion gestartet) und mittels einer schleife> wird> solange nichts getan, bis dieses Bit wieder auf 0 ist, also die> conversion beendet ist.
Eben diese Busy-Warterei kannst Du Dir sparen.
Entweder Free-Run und beim gelegentlichen Vorbeischaun (Timersynchron,
um einen Mindestabstand einzuhalten) den Wert nebenbei mitnehmen oder
Einzelwandlungen per ADC-Interrupt, bei der erst der Wert ausgelesen
wird und dann die Quelle umgeschaltet wird und der ADC neu gestartet
wird. Letzteres ist aber nur sinnvoll, wenn man eine schnelle Messfolge
braucht.
Für genaues (störungsarmes) Messen muss man sowiso anders herangehen,
dann muss das Timing so aufeinander abgeglichen werden, dass die
Wandlung bei angehaltenen Timern (Sleep-Mode ADC-Noise-Reduction)
erfolgen kann. Dies muss natürlich bei den Timern berücksichtigt werden.
>> Könnte jemand mit C-Erfahrung bitte kurz drüber schauen ?>
Das überlasse ich mangels C-Wissen jemand Anderes.
> -Danke-
---------
> vielleicht kannste mit meiner Funktion für single-ended-Messung was> anfangen
Ich glaube nicht, dass es sinnvoll ist, eine solche Routine als Beispiel
zu empfehlen. Denn Du startest den ADC, wartest auf sein Busy-Flag und
liest dann den Wert aus. Das kostet unnötig Rechenzeit und behindert
andere Prozesse des Programms. Denn wenn das Programm schon "klappert"
und dabei Störungen verursacht, dann kann es auch sinnvolle Arbeit
erledigen. Deine Routine ist also ein gutes Beispiel für schlechtes
Timing, sorry.
...
>Hat jemand ne Idee ?
Nur ganz kurz:
Du solltest nicht erwarten, dass jede Zeile deines Programms hier von
kompetenten Leuten sorgfältig analysiert wird. Sowas hätte ich für meine
Programme zwar auch manchmal gerne, aber kostenlos gibt es so etwas nur
ganz selten.
Wenn man so ein Projekt halbwegs professionell durchführen will, und
sich aber nicht völlig sicher ist, wie man es machen muss, sollte man es
in Einzelschritte zerlegen und diese sorgfältig prüfen.
Einige Leute wursteln einfach drauflos und hoffen das irgendetwas
halbwegs sinnvolles rauskommt. Das ist stümperhaft.
1. Teste das LCD separat, also Zahlen und Buchstaben ausgeben!
2. Teste den ADC separat. Definierte Spannung anlegen und Messwerte (auf
LCD) ausgeben.
3. Überlege dir sorgfältig, wie du den Temperaturfühler beschalten musst
(Datenblatt) und wie du die Messwerte in Temperatur umrechnen kannst.
4. Teste die Temperatur-Messwerte
5. Überlege Dir, wie Du den Lüfter ansteuern kannst.
6. Teste die Lüfteransteuerung.
7 ....
8. Teste ob alles zusammen funktioniert.
9 . Schreibe eine gute Dokumentation, damit Du auch Jahre später deinen
Aufbau noch verstehst und reparieren/erweitern kannst. Durch die
Dokumentation kann der Aufbau auch leicht von anderen nachgebaut werden,
wenn Du das möchtest.
Gruß
Stefan Salewski
Ja, teste dein LCD separat und gib nur eine Variable aus. Wenn das
klappt kannst du weitermachen. Und wenn du mit dem ADC1 misst solltest
du den Pullup für diesen Pin deaktivieren. Sonst kommt nix gescheites
'raus.
Hallo nochmal,
also hab mein ADC jetzt so eingestellt, das er im Freerun Mode läuft und
immer wenn eine Conversion zuende ist ein Interrupt ausgelöst wird,
in dem die Daten aus ADCL und ADCH gelesen werden sollen.
So direkt am Anfang der ISR vom ADC schalte ich eine LED ein, die an
PORTD7 hängt. Die LED geht auch an, was bedeutet, das diese ISR
aufgerufen wird.
Also muss eine Convertion beendet worden sein, denn sonst wäre der
Interrupt ja nicht ausgelöst worden...
Nur Ausgabe auf mein Display der Werte klapt noch nicht, das Display
zeigt aber Ready an, es ist also korrekt initialisiert.
Hier nochmal meine ISR des ADCs
===============================
///// ISR ADC Complete /////
SIGNAL(SIG_ADC)
{
PORTD |= 0x80; //LED Rt an
_delay_us(40); // Pause bis Multiplexer eingestellt ist
unsigned int ADC_temp;
//ADCSRA |= (1<<ADSC); // conversion einleiten
ADC_temp = ADCL; // ADCL Register lesen
ADC_temp += (ADCH << 8); // ADCH Register lesen
Messwert = ADC_temp; // Ergebnisse der Messungen addieren, Messwert
ist eine globale Variable
}
===============================
So dann im Hauptprogramm:
===============================
disp_init();
lcd_gotoxy(0,1);
lcd_puts("+Ready+");
ADCSRA |= 0x40; //Starte die erste Konvertierung,
PORTD |= 0x80; //LED Rt an
Buffer_ADC[4] = Messwert;
lcd_gotoxy(0,0);
lcd_puts(Buffer_ADC);
===============================
leider steht ausser dem +Ready+ nichts auf dem Display :(
Aber die Rote LED an PD7 leuchtet
es ist vielleicht ein Problem der Variablen ?
Also die globale Variable Messwert ist vom Ty double
double Messwert = 0;
und die zur Ausgabe auf dem Display benötigte ist eine char Variable
char Buffer_ADC[4];
Die Variable ADC_temp ist vom Typ unsigned int
unsigned int ADC_temp;
ich denke darin liegt ein weiteres Problem, oder ?
Ich hab nochmal einige Beiträge hier ausm Forum zum Thema ADC gelesen
und mich wirklich intensiv mit dem Kapitel ADC im Datasheet beschäftigt
und fummle nun schon seit 3 Tagen dadran herum, leider immer noch
erfolglos.
Ich hab es bisher nichteinmal geschafft, überhaupt die Werte aus ADCH
und ADCL auf dem Display anzuzeigen !
Ich bin da wirklich auf eure Hilfe angewiesen und hoffe ich kann mit
eurer Unterstützung rechnen.
Ich bin mir sicher, das es nur ein ganz kleiner doofer Fehler ist...
da ja die beendete Conversion ja einen Interrupt auslöst und die LED
angeht, die ich in dieser ISR setze.....
Ich bitte euch um eure Hilfe, alleine komme ich da jetzt nicht mehr
weiter, bin total am verzweifeln...
Versuche doch mal einen beliebigen Text oder eine Variable in der
ADC-INT-Routine auszugeben (da wo die LED eigeschaltet wird). Dann bist
du sicher dass deine Ausgabefunktion überhaupt angesprungen wird. Das
soll man zwar nicht machen, aber zu Testzwecken geht's schon mal.
Nochmal ich.
Ich poste dir mal einen ganz einfachen Displaytreiber. Damit kannst du
das Display initialisieren, löschen, den Cursor auf eine bestimmte
Position setzen (Zeile 1 und Zeile2 ) und den Text byteweise ausgeben.
Das Ganze für ein 2x16-Zeichen-Display, kann aber auf andere angepasst
werden.
Hallo Sonic,
also ich habe in die ADC Interruptroutine jetzt folgendes ergänzt:
lcd_gotoxy(0,1);
lcd_puts("ADC ISR");
das macht er auch, geht an die Stelle 0,1 und gibt den Text aus,
genauso, wie die LED angeht....
Aber ich habe noch folgendes geändert:
// Globale Variablen //
unsigned int Messwert = 0;
char Buffer_ADC[8];
so in der Endlosschleife
wird dann folgendes gemacht:
itoa(Messwert,Buffer_ADC,8);
lcd_gotoxy(0,0);
lcd_puts(Buffer_ADC);
das führt zu folgender Ausgabe auf dem Display:
=========================
=1777 =
=ADC ISR =
=========================
Die = Striche sind nur die Displayberahmung...
aber egal was ich mache, der Wert 1777 ändert sich nicht, auch nicht
wenn ich mit einem Feuerzeug in die Nähe des KTY Temperaturfühlers
komme, auch nicht wenn ich dann den uC Resette, es kommt immer nur
dieser Wert....
Im Anhang mal das ganze C-Programm
Ich hoffe echt das ihr mir alle dabei helfen könnt, so schwer kann das
mit dem ADC doch nicht sein. Egal wie ich zum ersten Ergebnis komme,
kann ruhig richtig dirty programmiert sein, hauptsache es tut sich
überhaupt mal was....
Setze
Messwert = ADCL;
Messwert += (ADCH << 8);
mal an den Anfang der ISR. Da sind irgendwelche Werte in den registern,
wenn ADCL und ADCH noch nicht ausgelesen sind.
Hab ich gemacht, passiert immer noch das gleiche...
ich habe parallel zum KTY... Temperaturfühler mein Multimeter
angeklemmt.
Also wenn ich mit einer Hitzequelle in die Nähe komme, dann ändert sich
die Spannung so wie es soll.. Nur der ADC-Wert, bzw. das was mir auf dem
LCD angezeigt wird (die 1777) ändert sich nicht, auch nicht nach
reset....
Also denke ich, das dieser Wert 1777 irgendein nsinn ist und nichts
besonderes aussagt...
Was könnte noch falsch sein ?
Also 1777 kann definitiv nichts mit ADC-Werten zu tun haben.
Kannst du nicht mal versuchen, die Bytes ADCL und ADCH OHNE das itoa auf
das Display auszugeben? Oder irgendwelche definierten Bytes? Dem itoa
traue ich nicht immer über den Weg!
Auch wenn ich es direkt ausgebe, also folgendermaßen:
lcd_gotoxy(0,0);
lcd_puts(Messwert);
erscheint immer wieder diese 1777 in der ersten Zeile und ändert sich
immer noch nicht..... ?!?!
Muss ich vll noch irgendwas bei den Fuse-Bits beachten, wenn ich mit dem
ADC hantieren will ? Eigentlich doch nicht, oder hab ich was übersehen ?
An den Fuses sicher nichts.
Aber da der Messwert in der ISR (außerhalb sub main) benutzt wird
initialisiere den mal mit
volatile unsigned int Messwert = 0;
Mit Buffer_ADC ist's das Gleiche. Muss 'volatile' sein (weiß jetzt
nicht, oder Compiler da meckert). Ansonsten wie gesagt: gib mal nur die
einzelnen Bytes aus, kein 16-bit-Wort. Also ADCH und ADCL getrennt.
wenn ich die beiden Werte aus ADCL und ADCH getrennt ausgebe, dann habe
ich folgende Werte:
300 aus ADCL
377 aus ADCH
so sieht die Ausgabe jetzt aus:
Messwert = ADCL;
itoa(Messwert,Buffer_ADC,8);
lcd_gotoxy(0,0);
lcd_puts(Buffer_ADC);
Messwert = ADCH;
itoa(Messwert,Buffer_ADC,8);
lcd_gotoxy(0,1);
lcd_puts(Buffer_ADC);
Also 300 und 377 können keine ASCII-Codes sein! Deshalb, versuche OHNE
das itoa auszukommen, das Teil ist etwas komliziert zu handeln. Baue
lieber deine LCD-Ausgabe so um, dass du itoa nicht mehr brauchst. Den
Display-Treiber den ich gepostet habe kannste ja mal testen. Den kann
man als stdout benutzen und mit printf die Ausgaben machen.
Ersetze mal bei Itoa die 8 durch eine 10, also
itoa(Messwert,Buffer_ADC,10).
Ist soweit ich weiß das Format für die Umwandlung. 10 für Dezimal, 8 für
Octal, 16 für Hex. 1777 Octal entspricht 1023 Dezimal, maximalwert vom
ADC.
Ja das weiß ich, aber leider bringt mich das auch nicht weiter,
denn dieser Wert steht immer da drin, auch wenn ich mit nem Feuerzeug in
der Nähe des Temperaturfühlers herumwedele. Der Wert ändert sich
niemals, nicht nach RESET, nicht mit Feuer nach RESET, garnicht..... der
will einfach nicht und das obwohl eine Spannungsänderung mit dem
Multimeter deutlich zu messen ist....
Hast du mal nachgemessen ob das Signal am Eingangspin passt? Welche
Referenzspannung hattest du angewählt? Kann gut sein dass der ADC das
Zeitliche gesegnet hat.
Wird die SIGNAL(SIG_ADC) mehr als einmal aufgerufen? Vielleicht einen
Zähler einbauen und am Display ausgeben.
Man kann auch feste Spannungen anstatt eines Kanals wählen (MUX4..0 =
11110 => 1,22V, 11111 => GND). Vielleicht hilft dir das noch weiter.
Hallo,
das Signal am Eingangspin passt leider genau mit der Spannung am
Temp-Sensor überein... Ändert sich somit auch, wenn ich ein kleines
Feuerchen in die Nähe bringe... Logisch, weil das ja genau der gleiche
Abgriff ist...
Das mit dem Zähler war eine gute Idee....
nun kann ich sehen, wie eine Zahl ziemlich schnell hochgezählt wird.
das bedeutet, das die ISR ständig ausgeführt wird, jedoch ändern sich
die werte nie.....
Aus der Tatsache, das die ISR ständig aufgerufen wird, schließe ich, das
ständig irgendwelche convertions beendet werden (das ist vorraussetzung
für den ADC Interrupt), nur das komische ist, das sich der Wert nie
ändert...
hier die ISR
============================
SIGNAL(SIG_ADC)
{
Aufrufe++;
//Messwert += (ADCH << 8);
PORTD |= 0x80; //LED Rt an
/*lcd_gotoxy(0,1);
lcd_puts("ADC ISR");
*/
Messwert = ADCL;
itoa(Messwert,Buffer_ADCL,10);
lcd_gotoxy(0,0);
lcd_puts(Buffer_ADCL);
Messwert = ADCH;
itoa(Messwert,Buffer_ADCH,10);
lcd_gotoxy(0,1);
lcd_puts(Buffer_ADCH);
itoa(Aufrufe,Buffer_ADCA,10);
lcd_gotoxy(9,1);
lcd_puts(Buffer_ADCA);
}
============================
und im Anhang das ganze .c-File
Achja da fällt mir ein,
als MUX4..0 hab ich 0001 eingestellt, da ich ja laut Table84 Single
Ended Input ADC1 haben will. Aber ich lasse den ADC im Frerun-Mode
laufen, könnte das eine Fehlerquelle sein ??
Das ich dann die MUX bits anders setzen muss,z.b. auf positive oder
negative differential input ?
hmm nöö scheint sich nichts zu ändern, also daran leigt es auch nicht...
Aber die Beschaltung des ADC ist doch soweit in Ordnung oder ?
Siehe Picture im Anhang (Es ist nur die Beschaltung des ADC
eingezeichnet)
Als Voltage Referenz Selection wurde natürlich GND eingestellt, sowie
AREF auch auf GND liegt im Plan !
>Als Voltage Referenz Selection wurde natürlich GND eingestellt, sowie>AREF auch auf GND liegt im Plan !
Wie du hast GND eingestellt? Mir ist nicht bewusst, das das geht.
Die Referenzspannung stellt die Obere Grenze da, wienn diese GND ist,
sind alle angelegten Spannungen = 1023
Ja sorry, nich weiter auf den Schaltplan geguckt :/ entsprechend
Editiert.
Aber wie hast du als Referenz GND ausgewählt? Etwa externe Referenz?
Dann kann das aber so nicht mit dem Kondensator gehen.
Die Referenz GND habe ich laut Datenblatt Table 83 eingestellt.
Also die Bits REFS1 und REFS0 im Register ADMUX beide auf 0 gesetzt...
Damit wird laut Datenblatt die Referenz auf GND gezogen,
und der Temp.sensor liegt ja in Spannungsteilerbeschaltung an GND und
über einen Widerstand von 1k an +5V, oder ist das so nicht erlaubt ??
Siehe Anhang
Da liegt ein Missverständnis vor.
Die Referenz muss gleich oder größer als die maximal zu messende
Spannung sein.
Also entweder 00 aber dann eine passende Spannung an AREF einspeisen
oder 01, dann wäre AVCC die Referenz
oder 11, dann darf aber die Eingangsspannung nicht über 2,56V steigen.
Also gut,
habe die Beschaltung nun so geändert, wie auf dem Schaltplan zu erkennen
ist und auch die Bits dementsprechend gesetzt, also
REFS1 = 0 und
REFS0 = 1
So und wenn ich nun mein Display beobachte, dann stelle ich fest, das
sich die Werte mit der Temperatur ändern :)
Normalerweies zappelt der obere Wert (der aus ADCL) immer so um die 103
herum, wenn ich nicht mit Wärmequelle in die Nähe komme,
aber der untere Wert (der von ADCH) bleibt immer konstant bei 2 stehen,
auch wenn ich sehr lange mit einem Feuerzeug in der Nähe bleibe.
Dann ändert sich nur der obere Wert also der von ADCL von ~103 bis auf
190,
aber Wert in ADCH bleibt gleich, ist das normal ?
Aber soweit schonmal herzlichen Dank an alle die "ihren Senf" dazu
gegeben haben !
Achja, noch ein etwas merkwürdiges Phänomen:
Wert von ADCL
~103 bei Raumtemperatur
halte ich ein Stück gefrorenes Hähnchenbrustfilet (oder was auch immer)
dran, dann geht der Wert schlagartig auf ~900 und geht dann langsam mit
der Abkühlung bis auf ~700 herunter...
Halte ich eine Feuerquelle in die Nähe, geht der Wert von den ~103 bei
Raumtemperatur bis auf ~200 hoch.....
Ist das normal ?
Der KTY-irgendwas Temperaturfühler hat einen Temperaturbereich von -55
bis 150°C
Also sollte das doch innerhalb des möglichen liegen.
Ok kann es sein, das ich dafür dann den Widerstand (also diesen 1k)
anpassen muss?
Eigentlich will ich ja eh nur im Bereich von 0° - 150°C messen...
Du kannst jetzt auch wieder den Wert als einen anzeigen lassen. Die
"geringe" veränderung liegt einfach daran, dass der KTY seinen
Widerstand nicht stark genug ändert. Wenn der Widerstand vom KTY nicht
größer als 1k wird, kannst du auch mal die 2,56V probieren (11) Dann
hast du eine höhere Auflösung. (Der Widerstand vom KTY darf bzw sollte
nicht über 1k steigen, da sonst die Eingangsspannung > Referenzspannung
wird und du nur noch 1023 rausbekommst)
Da der Widerstand des KTY ja nie 0 Ohm wird, und somit 0V gemessen
werden kann, ist es ratsam das Messignal aufzubereiten, z.B. mit einem
OP. Mit diesem kann ein Offset (Nullpunkt) und die Verstärkung (Spanne)
eingestellt werden. Dann kannst du dir den Temperaturbereich einstellen
den du benötigst und hast die vole Auflösung des ADC.
Morgen zusammen...
Im Anhang befindet sich die Widerstands-Temperatur Kennlinie, aus der zu
erkennen ist, das der Widerstand des KTY schon bei 25°C die 1k Grenze
überschreitet.
Leider habe ich keinerlei Ahnung bezüglich Op-Amps, da ich noch nie
damit hantiert habe. Folgende Bauteile habe ich zur Verfügung:
1) LM 311 DIP Voltage Comparator
2) 74HC 14 6xINV.SCHMITT-TRIGGE
3) LM 324 DIL Op-amp, DIL-14
4) LS 163 SCHOTTKY-TTL
Davon am besten eignen würde sich dich doch Nr. 3) oder ?
Aber wenn ich nun ins Datenblatt schaue, sehe ich da stehen:
VCC Supply voltage 32 or ±16 VDC
Aber solche Spannungen kriege ich in meiner Endgültigen Schaltung später
nicht hin, da gibts maximal 12V, also fällt das schonmal weg, oder gibts
noch ne Möglichkeit ???
Ok, das ist vom Wiki die Schalteung eines OPs als Summierer
(Invertierend).
Vor R1 ein Poti (Schleifer), Eingang auf +15V, Ausgang auf -15V (das ist
der Offset-Einsteller).
R12 weglassen.
R13 ist der Eingang vom KTY-Spannungsteiler.
R2 als Poti ausfühern, damit wird die Spanne (Verstärkung) eingestellt.