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%
Lesezeichen