Temperatursensor LM35DZ

LM35DZ – ein analoger Temperatursensor

Der LM35DZ ist ein einfacher und preisgünstiger Temperatursensor. Er misst Temperaturen zwischen 0 und 100°C und gibt die Werte analog zwischen 0 und 1 Volt aus – 1 Millivolt entspricht dabei 0,1°C. Wegen seiner Bauform TO-92 ist er dem verbreiteten DS18B20 optisch sehr ähnlich.

Technische Daten und Datenblatt

Datenblatt bei Texas Instruments: www.ti.com/lit/ds/symlink/lm35.pdf

  • Versorgungsspannung: 4 – 20 V
  • Messbereich: 0 – 100 °C
  • Auflösung: 0,1 °C
  • Genauigkeit: ±0,6 °C bei 25 °C (typisch: ±0,25 °C)
  • Ausgangsspannung: 1 mV pro 0,1 °C (max. 1 V)

Pinbelegung des LM35DZ

LM35 Pins (links): + (1) Out (2) - (3); Modul (rechts)
LM35 Pins (links): + (1) Out (2) – (3); Modul (rechts)

Der Sensor befindet sich in einem halbrunden Kunststoffgehäuse (Bauform TO-92). Von der flachen, beschrifteten Seite aus gesehen sind die Pins wie folgt belegt:

  1. Versorgungsspannung; VS bzw. „+”
  2. Ausgabesignal; VOUT
  3. Masse; GND bzw. „–”

Neben dem einfachen Sensor gibt es auch Modulplatinen (shields; ganz rechts). Außer der wegen der Größe etwas besseren Handhabbarkeit bietet so ein Modul aber keinen Vorteil – der Sensor benötigt keinen Pull-Up-Widerstand, wie er bei anderen Sensoren sonst oft dort eingelötet ist. (Ich würde es nicht noch einmal kaufen.)
Ein einzelner Sensor kostet im Versandhandel etwa einen Euro. Bei manchen asiatischen Händlern gibt es den Sensor auch in einer wasserdichten Hülse mit ca. 1 m langem Kabel (vergleichbar den DS18B20-Messfühlern).

Analoge Messung mit einem Arduino Uno

LM35DZ an einem Uno-Nachbau
LM35DZ an einem Uno-Nachbau

Zur Nutzung des Sensors muss keine Bibliothek installiert werden. Beim Programmieren mit der Arduino-IDE nutzt man einfach die Funktion analogRead().

Man verbindet die Versorgungspins des LM35DZ mit 5 Volt (rote Leitung) und GND (braun) und den mittleren Pin mit einem der analogen Eingänge A0, A1 usw. Im Bild ist er an den Eingang A0 eines Uno-Nachbaus angeschlossen (orange Leitung).

Den an A0 gemessenen Wert rechnet man wie folgt in eine Temperatur um:
     Ergebnis in Millivolt = Messwert * 5000 / 1023

Da beim LM35DZ ein Grad 10 Millivolt entspricht, erfolgt noch eine Division durch 10. Damit die Berechnung mit Fließkommazahlen durchgeführt wird, wird der Integer-Wert LM35_Value vor der Rechnung in float umgewandelt, und es ergibt sich:

  1.   temperature = (float)LM35_Value * 500 / 1023;

Der Rest des kleinen Programms ist (hoffentlich) selbsterklärend:

  1. /* Abfrage des LM35DZ Temperatur-Sensors am Arduino
  2.  *
  3.  * 2020-10-22 Heiko (unsinnsbasis.de)
  4.  */
  5.  
  6. #define LM35_PIN A0  // GPIO-Pin für die Datenleitung des LM35DZ
  7.  
  8. int LM35_Value  ;   // Messwert des Sensors
  9. float temperature;  // Temperatur in Grad Celsius
  10.  
  11. void setup() {
  12.   Serial.begin(9600);
  13.   delay(1000);
  14. }
  15.  
  16. void loop() {
  17.   LM35_Value = analogRead(LM35_PIN);
  18.   Serial.print(LM35_Value);
  19.   Serial.print(" - ");
  20.  
  21.   // Wert in Temperatur umrechnen
  22.   temperature = (float)LM35_Value * 500 / 1023;
  23.   Serial.print(temperature, 1);  // eine Nachkommastelle
  24.   Serial.println(" °C");
  25.   delay(5000);
  26. }

Quellcode auf Github

Ausgabe der Messungen des LM35DZ am Uno
Ausgabe der Messungen des LM35DZ am Uno

Man sieht im seriellen Monitor, dass die Auflösung des Analogeingangs am Uno nur dafür ausreicht, die Temperatur in Schritten von ca. ½°C anzuzeigen.

Zur Erklärung: 10 Bit Auflösung heißt, dass der Arduino (bzw. dessen Analog-Digital-Konverter) am Eingang einen Wert zwischen 0 und 1023 ermittelt. Diese 1023 Schritte verteilen sich über einen Spannungsbereich von 0 -5 V (5000 mV), sodass ein Schritt 5000 mV / 1023 ≈ 5 mV entspricht.
Der LM35DZ misst zwar mit einer Auflösung 0,1°C, die er mit jeweils 1 mV Spannungsdifferenz ausgibt, aber der Uno kann diese kleinen Unterschiede nicht erkennen.

Das lässt sich im Fall des LM35DZ in Verbindung mit einem Arduino Uno oder Nano aber ändern. Da er maximal eine Spannung von 1 V liefert, bleibt ein Großteil – nämlich 80 % – des Messbereichs des Arduinos ungenutzt. Mit der Funktion analogReference() kann man die Referenzspannung des Arduino ändern – statt der standardmäßigen 5 Volt stellt der Aufruf

analogReference(INTERNAL);

auf den Arduinos mit dem Prozessor ATmega328P (der in den Unos und Nanos verbaut ist) sie auf 1,1 Volt um. Das erhöht die Auflösung auf 1100 mV / 1023 ≈ 1,075 mV. Die Folge ist aber, dass der Arduino in diesem Fall keine höheren Spannungen mehr als 1,1 V messen kann – also Vorsicht, wenn man an den anderen Analog-Eingängen höhere Spannungen messen will.

Um diese Möglichkeit zu nutzen, ergänzt man die Codezeile in der Setup-Routine des Programms:

void setup() {
  Serial.begin(9600);
  delay(1000);
  analogReference(INTERNAL);
}
Ausgabe der Messungen mit geänderter Referenzspannung
Ausgabe der Messungen mit geänderter Referenzspannung

Zusätzlich ändert man die Berechnung der Temperatur:

  temperature = (float)LM35_Value * 110 / 1023;

Übersetzt man das Programm jetzt neu, sieht die Ausgabe im seriellen Monitor in etwa so aus wie rechts gezeigt.

Das klappt natürlich nicht in allen Fällen, aber beim LM35DZ passt dessen Ausgabespannung von 1 Volt sehr gut zur intern verwendeten Spannung des Arduino-Prozessors von 1,1 Volt.
(Diesen Trick habe ich im Arduino Playground gefunden. Welche interne Spannung die verschiedenen Arduino-Modelle zur Verfügung stellen, steht in der Dokumentation der Funktion analogReference().)

(Zwischen-)Fazit – nicht ganz ernst gemeint

Damit könnte dieser Beitrag zu Ende sein: „Für mich ist der LM35DZ ein preiswerter Sensor, mit dem man an einem Arduino sehr gut die Messung analoger Werte demonstrieren kann. Mit einem kleinen Trick lässt sich sogar (fast) dessen volle Auflösung von 0,1°C messen.”

Ich möchte den Sensor aber auch mit einem ESP32 nutzen – und dessen Fähigkeit zum Messen (vor allem kleiner) analoger Werte ist leider sehr begrenzt. Abhilfe kann ein externer Analog-Digital-Konverter (ADC) wie der ADS1115 schaffen. Wegen der deutlich höheren Auflösung von 16 Bit kann er auch am Arduino einen Zusatznutzen bringen. Der folgende Abschnitt zeigt die Verwendung mit einem ESP32.

