Hallo Forengemeinde,
ich lese den 10 Bit ADC eines Atega32 aus, an dem ein Feuchtesensor
hängt. Dazu lese ich den Sensor 255 mal aus und addiere alle Werte und
dividiere diese dann durch 255. Das klappt soweit ganz gut. Mein Problem
ist jedoch das der Feuchtesensor recht zappelt und auch mit 255
Messungen (Atmega läuft mit 8 MHz, Prescaler ist 64 -> macht also immer
noch 125 kHz Samplingfrequenz) werde ich der Lage nicht Herr.
Ich kenne nur noch die Methode wo man die Zahlen der Größe nach ordnet
und n größte und n kleinste Zahlen wegwirft um Spitzenwerte bzw.
sogenannte "Ausreißer" herauszufiltern.
Sicherlich gibt es klevere Methoden, wie man dass machen kann. Oder habt
Ihr einen Tip wonach ich suchen muss.
Bin für Tips und Hilfe dankbar!
Gruß Paul
Paul schrieb:> Oder habt Ihr einen Tip wonach ich suchen muss.
Du musst nach dem Fehler suchen.
Und dabei kann dir keiner helfen, da keiner weder dein Programm oder
deinen Schaltplan noch deinen Schaltungsaufbau kennt.
mfg.
Erstens verwende einen exponentiellen Mittelwert, der skaliert besser,
dh braucht nur eine Speicherstelle, kann aber per einem Wert langsamer
werden.
Dann .. sampelt er zu schnell. Geh lieber auf eine langsamere Frequenz.
Und allenfalls ist auch noch EMV im Spiel, dh ungenuegende Hardware.
Zeig doch mal ein Schema und ein Layout.
Paul schrieb:> Oder habt Ihr einen Tip wonach ich suchen muss.
Vielleicht stimmt's ja einfach was der ADC liefert.
Vielleicht schwankt deine zu erfassende Spannung ja tatsächlich stark.
Was ist denn deine VRef ? 5V ? Wie ist die Schaltung des Feuchtesensors,
Spannungsteiler ? Verträgt der Feuchtesensor überhaupt Gleichstrom oder
will der Wechselstrom ? Wie sind deine Versorgungsspannungen gefiltert
und was hängt noch so dran und stört ? Schon mal probieert, den ATmega
während der Umwandlung in SLEEP zu bringen damit er sich selbst nicht
stört ?
Paul schrieb:> ich lese den 10 Bit ADC eines Atega32 aus, an dem ein Feuchtesensor> hängt. Dazu lese ich den Sensor 255 mal aus und addiere alle Werte und> dividiere diese dann durch 255.
probier es mal mit weniger als 64 Werten.
Welcher Datentyp? Integer? (uint16_t ?)
Gruß Anja
@ Paul (Gast)
>hängt. Dazu lese ich den Sensor 255 mal aus und addiere alle Werte und>dividiere diese dann durch 255. Das klappt soweit ganz gut.
Wenn man 256 Werte ufsummiert und durch 256 "teilt", geht es noch
einfacher, weil /256 gleich einer Rechtschiebung um 8 Bit entspricht.
>ist jedoch das der Feuchtesensor recht zappelt und auch mit 255
WIEVIEL?
>Sicherlich gibt es klevere Methoden, wie man dass machen kann. Oder habt>Ihr einen Tip wonach ich suchen muss.
Erstmal grundlegend, WARUM deine Messung zappelt.
Fehler im Aufbau?
Wackelkontakt?
Störungen der Stromversorgung?
So eine ADC-Messung wackelt im Normalfall nur wenige LSB (1-3), auch
ohne Mittelwertbildung.
Paul schrieb:> Mein Problem ist jedoch das der Feuchtesensor recht zappelt
Dann löte ihn erstmal fest, damit er ruhig ist.
Als nächstes könntest du die Werte als Zeitserie angucken. Aus "recht
zappelt" anhand dieser Daten eine Zahl zu machen, wäre ein weiterer
Schritt. Diese Zahl würde ich mit der entsprechenden Angabe im
Datenblatt des Sensors vergleichen kannst. Vielleicht sind auch
Störungen im Spiel - who knows.
1.
Zeig den Schaltungsaufbau, sonst können wir nur raten.
2.
Falls der Aufbau halbwegs OK ist, könnten noch Einstreuungen
von der 50 Hz Netzwechselspannung die Ursache sein.
Gegenmaßnahme:
Samplerate und Anzahl der Messungen so wählen, dass sich der
50 Hz-Fehler herausmittelt.
Beispiel: 20 Messungen im Abstand von 1,00 ms (1/50 s), oder
16 Messungen im Abstand von 1,25 ms (1/50 s), oder
256 Messungen im Abstand von 0,625 ms (8/50 s), ...
3.
Wenn möglich, einen Ratiometrisch arbeitenden Sensor wählen.
Deine Methode, 256 Werte zu addieren und dann durch 256 zu teilen
reduziert Rauschen. Aber es hat keinen Einfluss auf Schwankungen des
tatsächlichen Nutzsignals.
Du kannst Signal stattdessen integrieren, als einen R/C Tiefpass
nachbilden.
#define FAKTOR 100
int16_t kondensator;
while (1)
{
int16_t adc=read_adc();
int16t diff=adc-kondensator/256;
kondensator=kondensator+diff*FAKTOR;
}
int16_t ergebnis=kondensator/256;
Damit wir auf Fließkomma-Operationen verzichten können, speichern wir im
Kondensator das 256-fache vom Messwert (also 8 bit mehr). Die unteren 8
Bit sind quasi unser Ersatz für Nachkommastellen.
Der FAKTOR muss im Bereich 1-256 liegen. Ein kleiner Wert bewirkt eine
starke Dämpfung von Schwankungen, ein großer Wert bewirkt eine geringe
Dämpfung. Beim Maximum 256 finde gar keine Dämpfung mehr statt.
Die letzte Code zeile wird wegen der Endlosschleife nie ausgeführt - war
mein Denkfehler. Aber ich denke, es ist trotzdem klar, was ich meinte.
Falls nicht, frag nochmal nach.
Wow, ein Buch voller Antworten :o)
Ich habe mich mal zu "gleitender Durchschnitt" belesen und finde vor
allem Diskussionen darüber was an den jeweiligen Formeln falsch ist. Das
hat mich also mehr verwirrt als es mir genutzt hat. Leider bin ich noch
nicht Fit so etwas selbst zu erstellen und gucke mir aktuell erst mal
was ab, vollziehe es nach und baue es dann ein. Somit habe ich
allerdings schon bisschen was verstanden.
Nun zu Euren Fragen:
Beim ADC-Wert schwanken die letzten beiden Stellen.
Das ganze hängt hinter einem "Stange USB ISP" der an dem USB-Port von
meinem Laptop hangt der wiederum 5,03 V liefert (genauer ist mein
Multimeter nicht).
Ich habe Tatsache nur das halbe RC-Glied an den ADC gehängt, also nur
eine 100nF Kerko zwischen die Signalleitung und GND von dem HMZ-333A1
Feuchtesensor. Den 4k7 Widerstand habe ich anscheinend vergessen. Hab
gerade noch mal in meiner Bastelkiste gesucht und keinen gefunden -
jetzt ist mir auch klar warum ich den nicht eingebaut habe, muss ich
also erst kaufen gehen.
Als VREF nehme ich VDD, also die 5,03 Volt vom USB. Wie glatt diese
Spannung ist kann ich nicht sagen. Ein Oszi habe ich nicht. Ich bin aber
gewillt die Schaltung mit einem Festspannungsregler auszustatten und
dann nochmal zu prüfen wie sehr alles schwankt. An Netzschwankungen habe
ich noch gar nicht gedacht.
Weiterhin hängen noch 2 Stück DS18S20 1-wire Temperatursensoren (nicht
parasitär), ein 8MHZ-Quarz inkl. 2x 22p Kondensatoren, ein LCD (1602A)
und ein Taster an dem Atmega32.
Zwischen Aref und AGnd befindent sich ein 100nF Kerko. Zwischen AVcc und
Gnd ist ebenfals ein 100n Kerko. AVcc ist über einen 56R Widerstand mit
Vcc verbunden.
Den Filter würde ich so versuchen:
[c]
#define FAKTOR 100
int16_t kondensator;
for(i=0; i<20; i++) { //16 Messungen durchführen
{
int16_t adc=read_adc();
int16t diff=adc-kondensator/20; // durch Anzahl der Messungen
teilen
kondensator=kondensator+diff*FAKTOR;
_delay_ms(1)
}
int16_t ergebnis=kondensator/20; // durch Anzahl der Messungen
teilen
[c]
An der Konstante "FAKTOR" kann ich dann herumschrauben bis ich glücklich
bin oder keine Lust mehr habe - je nachdem was zuerst eintritt.
Paul schrieb:> Ich habe Tatsache nur das halbe RC-Glied an den ADC gehängt, also nur> eine 100nF Kerko zwischen die Signalleitung und GND von dem HMZ-333A1> Feuchtesensor. Den 4k7 Widerstand habe ich anscheinend vergessen. Hab> gerade noch mal in meiner Bastelkiste gesucht und keinen gefunden -> jetzt ist mir auch klar warum ich den nicht eingebaut habe, muss ich> also erst kaufen gehen.
Na, dann nimm doch irgend einen anderen Widerstand im Bereich von 4.7K
bis 47K. Hauptsache der Tiefpass bewirkt überhaupt etwas, und mehr als
4.7K ist eh besser.
Paul schrieb:> HMZ-333A1
Aha, Chinamüll.
Es ist laut Datenblatt nicht klar, ob die Ausgangsspannung des Sensors
ratiometrisch von der Versorgungsspannung abhängt, oder eine eigene
Referenz hat.
http://www.ghitron.com/files/HMZ-333A1.pdf
Da dein ratiometrisches Messen so schlechte Resultate liefert, sollte
man es wohl mal absolut versuchen. Stelle deinen Microcontroller von 5V
ARef auf die interne 2.5V Referenz um und miss nochmal.
Der einzelne 100nF Kondensator am Ausgang des Sensors ist ok, aber die
ARef-Spannung des uC muss auch gefiltert sein, üblicherweise mit
10uH/100nF und 100nF an Ref.
Wenn die Messwerte mit der internen Ref deutlich stabiler sind, stellt
sich die Frage, wie man von den 3.3V auf die messbaren 2.5V herunter
kommt. Ein Spannungsteiler, der dem uC weniger als 10k anbietet,
belastet den Sensor mit 5k Ausgangswiderstand zu stark.
Es wird wohl einen zusätzlichen OpAmp kosten:
+5V
|
Sensor --|+\ LM358 oder besser
| >--+
+--|-/ |
| |
+--------+
|
10k
|
+-- A/D
|
25k
|
GND