PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Mehrere Analogeingänge abfragen erzeugt nur wirre Daten vom LM35...



Zeitsklave
12.12.2012, 20:36
Hallo Leute!
Ich steh hier gerade vor einer Wand, und habe gehofft ihr könnt mir vielleicht weiterhelfen...

Ich baue gerade mit einem Arduino Mega2560 und einem EthernetShield eine Telemetrie für meine Heizung.
Soweit funktioniert das ganz gut, schließe ich einen LM35 an kann ich ihn wunderbar auslesen und an meine Website senden.
Aber wehe ich versuche mehrere Analoge eingänge auszulesen! Dann kriege ich nur wirres Zeug raus!
Ich habs gestern schon bemerkt, als ich 5 Eingänge ausgelesen hab, aber nur an einem Eingang einen LM35 hatte, hat der komische Werte gebracht (immer 10-20° zuviel angezeigt, und jeder Messwert anders). Ich habs drauf geschoben dass ich an den anderen Pins nix habe und durch das Auslesen störungen verursacht. Also die entsprechenden Zeilen vom Code auskommentiert und alles war wunderbar.
Jetzt hab ich heute einen PT1000 für die Außentemperatur an einen anderen Pin angeschlossen, und plötzlich zeigt der LM35 wieder nur Müll an, der PT1000 dagegen liefert aber absolut saubere Werte. Sobald ich die Zeile, die den PT1000 liest auskommentiere, kommen vom LM35 auch wieder schöne Temperaturen.
Ich hab auch schon andere Pins versucht, keine Änderung.

Hier mal ein Bild meiner Beschaltung vom LM35:
http://imageshack.us/a/img825/1346/dsc8196a.th.jpg (http://imageshack.us/photo/my-images/825/dsc8196a.jpg/)

Und der Ausschnitt meines Codes:



#include <SPI.h>
#define aref_voltage 3.34


int Sensor1 = A11;
int Sensor5 = A15;
float Temperatur1 = 0;
float Temperatur5 = 0;

void setup()
{
Serial.begin(9600);
analogReference(EXTERNAL);
Serial.println("Programm gestartet");
}

void loop()
{
Sensor_lesen();


delay(1000);
}

void Sensor_lesen()
{
Temperatur1 = (analogRead(Sensor1) * aref_voltage / 1024 * 1000) / 10;
Serial.print("S1: ");Serial.println(Temperatur1);

int S5r = analogRead(Sensor5);
Serial.print("S5: ");Serial.println(S5r);
}

Ich hoffe mein Code ist übersichtlich, hab noch nie in C programmiert :wink:

Ich hoffe ihr habt einen heißen Tipp für mich... Ich möchte ungern nur PT1000 verwenden, wegen Kosten...!
100nf an VCC und GND direkt am LM35 haben übrigens nichts geholfen :-(
Auch ein delay(1000); zwischen beiden Sensoren hat nichts genützt...


Ach ja, der LM35 hängt mittlerweile am A11, also nicht wundern warum im Code was anderes steht als auf dem Bild zu sehen ist :wink:

RoboHolIC
12.12.2012, 23:25
Wirre Messwerte von verschiedenen ADC-Kanälen beruhen manchmal auf zu kurzer Samplingzeit. µC-ADCs haben i.d.R. einen internen Sample&Hold-Kondensator, der vor der Wandlung ausreichend Zeit benötigt, um sich an die externe zu messende Spannung anzugleichen. Erlaubte Eingangswiderstände liegen bei den mir bekannten Controllern im Bereich von maximal 10kOhm. Ich kenne deine LM35-Spannungsteilerschaltung nicht, vielleicht ist sie viel hochohmiger als 10kOhm. Man kann aber in gewissen Grenzen Impedanz gegen Samplingzeit eintauschen: Du könntest z.B. versuchen, eine Dummy-Messung zu machen, die alleine der Anwahl des ADC-Kanals dient, dieser Messwert wird verworfen. Anschließend eine ordentlich lange Samplingzeit durch Delay oder Timer ermöglichen, dann nochmal messen und erst diesen Wert (oder den Mittelwert mehrerer Messungen) nehmen und weiterverwerten.

Dass der PT1000 im Wechsel mit LM35 stabile Werte liefert, der LM35 dagegen nicht, spricht für die Sache mit der Impedanz/Samplingzeit.
Dass der LM35 alleine (ich nehme mal an, ohne andere Messkanäle) auch stabile Messwerte liefert, spricht ebenfalls für ein Impedanzproblem und gegen Störeinstreuung.
Dass der LM35 im Wechsel mit anderen offenen und auch gewandelten ADC-Eingängen auch Müll liefert, widerspricht dem zumindest nicht.

Zeitsklave
13.12.2012, 18:28
Viele dank für die kompetente Antwort!
Eine Spannungsteilerschaltung hab ich nicht, der Ausgang des LM35 hängt direkt am Analogen Eingang. Der LM35 wird mit VCC und GND an die Versorgungsspannung angeschlossen und liefert dann am Ausgang exakt 10mV pro °C.
Den Tipp mit der Dummy-Messung werd ich gleich mal testen, hast du einen Vorschlag wie lang der Delay sein sollte? Ich hab da leider 0 Vorstellung...!

Zeitsklave
13.12.2012, 22:10
oh man...
nachdem ich mir gestern noch den ganzen abend mit einem pt1000 um die ohren gehauen hab um einen rechenweg zu finden mit dem ich vernünftige temperaturen rauskrieg (ich hab keinen gefunden), hab ichs heut nochmal mit dem lm35 versucht.
3 stück angeschlossen, 3 stück abgefragt, super stabile werte bekommen. mit und ohne delay.
jetzt hab ich aus freude alle 5 sensoren fertig verkabelt, angeschlossen, und krieg wieder nur müll raus. erstmal mit abfragen von nur 3 sensoren, dann mit einer programmänderung dass alle 5 abgefragt werden, und auch mit delay zwischen 50 und 500ms.
ich verstehs nicht, und so langsam hab ich keinen bock mehr :(
was bitte mach ich falsch? die verkabelung war bei allen versuchen gleich, und auch die programmierung!

BMS
14.12.2012, 10:41
Hallo,
ich vermute eher, dass die Spannungsversorgung nicht ganz "sauber" ist. Kannst du mal die 3,3V mit einem Oszilloskop anschauen? Eventuell ist da noch ripple drauf.
Die AREF könnte man noch filtern, meist ist hier ein LC-Tiefpass üblich (RC geht auch). Also in die Leitung von den 3,3V zu AREF z.B. ein Widerstand (10...100Ohm?) und dann von AREF zu GND ein Kondensator (100nF, 1µF ?).
Beim LM35 kannst du auch einen Kondensator zwischen Analogpin und GND einbauen.
Da der Fehler scheinbar bei mehreren Sensoren auftritt, kannst du auch mal alle Analogpins nacheinander testen - also einen Sensor nehmen, und dann nacheinander immer nur einen Analogpin testen (auch in Software immer nur einen Pin messen), um hier Fehlerquellen auszuschließen. Evtl. kannst du den Analogpin auch mal direkt mit GND oder 3,3V verbinden, der Wert in der Software muss dann auch wirklich das Minimum oder Maximum erreichen können. Sonst ist etwas faul :-k
Und dann würde mich noch interessieren, wie die Methode analogRead programmiert ist (Stichworte Acquisition Time; ADC Clock).
Grüße, Bernhard

Zeitsklave
14.12.2012, 18:48
Also ein 100nF Kondensator und 50Ohm haben nichts bewirkt, 100nF direkt am LM35 leider auch nicht.
Ich habe 5 LM35 an 5 Analogen eingängen (1-5). Gestern hatte ich 3 LM35 an 3 Eingängen (1,3,5), und es hat funktioniert... Im Quelltext hab ich nur die vier Zeilen hinzugefügt, die zusätzlich die Eingänge 2 und 4 auslesen.
Egal ob ich das Board über USB mit Stom versorge oder über das Netzteil meiner ausgangierten Fritz!Box (das zufälligerweise perfekt passt!), die ergebnisse bleiben komplett gleich!

Hier mal ein Screenshot meiner Ergebnisse wie ich sie im Browser ausgebe:
http://imageshack.us/a/img818/8137/diagramm1.th.jpg (http://imageshack.us/photo/my-images/818/diagramm1.jpg/)

Wenns vorher ging und jetzt, nachdem ich sämtliche Sensoren fertig konfektioniert habe, kanns ja eigentlich fast nur noch an der Verkabelung liegen. Wenn ich die Abfrage für 2 und 4 wieder auskommentiere hab ich immernoch die gleichen verrückten Werte.
Allerdings hatte ich das Problem ja vorher auch schon, wie im ersten Post beschrieben, praktisch mit der gleichen Verkabelung, mit ders dann später plötzlich mal funktioniert hat...

Ich bin ratlos...

Ich hab zwar einen alten Oszillographen am Dachboden (der wohl älter ist als ich...), aber bis ich den wieder runterschlepp und enstaub... Ich weiß nichtmal ob das Ding für sowas geeignet ist, ganz zu schweigen davon dass ich nie richtig kapiert hab wie man das Monster bedient ^^



Edit: Endlich Erfolg! Ich war vorhin wohl doch zu voreilig... Die Kondensatoren direkt am LM35 zwischen Signal und GND haben das Ruder rumgerissen! :)
Die Werte sind zwar noch nicht 100% sauber, haben sich aber trotzdem deutlich stabilisiert, und wären jetzt prinzipiell für meinen Zweck zu gebrauchen. Wobei es natürlich schön wäre wenn die Kurve noch ein bisschen glatter wäre... Gehe ich richtig in der Annahmen, dass ein höherer Wert am Kondensator ein stabileres Signal liefert?
http://imageshack.us/a/img37/5404/diagramm2.th.jpg (http://imageshack.us/photo/my-images/37/diagramm2.jpg/)

BMS
14.12.2012, 20:29
Hallo,
das untere Diagramm sieht ja schon deutlich besser aus, freut mich :)
Eine größere Kapazität könnte eventuell noch eine Verbesserung bringen, wohl aber nicht beliebig besser, denke ich.
Aber mich wundert, dass die Messwerte im ersten Diagramm so stark verrauscht waren :shock: Da sind ja Sprünge um 20 Grad drin, wären bei 10mV/°C Sprünge um 200mV.
Kannst du bitte den Code von analogRead() raussuchen? Eventuell muss dort eine Pause nach der MUX-Einstellung rein (sog. Acquisition Time -> damit sich der interne Kondensator der Sample-And-Hold-Stufe im ADC lang genug auf die neue Spannung aufladen kann)
Grüße, Bernhard

