├── .gitignore ├── Adafruit_BME280.py ├── Adafruit_BME280_Example.py ├── Adafruit_BME280_Example_Curses.py ├── LICENSE ├── README.md └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore editor backup files: 2 | *~ 3 | *.bak 4 | 5 | 6 | # Ignore compiled Python files: 7 | *.pyc 8 | -------------------------------------------------------------------------------- /Adafruit_BME280.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014 Adafruit Industries 2 | # Author: Tony DiCola 3 | # 4 | # Based on the BMP280 driver with BME280 changes provided by 5 | # David J Taylor, Edinburgh (www.satsignal.eu). Additional functions added 6 | # by Tom Nardi (www.digifail.com) 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in 16 | # all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | # THE SOFTWARE. 25 | import logging 26 | import time 27 | 28 | 29 | # BME280 default address. 30 | BME280_I2CADDR = 0x77 31 | 32 | # Operating Modes 33 | BME280_OSAMPLE_1 = 1 34 | BME280_OSAMPLE_2 = 2 35 | BME280_OSAMPLE_4 = 3 36 | BME280_OSAMPLE_8 = 4 37 | BME280_OSAMPLE_16 = 5 38 | 39 | # Standby Settings 40 | BME280_STANDBY_0p5 = 0 41 | BME280_STANDBY_62p5 = 1 42 | BME280_STANDBY_125 = 2 43 | BME280_STANDBY_250 = 3 44 | BME280_STANDBY_500 = 4 45 | BME280_STANDBY_1000 = 5 46 | BME280_STANDBY_10 = 6 47 | BME280_STANDBY_20 = 7 48 | 49 | # Filter Settings 50 | BME280_FILTER_off = 0 51 | BME280_FILTER_2 = 1 52 | BME280_FILTER_4 = 2 53 | BME280_FILTER_8 = 3 54 | BME280_FILTER_16 = 4 55 | 56 | # BME280 Registers 57 | 58 | BME280_REGISTER_DIG_T1 = 0x88 # Trimming parameter registers 59 | BME280_REGISTER_DIG_T2 = 0x8A 60 | BME280_REGISTER_DIG_T3 = 0x8C 61 | 62 | BME280_REGISTER_DIG_P1 = 0x8E 63 | BME280_REGISTER_DIG_P2 = 0x90 64 | BME280_REGISTER_DIG_P3 = 0x92 65 | BME280_REGISTER_DIG_P4 = 0x94 66 | BME280_REGISTER_DIG_P5 = 0x96 67 | BME280_REGISTER_DIG_P6 = 0x98 68 | BME280_REGISTER_DIG_P7 = 0x9A 69 | BME280_REGISTER_DIG_P8 = 0x9C 70 | BME280_REGISTER_DIG_P9 = 0x9E 71 | 72 | BME280_REGISTER_DIG_H1 = 0xA1 73 | BME280_REGISTER_DIG_H2 = 0xE1 74 | BME280_REGISTER_DIG_H3 = 0xE3 75 | BME280_REGISTER_DIG_H4 = 0xE4 76 | BME280_REGISTER_DIG_H5 = 0xE5 77 | BME280_REGISTER_DIG_H6 = 0xE6 78 | BME280_REGISTER_DIG_H7 = 0xE7 79 | 80 | BME280_REGISTER_CHIPID = 0xD0 81 | BME280_REGISTER_VERSION = 0xD1 82 | BME280_REGISTER_SOFTRESET = 0xE0 83 | 84 | BME280_REGISTER_STATUS = 0xF3 85 | BME280_REGISTER_CONTROL_HUM = 0xF2 86 | BME280_REGISTER_CONTROL = 0xF4 87 | BME280_REGISTER_CONFIG = 0xF5 88 | BME280_REGISTER_DATA = 0xF7 89 | 90 | 91 | class BME280(object): 92 | def __init__(self, t_mode=BME280_OSAMPLE_1, p_mode=BME280_OSAMPLE_1, h_mode=BME280_OSAMPLE_1, 93 | standby=BME280_STANDBY_250, filter=BME280_FILTER_off, address=BME280_I2CADDR, i2c=None, 94 | **kwargs): 95 | self._logger = logging.getLogger('Adafruit_BMP.BMP085') 96 | # Check that t_mode is valid. 97 | if t_mode not in [BME280_OSAMPLE_1, BME280_OSAMPLE_2, BME280_OSAMPLE_4, 98 | BME280_OSAMPLE_8, BME280_OSAMPLE_16]: 99 | raise ValueError( 100 | 'Unexpected t_mode value {0}.'.format(t_mode)) 101 | self._t_mode = t_mode 102 | # Check that p_mode is valid. 103 | if p_mode not in [BME280_OSAMPLE_1, BME280_OSAMPLE_2, BME280_OSAMPLE_4, 104 | BME280_OSAMPLE_8, BME280_OSAMPLE_16]: 105 | raise ValueError( 106 | 'Unexpected p_mode value {0}.'.format(p_mode)) 107 | self._p_mode = p_mode 108 | # Check that h_mode is valid. 109 | if h_mode not in [BME280_OSAMPLE_1, BME280_OSAMPLE_2, BME280_OSAMPLE_4, 110 | BME280_OSAMPLE_8, BME280_OSAMPLE_16]: 111 | raise ValueError( 112 | 'Unexpected h_mode value {0}.'.format(h_mode)) 113 | self._h_mode = h_mode 114 | # Check that standby is valid. 115 | if standby not in [BME280_STANDBY_0p5, BME280_STANDBY_62p5, BME280_STANDBY_125, BME280_STANDBY_250, 116 | BME280_STANDBY_500, BME280_STANDBY_1000, BME280_STANDBY_10, BME280_STANDBY_20]: 117 | raise ValueError( 118 | 'Unexpected standby value {0}.'.format(standby)) 119 | self._standby = standby 120 | # Check that filter is valid. 121 | if filter not in [BME280_FILTER_off, BME280_FILTER_2, BME280_FILTER_4, BME280_FILTER_8, BME280_FILTER_16]: 122 | raise ValueError( 123 | 'Unexpected filter value {0}.'.format(filter)) 124 | self._filter = filter 125 | # Create I2C device. 126 | if i2c is None: 127 | import Adafruit_GPIO.I2C as I2C 128 | i2c = I2C 129 | # Create device, catch permission errors 130 | try: 131 | self._device = i2c.get_i2c_device(address, **kwargs) 132 | except IOError: 133 | print("Unable to communicate with sensor, check permissions.") 134 | exit() 135 | # Load calibration values. 136 | self._load_calibration() 137 | self._device.write8(BME280_REGISTER_CONTROL, 0x24) # Sleep mode 138 | time.sleep(0.002) 139 | self._device.write8(BME280_REGISTER_CONFIG, ((standby << 5) | (filter << 2))) 140 | time.sleep(0.002) 141 | self._device.write8(BME280_REGISTER_CONTROL_HUM, h_mode) # Set Humidity Oversample 142 | self._device.write8(BME280_REGISTER_CONTROL, ((t_mode << 5) | (p_mode << 2) | 3)) # Set Temp/Pressure Oversample and enter Normal mode 143 | self.t_fine = 0.0 144 | 145 | def _load_calibration(self): 146 | 147 | self.dig_T1 = self._device.readU16LE(BME280_REGISTER_DIG_T1) 148 | self.dig_T2 = self._device.readS16LE(BME280_REGISTER_DIG_T2) 149 | self.dig_T3 = self._device.readS16LE(BME280_REGISTER_DIG_T3) 150 | 151 | self.dig_P1 = self._device.readU16LE(BME280_REGISTER_DIG_P1) 152 | self.dig_P2 = self._device.readS16LE(BME280_REGISTER_DIG_P2) 153 | self.dig_P3 = self._device.readS16LE(BME280_REGISTER_DIG_P3) 154 | self.dig_P4 = self._device.readS16LE(BME280_REGISTER_DIG_P4) 155 | self.dig_P5 = self._device.readS16LE(BME280_REGISTER_DIG_P5) 156 | self.dig_P6 = self._device.readS16LE(BME280_REGISTER_DIG_P6) 157 | self.dig_P7 = self._device.readS16LE(BME280_REGISTER_DIG_P7) 158 | self.dig_P8 = self._device.readS16LE(BME280_REGISTER_DIG_P8) 159 | self.dig_P9 = self._device.readS16LE(BME280_REGISTER_DIG_P9) 160 | 161 | self.dig_H1 = self._device.readU8(BME280_REGISTER_DIG_H1) 162 | self.dig_H2 = self._device.readS16LE(BME280_REGISTER_DIG_H2) 163 | self.dig_H3 = self._device.readU8(BME280_REGISTER_DIG_H3) 164 | self.dig_H6 = self._device.readS8(BME280_REGISTER_DIG_H7) 165 | 166 | h4 = self._device.readS8(BME280_REGISTER_DIG_H4) 167 | h4 = (h4 << 4) 168 | self.dig_H4 = h4 | (self._device.readU8(BME280_REGISTER_DIG_H5) & 0x0F) 169 | 170 | h5 = self._device.readS8(BME280_REGISTER_DIG_H6) 171 | h5 = (h5 << 4) 172 | self.dig_H5 = h5 | ( 173 | self._device.readU8(BME280_REGISTER_DIG_H5) >> 4 & 0x0F) 174 | 175 | ''' 176 | print '0xE4 = {0:2x}'.format (self._device.readU8 (BME280_REGISTER_DIG_H4)) 177 | print '0xE5 = {0:2x}'.format (self._device.readU8 (BME280_REGISTER_DIG_H5)) 178 | print '0xE6 = {0:2x}'.format (self._device.readU8 (BME280_REGISTER_DIG_H6)) 179 | 180 | print 'dig_H1 = {0:d}'.format (self.dig_H1) 181 | print 'dig_H2 = {0:d}'.format (self.dig_H2) 182 | print 'dig_H3 = {0:d}'.format (self.dig_H3) 183 | print 'dig_H4 = {0:d}'.format (self.dig_H4) 184 | print 'dig_H5 = {0:d}'.format (self.dig_H5) 185 | print 'dig_H6 = {0:d}'.format (self.dig_H6) 186 | ''' 187 | 188 | def read_raw_temp(self): 189 | """Waits for reading to become available on device.""" 190 | """Does a single burst read of all data values from device.""" 191 | """Returns the raw (uncompensated) temperature from the sensor.""" 192 | while (self._device.readU8(BME280_REGISTER_STATUS) & 0x08): # Wait for conversion to complete (TODO : add timeout) 193 | time.sleep(0.002) 194 | self.BME280Data = self._device.readList(BME280_REGISTER_DATA, 8) 195 | raw = ((self.BME280Data[3] << 16) | (self.BME280Data[4] << 8) | self.BME280Data[5]) >> 4 196 | return raw 197 | 198 | def read_raw_pressure(self): 199 | """Returns the raw (uncompensated) pressure level from the sensor.""" 200 | """Assumes that the temperature has already been read """ 201 | """i.e. that BME280Data[] has been populated.""" 202 | raw = ((self.BME280Data[0] << 16) | (self.BME280Data[1] << 8) | self.BME280Data[2]) >> 4 203 | return raw 204 | 205 | def read_raw_humidity(self): 206 | """Returns the raw (uncompensated) humidity value from the sensor.""" 207 | """Assumes that the temperature has already been read """ 208 | """i.e. that BME280Data[] has been populated.""" 209 | raw = (self.BME280Data[6] << 8) | self.BME280Data[7] 210 | return raw 211 | 212 | def read_temperature(self): 213 | """Gets the compensated temperature in degrees celsius.""" 214 | # float in Python is double precision 215 | UT = float(self.read_raw_temp()) 216 | var1 = (UT / 16384.0 - float(self.dig_T1) / 1024.0) * float(self.dig_T2) 217 | var2 = ((UT / 131072.0 - float(self.dig_T1) / 8192.0) * ( 218 | UT / 131072.0 - float(self.dig_T1) / 8192.0)) * float(self.dig_T3) 219 | self.t_fine = int(var1 + var2) 220 | temp = (var1 + var2) / 5120.0 221 | return temp 222 | 223 | def read_pressure(self): 224 | """Gets the compensated pressure in Pascals.""" 225 | adc = float(self.read_raw_pressure()) 226 | var1 = float(self.t_fine) / 2.0 - 64000.0 227 | var2 = var1 * var1 * float(self.dig_P6) / 32768.0 228 | var2 = var2 + var1 * float(self.dig_P5) * 2.0 229 | var2 = var2 / 4.0 + float(self.dig_P4) * 65536.0 230 | var1 = ( 231 | float(self.dig_P3) * var1 * var1 / 524288.0 + float(self.dig_P2) * var1) / 524288.0 232 | var1 = (1.0 + var1 / 32768.0) * float(self.dig_P1) 233 | if var1 == 0: 234 | return 0 235 | p = 1048576.0 - adc 236 | p = ((p - var2 / 4096.0) * 6250.0) / var1 237 | var1 = float(self.dig_P9) * p * p / 2147483648.0 238 | var2 = p * float(self.dig_P8) / 32768.0 239 | p = p + (var1 + var2 + float(self.dig_P7)) / 16.0 240 | return p 241 | 242 | def read_humidity(self): 243 | adc = float(self.read_raw_humidity()) 244 | # print 'Raw humidity = {0:d}'.format (adc) 245 | h = float(self.t_fine) - 76800.0 246 | h = (adc - (float(self.dig_H4) * 64.0 + float(self.dig_H5) / 16384.0 * h)) * ( 247 | float(self.dig_H2) / 65536.0 * (1.0 + float(self.dig_H6) / 67108864.0 * h * ( 248 | 1.0 + float(self.dig_H3) / 67108864.0 * h))) 249 | h = h * (1.0 - float(self.dig_H1) * h / 524288.0) 250 | if h > 100: 251 | h = 100 252 | elif h < 0: 253 | h = 0 254 | return h 255 | 256 | def read_temperature_f(self): 257 | # Wrapper to get temp in F 258 | celsius = self.read_temperature() 259 | temp = celsius * 1.8 + 32 260 | return temp 261 | 262 | def read_pressure_inches(self): 263 | # Wrapper to get pressure in inches of Hg 264 | pascals = self.read_pressure() 265 | inches = pascals * 0.0002953 266 | return inches 267 | 268 | def read_dewpoint(self): 269 | # Return calculated dewpoint in C, only accurate at > 50% RH 270 | celsius = self.read_temperature() 271 | humidity = self.read_humidity() 272 | dewpoint = celsius - ((100 - humidity) / 5) 273 | return dewpoint 274 | 275 | def read_dewpoint_f(self): 276 | # Return calculated dewpoint in F, only accurate at > 50% RH 277 | dewpoint_c = self.read_dewpoint() 278 | dewpoint_f = dewpoint_c * 1.8 + 32 279 | return dewpoint_f 280 | -------------------------------------------------------------------------------- /Adafruit_BME280_Example.py: -------------------------------------------------------------------------------- 1 | from Adafruit_BME280 import * 2 | 3 | sensor = BME280(t_mode=BME280_OSAMPLE_8, p_mode=BME280_OSAMPLE_8, h_mode=BME280_OSAMPLE_8) 4 | 5 | degrees = sensor.read_temperature() 6 | pascals = sensor.read_pressure() 7 | hectopascals = pascals / 100 8 | humidity = sensor.read_humidity() 9 | 10 | print 'Temp = {0:0.3f} deg C'.format(degrees) 11 | print 'Pressure = {0:0.2f} hPa'.format(hectopascals) 12 | print 'Humidity = {0:0.2f} %'.format(humidity) 13 | -------------------------------------------------------------------------------- /Adafruit_BME280_Example_Curses.py: -------------------------------------------------------------------------------- 1 | from Adafruit_BME280 import * 2 | import curses 3 | 4 | def main(stdscr): 5 | sensor = BME280(p_mode=BME280_OSAMPLE_8, t_mode=BME280_OSAMPLE_2, h_mode=BME280_OSAMPLE_1, filter=BME280_FILTER_16) 6 | stdscr.nodelay(1) 7 | tstart = time.time() 8 | while (stdscr.getch() == -1) : 9 | degrees = sensor.read_temperature() 10 | pascals = sensor.read_pressure() 11 | hectopascals = pascals / 100 12 | humidity = sensor.read_humidity() 13 | 14 | stdscr.addstr(0, 0, 'Timestamp = %0.3f sec' % (time.time() - tstart)) 15 | stdscr.addstr(1, 0, 'Temp = %0.3f deg C (%0.3f deg F)' % (degrees, ((degrees*9/5)+32))) 16 | stdscr.addstr(2, 0, 'Pressure = %0.2f hPa' % hectopascals) 17 | stdscr.addstr(3, 0, 'Humidity = %0.2f %%' % humidity) 18 | stdscr.addstr(5, 0, 'Press any key to exit...') 19 | stdscr.refresh() 20 | 21 | time.sleep(3) 22 | 23 | stdscr.erase() 24 | 25 | 26 | curses.wrapper(main) 27 | 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Adafruit Industries 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | DEPRECATED LIBRARY Adafruit_Python_BME280 2 | =================== 3 | 4 | This library has been deprecated! 5 | 6 | we are now only using our circuitpython sensor libraries in python 7 | 8 | we are leaving the code up for historical/research purposes but archiving the repository. 9 | 10 | check out this guide for using the bme280 with python! 11 | https://learn.adafruit.com/adafruit-bme280-humidity-barometric-pressure-temperature-sensor-breakout 12 | 13 | # 14 | 15 | This Python driver allows you to read data from the [Adafruit BME280 Breakout](https://www.adafruit.com/products/2652) on a Raspberry Pi, Pi2 or similar device. 16 | 17 | ## Requirements 18 | 19 | This driver requires that you have previously installed the 20 | [Adafruit_Python_GPIO](https://github.com/adafruit/Adafruit_Python_GPIO) package. 21 | 22 | On Raspbian, you can install this package with the following commands: 23 | 24 | ``` 25 | sudo apt-get update 26 | sudo apt-get install build-essential python-pip python-dev python-smbus git 27 | git clone https://github.com/adafruit/Adafruit_Python_GPIO.git 28 | cd Adafruit_Python_GPIO 29 | sudo python setup.py install 30 | ``` 31 | 32 | ## Usage 33 | 34 | To read a single set of data points from the BME, connect your Pi 35 | to the BME280 breakout using I2C (connect SCL to the SCK pin and SDA 36 | to the SDI pin), and run the following command from this folder: 37 | 38 | ``` 39 | python Adafruit_BME280_Example.py 40 | ``` 41 | 42 | ## Credits 43 | 44 | This driver is based on the [Adafruit_BMP](https://github.com/adafruit/Adafruit_Python_BMP) 45 | driver by Tony DiCola (Adafruit Industries), with BME280 additions kindly provided by 46 | David J. Taylor (www.satsignal.eu). 47 | 48 | # MIT License 49 | 50 | Permission is hereby granted, free of charge, to any person obtaining a copy 51 | of this software and associated documentation files (the "Software"), to deal 52 | in the Software without restriction, including without limitation the rights 53 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 54 | copies of the Software, and to permit persons to whom the Software is 55 | furnished to do so, subject to the following conditions: 56 | 57 | The above copyright notice and this permission notice shall be included in 58 | all copies or substantial portions of the Software. 59 | 60 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 61 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 62 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 63 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 64 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 65 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 66 | THE SOFTWARE. 67 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from distutils.core import setup 4 | 5 | setup(name='Adafruit_BME280', 6 | version='1.0', 7 | description='Adafruit Python BME280 Liibrary', 8 | url='https://github.com/adafruit/Adafruit_Python_BME280', 9 | py_modules=['Adafruit_BME280'], 10 | ) 11 | --------------------------------------------------------------------------------