UPDATE: the bme280 sensor FAILED after four hours of use and queries on one-minute intervals; i'm disappointed, but may try another one to see if it was an anomaly (hey, shit happens, right?)
fortunately, i had a spare bmp180 on hand, and have put that into use instead - we'll see how it holds up... i'm sure i'm not the first n00b to run across sensor hardware failures - i've even seen pictures of a bme280 melted from what i can only assume is an over- or reverse-voltage run...
:-)
just spent a bit of a morning crafting a logging script to read bme280 sensor data... the file has a format like this:
2016-08-22 12:17 78.80 30.14 52.60 2016-08-22 12:17 78.33 30.14 52.57 2016-08-22 12:18 78.28 30.14 52.56
...
the bme280 is an interesting sensor that returns temperature, barometric pressure and humidty...
HOWEVER, many users report that the temperature runs about 4F higher than that reported by most other sensors... and i found this to be true, as i gauged the bme280's temp readout against a bmp180 and an LCD digital thermometer... in light of this, i've included a 4-degree 'correction' in the conversion code in the script - just so you know why
i installed the lighttpd web server on a Raspberry Pi 2, with the sensor attached and fed out to the side of the garage... the script logs data once a minute (the log will grow to 50MB over the course of a year)... current weather info can be retrieved via a simple one-liner shell script:
#!/bin/sh
# retrieve weather info from data log
# 3 - temperature
# 4 - barometric pressure
# 5 - relative humidity
curl http://192.168.1.20/weather.txt -s -d ascii | tail -1 | cut -f $1 -d ' '
here's the logging script in Python:
#!/usr/bin/python
# version 0.1 - bme280 data reader and logger
# 082216
# added 1-minute logging
#
# data fields:
# DATE TEMP BARO HUMID
# YYYY-MM-DD HH:MM TT.TT PP.PP HH.HH
import smbus
import time
from datetime import datetime
from ctypes import c_short
from ctypes import c_byte
from ctypes import c_ubyte
DEVICE = 0x76 # Default device I2C address
bus = smbus.SMBus(1) # Rev 2 Pi, Pi 2 & Pi 3 uses bus 1
# Rev 1 Pi uses bus 0
def getShort(data, index):
# return two bytes from data as a signed 16-bit value
return c_short((data[index+1] << 8) + data[index]).value
def getUShort(data, index):
# return two bytes from data as an unsigned 16-bit value
return (data[index+1] << 8) + data[index]
def getChar(data,index):
# return one byte from data as a signed char
result = data[index]
if result > 127:
result -= 256
return result
def getUChar(data,index):
# return one byte from data as an unsigned char
result = data[index] & 0xFF
return result
def readBME280ID(addr=DEVICE):
# Chip ID Register Address
REG_ID = 0xD0
(chip_id, chip_version) = bus.read_i2c_block_data(addr, REG_ID, 2)
return (chip_id, chip_version)
def readBME280All(addr=DEVICE):
# Register Addresses
REG_DATA = 0xF7
REG_CONTROL = 0xF4
REG_CONFIG = 0xF5
REG_HUM_MSB = 0xFD
REG_HUM_LSB = 0xFE
# Oversample setting - page 27
OVERSAMPLE_TEMP = 2
OVERSAMPLE_PRES = 2
MODE = 1
control = OVERSAMPLE_TEMP<<5 | OVERSAMPLE_PRES<<2 | MODE
bus.write_byte_data(addr, REG_CONTROL, control)
# Read blocks of calibration data from EEPROM
# See Page 22 data sheet
cal1 = bus.read_i2c_block_data(addr, 0x88, 24)
cal2 = bus.read_i2c_block_data(addr, 0xA1, 1)
cal3 = bus.read_i2c_block_data(addr, 0xE1, 7)
# Convert byte data to word values
dig_T1 = getUShort(cal1, 0)
dig_T2 = getShort(cal1, 2)
dig_T3 = getShort(cal1, 4)
dig_P1 = getUShort(cal1, 6)
dig_P2 = getShort(cal1, 8)
dig_P3 = getShort(cal1, 10)
dig_P4 = getShort(cal1, 12)
dig_P5 = getShort(cal1, 14)
dig_P6 = getShort(cal1, 16)
dig_P7 = getShort(cal1, 18)
dig_P8 = getShort(cal1, 20)
dig_P9 = getShort(cal1, 22)
dig_H1 = getUChar(cal2, 0)
dig_H2 = getShort(cal3, 0)
dig_H3 = getUChar(cal3, 2)
dig_H4 = getChar(cal3, 3)
dig_H4 = (dig_H4 << 24) >> 20
dig_H4 = dig_H4 | (getChar(cal3, 4) & 0x0F)
dig_H5 = getChar(cal3, 5)
dig_H5 = (dig_H5 << 24) >> 20
dig_H5 = dig_H5 | (getUChar(cal3, 4) >> 4 & 0x0F)
dig_H6 = getChar(cal3, 6)
# Read temperature/pressure/humidity
data = bus.read_i2c_block_data(addr, REG_DATA, 8)
pres_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4)
temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4)
hum_raw = (data[6] << 8) | data[7]
#Refine temperature
var1 = ((((temp_raw>>3)-(dig_T1<<1)))*(dig_T2)) >> 11^M var2 = (((((temp_raw>>4) - (dig_T1)) * ((temp_raw>>4) - (dig_T1))) >> 12) * (dig_T3)) >> 14
t_fine = var1+var2
temperature = float(((t_fine * 5) + 128) >> 8);
# Refine pressure and adjust for temperature
var1 = t_fine / 2.0 - 64000.0
var2 = var1 * var1 * dig_P6 / 32768.0
var2 = var2 + var1 * dig_P5 * 2.0
var2 = var2 / 4.0 + dig_P4 * 65536.0
var1 = (dig_P3 * var1 * var1 / 524288.0 + dig_P2 * var1) / 524288.0
var1 = (1.0 + var1 / 32768.0) * dig_P1
if var1 == 0:
pressure=0
else:
pressure = 1048576.0 - pres_raw
pressure = ((pressure - var2 / 4096.0) * 6250.0) / var1
var1 = dig_P9 * pressure * pressure / 2147483648.0
var2 = pressure * dig_P8 / 32768.0
pressure = pressure + (var1 + var2 + dig_P7) / 16.0
# Refine humidity
humidity = t_fine - 76800.0
humidity = (hum_raw - (dig_H4 * 64.0 + dig_H5 / 16384.8 * humidity)) * (dig_H2 / 65536.0 * (1.0 + dig_H6 / 67108864.0 * humidity * (1.0 + dig_H3 / 67108864.0 * humidity)))
humidity = humidity * (1.0 - dig_H1 * humidity / 524288.0)
if humidity > 100:
humidity = 100
elif humidity < 0:
humidity = 0
return temperature/100.0,pressure/100.0,humidity
while True:
temperature,pressure,humidity = readBME280All()
text_file = open("/var/www/html/weather.txt", "a")
text_file.write(str(datetime.now().strftime('%F %H:%M ')))
# correct for bme280's high temp readout
text_file.write("%.2f " % (((temperature)*9/5)+32-4))
text_file.write("%.2f " % ((pressure)/33.8638866667))
text_file.write("%.2f\n" % humidity)
text_file.close()
time.sleep(60)
No comments:
Post a Comment