Nachtrag: Was auch helfen sollte, ist eine Mittelung im Programm. Also du könntest mehrere Messungen direkt nacheinander durchführen (nur an einem Kanal) und dann den Durchschnitt berechnen. Das dürfte das Rauschen auch noch reduzieren.

Zeitsklave
14.12.2012, 20:57
Ich hab jetzt mal auf dem ersten Sensor eine Mittelwertmessung gebastelt, mal sehen was dabei rauskommt ;) Ich wart bis morgen damit, weil ich schonmal das Intervall auf 10 Minuten gestellt hab, so wies sein soll...

Ich bin nicht sicher ob ich das Richtige in den Arduino-libaries gefunden hab:



int analogRead(uint8_t pin)
{
uint8_t low, high;

#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
if (pin >= 54) pin -= 54; // allow for channel or pin numbers
#elif defined(__AVR_ATmega32U4__)
if (pin >= 18) pin -= 18; // allow for channel or pin numbers
#elif defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__)
if (pin >= 24) pin -= 24; // allow for channel or pin numbers
#else
if (pin >= 14) pin -= 14; // allow for channel or pin numbers
#endif

#if defined(__AVR_ATmega32U4__)
pin = analogPinToChannel(pin);
ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5);
#elif defined(ADCSRB) && defined(MUX5)
// the MUX5 bit of ADCSRB selects whether we're reading from channels
// 0 to 7 (MUX5 low) or 8 to 15 (MUX5 high).
ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5);
#endif

// set the analog reference (high two bits of ADMUX) and select the
// channel (low 4 bits). this also sets ADLAR (left-adjust result)
// to 0 (the default).
#if defined(ADMUX)
ADMUX = (analog_reference << 6) | (pin & 0x07);
#endif

// without a delay, we seem to read from the wrong channel
//delay(1);

#if defined(ADCSRA) && defined(ADCL)
// start the conversion
sbi(ADCSRA, ADSC);

// ADSC is cleared when the conversion finishes
while (bit_is_set(ADCSRA, ADSC));

// we have to read ADCL first; doing so locks both ADCL
// and ADCH until ADCH is read. reading ADCL second would
// cause the results of each conversion to be discarded,
// as ADCL and ADCH would be locked when it completed.
low = ADCL;
high = ADCH;
#else
// we dont have an ADC, return 0
low = 0;
high = 0;
#endif

// combine the two bytes
return (high << 8) | low;
}

BMS
14.12.2012, 21:27
Hallo,
im Code ist keine wirkliche Wartezeit (Acquisition Time) drin. Hier die wichtigen Zeilen aus deinem Code, die dafür verantwortlich sind (gekürzt, geändert):

//hier wird festgelegt, welcher Analogeingang gelesen werden soll
ADMUX = (analog_reference << 6) | (pin & 0x07);

//Das ist die quasi nicht vorhandene Acquisition Time
//hier solltest du unbedingt eine kleine Wartezeit einbauen, mehrere Mikrosekunden sind unbedingt erforderlich!
//RC-Kombination im Sample-And-Hold: ca. 1...100kOhm und 14pF in vergleichbaren ATmegas, also Zeitkonstante t=R*C=1,4 Mikrosekunden mindestens an Wartezeit nötig, lieber etwas mehr!
//without a delay, we seem to read from the wrong channel <-- da hat sich der Programmierer wohl etwas dabei gedacht, dann aber das delay wieder auskommentiert !?
//delay(1); ///<---------HIER

//AD-Wandlung geht los...
sbi(ADCSRA, ADSC);
Mit einer kleinen Wartezeit an der genannten Stelle sollte die AD-Wandlung deutlich stabilere Ergebnisse bringen. Wenn das noch nicht reicht, kann man noch den Takt für den AD-Wandler reduzieren (Register ADCSRA, Prescaler-Einstellungen, z.B. ADCSRA |= 0x07; ).
Gutes Gelingen weiterhin!
Grüße, Bernhard

RoboHolIC
15.12.2012, 01:35
Eine Abschätzung zur Delayzeit:

Die Signalquelle, hier der Ausgang des LM35, hat einen gewissen Innenwiderstand. Im Inneren des Controller ist ebenfalls ein Widerstand wirksam, der die Aufladung des Samplingkondensators bremst, Größenordnung 1kOhm, spezifiziert im Datenblatt des Controllers.

Die Reihenschaltung des äußeren und inneren Widerstandes und die Kapazität des Samplingkondensators bilden eine Zeitkonstante tau = (R_ext + R_int) * C_sampling. Das sieht auf den ersten Blick komisch aus, ist nach den Einheiten aber wirklich eine Zeit: (V/A) * (A*s/V) --> s.

Eine sprungartige Veränderung der zu messenden Spannung (z.B. beim ADC-Kanalwechsel) ist nach 1x tau erst zu 63% am Samplingkondensator sichtbar, d.h. es fehlen zum Endwert noch 37%. Nach 2* tau fehlen nur noch (oder: immer noch) 0,37*0,37*100 = 14% des eingangsseitigen Spannungshubes bis zur völligen Angleichung der Samplingspannung an die zu messende Spannung.

Es braucht folglich schon einige tau, um unter 1 Bit Abweichung des ADC-Ergebnisses (Reading) von tatsächlichen Wert zu kommen. Je größer der Spannunhshub zwischen (n-1)-tem und n-tem Sampling ist, desto mehr tau's braucht es, um die 1-Bit-Grenze zu unterschreiten.

P.S.: Ich habe gerade gesehen, dass wikipedia eine gute Abhandlung über das Thema "Zeitkonstante" bietet.