Die Anschaffung des ADS1115 lohnt aber nicht, wenn man nur den LM35DZ auslesen will, denn er kostet ein Mehrfaches des Sensors. Geht es nur um einen preiswerten Temperatursensor, ist man am ESP32 besser mit dem digital auslesbaren DS18B20 bedient.

ESP32: Nutzung des ADS1115-Analog-Digital-Konverters

Der Beitrag Analogwerte messen mit dem ADS1115 beschreibt die Anschlüsse des ADS1115 und die Bibliothek Adafruit_ADS1x15, die ich für die Programmierung mit der Arduino-IDE installiert habe. Deshalb gehe ich hier nicht weiter auf Details ein.

Im Beitrag wird auch die hohe Messungenauigkeit der ADCs des ESP32 behandelt. Inbes. sind sie nicht in der Lage, Spannungen unterhalb von 0,1 oder oberhalb von 3,1 Volt zu messen. Da der LM35DZ je 0,1°C die Spannung um 1 mV erhöht, kann man Temperaturmessungen unterhalb von 10°C (100 mV) mit einem ESP32 nicht direkt durchführen, und auch knapp darüber sind die Werte noch etwas unzuverlässig. Auch höhere analoge Messwerte kann man nicht so einfach wie beim Arduino in einen Temperaturwert umrechnen, da die Messungen beim ESP nicht linear verlaufen. Der Beitrag nennt aber eine passende Korrekturfunktion für Spannungsmessungen von 0,1 bis etwa 2,7 Volt:

     Spannung in Millivolt = (Messwert + 124,38) / 1,239 = Messwert / 1,239 + 100,38

Um die LM35DZ-Messwerte des ESP32 mit denen des ADS1115 zu vergleichen, habe ich eine Schaltung mit folgenden Verbindungen aufgebaut:

LM35DZ und ADS1115 zur Messung analoger Werte am ESP32
LM35DZ und ADS1115 zur Messung analoger Werte am ESP32
  • orangerot: 5 Volt
    Die Standardspannung des ESP32 von 3,3 Volt reicht nicht für den LM35DZ. Die Steckbrücke verläuft unterhalb des ESP32 und liefert 5 V vom Pin »VIN«; sie versorgt auch den ADS1115.
  • blau: Ausgabepin des LM35DZ an Kanal A0 des ADS1115
  • weiß: Ausgabepin des LM35DZ an GPIO 4 des ESP, der als analoger Eingang arbeitet
  • gelb und grün: I2C-Verbindung zwischen ADS1115 und den ESP32-Standardpins GPIO 22 für SCL (gelb) und 21 für SDA (grün)
  • schwarz: Masseverbindungen ESP32 – LM35DZ – ADS1115

Das Programm misst die Ausgaben des LM35DZ am anlogen Eingabepin GPIO 4 sowie mit dem ADC ADS1115 und schreibt die Werte bzw. die daraus berechnetetn Temperaturen in den seriellen Monitor.

  1. /* Abfrage des LM35DZ Temperatur-Sensors am ESP32
  2.  *  - analog am ESP32
  3.  *  - analog am ADS1115 mit Weitergabe per I2C
  4.  *
  5.  * 2021-05-31 Heiko (unsinnsbasis.de)
  6.  */
  7.  
  8. #define LM35_PIN 4  // GPIO-Pin für die Datenleitung des LM35DZ
  9.  
  10. #include <Adafruit_ADS1X15.h> // bindet Wire.h für I2C mit ein
  11. Adafruit_ADS1115 ads;
  12. #define ADS_I2C_ADDR 0x48
  13.  
  14. void setup() {
  15.   Serial.begin(115200);
  16.   delay(500);
  17.   Serial.println("LM35DZ am ESP32 - Test");
  18.  
  19.   ads.begin(ADS_I2C_ADDR, &Wire);
  20.   // Werte des LM35DZ 1-fach verstärken (er liefert  max. 1 V)
  21.   // wg. der hohen Auflösung des ADS1115 ist keine größere
  22.   // Verstärkung nötig
  23.   ads.setGain(GAIN_ONE);
  24. }
  25.  
  26. void loop() {
  27.   int LM35_Value;      // Messwert des Sensors per GPIO
  28.   int adc0;            // Messwert an Kanal 0 des ADS1115
  29.   float millivolt, temperature;
  30.  
  31.   LM35_Value = analogRead(LM35_PIN);
  32.   Serial.printf("ESP32 Analog-Rohwert: %d mV", LM35_Value);
  33.  
  34.   // Wert in Temperatur umrechnen
  35.   temperature = (float)LM35_Value * 330.0 / 4095.0;
  36.   Serial.printf("; ESP32 Temp.: %3.1f °C", temperature);
  37.  
  38.   // Temperatur mit Korrekturfunktion berechnen
  39.   // (siehe https://unsinnsbasis.de/ads1115/#tgt-dia)
  40.   temperature = ((float)LM35_Value / 1.239 + 100.38) / 10.0;
  41.   Serial.printf("; ESP32 korr.: %3.1f °C", temperature);
  42.  
  43.   // Messung per ADS1115
  44.   adc0 = ads.readADC_SingleEnded(0);  // Kanal 0 messen
  45.   millivolt = ads.computeVolts(adc0) * 1000;
  46.   Serial.printf("; ADS1115: %3.1f °C\n", millivolt/10.0);
  47.  
  48.   delay(5000);
  49. }

Quellcode auf Github
Das Programm gibt folgende Werte aus:

LM35DZ Vergleichsmessung ESP32 / ADS1115
LM35DZ Vergleichsmessung ESP32 / ADS1115
  • Messwert am analogen Eingang des ESP32
  • daraus berechneter Temperaturwert; es wird die Standardformel verwendet, die beim Arduino gut funktioniert; wegen des nicht-linearen Verlaufs der Messwerte kommen am ESP32 aber keine sinnvollen Angaben zustande
  • mit der o.g. Korrekturfunktion berechneter Temperaturwert
  • vom ADS1115 ermittelte Temperatur
LM35DZ: Diagramm der Messwerte von ESP32 und ADS1115
LM35DZ: Diagramm der Messwerte von ESP32 und ADS1115

Die Korrekturfunktion liefert auch bei relativ kleinen analogen Messwerten zwischen 0,1 und 0,2 Volt recht gute Werte. Um auch deutlich kleinere Temperaturen als die Raumtemperatur messen zu können, habe ich die Luft in der Umgebung des LM35DZ mit einem Gelpad aus dem Eisfach stark abgekühlt. Aus den Messwerten ist folgendes Diagramm entstanden, das die mit der Korrekturfunktion berechneten Temperaturen (orange) mit den vom ADS gemessenen (blau) vergleicht.
Es zeigt, dass die Messungen am ESP32 etwas streuen; die Kurve der ADS1115-Messungen ist glatter. Bei Temperaturen unterhalb von 10°C liefert der ESP32 nur noch 0 als Messwert; darüber unterscheiden sich die Werte nur selten um mehr als 0,3°C.

Mein Fazit – jetzt aber wirklich 😉

Für mich ist der LM35DZ ein preiswerter Temperatursensor, mit dem man an einem Arduino sehr gut die Messung analoger Werte demonstrieren kann. Direkt am ESP32 ist er bei Temperaturen deutlich unter Zimmertemperatur nicht nutzbar – und auch sonst nur, wenn man weiß, wie man die analogen Messwerte des ESP32 korrigieren kann. Mit dem – im Vergleich zum Sensor teuren – Analog-Digital-Konverter ADS1115 kann man ihn auch am ESP32 leicht einsetzen und am Arduino die volle Auflösung von 0,1°C messen.

 

Kommentar hinterlassen

Deine E-Mail-Adresse wird nicht veröffentlicht.