Bei den nur 10 Bit Auflösung ist Rauschen normal kein Problem. Ehe halt man Problem durch Einkoppelung von Störungen, wie 50 Hz.
Druckbare Version
Bei den nur 10 Bit Auflösung ist Rauschen normal kein Problem. Ehe halt man Problem durch Einkoppelung von Störungen, wie 50 Hz.
Danke, das ist schon mal gut zu wissen.Zitat:
Bei den nur 10 Bit Auflösung ist Rauschen normal kein Problem. Ehe halt man Problem durch Einkoppelung von Störungen, wie 50 Hz.
Das Programm ist ja vorerst mal sehr minimalistisch und es sind keine exterenen Störquellen angeschlossen...
Aber wie erklären sich dann die schwankungen? Kann ich dagegen was machen? Wenn es nicht das Rauschen ist, hilft ein Kondensator?
Der erste Punkt Wegen der Schwankungen wäre es die Schaltung und das Programm auf grobe Fehler zu untersuchen. D.h.
- stimmt der Teiler für den AD-takt: so etwa 50 - 250 kHz sollte es sein
- genug ( > 100 µs) Zeit nach dem Einschalten der Referenz, wenn die interne Ref. genutz wird ?
- sind Abblockkondensatoren an GND-VCC und AGND-AVCC vorhanden ?
- sind GND und AGND sovie VCC und VCC angeschlossen ?
- Stimmt die Ref. Spannung (unter 2 V bzw. 1 V) sind je nach µC nicht gut
Wenn der Sensor extern per langem Kabel verbunden ist, kann ein Kondensator (ca. 100 nF) parallel zum Sensor helfen HF Einkopplungen abzuschwächen. Gegen 50 Hz hilft das aber nicht viel.
Wenn es 50 Hz Einkopplungen sind, hilft es ein paar (z.B: 100) Werte zu mitteln, am besten über eine Zeit die ein vielfaches von 20 ms ist.
Als test für die Art der Störungen wäre ein Testprogramm geeigent, dass erstmal etwa 100 Werte in RAM schreibt, und die dann zum PC sendet. An den Werten kann man dann meist sehen was man für Störungen hat.
Das ist der Code meines LM335... Zuerst habe ich nur den ADC eingelesn, das ging prima. Aber dann soll er es in Temperatur umrechnenCode://----------------------------------------------------------------------
#define F_CPU 3686400 // Taktfrequenz des myAVR-Boards
#include <avr\io.h> // AVR Register und Konstantendefinitionen
#include <inttypes.h>
//----------------------------------------------------------------------
uint16_t readADC(uint8_t channel)
{
uint8_t i;
uint16_t result = 0;
ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1); //ADEN = ADC Enable
ADMUX = channel; //Kanal wählen; REFs0+1 -> interne Referenz 2,56V verwenden, REFS1 gibt es bei Attiny13 nicht
//Dummy-Readout (unten), misst 1* Ergebnis, wird nicht gespeichert
ADCSRA = ADCSRA | (1<<ADSC); // Schaltet bei ADCSRA das ADSC-Bit ein, d.h. Messung starten
while(ADCSRA & (1<<ADSC)); //Warte bis Messvorgang vorbei ist
// Nun 3* Spannung auslesen, Durchschnittswert ausrechnen
for (i=0; i<3; i++)
{
// Schleife, startet 3*
ADCSRA = ADCSRA |(1<<ADSC); // Einmal messen
while(ADCSRA & (1<<ADSC)); //Warte bis Messung vorbei
result = result + ADCW; // Resultate zusammenzählen (R1+R2+R3) -> später alles /3
}
ADCSRA = ADCSRA & (~(1<<ADEN)); //ADC wieder deaktivieren
result=result/3; // Durchschnittswert
return result;
}
main ()
{
int spannung, einer,zehner, komma, temperatur=0;
DDRB=0b00001111;
while (true)
{
PORTB=PORTB|(1<<PB1);
waitMs(50);
PORTB=PORTB&(~(1<<PB1));
waitMs(50);
uint16_t result = readADC(2);
spannung=(result*2978)/100;
temperatur=(spannung-20000);
zehner=(temperatur)/100;
einer=(temperatur-100*zehner)/10;
komma=(temperatur-100*zehner-10*einer);
for (int k=0;k<zehner;k++)
{
PORTB=PORTB|(1<<PB2);
waitMs(100);
PORTB=PORTB&(~(1<<PB2));
waitMs(100);
}
for (int h=0;h<einer;h++)
{
PORTB=PORTB|(1<<PB1);
waitMs(100);
PORTB=PORTB&(~(1<<PB1));
waitMs(100);
}
for (int g=0;g<komma;g++)
{
PORTB=PORTB|(1<<PB0);
waitMs(100);
PORTB=PORTB&(~(1<<PB0));
waitMs(100);
}
waitMs(1100);
}
return 0;
}
(Wenn Spannung = 2019mV, dann sind es 19 °C also d=-2000)
Und jetzt macht er nur den ersten Blink-Befehl in der while schleife, dann wartet er und macht ihn wieder....
Teiler habe ich keine Ahnung...Zitat:
Der erste Punkt Wegen der Schwankungen wäre es die Schaltung und das Programm auf grobe Fehler zu untersuchen. D.h.
- stimmt der Teiler für den AD-takt: so etwa 50 - 250 kHz sollte es sein
- genug ( > 100 µs) Zeit nach dem Einschalten der Referenz, wenn die interne Ref. genutz wird ?
- sind Abblockkondensatoren an GND-VCC und AGND-AVCC vorhanden ?
- sind GND und AGND sovie VCC und VCC angeschlossen ?
- Stimmt die Ref. Spannung (unter 2 V bzw. 1 V) sind je nach µC nicht gut
Wenn der Sensor extern per langem Kabel verbunden ist, kann ein Kondensator (ca. 100 nF) parallel zum Sensor helfen HF Einkopplungen abzuschwächen. Gegen 50 Hz hilft das aber nicht viel.
Wenn es 50 Hz Einkopplungen sind, hilft es ein paar (z.B: 100) Werte zu mitteln, am besten über eine Zeit die ein vielfaches von 20 ms ist.
Muss ich gleich mal nachschauen, aber da er aus einem Demoprogramm stammt...
Nachdem ixch die interne Referenz eingeschaltet habe, wartet er nicht, sondern startet gleich. Allerdings ist dies eine Dummy-Messung.
Das passt dann doch?
AVCC gibt es beim ATtiny13 gar nicht. Kondensator hängt keiner dran... Soll ich zwischen VCC und GND einen Keramikkondensator einbauen?
Referenz ist intern 1,1V beim Widerstandsmesser, das solte also stimmen
Mit einem längerem Kabel ist er übrigens auch nicht verbunden....
Leider beherrsche ich noch kein UART, das geht somit erst später :(Zitat:
Als test für die Art der Störungen wäre ein Testprogramm geeigent, dass erstmal etwa 100 Werte in RAM schreibt, und die dann zum PC sendet. An den Werten kann man dann meist sehen was man für Störungen hat.
Beim Tiny13 erübrigt sich der Kondensator an AVCC natürlich. Der Kondensator von VCC nach GND, auf kurzen Wege dicht am IC sollte schon sein. Nicht nur wegen des AD-wandler, auch schon wegen Funkstörungen.
Der Teiler wird über ADPS0...ADPS4 eingestellt. Im Code ist ein Teiler von 6 eingestellt. Das ist etwa wenig - besser ein Wert von etwa 20, das sollte aber nur etwas mehr rauschen ergeben.
In der Zeile:
" spannung=(result*2978)/100; "
kann es zu einem Überlauf kommen. Result*2978 passt nicht mehr unbedingt in eine integer Zahl. Da sollte man das Abziehen aus der Nächsten Zeile Vorziehen, oder mit Longint Zahlen rechnen.
Also 6 ergibt mehr Rauschen als 20 oder umgekehert?Zitat:
Im Code ist ein Teiler von 6 eingestellt. Das ist etwa wenig - besser ein Wert von etwa 20, das sollte aber nur etwas mehr rauschen ergeben.
Das kann ich machen. Was für einen würdest du denn da empfehlen (Farad-mäßig)?Zitat:
Beim Tiny13 erübrigt sich der Kondensator an AVCC natürlich. Der Kondensator von VCC nach GND, auf kurzen Wege dicht am IC sollte schon sein. Nicht nur wegen des AD-wandler, auch schon wegen Funkstörungen.
19 Grad C sind schon 678 ADC.Zitat:
In der Zeile:
" spannung=(result*2978)/100; "
kann es zu einem Überlauf kommen. Result*2978 passt nicht mehr unbedingt in eine integer Zahl. Da sollte man das Abziehen aus der Nächsten Zeile Vorziehen, oder mit Longint Zahlen rechnen.
Kommt es da schon zum Überlauf??
Danke vielmals, da wär ich ja nie draufgekommen =D>
Naja, das Abziehen kann ich ja kaum vorziehen, denn dabei geht es ja darum, Kommazahlen zu screiben mit Integer. Später dann wieder durch 10^x und fertig :)
678*2978 sind schon deutlich mehr als 32767, das ist die maximale zahl die in die 16 Bit Integer rein passt. Da hat man also schon längst einen Überlauf. Selbst wenn man den Faktor 4 raus kürzt reicht es nicht.
Das Abziehen kann man schon vorziehen, indem an gleich eine Formel für die Temperatur aus den AD werten berechnet als
Temp = (AD_wert - A) * B
mit konstanten Werten A und B. Man kann da in der Regel auch gleich auf das Teilen Verzichten und B entsprechend passend Berechnen.
Der einfache Weg ist es natürlich einfach auf longint als Datentyp auszuweichen. Da reicht es schon wenn man
statt (result*2978)/100; einfach (result*2978L)/100; schreibt. Die Rechnung wird dann mit 32 Bit, ausgeführt.
Der Teiler 20 für den AD Takt gibt etwas weniger Rauschen. Der alte Teiler von 6 ist aber noch nicht so schlimm.
Der Abblockkondensator ist typischerweise 100 nF. Zur Not tun es auch 10 nF als Kondensator, wenn da noch ein Elko mit z.B. 10 µF in der Nähe ist.
habe einen 104-Kondensator gefunden, der müsstge ideal sien.
Und in der Tat, das LM335 springt nicht herum....
Allerding fürchte ich, das die Auflösung zu gering ist: ADC 673 = -4,5°C
ADC 678 = 19°C.
Klappt wunderbar, danke ;)Zitat:
einfach (result*2978L)/100;
Bei der Einstellung zum AD-Takt hatte ich einen Fehler drin. Die alte Einstellung mit ADPS1/ADPS2 = 1 gibt schon einen Teiler von 64. Das ist so OK.
Wenn der LM335 10 mV/K hat, kommt man wohl nicht mehr mit der intern 1,1 V ref. aus. Mit Vcc=5V als Referenz sollte das für etwa 5 mV Auflösung oder etwa 0,5 C reichen.
Für etwas mehr Auflösung, aber nicht unbedingt Genauigkeit, kann Oversampling nutzen: den AD nicht nur 3 mal, sondern z.B. 64 mal auslesen und dann aber nicht durch 64 Teilen, sondern nur durch 16. Das Ergebnis ist dann eine Zahl zwischen 0 und 4096, so als hätte der AD Wandler 12 Bit Auflösung. Ein Voraussetzung ist dabei, dass der AD Wandler gerade keine immer Konstanten werte ausgibt, sondern schon etwas Schwankungen zeigt - ggf. kann man die Schwankungen sogar absichtlich hinzu addieren.
Darum musste ich auch auf Versorgungsspannung (3,05V, 2 Batterien) zurückgreifen. Mit eben 4°C oder so Auflösung.Zitat:
Wenn der LM335 10 mV/K hat, kommt man wohl nicht mehr mit der intern 1,1 V ref. aus.
Mit 5V käme ich auf 0,5 °C Auflösung? Das wäre ja super!
Allerdings - ob der Sprung von 3V auf 5V so viel ausmacht?
Ich probiers einfach mal.
Das klingt ganz interessant, aber eigentlich hat er ja fast keine Schwankungen mehr...Zitat:
Für etwas mehr Auflösung, aber nicht unbedingt Genauigkeit, kann Oversampling nutzen: den AD nicht nur 3 mal, sondern z.B. 64 mal auslesen und dann aber nicht durch 64 Teilen, sondern nur durch 16. Das Ergebnis ist dann eine Zahl zwischen 0 und 4096, so als hätte der AD Wandler 12 Bit Auflösung. Ein Voraussetzung ist dabei, dass der AD Wandler gerade keine immer konstanten Werte ausgibt, sondern schon etwas Schwankungen zeigt - ggf. kann man die Schwankungen sogar absichtlich hinzu addieren.
19°C zeigt er seitdem ich den Kondensator angehängt habe immer an, (und einmal 16,1)