BMS
15.12.2012, 10:01
Die genauen Werte finden sich im Datenblatt ( www.datasheetcatalog.org/datasheets2/30/3055029_1.pdf (http://www.datasheetcatalog.org/datasheets2/30/3055029_1.pdf) ) auf Seite 282.
R=1...100kOhm, C=14pF
Nehmen wir mal den worst-case an (R=100kOhm) und warten 5*tau, damit sich der Kondensator auf über 99% aufladen kann.
Dann müssen wir 5*tau=5*R*C=5*1e5Ohm*1,4e-11F=7µs warten (Mikrosekunden); bei z.B. 10kOhm Quellimpedanz dann 10% länger.

Zeitsklave
15.12.2012, 13:13
Oh je, sooo tief wollt ich doch auch nicht in die Materie einsteigen ;)
So viel Fachwissen darf doch eigentlich nicht nötig sein um einfach 5 Analoge Anschlüsse auszulesen, ganz besonders bei einem Board wie Arduino...
Aber gut, was solls :)
7µs ist ja ziemlich wenig, da sollte das delay(1), das ich gestern noch "de-auskommentiert" hab locker reichen.
Ich hab auch gestern (oder wars vorgestern schon?) die Mittelwertrechnung eingebaut, mit 5 Werten und 10ms Abstand. Trotz dem Mittelwert und dem delay(1) waren jetzt die Werte noch ziemlich wackelig, obwohl ich jetzt schon innerhalb von einem Grad bin, also durchaus brauchbar. Einzig der Sensor mit der längsten Leitungslänge schwankt noch um etwas mehr als 1 Grad, der hat allerdings nur 68nF dranhängen, ich hatte nix besseres mehr da...
Jetzt hab ich mal die Mittelwertrechnung auf 10 Werte mit je 20ms Abstand ausgedehnt, mal sehen ob ich jetzt das Diagramm etwas geglättet krieg (Sieht einfach schöner aus). :)

Vielen vielen Dank für das Hirnschmalz erstmal, ich werd weiter berichten!

Zeitsklave
16.12.2012, 11:37
So, ich würd mal behaupten so wies jetzt läuft gefällts mir :)
http://imageshack.us/a/img809/4241/diagramm3.th.jpg (http://imageshack.us/photo/my-images/809/diagramm3.jpg/)
man sieht hier schön was ich gemacht hab:
- um 14 Uhr hab ich das Gerät in den Heizungsraum gepackt und die Sensoren positioniert. Alles vorher ist Raumtemperatur im Wohnzimmer
- Kurz darauf, ca. 14:10 hab ich den Ofen angeschürt
- um 16:00 hab ich nachgelegt
- um 6 Uhr morgens haben die Heizkörperthermostate im Haus zeitgesteuert aufgedreht
Es ist nur alles um eine Stunde verschoben, weil die Uhr auf dem Server um eine Stunde nachgeht... Sollt ich vielleicht mal einstellen ^^

Für die Außentemperatur werd ich bei gelegenheit noch mit einem PT1000 rumexperimentieren, weil mit dem LM35 die Temperatur offenbar nicht unter 8° kommt...
Da werd ich nur nen OP dafür brauchen, ob das wohl mit dem LM324 auch geht?

Hubert.G
16.12.2012, 13:14
LM324 ist da nicht sehr geeignet.
Von Pollin gibt es einen Meßwandlerbausatz für den PT1000. Funktioniert recht gut und ist leicht nachzubauen.

RoboHolIC
16.12.2012, 22:24
Nehmen wir mal den worst-case an (R=100kOhm) und warten 5*tau, damit sich der Kondensator auf über 99% aufladen kann.
Für einen Tiefpass oder eine Glättung ist das schon recht ordentlich. Für eine Messung bedeutet es aber 1% Unsicherheit, die vermieden werden kann, zumal Temperaturen in einem Heizungskeller / Technikraum sehr langsam veränderliche Signale sind.

BMS
17.12.2012, 09:51
Für einen Tiefpass oder eine Glättung ist das schon recht ordentlich. Für eine Messung bedeutet es aber 1% Unsicherheit, die vermieden werden kann, zumal Temperaturen in einem Heizungskeller / Technikraum sehr langsam veränderliche Signale sind.
Das war - wie schon geschrieben - der worst-case :)
Der Bereich von R ist mit 1...100kOhm im Datenblatt ja sehr vage angegeben.
Bei R=10kOhm (intern) und der angenommenen Wartezeit kommst du schon deutlich unter 1%.
Man kann es natürlich auch ganz genau nachrechnen: mit exponentieller Aufladefunktion die Zeit bestimmen, bis der Fehler kleiner als U_LSB des AD-Wandlers ist ;)
Den genauen Wert von R (intern) kann man aber dennoch nicht einfach nachmessen, sodass man das eben schätzen muss.
Grüße, Bernhard