Inhaltsverzeichnis

Temperatur

Die Temperaturmessung kann auf verschiedenste Art und Weise durchgeführt werden. Es gibt dazu jede Menge verschiedene Methoden. Ich habe viele bereits ausprobiert, möchte die aber nicht alle hier auf der Seite veröffentlichen.

Temperatursensor LM35 CZ

Der LM35 CZ ist ein linearer Temperatursensor. Um die Temperatur zu messen, muss der Baustein an die analoge Schnittstelle angeschlossen werden.

Pro °C gibt der Baustein 10mV mehr aus. 0° sind 0mV. Der Messbereich ist -55°C..150°C. Die GEnauigkeit: eine Genauigkeit von ±0,25°C. Leider können wir so ohne weiteren negative Temperaturen nicht messen, da der analoge Eingang des Arduino ohne externe BEschaltung nur positive Spannungen messen kann.
Um nun die Temperatur zu ermitteln muss man zunächst den Messwert bestimmen. Da der Baustein max. 1V ausgibt (was 100°C entspricht) können wir die interne 1V1 Referenz verwenden. Ein Schritt ergibt dann eine Spannung von 1,1V / 1024 = 0,0010742 V/S = 1,0742mV/S. d.h. somit ergibt das 1° ~ 9,31 Schritte bedeuten. ( 10mV / 1,0742mv/S). Somit bekommen wir die Temperatur heraus indem wir einfach den Messwert / 9,31 dividieren. Also:

LM35.ino
const float DIVISOR = 1024 / 110;  // 1024 Schritte * 10mV/°  / 1100mV = 9.31 S/°;
float tempC;
int reading;
int tempPin = 0;
 
void setup() {
  analogReference(INTERNAL);
}
 
void loop() {
  reading = analogRead(tempPin);
  tempC = reading / DIVISOR;
}

Doch Vorsicht, die interne Referenz kann machmal etwas abweichen. Man sollte dann zumindest das Ergebniss mit einem anderen Thermometer vergleichen. Zum Anpassen muss man dann den Divisor ändern. Bei 1V2 als Referenz bräuchte man dann also einen Divisor von 1024/120. Durch diese Art der Beschaltung ist man auf einen Temperaturbereich von 0..110° beschränkt.

Temperatursensor DS18B20

Der DS18B20 ist der von meinen Versuchen her einfachste digitale Temperatursensor, der mir untergekommen ist.
Nicht nur die einfache Beschaltung, man braucht nur 1 ext. Widerstand und der ist auch noch nur für den Bus zuständig, sondern auch das gute Messergebniss sprechen für sich. Der DS18B20 ist ein digitaler Temperatursensor, d.h. der Sensor mißt die Temperatur und stellt das Ergebniss digital zur Verfügung. Der Messbereich beträgt: -55°C..125°C, wobei im Bereich von -10°C..85°C eine Genauigkeit von ±0,5°C erreicht wird.
Der Bus besteht aus min 2 Leitungen, oder besser aus 3 Leitungen. V+, Bus, und GND. V+ kann auch weggelasen werden, dann versorgt sich der Baustein über den Bus selbst.
Um den Baustein anzusprechen ist eine spezielle Bibliothek nötig. Diese gibt's hier. Einfach in das libraries Verzeichniss im Sketchbook Ordner kopieren.
Hier mal der Schaltplan.

Will man mehr als einen Baustein benutzen ist das noch einfacher. Einfach den 2. Baustein parallel schalten. Jeder Baustein hat seine eigene Adresse und somit kommen sich die einzelnen DS Baustein nicht ins Gehege.

Und hier ein Programm, das zunächst die Adressen der einzelnen DS Bausteine ermittelt, dann den Messvorgang startet und das Ergebniss auf einem Display ausgibt.

DS18B20.ino
#include <OneWire.h>
#include <Wire.h>
 
#define DISPLAY_ADDRESS1 0x71 //This is the default address of the OpenSegment with both solder jumpers open
 
// DS18S20 Temperature chip i/o
OneWire ds(10);  // on pin 10
 
void setup(void) {
  Wire.begin(); //Join the bus as master
 
  // initialize inputs/outputs
  // start serial port
  lookUpSensors();
 
  //Send the reset command to the display - this forces the cursor to return to the beginning of the display
  Wire.beginTransmission(DISPLAY_ADDRESS1);
  Wire.write('v');
  Wire.endTransmission();
}
 
void lookUpSensors()
{
  byte address[8];
  int i=0;
  byte ok = 0, tmp = 0;
 
  while (ds.search(address)) {
    tmp = 0;
    //0x10 = DS18S20
    if (address[0] == 0x10) {
      tmp = 1;
    }
    else {
      //0x28 = DS18B20
      if (address[0] == 0x28) {
        tmp = 1;
      }
    }
    //display the address, if tmp is ok
    if (tmp == 1) {
      if (OneWire::crc8(address, 7) != address[7]) {
        // but it doesn't have a valid CRC!
      }
      else {
        ok = 1;
      }
    }//end if tmp
  }//end while
}
 
int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;
 
void loop(void) {
  byte i;
  byte present = 0;
  byte data[12];
  byte addr[8];
 
  byte dscount = 0;
  while (ds.search(addr)) {
 
    ds.reset();
    ds.select(addr);
    ds.write(0x44,1);         // start conversion, with parasite power on at the end
 
    delay(1000);     // maybe 750ms is enough, maybe not
    // we might do a ds.depower() here, but the reset will take care of it.
 
    present = ds.reset();
    ds.select(addr);    
    ds.write(0xBE);         // Read Scratchpad
 
    for ( i = 0; i < 9; i++) {           // we need 9 bytes
      data[i] = ds.read();
    }
 
    LowByte = data[0];
    HighByte = data[1];
    TReading = (HighByte << 8) + LowByte;
    SignBit = TReading & 0x8000;  // test most sig bit
    if (SignBit) {
      // negative
      TReading = (TReading ^ 0xffff) + 1; // 2's comp
    }
    Tc_100 = (6 * TReading) + TReading / 4;    // multiply by (100 * 0.0625) or 6.25
 
    Whole = Tc_100 / 100;  // separate off the whole and fractional portions
    Fract = Tc_100 % 100;
 
    // Output the value to the Display
    // First write delimiter and Sign for first or second DS.
    Wire.beginTransmission(DISPLAY_ADDRESS1);
    Wire.write(0x77);
    if (dscount ==0) {
      Wire.write(0x22); 
    } 
    else {
      Wire.write(0x02); 
    }
    Wire.endTransmission();
 
    // write Value to Display
    Wire.beginTransmission(DISPLAY_ADDRESS1);
    byte value = Whole / 10;
    Wire.write(value);
    value = Whole % 10;
    Wire.write(value);
    value = Fract / 10;
    Wire.write(value);
    value = Fract % 10;
    Wire.write(value);
    Wire.endTransmission();
 
    dscount++;
  }
}