- 3D-Druck Einstieg und Tipps         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 14

Thema: Temperatur mit BMP180 und DS18B20 entspricht nicht der Real-Temperatur

  1. #1
    Erfahrener Benutzer Fleißiges Mitglied Avatar von RoboTrader
    Registriert seit
    08.11.2017
    Beiträge
    125
    Blog-Einträge
    1

    Frage Temperatur mit BMP180 und DS18B20 entspricht nicht der Real-Temperatur

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Hallo, ich bin's mal wieder.
    Ja, mit dem lustigen Explorer700 für den Pi taste ich mich so von Problem zu Problem. Ich habe nun die Temperatursensoren (BMP180 on board und DS18B20 aufgesteckt in 1-WIRE-Schnittstelle) ausgiebig getestet und komme auf seltsame Werte.

    Beispiele zum gleichen Zeitpunkt:
    a) BMP180 = 27.8°C
    b) DS18B20 = 32.0°C
    c) Heim-Anzeige am Barometer = 23.0°C

    Und nein, ich habe da nicht selbst meine ersten Programme mit 1-WIRE & Co gebastelt, sondern nutze die reinen Beispielcodes.

    Für (a) gibt es den Beispielcode:
    Code:
    #!/usr/bin/python
    
    import time
    from BMP180 import BMP180
    
    # ===========================================================================
    # Example Code
    # ===========================================================================
    
    # Initialise the BMP085 and use STANDARD mode (default value)
    # bmp = BMP085(0x77, debug=True)
    bmp = BMP180()
    
    # To specify a different operating mode, uncomment one of the following:
    # bmp = BMP085(0x77, 0)  # ULTRALOWPOWER Mode
    # bmp = BMP085(0x77, 1)  # STANDARD Mode
    # bmp = BMP085(0x77, 2)  # HIRES Mode
    # bmp = BMP085(0x77, 3)  # ULTRAHIRES Mode
    while True:
    	temp = bmp.read_temperature()
    
    # Read the current barometric pressure level
    	pressure = bmp.read_pressure()
    
    # To calculate altitude based on an estimated mean sea level pressure
    # (1013.25 hPa) call the function as follows, but this won't be very accurate
    	altitude = bmp.read_altitude()
    
    # To specify a more accurate altitude, enter the correct mean sea level
    # pressure level.  For example, if the current pressure level is 1023.50 hPa
    # enter 102350 since we include two decimal places in the integer value
    # altitude = bmp.readAltitude(102350)
    
    	print "Temperature: %.2f C" % temp
    	print "Pressure:    %.2f hPa" % (pressure / 100.0)
    	print "Altitude:    %.2f\n" % altitude
    	time.sleep(1)
    ... und die Library dazu:
    Code:
    import time
    import smbus
    
    # BMP085 default address.
    BMP180_I2CADDR           = 0x77
    
    # Operating Modes
    BMP180_ULTRALOWPOWER     = 0
    BMP180_STANDARD          = 1
    BMP180_HIGHRES           = 2
    BMP180_ULTRAHIGHRES      = 3
    
    # BMP085 Registers
    BMP180_CAL_AC1           = 0xAA  # R   Calibration data (16 bits)
    BMP180_CAL_AC2           = 0xAC  # R   Calibration data (16 bits)
    BMP180_CAL_AC3           = 0xAE  # R   Calibration data (16 bits)
    BMP180_CAL_AC4           = 0xB0  # R   Calibration data (16 bits)
    BMP180_CAL_AC5           = 0xB2  # R   Calibration data (16 bits)
    BMP180_CAL_AC6           = 0xB4  # R   Calibration data (16 bits)
    BMP180_CAL_B1            = 0xB6  # R   Calibration data (16 bits)
    BMP180_CAL_B2            = 0xB8  # R   Calibration data (16 bits)
    BMP180_CAL_MB            = 0xBA  # R   Calibration data (16 bits)
    BMP180_CAL_MC            = 0xBC  # R   Calibration data (16 bits)
    BMP180_CAL_MD            = 0xBE  # R   Calibration data (16 bits)
    BMP180_CONTROL           = 0xF4
    BMP180_TEMPDATA          = 0xF6
    BMP180_PRESSUREDATA      = 0xF6
    
    # Commands
    BMP180_READTEMPCMD       = 0x2E
    BMP180_READPRESSURECMD   = 0x34
    
    
    class BMP180(object):
    	def __init__(self, address=BMP180_I2CADDR, mode=BMP180_STANDARD):
    		self._mode = mode
    		self._address = address
    		self._bus = smbus.SMBus(1)
    		# Load calibration values.
    		self._load_calibration()
    	def _read_byte(self,cmd):
    		return self._bus.read_byte_data(self._address,cmd)
    	
    	def _read_u16(self,cmd):
    		MSB = self._bus.read_byte_data(self._address,cmd)
    		LSB = self._bus.read_byte_data(self._address,cmd+1)
    		return (MSB	<< 8) + LSB
    
    	def _read_s16(self,cmd):
    		result = self._read_u16(cmd)
    		if result > 32767:result -= 65536
    		return result
    
    	def _write_byte(self,cmd,val):
    		self._bus.write_byte_data(self._address,cmd,val)
    
    	def _load_calibration(self):
    		"load calibration"
    		self.cal_AC1 = self._read_s16(BMP180_CAL_AC1)   # INT16
    		self.cal_AC2 = self._read_s16(BMP180_CAL_AC2)   # INT16
    		self.cal_AC3 = self._read_s16(BMP180_CAL_AC3)   # INT16
    		self.cal_AC4 = self._read_u16(BMP180_CAL_AC4)   # UINT16
    		self.cal_AC5 = self._read_u16(BMP180_CAL_AC5)   # UINT16
    		self.cal_AC6 = self._read_u16(BMP180_CAL_AC6)   # UINT16
    		self.cal_B1  = self._read_s16(BMP180_CAL_B1)     # INT16
    		self.cal_B2  = self._read_s16(BMP180_CAL_B2)     # INT16
    		self.cal_MB  = self._read_s16(BMP180_CAL_MB)     # INT16
    		self.cal_MC  = self._read_s16(BMP180_CAL_MC)     # INT16
    		self.cal_MD  = self._read_s16(BMP180_CAL_MD)     # INT16
            
    	def read_raw_temp(self):
    		"""Reads the raw (uncompensated) temperature from the sensor."""
    		self._write_byte(BMP180_CONTROL, BMP180_READTEMPCMD)
    		time.sleep(0.005)  # Wait 5ms
    		MSB = self._read_byte(BMP180_TEMPDATA)
    		LSB = self._read_byte(BMP180_TEMPDATA+1)
    		raw = (MSB << 8) + LSB
    		return raw
    			
    	def read_raw_pressure(self):
    		"""Reads the raw (uncompensated) pressure level from the sensor."""
    		self._write_byte(BMP180_CONTROL, BMP180_READPRESSURECMD + (self._mode << 6))
    		if self._mode == BMP180_ULTRALOWPOWER:
    			time.sleep(0.005)
    		elif self._mode == BMP180_HIGHRES:
    			time.sleep(0.014)
    		elif self._mode == BMP180_ULTRAHIGHRES:
    			time.sleep(0.026)
    		else:
    			time.sleep(0.008)
    		MSB = self._read_byte(BMP180_PRESSUREDATA)
    		LSB = self._read_byte(BMP180_PRESSUREDATA+1)
    		XLSB = self._read_byte(BMP180_PRESSUREDATA+2)
    		raw = ((MSB << 16) + (LSB << 8) + XLSB) >> (8 - self._mode)
    		return raw
    
    	def read_temperature(self):
    		"""Gets the compensated temperature in degrees celsius."""
    		UT = self.read_raw_temp()
    		# Datasheet value for debugging:
    		# UT = 27898
    		# Calculations below are taken straight from section 3.5 of the datasheet.
    		X1 = ((UT - self.cal_AC6) * self.cal_AC5) >> 15
    		X2 = (self.cal_MC << 11) / (X1 + self.cal_MD)
    		B5 = X1 + X2
    		temp = ((B5 + 8) >> 4) / 10.0
    		return temp
    
    	def read_pressure(self):
    		"""Gets the compensated pressure in Pascals."""
    		UT = self.read_raw_temp()
    		UP = self.read_raw_pressure()
    		# Datasheet values for debugging:
    		#UT = 27898
    		#UP = 23843
    
    		X1 = ((UT - self.cal_AC6) * self.cal_AC5) >> 15
    		X2 = (self.cal_MC << 11) / (X1 + self.cal_MD)
    		B5 = X1 + X2
    
    		# Pressure Calculations
    		B6 = B5 - 4000
    		X1 = (self.cal_B2 * (B6 * B6) >> 12) >> 11
    		X2 = (self.cal_AC2 * B6) >> 11
    		X3 = X1 + X2
    		B3 = (((self.cal_AC1 * 4 + X3) << self._mode) + 2) / 4
    
    		X1 = (self.cal_AC3 * B6) >> 13
    		X2 = (self.cal_B1 * ((B6 * B6) >> 12)) >> 16
    		X3 = ((X1 + X2) + 2) >> 2
    		B4 = (self.cal_AC4 * (X3 + 32768)) >> 15
    		B7 = (UP - B3) * (50000 >> self._mode)
    
    		if B7 < 0x80000000:
    			p = (B7 * 2) / B4
    		else:
    			p = (B7 / B4) * 2
    		X1 = (p >> 8) * (p >> 8)
    		X1 = (X1 * 3038) >> 16
    		X2 = (-7357 * p) >> 16
    
    		p = p + ((X1 + X2 + 3791) >> 4)
    		return p
    
    	def read_altitude(self, sealevel_pa=101325.0):
    		"""Calculates the altitude in meters."""
    		# Calculation taken straight from section 3.6 of the datasheet.
    		pressure = float(self.read_pressure())
    		altitude = 44330.0 * (1.0 - pow(pressure / sealevel_pa, (1.0/5.255)))
    		return altitude
    
    	def read_sealevel_pressure(self, altitude_m=0.0):
    		"""Calculates the pressure at sealevel when given a known altitude in
    		meters. Returns a value in Pascals."""
    		pressure = float(self.read_pressure())
    		p0 = pressure / pow(1.0 - altitude_m/44330.0, 5.255)
    		return p0
    Hier der Code zu (b):
    Code:
    #!/usr/bin/python
    # -*- coding:utf-8 -*-
    import os
    import glob
    import time
    
    os.system('modprobe w1-gpio')
    os.system('modprobe w1-therm')
    
    base_dir = '/sys/bus/w1/devices/'
    device_folder = glob.glob(base_dir + '28*')[0]
    device_file = device_folder + '/w1_slave'
    def read_rom():
    	name_file=device_folder+'/name'
    	f = open(name_file,'r')
    	return f.readline()
    
    def read_temp_raw():
    	f = open(device_file, 'r')
    	lines = f.readlines()
    	f.close()
    	return lines
    
    def read_temp():
    	lines = read_temp_raw()
    	while lines[0].strip()[-3:] != 'YES':
    		time.sleep(0.2)
    		lines = read_temp_raw()
    	equals_pos = lines[1].find('t=')
    	if equals_pos != -1:
    		temp_string = lines[1][equals_pos+2:]
    		temp_c = float(temp_string) / 1000.0
    		temp_f = temp_c * 9.0 / 5.0 + 32.0
    		return temp_c, temp_f
    
    print(' rom: '+ read_rom())
    while True:
    	print(' C=%3.3f  F=%3.3f'% read_temp())
    	time.sleep(1)
    Ich teste später auch zum Vergleich noch den DHT22. Bin sehr gespannt. Aber gerade der BMP180 wäre eben praktisch mit seinen Werten, da "on board" und somit für schnelle Messungen klasse.

    Vielleicht sieht jemand sofort, woran es mangelt oder was ich beachten muss!?
    Ich habe auch bei meiner Zusammenstellung beider Codes und Anzeige auf dem OLED die gleichen Unterschiede ...

    Danke und einen tollen Mittwoch!

    - - - Aktualisiert - - -

    Also, der DHT22 mit dem Adafruit-Code fast wie in diesem Tutorial (nur 3 Pins am DHT22, daher direkt 3.3V, GND und Daten-Pin und mit python3 aufgerufen), erhalte ich:

    T = 25.5

    Hier nochmal zu einem Zeitpunkt alle Daten:

    Tdht = 25.3
    Thumidity = 40.0%
    Tds = 28.437
    Tbmp = 32.1
    Tbmp_press = 984.16
    Tbmp_alt = 244.797

    Und das alte Zeigermodell: T=23 Press=996 Humidity=48.5%

    Hm, sind hier am Arbeitsplatz nun 23, 25, 28 oder 32°C?

    - - - Aktualisiert - - -

    Ja, nun habe ich das OLED aussen vor gelassen und nur eine reine Ausgabe aller Sensoren programmiert. Gleiches Ergebnis, irgendetwas stimmt nicht in den Quell-Libraries oder es sind doch die Sensoren fehlerhaft - wie ich hier im Forum nachlesen konnte:

    Code:
    T[DS18B20] = 28.062 C
    T[BMP180]  = 32.0 C
    Pressure   = 985.11 hPa
    Altitude   = 237.2131959795308 m
    T[DHT22]   = 25.5 C
    Humidity   = 39.0%
    -30Y: Basic@Schneider_CPC, Kosmos-Baukästen • -20Y: Mindstorms RCX 1.5, Visual Basic, Pascal, php • NOW: Python3, Arduino MEGA, Raspberry Pi 3, NiboBurger, LEGO Boost/Mindstorms

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von Rabenauge
    Registriert seit
    13.10.2007
    Ort
    Osterzgebirge
    Alter
    55
    Beiträge
    2.198
    Mein BMP gibt auch ein bisschen mehr aus- liegt bei mir an der Einbausituation: da ich den für nix vernünftiges mehr nutze (ich nehm inzwischen lieber die BME, weil die die Luftfeuchte auch können), hab ich ihn zusammen mit allem möglichen anderen Kram auf ein Proto-Shield für Arduino gelötet.
    Nun sitzt der praktisch fast genau über dem Hauptprozessor- mit nem Zentimeter Abstand.
    Schalt ich das Ding ein, haut es ne Weile hin, danach steigt die Temperatur durchaus um einige Grad...irgendwann hört das dann aber auf, weil die Temperatur der Bauteile wohl nur nen gewissen Wert erreicht. Im Dauerbetrieb könnte man das einfach mit nem Offset erschlagen.

    An der Wetterstation den BME hab ich deshalb so angeordnet, dass er am tiefsten (und quasi frei hängend) auf der Platine sitzt (warme Luft steigt rauf...), und da die Platine senkrecht steht, bekommt er von unten immer frische Luft.
    So funktioniert es dann.

    Der DHT22 (hab ich neben dem BMP hocken, eben weil der die Feuchte nich kann) hat übrigens genau das selbe Problem- aber die Dinger sind weit weniger genau als die Bosch-Sensoren.
    Wenn du Spass haben willst, besorg dir mal nen DHT 11- während die 22er immerhin noch halbwegs schätzen können, wird im 11er scheinbar intern gewürfelt.
    Grüssle, Sly
    ..dem Inschenör ist nix zu schwör..

  3. #3
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    09.04.2008
    Beiträge
    384
    Mit den DS18B20 habe ich sehr gute Erfahrungen.Sowohl mit auslesen mit eine Python lib auf den Pi, wie mit Arduino (ESP, Wemos D1). Die Temperaturen sind immer +/- 0,5°C gleich an andere Messmethoden.

  4. #4
    Erfahrener Benutzer Fleißiges Mitglied Avatar von RoboTrader
    Registriert seit
    08.11.2017
    Beiträge
    125
    Blog-Einträge
    1
    Danke euch für die Erfahrungen!

    Heisst also, dass der Code des Herstellers in Ordnung ist, aber ich versuchen sollte, die Sensoren weiter entfernt oder eben unter der Wärmeentwicklung zu platzieren?
    Und dann wirklich ein DS18B20 besser misst als ein BMP180 und dieser wiederum besser als der DHT22?

    Dennoch wären mir die 28°C des DS18B20 zu warm ...
    Ich versuche die Entfernungsvariante.
    -30Y: Basic@Schneider_CPC, Kosmos-Baukästen • -20Y: Mindstorms RCX 1.5, Visual Basic, Pascal, php • NOW: Python3, Arduino MEGA, Raspberry Pi 3, NiboBurger, LEGO Boost/Mindstorms

  5. #5
    Erfahrener Benutzer Robotik Einstein Avatar von Rabenauge
    Registriert seit
    13.10.2007
    Ort
    Osterzgebirge
    Alter
    55
    Beiträge
    2.198
    Nö- der DS ist keineswegs besser.
    Er hat andere Vorteile 1-Wire-Bus)- aber genauerwird der auch nicht sein. Dafür ist die Handhabung etwas kniffeliger.
    Leg mal _irgendein_ Thermometer auf die Heizung, und versuch dann, die wirkliche Raumtemperatur zu ermitteln- das wird mit _keinem_ klappen.
    Insofern ist es egal, welchen du benutzt.
    Jeder misst nur seine Umgebung, und wenn da ne kleine Wärmequelle in der Nähe ist, misst er eben Mist.
    Die Bosch-Sensoren sind hervorragend (meiner Meinung nach im Bastelsegment das Beste, was man derzeit kriegen kann), da sie eben noch mehr als nur Thermometer sind.
    Und die messen schon genau....da kann ich absolut nix gegen sagen

    Ob der Maxim theoretisch noch genauer kann, da musst du dich mal durch die Datenblätter wühlen, ich hab hier drei Bosch (2xBME und einmal den BMP, den aber mit dem Offset, wegen der blöden Einbausituation), die geben nen Unterschied von maximal 0.1 Grad aus....das wird dann wohl hin hauen.

    Im Grunde isses bei jedem Thermometer so: willst du die wirkliche Aussentemperatur messen, muss das Ding nen Meter von der Hauswand weg.
    Und: wen juckt denn ein halbes Grad- viel interessanter finde ich, zu sehen, ob die Temperatur steigt oder fällt (zeigt mein Thermometer auch an), das halbe Grad Unterschied hat man gewöhnlich schon zwischen Fussboden-und Tischhöhe.
    Grüssle, Sly
    ..dem Inschenör ist nix zu schwör..

  6. #6
    HaWe
    Gast
    ich habe jetzt ein paar Tage lang die Bosch BMP280 gegen DHT22 gemessen, 50cm vom Board entfernt (nodeMCU), direkt nebeneinander, und hatte höchstens 0,7°C Unterschied.

  7. #7
    Erfahrener Benutzer Fleißiges Mitglied Avatar von RoboTrader
    Registriert seit
    08.11.2017
    Beiträge
    125
    Blog-Einträge
    1
    Danke. Insbesondere für eure immer ausführlichen Antworten. So verstehe ich das Handling und Thema viel besser!

    Wenn ich das richtig verstehe, dann könnte man mit einem Offset die "zu heiße Situation" ausgleichen und die Temperaturunterschiede messen (insbesondere für den "onboard"-Sensor, der exakt den gleichen Abstand zur Wärmequelle behält). In meinem Fall wäre das:

    Code:
    T[Analoges Messgerät] = 23°C
    
    T[DS18B20] = 28.062°C -5°C =23°C
    T[BMP180]  = 32.0°C -9°C =23°C
    T[DHT22]   = 25.5 C -2.5°C =23°C
    Somit wäre der Offset für den DS18B20 -5, für den BMP180 -9 und für den DHT22 -2.5.
    Damit würdet ihr arbeiten?
    Oder sollte ich mir die Referenz an anderer Stelle suchen?

    Und was meint ihr zu Pressure, Altitude und Humidity? Alle 3 sind auch ziemlich unterschiedlich zu meinem analogen Messgerät.

    Code:
    Pressure   = 985.11 hPa
    Altitude   = 237.2131959795308 m
    Humidity   = 39.0%
    Da dürfte doch die Wärme keine Rolle spielen, oder?

    Grüße in einen schönen Samstagabend!

    - - - Aktualisiert - - -

    Habe gerade nochmal über die Offsetwerte nachgedacht.
    Die machen vielleicht wirklich Sinn:

    BMP180 - onboard > -9
    DS18B20 - aufgesteckt als 1-Wire, somit etwa 0.5cm vom Board entfernt > -5
    DHT22 - mit diesen typischen Kabeln an den GPIOs, somit etwa 4cm entfernt > -2.5
    -30Y: Basic@Schneider_CPC, Kosmos-Baukästen • -20Y: Mindstorms RCX 1.5, Visual Basic, Pascal, php • NOW: Python3, Arduino MEGA, Raspberry Pi 3, NiboBurger, LEGO Boost/Mindstorms

  8. #8
    HaWe
    Gast
    offset nur, wenn du die Sensor-Temperaturen mit einem direkt benachbarten und geeichten Thermometer über weitere Temperaturbreiche abgeglichen hast. Aber mit einem Onboard-Sensor wirst du immer nur die Onboard-Temperatur messen, niemals die exakte Umgebungstemperatur, das muss dir klar sein, denn sie wird bei -20° bis +80° bei unterschiedlichen Luftströmungen in unkalkulierbarer Weise verfälscht, und es würden im besten Falle höchstens Eichkurven etwas verbessern, samt Ventilator, keinesfalls konstante Offsets.

  9. #9
    Erfahrener Benutzer Fleißiges Mitglied Avatar von RoboTrader
    Registriert seit
    08.11.2017
    Beiträge
    125
    Blog-Einträge
    1
    Danke, so etwas dachte ich zunächst auch. Das kann kaum eine lineare Abhängigkeit sein.
    Vielleicht nehme ich mir einige Referenzwerte und wandere mit den 3 Sensoren auf einen schneebedeckten Berg, in eine Sauna und so 5 Werte dazwischen. Dann dürft sich etwas ergeben.

    Wollte schon lange die Polynom-Funktion der numpy-Bibliothek testen!
    -30Y: Basic@Schneider_CPC, Kosmos-Baukästen • -20Y: Mindstorms RCX 1.5, Visual Basic, Pascal, php • NOW: Python3, Arduino MEGA, Raspberry Pi 3, NiboBurger, LEGO Boost/Mindstorms

  10. #10
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    02.09.2009
    Ort
    Berlin (Mariendorf)
    Beiträge
    1.023
    @HaWe:
    Danke! Du hast das was ich auch schon zu formulieren versuchte und wieder verworfen habe, treffend auf den Punkt gebracht.

    @RoboTrader:
    Nein . Mit der Polynom-Funktion kannst du einen nichtlinearen Sensor bestimmt trefflich auswerten.
    Aber du kannst aber eine methodisch falsche Messung mit unbekannten Einflussfaktoren damit nicht ausbügeln. Optimiere deine Messanordnung und du kommst in den Genuss der guten, herstellerseitigen Kalibrierung der Sensoren.
    OK, beim Onboard-BMP180 ist dahingehend natürlich nichts mehr zu machen.

    Die Schneewanderung solltest du trotzdem machen
    Geändert von RoboHolIC (06.01.2018 um 19:20 Uhr) Grund: Schneewanderung

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. Temperatur wert wird nicht aktualisiert.
    Von Ferdinand im Forum C - Programmierung (GCC u.a.)
    Antworten: 3
    Letzter Beitrag: 31.03.2012, 20:52
  2. Temperatur anzeige auf dem LCD wird nicht aktualisiert?
    Von Ferdinand im Forum C - Programmierung (GCC u.a.)
    Antworten: 16
    Letzter Beitrag: 16.01.2012, 13:55
  3. temperatur
    Von Che Guevara im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 4
    Letzter Beitrag: 13.07.2008, 19:21
  4. Temperatur via I2C
    Von Haveaniceday im Forum C - Programmierung (GCC u.a.)
    Antworten: 13
    Letzter Beitrag: 05.09.2007, 20:12
  5. ATmega16 mit M24C16 und DS18B20 Temperatur messen & spei
    Von logikbomb im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 0
    Letzter Beitrag: 08.09.2005, 09:10

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad