first commit
This commit is contained in:
commit
a5a0434432
1126 changed files with 439481 additions and 0 deletions
|
|
@ -0,0 +1,42 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# GrovePi Example for using the Grove Barometer module (http://www.seeedstudio.com/depot/Grove-Barometer-HighAccuracy-p-1865.html)
|
||||
#
|
||||
# The GrovePi connects the Raspberry Pi and Grove sensors. You can learn more about GrovePi here: http://www.dexterindustries.com/GrovePi
|
||||
#
|
||||
# Have a question about this example? Ask on the forums here: http://forum.dexterindustries.com/c/grovepi
|
||||
#
|
||||
'''
|
||||
## License
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
GrovePi for the Raspberry Pi: an open source platform for connecting Grove Sensors to the Raspberry Pi.
|
||||
Copyright (C) 2017 Dexter Industries
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
'''
|
||||
|
||||
|
||||
import grove_barometer_lib
|
||||
b = grove_barometer_lib.barometer()
|
||||
while True():
|
||||
print ("Temp:",b.temperature," Pressure:",b.pressure," Altitude:",b.altitude)
|
||||
b.update()
|
||||
time.sleep(.1)
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
#!/usr/bin/env python
|
||||
# #######################################################################
|
||||
# This library is for using the Grove Barometer module with he GrovePi
|
||||
# http://www.dexterindustries.com/GrovePi/
|
||||
# Barometer module: http://www.seeedstudio.com/depot/Grove-Barometer-HighAccuracy-p-1865.html
|
||||
#
|
||||
# History
|
||||
# ------------------------------------------------
|
||||
# Author Date Comments
|
||||
# Bill 26.07.2014 Initial Port to Python
|
||||
# Guruth 29.08.2014 Clean up and put to usable libary
|
||||
#
|
||||
# Re-written from: https://github.com/Seeed-Studio/Grove_Barometer_HP20x
|
||||
# Refer to the datasheet to add additional functionality http://www.seeedstudio.com/wiki/images/d/d8/HP206C_Datasheet.pdf
|
||||
########################################################################
|
||||
|
||||
# Released under the MIT license (http://choosealicense.com/licenses/mit/).
|
||||
# For more information see https://github.com/DexterInd/GrovePi/blob/master/LICENSE
|
||||
|
||||
|
||||
import smbus
|
||||
import time
|
||||
import RPi.GPIO as GPIO
|
||||
|
||||
|
||||
rev = GPIO.RPI_REVISION
|
||||
if rev == 2 or rev == 3:
|
||||
bus = smbus.SMBus(1)
|
||||
else:
|
||||
bus = smbus.SMBus(0)
|
||||
|
||||
HP20X_I2C_DEV_ID = 0x76 # Barometer device address
|
||||
|
||||
HP20X_SOFT_RST = 0x06 # Soft reset the device
|
||||
OK_HP20X_DEV = 0X80 # Default value for
|
||||
|
||||
HP20X_READ_PARA_REG = 0x8F # Read Register
|
||||
|
||||
HP20X_ADC_CVT = 0x48 # Digital filter rate and channel
|
||||
|
||||
HP20X_READ_P = 0x30 # Read Pressure
|
||||
HP20X_READ_A = 0x31 # Read Altitude
|
||||
HP20X_READ_T = 0x32 # Read Temperature
|
||||
|
||||
|
||||
class barometer:
|
||||
temperature = 0
|
||||
pressure = 0
|
||||
altitude = 0
|
||||
|
||||
def __init__(self):
|
||||
# Send reset cmd to sensor
|
||||
bus.write_byte(HP20X_I2C_DEV_ID, HP20X_SOFT_RST)
|
||||
time.sleep(0.1)
|
||||
# Check if reset was successful
|
||||
if self.isAvailable():
|
||||
self.update()
|
||||
|
||||
def isAvailable(self):
|
||||
# Read register status register
|
||||
bus.write_byte(HP20X_I2C_DEV_ID, HP20X_READ_PARA_REG)
|
||||
# Retrieve the value from he bus
|
||||
ret = bus.read_byte(HP20X_I2C_DEV_ID)
|
||||
# Check if reset was successful
|
||||
if ret == OK_HP20X_DEV:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
# Read sensor value
|
||||
def readSensor(self, sensor):
|
||||
# Set digital filter rate
|
||||
bus.write_byte(HP20X_I2C_DEV_ID, HP20X_ADC_CVT)
|
||||
time.sleep(.25)
|
||||
# Send cmd to read from sensor X
|
||||
# 0x30 || 0x31 || 0x32
|
||||
bus.write_byte(HP20X_I2C_DEV_ID, sensor)
|
||||
# Read data from bus
|
||||
data = bus.read_i2c_block_data(HP20X_I2C_DEV_ID, 0)
|
||||
value = data[0] << 16 | data[1] << 8 | data[2]
|
||||
return value
|
||||
|
||||
# Update barometer values
|
||||
def update(self):
|
||||
# Read temp
|
||||
self.temperature = self.readSensor(HP20X_READ_T)
|
||||
time.sleep(0.2)
|
||||
# Read pressure
|
||||
self.pressure = self.readSensor(HP20X_READ_P)
|
||||
time.sleep(0.2)
|
||||
# Read altitude
|
||||
self.altitude = self.readSensor(HP20X_READ_A)
|
||||
time.sleep(0.2)
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
This is a Python 2.7 script wich can be used to get readings from the Grove Digital Barometic Sensor(BMP085) (http://www.seeedstudio.com/depot/Grove-Barometer-Sensor-p-1199.html) connected to the GrovePi on a Raspberry Pi.
|
||||
|
||||
The script Grove_Barometic_Sensor.py containes a class BMP085 (this is the actual sensor-chip on the device). All functions are inside this class and can be called from other scripts if you set the following code in the script:
|
||||
from Grove_Barometic_Sensor import BMP085
|
||||
|
||||
If you set debug = True in the def__init__ function it displays all calculations on screen. If you set debug = False, the script just runs and sends the output to the calling script.
|
||||
|
||||
The script reads the raw temperature and raw pressure from the sensor. It then performs some calculations to transform the readed temperature to a calbrated temperature in °C and to perform a compenstion to the readed pressure to changed it to a calibrated value in Pascal. Finaly it calculates the altitude in meters above sea level using the barometric hight formula (sea http://en.wikipedia.org/wiki/Atmospheric_pressure). Standard it uses the sea level standard atmospheric pressure 101329 Pa. If you want to use a local sea level pressure, call the function readAltitude(123456) with the correct value between brackryd (make sure to give the value in Pascal (or multiply the value in hPa by 100)).
|
||||
|
||||
The script works in 4 modes (depending on how the initialisations is done in the calling script:
|
||||
0 ULTRA LOW POWER Mode
|
||||
1 Standard Mode
|
||||
2 HIRES Mode
|
||||
3 ULTRAHIRES Mode
|
||||
|
||||
If you need a value of the pressure in hPa, make sure to divide the returned value by 100 in the calling script.
|
||||
|
||||
September 2014.
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
#!/usr/bin/python
|
||||
import re
|
||||
import smbus
|
||||
|
||||
# ===========================================================================
|
||||
# Adafruit_I2C Class
|
||||
# ===========================================================================
|
||||
|
||||
class Adafruit_I2C(object):
|
||||
|
||||
@staticmethod
|
||||
def getPiRevision():
|
||||
"Gets the version number of the Raspberry Pi board"
|
||||
# Revision list available at: http://elinux.org/RPi_HardwareHistory#Board_Revision_History
|
||||
try:
|
||||
with open('/proc/cpuinfo', 'r') as infile:
|
||||
for line in infile:
|
||||
# Match a line of the form "Revision : 0002" while ignoring extra
|
||||
# info in front of the revsion (like 1000 when the Pi was over-volted).
|
||||
match = re.match('Revision\s+:\s+.*(\w{4})$', line)
|
||||
if match and match.group(1) in ['0000', '0002', '0003']:
|
||||
# Return revision 1 if revision ends with 0000, 0002 or 0003.
|
||||
return 1
|
||||
elif match:
|
||||
# Assume revision 2 if revision ends with any other 4 chars.
|
||||
return 2
|
||||
# Couldn't find the revision, assume revision 0 like older code for compatibility.
|
||||
return 0
|
||||
except:
|
||||
return 0
|
||||
|
||||
@staticmethod
|
||||
def getPiI2CBusNumber():
|
||||
# Gets the I2C bus number /dev/i2c#
|
||||
return 1 if Adafruit_I2C.getPiRevision() > 1 else 0
|
||||
|
||||
def __init__(self, address, busnum=-1, debug=False):
|
||||
self.address = address
|
||||
# By default, the correct I2C bus is auto-detected using /proc/cpuinfo
|
||||
# Alternatively, you can hard-code the bus version below:
|
||||
# self.bus = smbus.SMBus(0); # Force I2C0 (early 256MB Pi's)
|
||||
# self.bus = smbus.SMBus(1); # Force I2C1 (512MB Pi's)
|
||||
self.bus = smbus.SMBus(busnum if busnum >= 0 else Adafruit_I2C.getPiI2CBusNumber())
|
||||
self.debug = debug
|
||||
|
||||
def reverseByteOrder(self, data):
|
||||
"Reverses the byte order of an int (16-bit) or long (32-bit) value"
|
||||
# Courtesy Vishal Sapre
|
||||
byteCount = len(hex(data)[2:].replace('L','')[::2])
|
||||
val = 0
|
||||
for i in range(byteCount):
|
||||
val = (val << 8) | (data & 0xff)
|
||||
data >>= 8
|
||||
return val
|
||||
|
||||
def errMsg(self):
|
||||
print("Error accessing 0x%02X: Check your I2C address" % self.address)
|
||||
return -1
|
||||
|
||||
def write8(self, reg, value):
|
||||
"Writes an 8-bit value to the specified register/address"
|
||||
try:
|
||||
self.bus.write_byte_data(self.address, reg, value)
|
||||
if self.debug:
|
||||
print("I2C: Wrote 0x%02X to register 0x%02X" % (value, reg))
|
||||
except IOError as err:
|
||||
return self.errMsg()
|
||||
|
||||
def write16(self, reg, value):
|
||||
"Writes a 16-bit value to the specified register/address pair"
|
||||
try:
|
||||
self.bus.write_word_data(self.address, reg, value)
|
||||
if self.debug:
|
||||
print ("I2C: Wrote 0x%02X to register pair 0x%02X,0x%02X" %
|
||||
(value, reg, reg+1))
|
||||
except IOError as err:
|
||||
return self.errMsg()
|
||||
|
||||
def writeRaw8(self, value):
|
||||
"Writes an 8-bit value on the bus"
|
||||
try:
|
||||
self.bus.write_byte(self.address, value)
|
||||
if self.debug:
|
||||
print("I2C: Wrote 0x%02X" % value)
|
||||
except IOError as err:
|
||||
return self.errMsg()
|
||||
|
||||
def writeList(self, reg, list):
|
||||
"Writes an array of bytes using I2C format"
|
||||
try:
|
||||
if self.debug:
|
||||
print("I2C: Writing list to register 0x%02X:" % reg)
|
||||
print(list)
|
||||
self.bus.write_i2c_block_data(self.address, reg, list)
|
||||
except IOError as err:
|
||||
return self.errMsg()
|
||||
|
||||
def readList(self, reg, length):
|
||||
"Read a list of bytes from the I2C device"
|
||||
try:
|
||||
results = self.bus.read_i2c_block_data(self.address, reg, length)
|
||||
if self.debug:
|
||||
print ("I2C: Device 0x%02X returned the following from reg 0x%02X" %
|
||||
(self.address, reg))
|
||||
print(results)
|
||||
return results
|
||||
except IOError as err:
|
||||
return self.errMsg()
|
||||
|
||||
def readU8(self, reg):
|
||||
"Read an unsigned byte from the I2C device"
|
||||
try:
|
||||
result = self.bus.read_byte_data(self.address, reg)
|
||||
if self.debug:
|
||||
print("I2C: Device 0x%02X returned 0x%02X from reg 0x%02X" %
|
||||
(self.address, result & 0xFF, reg))
|
||||
return result
|
||||
except IOError as err:
|
||||
return self.errMsg()
|
||||
|
||||
def readS8(self, reg):
|
||||
"Reads a signed byte from the I2C device"
|
||||
try:
|
||||
result = self.bus.read_byte_data(self.address, reg)
|
||||
if result > 127: result -= 256
|
||||
if self.debug:
|
||||
print("I2C: Device 0x%02X returned 0x%02X from reg 0x%02X" %
|
||||
(self.address, result & 0xFF, reg))
|
||||
return result
|
||||
except IOError as err:
|
||||
return self.errMsg()
|
||||
|
||||
def readU16(self, reg, little_endian=True):
|
||||
"Reads an unsigned 16-bit value from the I2C device"
|
||||
try:
|
||||
result = self.bus.read_word_data(self.address,reg)
|
||||
# Swap bytes if using big endian because read_word_data assumes little
|
||||
# endian on ARM (little endian) systems.
|
||||
if not little_endian:
|
||||
result = ((result << 8) & 0xFF00) + (result >> 8)
|
||||
if (self.debug):
|
||||
print("I2C: Device 0x%02X returned 0x%04X from reg 0x%02X" % (self.address, result & 0xFFFF, reg))
|
||||
return result
|
||||
except IOError as err:
|
||||
return self.errMsg()
|
||||
|
||||
def readS16(self, reg, little_endian=True):
|
||||
"Reads a signed 16-bit value from the I2C device"
|
||||
try:
|
||||
result = self.readU16(reg,little_endian)
|
||||
if result > 32767: result -= 65536
|
||||
return result
|
||||
except IOError as err:
|
||||
return self.errMsg()
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
bus = Adafruit_I2C(address=0)
|
||||
print("Default I2C bus is accessible")
|
||||
except:
|
||||
print("Error accessing default I2C bus")
|
||||
|
|
@ -0,0 +1,288 @@
|
|||
#!/usr/bin/python
|
||||
# Copyright 2014 Johan Vandewalle. All rights reserved.
|
||||
#
|
||||
# Redistributian and use in source and binary forms, with or without
|
||||
# modification, are permitted provide that the following conditions are
|
||||
# met:
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following
|
||||
# disclaimer in the documentation and/or other materials provided
|
||||
# with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import time
|
||||
from Adafruit_I2C import Adafruit_I2C
|
||||
import math
|
||||
|
||||
# ===========================================================================
|
||||
# BMP085 Class
|
||||
# ===========================================================================
|
||||
|
||||
class BMP085 :
|
||||
i2c = None
|
||||
|
||||
# Operating Modes
|
||||
__BMP085_ULTRALOWPOWER = 0
|
||||
__BMP085_STANDARD = 1
|
||||
__BMP085_HIGHRES = 2
|
||||
__BMP085_ULTRAHIGHRES = 3
|
||||
|
||||
# BMP085 Registers
|
||||
__BMP085_CAL_AC1 = 0xAA # R Calibration data (16 bits)
|
||||
__BMP085_CAL_AC2 = 0xAC # R Calibration data (16 bits)
|
||||
__BMP085_CAL_AC3 = 0xAE # R Calibration data (16 bits)
|
||||
__BMP085_CAL_AC4 = 0xB0 # R Calibration data (16 bits)
|
||||
__BMP085_CAL_AC5 = 0xB2 # R Calibration data (16 bits)
|
||||
__BMP085_CAL_AC6 = 0xB4 # R Calibration data (16 bits)
|
||||
__BMP085_CAL_B1 = 0xB6 # R Calibration data (16 bits)
|
||||
__BMP085_CAL_B2 = 0xB8 # R Calibration data (16 bits)
|
||||
__BMP085_CAL_MB = 0xBA # R Calibration data (16 bits)
|
||||
__BMP085_CAL_MC = 0xBC # R Calibration data (16 bits)
|
||||
__BMP085_CAL_MD = 0xBE # R Calibration data (16 bits)
|
||||
__BMP085_CONTROL = 0xF4
|
||||
__BMP085_TEMPDATA = 0xF6
|
||||
__BMP085_PRESSUREDATA = 0xF6
|
||||
__BMP085_READTEMPCMD = 0x2E
|
||||
__BMP085_READPRESSURECMD = 0x34
|
||||
|
||||
# Private Fields
|
||||
_cal_AC1 = 0
|
||||
_cal_AC2 = 0
|
||||
_cal_AC3 = 0
|
||||
_cal_AC4 = 0
|
||||
_cal_AC5 = 0
|
||||
_cal_AC6 = 0
|
||||
_cal_B1 = 0
|
||||
_cal_B2 = 0
|
||||
_cal_MB = 0
|
||||
_cal_MC = 0
|
||||
_cal_MD = 0
|
||||
|
||||
# Constructor
|
||||
def __init__(self, address=0x77, mode=1, debug=False):
|
||||
self.i2c = Adafruit_I2C(address)
|
||||
|
||||
self.address = address
|
||||
self.debug = debug
|
||||
# Make sure the specified mode is in the appropriate range
|
||||
if ((mode < 0) | (mode > 3)):
|
||||
if (self.debug):
|
||||
print("Invalid Mode: Using STANDARD by default")
|
||||
self.mode = self.__BMP085_STANDARD
|
||||
else:
|
||||
self.mode = mode
|
||||
# Read the calibration data
|
||||
self.readCalibrationData()
|
||||
|
||||
def readS16(self, register):
|
||||
"Reads a signed 16-bit value"
|
||||
hi = self.i2c.readS8(register)
|
||||
lo = self.i2c.readU8(register+1)
|
||||
return (hi << 8) + lo
|
||||
|
||||
def readU16(self, register):
|
||||
"Reads an unsigned 16-bit value"
|
||||
hi = self.i2c.readU8(register)
|
||||
lo = self.i2c.readU8(register+1)
|
||||
return (hi << 8) + lo
|
||||
|
||||
def readCalibrationData(self):
|
||||
"Reads the calibration data from the IC"
|
||||
self._cal_AC1 = self.readS16(self.__BMP085_CAL_AC1) # INT16
|
||||
self._cal_AC2 = self.readS16(self.__BMP085_CAL_AC2) # INT16
|
||||
self._cal_AC3 = self.readS16(self.__BMP085_CAL_AC3) # INT16
|
||||
self._cal_AC4 = self.readU16(self.__BMP085_CAL_AC4) # UINT16
|
||||
self._cal_AC5 = self.readU16(self.__BMP085_CAL_AC5) # UINT16
|
||||
self._cal_AC6 = self.readU16(self.__BMP085_CAL_AC6) # UINT16
|
||||
self._cal_B1 = self.readS16(self.__BMP085_CAL_B1) # INT16
|
||||
self._cal_B2 = self.readS16(self.__BMP085_CAL_B2) # INT16
|
||||
self._cal_MB = self.readS16(self.__BMP085_CAL_MB) # INT16
|
||||
self._cal_MC = self.readS16(self.__BMP085_CAL_MC) # INT16
|
||||
self._cal_MD = self.readS16(self.__BMP085_CAL_MD) # INT16
|
||||
if (self.debug):
|
||||
self.showCalibrationData()
|
||||
|
||||
def showCalibrationData(self):
|
||||
"Displays the calibration values for debugging purposes"
|
||||
print("DBG: AC1 = %6d" % (self._cal_AC1))
|
||||
print("DBG: AC2 = %6d" % (self._cal_AC2))
|
||||
print("DBG: AC3 = %6d" % (self._cal_AC3))
|
||||
print("DBG: AC4 = %6d" % (self._cal_AC4))
|
||||
print("DBG: AC5 = %6d" % (self._cal_AC5))
|
||||
print("DBG: AC6 = %6d" % (self._cal_AC6))
|
||||
print("DBG: B1 = %6d" % (self._cal_B1))
|
||||
print("DBG: B2 = %6d" % (self._cal_B2))
|
||||
print("DBG: MB = %6d" % (self._cal_MB))
|
||||
print("DBG: MC = %6d" % (self._cal_MC))
|
||||
print("DBG: MD = %6d" % (self._cal_MD))
|
||||
|
||||
def readRawTemp(self):
|
||||
"Reads the raw (uncompensated) temperature from the sensor"
|
||||
self.i2c.write8(self.__BMP085_CONTROL, self.__BMP085_READTEMPCMD)
|
||||
time.sleep(0.005) # Wait 5ms
|
||||
raw = self.readU16(self.__BMP085_TEMPDATA)
|
||||
if (self.debug):
|
||||
print("DBG: Raw Temp: 0x%04X (%d)" % (raw & 0xFFFF, raw))
|
||||
return raw
|
||||
|
||||
def readRawPressure(self):
|
||||
"Reads the raw (uncompensated) pressure level from the sensor"
|
||||
self.i2c.write8(self.__BMP085_CONTROL, self.__BMP085_READPRESSURECMD + (self.mode << 6))
|
||||
if (self.mode == self.__BMP085_ULTRALOWPOWER):
|
||||
time.sleep(0.005)
|
||||
elif (self.mode == self.__BMP085_HIGHRES):
|
||||
time.sleep(0.014)
|
||||
elif (self.mode == self.__BMP085_ULTRAHIGHRES):
|
||||
time.sleep(0.026)
|
||||
else:
|
||||
time.sleep(0.008)
|
||||
msb = self.i2c.readU8(self.__BMP085_PRESSUREDATA)
|
||||
lsb = self.i2c.readU8(self.__BMP085_PRESSUREDATA+1)
|
||||
xlsb = self.i2c.readU8(self.__BMP085_PRESSUREDATA+2)
|
||||
raw = ((msb << 16) + (lsb << 8) + xlsb) >> (8 - self.mode)
|
||||
if (self.debug):
|
||||
print("DBG: Raw Pressure: 0x%04X (%d)" % (raw & 0xFFFF, raw))
|
||||
return raw
|
||||
|
||||
def readTemperature(self):
|
||||
"Gets the compensated temperature in degrees celcius"
|
||||
UT = 0
|
||||
X1 = 0
|
||||
X2 = 0
|
||||
B5 = 0
|
||||
temp = 0.0
|
||||
|
||||
# Read raw temp before aligning it with the calibration values
|
||||
UT = self.readRawTemp()
|
||||
X1 = ((UT - self._cal_AC6) * self._cal_AC5) >> 15
|
||||
X2 = (self._cal_MC << 11) / (X1 + self._cal_MD)
|
||||
B5 = X1 + X2
|
||||
temp = (int(B5 + 8) >> 4) / 10.0
|
||||
if (self.debug):
|
||||
print("DBG: Calibrated temperature = %f C" % temp)
|
||||
return temp
|
||||
|
||||
def readPressure(self):
|
||||
"Gets the compensated pressure in pascal"
|
||||
UT = 0
|
||||
UP = 0
|
||||
B3 = 0
|
||||
B5 = 0
|
||||
B6 = 0
|
||||
X1 = 0
|
||||
X2 = 0
|
||||
X3 = 0
|
||||
p = 0
|
||||
B4 = 0
|
||||
B7 = 0
|
||||
|
||||
UT = self.readRawTemp()
|
||||
UP = self.readRawPressure()
|
||||
|
||||
# You can use the datasheet values to test the conversion results
|
||||
# dsValues = True
|
||||
dsValues = False
|
||||
|
||||
if (dsValues):
|
||||
UT = 27898
|
||||
UP = 23843
|
||||
self._cal_AC6 = 23153
|
||||
self._cal_AC5 = 32757
|
||||
self._cal_MB = -32768;
|
||||
self._cal_MC = -8711
|
||||
self._cal_MD = 2868
|
||||
self._cal_B1 = 6190
|
||||
self._cal_B2 = 4
|
||||
self._cal_AC3 = -14383
|
||||
self._cal_AC2 = -72
|
||||
self._cal_AC1 = 408
|
||||
self._cal_AC4 = 32741
|
||||
self.mode = self.__BMP085_ULTRALOWPOWER
|
||||
if (self.debug):
|
||||
self.showCalibrationData()
|
||||
|
||||
# True Temperature Calculations
|
||||
X1 = ((UT - self._cal_AC6) * self._cal_AC5) >> 15
|
||||
X2 = (self._cal_MC << 11) / (X1 + self._cal_MD)
|
||||
B5 = X1 + X2
|
||||
if (self.debug):
|
||||
print("DBG: X1 = %d" % (X1))
|
||||
print("DBG: X2 = %d" % (X2))
|
||||
print("DBG: B5 = %d" % (B5))
|
||||
print("DBG: True Temperature = %.2f C" % (((B5 + 8) >> 4) / 10.0))
|
||||
|
||||
# Pressure Calculations
|
||||
B6 = B5 - 4000
|
||||
X1 = (int(self._cal_B2) * int(B6 * B6) >> 12) >> 11
|
||||
X2 = int(self._cal_AC2 * B6) >> 11
|
||||
X3 = X1 + X2
|
||||
B3 = (((self._cal_AC1 * 4 + X3) << self.mode) + 2) / 4
|
||||
if (self.debug):
|
||||
print("DBG: B6 = %d" % (B6))
|
||||
print("DBG: X1 = %d" % (X1))
|
||||
print("DBG: X2 = %d" % (X2))
|
||||
print("DBG: X3 = %d" % (X3))
|
||||
print("DBG: B3 = %d" % (B3))
|
||||
|
||||
X1 = int(self._cal_AC3 * B6) >> 13
|
||||
X2 = (int(self._cal_B1) * (int(B6 * B6) >> 12)) >> 16
|
||||
X3 = ((X1 + X2) + 2) >> 2
|
||||
B4 = (self._cal_AC4 * (X3 + 32768)) >> 15
|
||||
B7 = (UP - B3) * (50000 >> self.mode)
|
||||
if (self.debug):
|
||||
print("DBG: X1 = %d" % (X1))
|
||||
print("DBG: X2 = %d" % (X2))
|
||||
print("DBG: X3 = %d" % (X3))
|
||||
print("DBG: B4 = %d" % (B4))
|
||||
print("DBG: B7 = %d" % (B7))
|
||||
|
||||
if (B7 < 0x80000000):
|
||||
p = (B7 * 2) / B4
|
||||
else:
|
||||
p = (B7 / B4) * 2
|
||||
|
||||
if (self.debug):
|
||||
print("DBG: X1 = %d" % (X1))
|
||||
|
||||
X1 = (int(p) >> 8) * (int(p) >> 8)
|
||||
X1 = (X1 * 3038) >> 16
|
||||
X2 = (-7357 * int(p)) >> 16
|
||||
if (self.debug):
|
||||
print("DBG: p = %d" % (p))
|
||||
print("DBG: X1 = %d" % (X1))
|
||||
print("DBG: X2 = %d" % (X2))
|
||||
|
||||
p = p + ((X1 + X2 + 3791) >> 4)
|
||||
if (self.debug):
|
||||
print("DBG: Pressure = %d Pa" % (p))
|
||||
|
||||
return p
|
||||
|
||||
def readAltitude(self, seaLevelPressure=101325):
|
||||
"Calculates the altitude in meters"
|
||||
altitude = 0.0
|
||||
pressure = float(self.readPressure())
|
||||
temperature = float(self.readTemperature())
|
||||
# altitude = 44330.0 * (1.0 - pow(pressure / seaLevelPressure, 0.1903))
|
||||
altitude = round( -math.log( pressure / seaLevelPressure ) * 8314 * ( temperature + 273.15 ) / ( 25 * 9.81 ) , 2 )
|
||||
# this isn't completely correct. The formula uses the temperature of the sensor while it should be using the temperature
|
||||
# at sea level. At lower altitudes and close (less then 200 km) from the shore, the difference is neglectable. If you want
|
||||
# to use the script at higher locations or deeper inland, comment this line and uncomment the line above.
|
||||
if (self.debug):
|
||||
print("DBG: Altitude = %.2f m" % (altitude))
|
||||
return altitude
|
||||
|
||||
return 0
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import smbus
|
||||
import RPi.GPIO as GPIO
|
||||
#import grovepi
|
||||
from grove_i2c_barometic_sensor_BMP180 import BMP085
|
||||
|
||||
# ===========================================================================
|
||||
# Example Code
|
||||
# ===========================================================================
|
||||
|
||||
# Initialise the BMP085 and use STANDARD mode (default value)
|
||||
# bmp = BMP085(0x77, debug=True)
|
||||
bmp = BMP085(0x77, 1)
|
||||
|
||||
# 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
|
||||
|
||||
rev = GPIO.RPI_REVISION
|
||||
if rev == 2 or rev == 3:
|
||||
bus = smbus.SMBus(1)
|
||||
else:
|
||||
bus = smbus.SMBus(0)
|
||||
|
||||
temp = bmp.readTemperature()
|
||||
|
||||
# Read the current barometric pressure level
|
||||
pressure = bmp.readPressure()
|
||||
|
||||
# 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.readAltitude()
|
||||
|
||||
# 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(101560)
|
||||
|
||||
print("Temperature: %.2f C" % temp)
|
||||
print("Pressure: %.2f hPa" % (pressure / 100.0))
|
||||
print("Altitude: %.2f m" % altitude)
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
These python scripts work on both major versions of it (2.x and 3.x).
|
||||
|
||||
These scripts are used for getting readings from the [Grove - Barometer Sensor(BMP180)](http://www.seeedstudio.com/depot/Grove-Barometer-SensorBMP180-p-1840.html) which has to be connected to the GrovePi's I2C port.
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Kalman filter Library for using the Grove - Barometer (High-Accuracy)(http://www.seeedstudio.com/depot/Grove-Barometer-HighAccuracy-p-1865.html
|
||||
#
|
||||
# The GrovePi connects the Raspberry Pi and Grove sensors. You can learn more about GrovePi here: http://www.dexterindustries.com/GrovePi
|
||||
#
|
||||
# Have a question about this library? Ask on the forums here: http://forum.dexterindustries.com/c/grovepi
|
||||
#
|
||||
# This library is derived from the Arduino library written by Oliver Wang for SeeedStudio (https://github.com/Seeed-Studio/Grove_Barometer_HP20x/tree/master/HP20x_dev)
|
||||
|
||||
from random import randint
|
||||
Rand_Table=[
|
||||
0.5377,1.8339,-2.2588,0.8622,0.3188,-1.3077,-0.4336,0.342,3.5784,
|
||||
2.7694,-1.3499,3.0349,0.7254,-0.0631,0.7147,-0.2050,-0.1241,1.4897,
|
||||
1.4090,1.4172,0.6715,-1.2075,0.7172,1.6302,0.4889,1.0347,0.7269,
|
||||
-0.3034,0.2939,-0.7873,0.8884,-1.1471,-1.0689,-0.8095,-2.9443,1.4384,
|
||||
0.3252,-0.7549,1.3703,-1.7115,-0.1022,-0.2414,0.3192,0.3129,-0.8649,
|
||||
-0.0301,-0.1649,0.6277,1.0933,1.1093,-0.8637,0.0774,-1.2141,-1.1135,
|
||||
-0.0068,1.5326,-0.7697,0.3714,-0.2256,1.1174,-1.0891,0.0326,0.5525,
|
||||
1.1006,1.5442,0.0859,-1.4916,-0.7423,-1.0616,2.3505,-0.6156,0.7481,
|
||||
-0.1924,0.8886,-0.7648,-1.4023,-1.4224,0.4882,-0.1774,-0.1961,1.4193,
|
||||
0.2916,0.1978,1.5877,-0.8045,0.6966,0.8351,-0.2437,0.2157,-1.1658,
|
||||
-1.1480,0.1049,0.7223,2.5855,-0.6669,0.1873,-0.0825,-1.9330,-0.439,
|
||||
-1.7947]
|
||||
class KalmanFilter:
|
||||
X_pre=0
|
||||
X_post=0
|
||||
P_pre=0
|
||||
P_post=0
|
||||
K_cur=0
|
||||
|
||||
def __init__(self):
|
||||
self.X_pre=0
|
||||
|
||||
def Gaussian_Noise_Cov(self):
|
||||
index = 0
|
||||
tmp=[0.0]*10
|
||||
average = 0.0
|
||||
sum = 0.0
|
||||
|
||||
#Get random number */
|
||||
for i in range(10):
|
||||
|
||||
index = randint(0,90)
|
||||
tmp[i] = Rand_Table[index]
|
||||
sum += tmp[i];
|
||||
|
||||
# Calculate average
|
||||
average = sum/10
|
||||
|
||||
#Calculate Variance
|
||||
Variance = 0.0
|
||||
for j in range(10):
|
||||
Variance += (tmp[j]-average)*(tmp[j]-average)
|
||||
Variance/=10.0
|
||||
return Variance
|
||||
|
||||
def Filter(self,origin):
|
||||
modelNoise = 0.0
|
||||
observeNoise = 0.0
|
||||
|
||||
# Get model and observe Noise
|
||||
modelNoise = self.Gaussian_Noise_Cov()
|
||||
observeNoise = self.Gaussian_Noise_Cov()
|
||||
|
||||
# Algorithm
|
||||
self.X_pre = self.X_post
|
||||
self.P_pre = self.P_post + modelNoise;
|
||||
self.K_cur = self.P_pre/(self.P_pre + observeNoise);
|
||||
self.P_post = (1 - self.K_cur)*self.P_pre;
|
||||
self.X_post = self.X_pre + self.K_cur*(origin - self.X_pre);
|
||||
|
||||
return self.X_post
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# GrovePi Example for using the Grove - Barometer (High-Accuracy)(http://www.seeedstudio.com/depot/Grove-Barometer-HighAccuracy-p-1865.html
|
||||
#
|
||||
# The GrovePi connects the Raspberry Pi and Grove sensors. You can learn more about GrovePi here: http://www.dexterindustries.com/GrovePi
|
||||
#
|
||||
# Have a question about this library? Ask on the forums here: http://forum.dexterindustries.com/c/grovepi
|
||||
#
|
||||
# This library is derived from the Arduino library written by Oliver Wang for SeeedStudio (https://github.com/Seeed-Studio/Grove_Barometer_HP20x/tree/master/HP20x_dev)
|
||||
'''
|
||||
## License
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
GrovePi for the Raspberry Pi: an open source platform for connecting Grove Sensors to the Raspberry Pi.
|
||||
Copyright (C) 2017 Dexter Industries
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
'''
|
||||
import hp206c
|
||||
h= hp206c.hp206c()
|
||||
|
||||
ret=h.isAvailable()
|
||||
if h.OK_HP20X_DEV == ret:
|
||||
print("HP20x_dev is available.")
|
||||
else:
|
||||
print("HP20x_dev isn't available.")
|
||||
|
||||
temp=h.ReadTemperature()
|
||||
pressure=h.ReadPressure()
|
||||
altitude=h.ReadAltitude()
|
||||
print("Temperature\t: %.2f C\nPressure\t: %.2f hPa\nAltitude\t: %.2f m" %(temp,pressure,altitude))
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# GrovePi Library for using the Grove - Barometer (High-Accuracy)(http://www.seeedstudio.com/depot/Grove-Barometer-HighAccuracy-p-1865.html
|
||||
#
|
||||
# The GrovePi connects the Raspberry Pi and Grove sensors. You can learn more about GrovePi here: http://www.dexterindustries.com/GrovePi
|
||||
#
|
||||
# Have a question about this library? Ask on the forums here: http://forum.dexterindustries.com/c/grovepi
|
||||
#
|
||||
# This library is derived from the Arduino library written by Oliver Wang for SeeedStudio (https://github.com/Seeed-Studio/Grove_Barometer_HP20x/tree/master/HP20x_dev)
|
||||
|
||||
# Released under the MIT license (http://choosealicense.com/licenses/mit/).
|
||||
# For more information see https://github.com/DexterInd/GrovePi/blob/master/LICENSE
|
||||
|
||||
import time,sys
|
||||
import RPi.GPIO as GPIO
|
||||
import smbus
|
||||
|
||||
# use the bus that matches your raspi version
|
||||
rev = GPIO.RPI_REVISION
|
||||
if rev == 2 or rev == 3:
|
||||
bus = smbus.SMBus(1)
|
||||
else:
|
||||
bus = smbus.SMBus(0)
|
||||
|
||||
class hp206c:
|
||||
address = None
|
||||
|
||||
HP20X_I2C_DEV_ID =(0xEC)>>1 #CSB PIN is VDD level(address is 0x76)
|
||||
HP20X_I2C_DEV_ID2 =(0XEE)>>1 #CSB PIN is GND level(address is 0x77)
|
||||
HP20X_SOFT_RST =0x06
|
||||
HP20X_WR_CONVERT_CMD =0x40
|
||||
HP20X_CONVERT_OSR4096 =0<<2
|
||||
HP20X_CONVERT_OSR2048 =1<<2
|
||||
HP20X_CONVERT_OSR1024 =2<<2
|
||||
HP20X_CONVERT_OSR512 =3<<2
|
||||
HP20X_CONVERT_OSR256 =4<<2
|
||||
HP20X_CONVERT_OSR128 =5<<2
|
||||
|
||||
HP20X_READ_P =0x30 #read_p command
|
||||
HP20X_READ_A =0x31 #read_a command
|
||||
HP20X_READ_T =0x32 #read_t command
|
||||
HP20X_READ_PT =0x10 #read_pt command
|
||||
HP20X_READ_AT =0x11 #read_at command
|
||||
HP20X_READ_CAL =0X28 #RE-CAL ANALOG
|
||||
|
||||
HP20X_WR_REG_MODE =0xC0
|
||||
HP20X_RD_REG_MODE =0x80
|
||||
|
||||
ERR_WR_DEVID_NACK =0x01
|
||||
ERR_RD_DEVID_NACK =0x02
|
||||
ERR_WR_REGADD_NACK =0x04
|
||||
ERR_WR_REGCMD_NACK =0x08
|
||||
ERR_WR_DATA_NACK =0x10
|
||||
ERR_RD_DATA_MISMATCH =0x20
|
||||
|
||||
I2C_DID_WR_MASK =0xFE
|
||||
I2C_DID_RD_MASK =0x01
|
||||
|
||||
T_WIN_EN =0X01
|
||||
PA_WIN_EN =0X02
|
||||
T_TRAV_EN =0X04
|
||||
PA_TRAV_EN =0X08
|
||||
PA_RDY_EN =0X20
|
||||
T_RDY_EN =0X10
|
||||
|
||||
T_WIN_CFG =0X01
|
||||
PA_WIN_CFG =0X02
|
||||
PA_MODE_P =0X00
|
||||
PA_MODE_A =0X40
|
||||
|
||||
T_TRAV_CFG =0X04
|
||||
|
||||
OK_HP20X_DEV =0X80 #HP20x_dev successfully initialized
|
||||
REG_PARA =0X0F #Status register
|
||||
|
||||
OSR_CFG = HP20X_CONVERT_OSR1024
|
||||
OSR_ConvertTime = 25
|
||||
|
||||
def __init__(self,address=0x76):
|
||||
self.address=address
|
||||
self.HP20X_IIC_WriteCmd(self.HP20X_SOFT_RST)
|
||||
time.sleep(.1)
|
||||
|
||||
def isAvailable(self):
|
||||
return self.HP20X_IIC_ReadReg(self.REG_PARA)
|
||||
|
||||
def ReadTemperature(self):
|
||||
self.HP20X_IIC_WriteCmd(self.HP20X_WR_CONVERT_CMD|self.OSR_CFG)
|
||||
time.sleep(self.OSR_ConvertTime/1000.0)
|
||||
t_raw = bus.read_i2c_block_data(self.address, self.HP20X_READ_T, 3)
|
||||
t=t_raw[0]<<16|t_raw[1]<<8|t_raw[2]
|
||||
if t&0x800000:
|
||||
t|=0xff000000;
|
||||
us = (1<<32)
|
||||
t = -1 * (us - t)
|
||||
return t/100.0
|
||||
|
||||
def ReadPressure(self):
|
||||
self.HP20X_IIC_WriteCmd(self.HP20X_WR_CONVERT_CMD|self.OSR_CFG)
|
||||
time.sleep(self.OSR_ConvertTime/1000.0)
|
||||
p_raw = bus.read_i2c_block_data(self.address, self.HP20X_READ_P, 3)
|
||||
p=p_raw[0]<<16|p_raw[1]<<8|p_raw[2]
|
||||
if p&0x800000:
|
||||
p|=0xff000000;
|
||||
return p/100.0
|
||||
|
||||
def ReadAltitude(self):
|
||||
self.HP20X_IIC_WriteCmd(self.HP20X_WR_CONVERT_CMD|self.OSR_CFG)
|
||||
time.sleep(self.OSR_ConvertTime/1000.0)
|
||||
a_raw = bus.read_i2c_block_data(self.address, self.HP20X_READ_A, 3)
|
||||
a=a_raw[0]<<16|a_raw[1]<<8|a_raw[2]
|
||||
if a&0x800000:
|
||||
a|=0xff000000;
|
||||
us = (1<<32)
|
||||
a = -1 * (us - a)
|
||||
return a/100.0
|
||||
|
||||
def HP20X_IIC_WriteCmd(self,uCmd):
|
||||
bus.write_byte(self.address, uCmd)
|
||||
|
||||
def HP20X_IIC_ReadReg(self, bReg):
|
||||
# self.HP20X_IIC_WriteCmd(bReg|self.HP20X_RD_REG_MODE)
|
||||
return bus.read_byte_data(self.address, bReg|self.HP20X_RD_REG_MODE)
|
||||
|
||||
if __name__ == "__main__":
|
||||
h= hp206c()
|
||||
ret=h.isAvailable()
|
||||
if h.OK_HP20X_DEV == ret:
|
||||
print("HP20x_dev is available.")
|
||||
else:
|
||||
print("HP20x_dev isn't available.")
|
||||
|
||||
temp=h.ReadTemperature()
|
||||
pressure=h.ReadPressure()
|
||||
altitude=h.ReadAltitude()
|
||||
print(temp,pressure,altitude)
|
||||
Loading…
Add table
Add a link
Reference in a new issue