Skip to content

Commit b338e18

Browse files
AsCressbessman
authored andcommitted
fix: fixed BMP180
1 parent 4e53d8f commit b338e18

File tree

2 files changed

+186
-109
lines changed

2 files changed

+186
-109
lines changed

pslab/external/BMP180.py

Lines changed: 0 additions & 109 deletions
This file was deleted.

pslab/external/bmp180.py

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
"""BMP180 Altimeter."""
2+
3+
import time
4+
import logging
5+
import struct
6+
from pslab.bus import I2CSlave
7+
8+
# BMP180 default address
9+
_ADDRESS = 0x77
10+
11+
# Operating Modes
12+
_ULTRALOWPOWER = 0
13+
_STANDARD = 1
14+
_HIGHRES = 2
15+
_ULTRAHIGHRES = 3
16+
17+
# BMP180 Registers
18+
_CAL_AC1 = 0xAA # R Calibration data (16 bits)
19+
_CAL_AC2 = 0xAC # R Calibration data (16 bits)
20+
_CAL_AC3 = 0xAE # R Calibration data (16 bits)
21+
_CAL_AC4 = 0xB0 # R Calibration data (16 bits)
22+
_CAL_AC5 = 0xB2 # R Calibration data (16 bits)
23+
_CAL_AC6 = 0xB4 # R Calibration data (16 bits)
24+
_CAL_B1 = 0xB6 # R Calibration data (16 bits)
25+
_CAL_B2 = 0xB8 # R Calibration data (16 bits)
26+
_CAL_MB = 0xBA # R Calibration data (16 bits)
27+
_CAL_MC = 0xBC # R Calibration data (16 bits)
28+
_CAL_MD = 0xBE # R Calibration data (16 bits)
29+
_CONTROL = 0xF4
30+
_TEMPDATA = 0xF6
31+
_PRESSUREDATA = 0xF6
32+
33+
# Commands
34+
_READTEMPCMD = 0x2E
35+
_READPRESSURECMD = 0x34
36+
37+
_logger = logging.getLogger(__name__)
38+
39+
40+
class BMP180(I2CSlave):
41+
"""Class to interface with the BMP180 Altimeter.
42+
43+
Parameters
44+
----------
45+
mode : int, optional
46+
The mode of operation for the sensor, determining the oversampling setting.
47+
The default mode is `_HIGHRES`. This parameter affects the precision and speed
48+
of the temperature and pressure measurements.
49+
50+
**kwargs : dict, optional
51+
Additional keyword arguments, such as:
52+
- address (int): The I2C address of the BMP180 sensor. Default is `_ADDRESS`.
53+
54+
Attributes
55+
----------
56+
temperature : float
57+
The measured temperature in degrees Celsius.
58+
59+
pressure : float
60+
The measured pressure in Pa (Pascals).
61+
62+
altitude : float
63+
The calculated altitude in meters based on the current pressure reading
64+
and a reference sea level pressure.
65+
"""
66+
67+
NUMPLOTS = 3
68+
PLOTNAMES = ["Temperature", "Pressure", "Altitude"]
69+
name = "BMP180 Altimeter"
70+
71+
def __init__(self, mode=_HIGHRES, **kwargs):
72+
self._ADDRESS = kwargs.get("address", _ADDRESS)
73+
super().__init__(self._ADDRESS)
74+
self._mode = mode
75+
76+
# Load calibration values
77+
self._ac1 = self._read_int16(_CAL_AC1)
78+
self._ac2 = self._read_int16(_CAL_AC2)
79+
self._ac3 = self._read_int16(_CAL_AC3)
80+
self._ac4 = self._read_uint16(_CAL_AC4)
81+
self._ac5 = self._read_uint16(_CAL_AC5)
82+
self._ac6 = self._read_uint16(_CAL_AC6)
83+
self._b1 = self._read_int16(_CAL_B1)
84+
self._b2 = self._read_int16(_CAL_B2)
85+
self._mb = self._read_int16(_CAL_MB)
86+
self._mc = self._read_int16(_CAL_MC)
87+
self._md = self._read_int16(_CAL_MD)
88+
89+
_logger.debug(f"ac1: {self._ac1}")
90+
_logger.debug(f"ac2: {self._ac2}")
91+
_logger.debug(f"ac3: {self._ac3}")
92+
_logger.debug(f"ac4: {self._ac4}")
93+
_logger.debug(f"ac5: {self._ac5}")
94+
_logger.debug(f"ac6: {self._ac6}")
95+
_logger.debug(f"b1: {self._b1}")
96+
_logger.debug(f"b2: {self._b2}")
97+
_logger.debug(f"mb: {self._mb}")
98+
_logger.debug(f"mc: {self._mc}")
99+
_logger.debug(f"md: {self._md}")
100+
101+
def _read_int16(self, addr):
102+
BE_INT16 = struct.Struct(">h") # signed short, big endian
103+
return BE_INT16.unpack(self.read(2, addr))[0]
104+
105+
def _read_uint16(self, addr):
106+
BE_UINT16 = struct.Struct(">H") # unsigned short, big endian
107+
return BE_UINT16.unpack(self.read(2, addr))[0]
108+
109+
def _read_raw_temperature(self):
110+
"""Read the raw temperature from the sensor."""
111+
self.write([_READTEMPCMD], _CONTROL)
112+
time.sleep(0.005)
113+
raw = self._read_uint16(_TEMPDATA)
114+
return raw
115+
116+
@property
117+
def temperature(self):
118+
"""Get the actual temperature in degrees celsius."""
119+
ut = self._read_raw_temperature()
120+
# Calculations from section 3.5 of the datasheet
121+
x1 = ((ut - self._ac6) * self._ac5) >> 15
122+
x2 = (self._mc << 11) // (x1 + self._md)
123+
b5 = x1 + x2
124+
temp = ((b5 + 8) >> 4) / 10.0
125+
return temp
126+
127+
@property
128+
def oversampling(self):
129+
"""oversampling : int
130+
The oversampling setting used by the sensor. This attribute is settable and
131+
determines the trade-off between measurement accuracy and speed. Possible values
132+
include `_ULTRALOWPOWER`, `_STANDARD`, `_HIGHRES`, and `_ULTRAHIGHRES`.
133+
"""
134+
return self._mode
135+
136+
@oversampling.setter
137+
def oversampling(self, value):
138+
self._mode = value
139+
140+
def _read_raw_pressure(self):
141+
"""Read the raw pressure level from the sensor."""
142+
delays = [0.005, 0.008, 0.014, 0.026]
143+
self.write([_READPRESSURECMD + (self._mode << 6)], _CONTROL)
144+
time.sleep(delays[self._mode])
145+
msb = self.read_byte(_PRESSUREDATA) & 0xFF
146+
lsb = self.read_byte(_PRESSUREDATA + 1) & 0xFF
147+
xlsb = self.read_byte(_PRESSUREDATA + 2) & 0xFF
148+
raw = ((msb << 16) + (lsb << 8) + xlsb) >> (8 - self._mode)
149+
return raw
150+
151+
@property
152+
def pressure(self):
153+
"""Get the actual pressure in Pascals."""
154+
ut = self._read_raw_temperature()
155+
up = self._read_raw_pressure()
156+
# Calculations from section 3.5 of the datasheet
157+
x1 = ((ut - self._ac6) * self._ac5) >> 15
158+
x2 = (self._mc << 11) // (x1 + self._md)
159+
b5 = x1 + x2
160+
# Pressure Calculations
161+
b6 = b5 - 4000
162+
x1 = (self._b2 * (b6 * b6) >> 12) >> 11
163+
x2 = (self._ac2 * b6) >> 11
164+
x3 = x1 + x2
165+
b3 = (((self._ac1 * 4 + x3) << self._mode) + 2) // 4
166+
x1 = (self._ac3 * b6) >> 13
167+
x2 = (self._b1 * ((b6 * b6) >> 12)) >> 16
168+
x3 = ((x1 + x2) + 2) >> 2
169+
b4 = (self._ac4 * (x3 + 32768)) >> 15
170+
b7 = (up - b3) * (50000 >> self._mode)
171+
if b7 < 0x80000000:
172+
p = (b7 * 2) // b4
173+
else:
174+
p = (b7 // b4) * 2
175+
x1 = (p >> 8) * (p >> 8)
176+
x1 = (x1 * 3038) >> 16
177+
x2 = (-7357 * p) >> 16
178+
pres = p + ((x1 + x2 + 3791) >> 4)
179+
return pres
180+
181+
@property
182+
def altitude(self):
183+
# Calculation from section 3.6 of datasheet
184+
pressure = float(self.pressure)
185+
alt = 44330.0 * (1.0 - pow(pressure / 101325.0, (1.0 / 5.255)))
186+
return alt

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy