Skip to content

Commit ec4ecf3

Browse files
committed
add grove_i2c_hp206f_driver.py
1 parent 2f1da6d commit ec4ecf3

File tree

1 file changed

+241
-0
lines changed

1 file changed

+241
-0
lines changed

grove/grove_i2c_hp206f_driver.py

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
#!/usr/bin/env python
2+
#
3+
# Library for interacting with Grove - HP20x sensor (used to measure temperature, pressure and altitude)
4+
#
5+
# This is the library for Grove Base Hat which used to connect grove sensors for raspberry pi.
6+
#
7+
8+
'''
9+
## License
10+
11+
The MIT License (MIT)
12+
13+
Grove Base Hat for the Raspberry Pi, used to connect grove sensors.
14+
Copyright (C) [Your Company Name or Relevant Party]
15+
16+
Permission is hereby granted, free of charge, to any person obtaining a copy
17+
of this software and associated documentation files (the "Software"), to deal
18+
in the Software without restriction, including without limitation the rights
19+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
20+
copies of the Software, and to permit persons to whom the Software is
21+
furnished to do so, subject to the following conditions:
22+
23+
The above copyright notice and this permission notice shall be included in
24+
all copies or substantial portions of the Software.
25+
26+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
32+
THE SOFTWARE.
33+
'''
34+
35+
from grove.i2c import Bus
36+
import time
37+
38+
# Class for interacting with the HP20x sensor
39+
class HP20x:
40+
def __init__(self):
41+
# Initialize the I2C bus on Raspberry Pi (bus 1)
42+
self.bus = Bus()
43+
# I2C address of the HP206F sensor, may need adjustment based on actual situation
44+
self.address = 0x76
45+
46+
# I2C device ID when CSB PIN is at VDD level (address is 0x76)
47+
self.HP20X_I2C_DEV_ID = (0xEC) >> 1
48+
# I2C device ID when CSB PIN is at GND level (address is 0x77)
49+
self.HP20X_I2C_DEV_ID2 = (0XEE) >> 1
50+
# Soft reset command for the HP20x sensor
51+
self.HP20X_SOFT_RST = 0x06
52+
# Write conversion command for the HP20x sensor
53+
self.HP20X_WR_CONVERT_CMD = 0x40
54+
# Different oversampling rate (OSR) configurations for conversion
55+
self.HP20X_CONVERT_OSR4096 = 0 << 2
56+
self.HP20X_CONVERT_OSR2048 = 1 << 2
57+
self.HP20X_CONVERT_OSR1024 = 2 << 2
58+
self.HP20X_CONVERT_OSR512 = 3 << 2
59+
self.HP20X_CONVERT_OSR256 = 4 << 2
60+
self.HP20X_CONVERT_OSR128 = 5 << 2
61+
62+
# Commands for reading pressure, altitude, temperature, etc.
63+
self.HP20X_READ_P = 0x30 # Read pressure command
64+
self.HP20X_READ_A = 0x31 # Read altitude command
65+
self.HP20X_READ_T = 0x32 # Read temperature command
66+
self.HP20X_READ_PT = 0x10 # Read pressure and temperature command
67+
self.HP20X_READ_AT = 0x11 # Read altitude and temperature command
68+
self.HP20X_READ_CAL = 0X28 # RE-CAL ANALOG command
69+
70+
# Write register mode for the HP20x sensor
71+
self.HP20X_WR_REG_MODE = 0xC0
72+
# Read register mode for the HP20x sensor
73+
self.HP20X_RD_REG_MODE = 0x80
74+
75+
# Set the oversampling rate configuration
76+
self.OSR_CFG = self.HP20X_CONVERT_OSR1024
77+
# Conversion time corresponding to the oversampling rate (in milliseconds)
78+
self.OSR_ConvertTime = 25
79+
80+
def begin(self):
81+
# Send a soft reset command to the HP20x sensor
82+
self.HP20X_IIC_WriteCmd(self.HP20X_SOFT_RST)
83+
# Wait for 0.1 seconds to ensure the reset operation is completed
84+
time.sleep(0.1)
85+
86+
def isAvailable(self):
87+
# Check if the HP20x sensor is available by reading the register at address 0x0F
88+
return self.HP20X_IIC_ReadReg(0x0F)
89+
90+
def ReadTemperature(self):
91+
# Send a conversion command with the specified oversampling rate configuration
92+
self.HP20X_IIC_WriteCmd(self.HP20X_WR_CONVERT_CMD | self.OSR_CFG)
93+
# Wait for the conversion time (converted to seconds)
94+
time.sleep(self.OSR_ConvertTime / 1000.0)
95+
# Read 3 bytes of raw temperature data from the sensor
96+
t_raw = self.bus.read_i2c_block_data(self.address, self.HP20X_READ_T, 3)
97+
# Combine the 3 bytes of data to form a single value
98+
t = t_raw[0] << 16 | t_raw[1] << 8 | t_raw[2]
99+
# Handle negative values using 2's complement
100+
if t & 0x800000:
101+
t |= 0xff000000
102+
us = (1 << 32)
103+
t = -1 * (us - t)
104+
# Return the temperature value in degrees Celsius (divided by 100)
105+
return t / 100.0
106+
107+
def ReadPressure(self):
108+
# Send a conversion command with the specified oversampling rate configuration
109+
self.HP20X_IIC_WriteCmd(self.HP20X_WR_CONVERT_CMD | self.OSR_CFG)
110+
# Wait for the conversion time (converted to seconds)
111+
time.sleep(self.OSR_ConvertTime / 1000.0)
112+
# Read 3 bytes of raw pressure data from the sensor
113+
p_raw = self.bus.read_i2c_block_data(self.address, self.HP20X_READ_P, 3)
114+
# Combine the 3 bytes of data to form a single value
115+
p = p_raw[0] << 16 | p_raw[1] << 8 | p_raw[2]
116+
# Handle negative values using 2's complement
117+
if p & 0x800000:
118+
p |= 0xff000000
119+
# Return the pressure value in hectopascals (divided by 100)
120+
return p / 100.0
121+
122+
def ReadAltitude(self):
123+
# Send a conversion command with the specified oversampling rate configuration
124+
self.HP20X_IIC_WriteCmd(self.HP20X_WR_CONVERT_CMD | self.OSR_CFG)
125+
# Wait for the conversion time (converted to seconds)
126+
time.sleep(self.OSR_ConvertTime / 1000.0)
127+
# Read 3 bytes of raw altitude data from the sensor
128+
a_raw = self.bus.read_i2c_block_data(self.address, self.HP20X_READ_A, 3)
129+
# Combine the 3 bytes of data to form a single value
130+
a = a_raw[0] << 16 | a_raw[1] << 8 | a_raw[2]
131+
# Handle negative values using 2's complement
132+
if a & 0x800000:
133+
a |= 0xff000000
134+
us = (1 << 32)
135+
a = -1 * (us - a)
136+
# Return the altitude value in meters (divided by 100)
137+
return a / 100.0
138+
139+
def HP20X_IIC_WriteCmd(self, uCmd):
140+
# Write a command byte to the specified I2C address
141+
self.bus.write_byte_data(0,self.address,uCmd)
142+
143+
def HP20X_IIC_ReadReg(self, bReg):
144+
# Read a byte from the specified register address
145+
return self.bus.read_byte_data(self.address, bReg | self.HP20X_RD_REG_MODE)
146+
147+
# Class representing the Kalman filter
148+
class KalmanFilter:
149+
def __init__(self):
150+
# Process noise covariance
151+
self.q = 0.01
152+
# Measurement noise covariance
153+
self.r = 0.1
154+
# Initial estimated value
155+
self.x = 0
156+
# Initial estimated error covariance
157+
self.p = 1
158+
# Initial Kalman gain
159+
self.k = 0
160+
161+
def Filter(self, measurement):
162+
# Prediction step: Update the estimated error covariance
163+
self.p = self.p + self.q
164+
# Update step: Calculate the Kalman gain
165+
self.k = self.p / (self.p + self.r)
166+
# Update step: Update the estimated value based on the measurement
167+
self.x = self.x + self.k * (measurement - self.x)
168+
# Update step: Update the estimated error covariance
169+
self.p = (1 - self.k) * self.p
170+
# Return the filtered estimated value
171+
return self.x
172+
173+
174+
# Kalman filter for temperature data
175+
t_filter = KalmanFilter()
176+
# Kalman filter for pressure data
177+
p_filter = KalmanFilter()
178+
# Kalman filter for altitude data
179+
a_filter = KalmanFilter()
180+
181+
# Create an instance of the HP20x sensor
182+
hp20x = HP20x()
183+
184+
185+
# Function to simulate the setup process
186+
def setup():
187+
print("****HP20x_dev demo by seeed studio****\n")
188+
print("Calculation formula: H = [8.5(101325-P)]/100 \n")
189+
# Wait for 0.15 seconds after power-on to stabilize the voltage
190+
time.sleep(0.15)
191+
# Initialize the HP20x sensor
192+
hp20x.begin()
193+
# Wait for 0.1 seconds
194+
time.sleep(0.1)
195+
# Check if the HP20x sensor is available
196+
ret = hp20x.isAvailable()
197+
if ret:
198+
print("HP20x_dev is available.\n")
199+
else:
200+
print("HP20x_dev isn't available.\n")
201+
return ret
202+
203+
204+
# Function to simulate the loop process
205+
def loop(ret):
206+
if ret:
207+
while True:
208+
print("------------------\n")
209+
# Read the temperature value from the HP20x sensor
210+
temper = hp20x.ReadTemperature()
211+
print("Temper:")
212+
print(f"{temper}C.\n")
213+
print("Filter:")
214+
# Apply the Kalman filter to the temperature value
215+
print(f"{t_filter.Filter(temper)}C.\n")
216+
217+
# Read the pressure value from the HP20x sensor
218+
pressure = hp20x.ReadPressure()
219+
print("Pressure:")
220+
print(f"{pressure}hPa.\n")
221+
print("Filter:")
222+
# Apply the Kalman filter to the pressure value
223+
print(f"{p_filter.Filter(pressure)}hPa\n")
224+
225+
# Read the altitude value from the HP20x sensor
226+
altitude = hp20x.ReadAltitude()
227+
print("Altitude:")
228+
print(f"{altitude}m.\n")
229+
print("Filter:")
230+
# Apply the Kalman filter to the altitude value
231+
print(f"{a_filter.Filter(altitude)}m.\n")
232+
print("------------------\n")
233+
# Wait for 1 second before the next reading
234+
time.sleep(1)
235+
236+
237+
if __name__ == "__main__":
238+
# Perform the setup process
239+
ret = setup()
240+
# Start the loop process if the sensor is available
241+
loop(ret)

0 commit comments

Comments
 (0)