aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
author林玮 (Jade Lin) <linw1995@icloud.com>2024-04-25 09:45:05 +0800
committerGitHub <noreply@github.com>2024-04-24 21:45:05 -0400
commitc3ec4af6cc3a62353e1eed57e0514356eeef1fb6 (patch)
tree634cbb7789edf3940526a0b12cc6448ce30314cb
parent2f6e94c94cae036b70b02df996dc12e2e61e5dcb (diff)
downloadkutter-c3ec4af6cc3a62353e1eed57e0514356eeef1fb6.tar.gz
kutter-c3ec4af6cc3a62353e1eed57e0514356eeef1fb6.tar.xz
kutter-c3ec4af6cc3a62353e1eed57e0514356eeef1fb6.zip
bme280: Add BMP388 sensor support to BMxx80 (#6576)
Extends the BMxx80 category with support for the BMP388 sensor, providing temperature and pressure output similar to the existing BMxx80 class of sensors. Signed-off-by: 林玮 (Jade Lin) <linw1995@icloud.com>
-rw-r--r--docs/Config_Reference.md8
-rw-r--r--klippy/extras/bme280.py153
2 files changed, 155 insertions, 6 deletions
diff --git a/docs/Config_Reference.md b/docs/Config_Reference.md
index 71cdfed8..b6614055 100644
--- a/docs/Config_Reference.md
+++ b/docs/Config_Reference.md
@@ -2490,9 +2490,9 @@ sensor_pin:
# name in the above list.
```
-### BMP180/BMP280/BME280/BME680 temperature sensor
+### BMP180/BMP280/BME280/BMP388/BME680 temperature sensor
-BMP180/BMP280/BME280/BME680 two wire interface (I2C) environmental sensors.
+BMP180/BMP280/BME280/BMP388/BME680 two wire interface (I2C) environmental sensors.
Note that these sensors are not intended for use with extruders and
heater beds, but rather for monitoring ambient temperature (C),
pressure (hPa), relative humidity and in case of the BME680 gas level.
@@ -2503,8 +2503,8 @@ temperature.
```
sensor_type: BME280
#i2c_address:
-# Default is 118 (0x76). The BMP180 and some BME280 sensors have an address of 119
-# (0x77).
+# Default is 118 (0x76). The BMP180, BMP388 and some BME280 sensors
+# have an address of 119 (0x77).
#i2c_mcu:
#i2c_bus:
#i2c_software_scl_pin:
diff --git a/klippy/extras/bme280.py b/klippy/extras/bme280.py
index 3bc3c471..262dc130 100644
--- a/klippy/extras/bme280.py
+++ b/klippy/extras/bme280.py
@@ -17,6 +17,29 @@ BME280_REGS = {
'HUM_MSB': 0xFD, 'HUM_LSB': 0xFE, 'CAL_1': 0x88, 'CAL_2': 0xE1
}
+BMP388_REGS = {
+ "CMD": 0x7E,
+ "STATUS": 0x03,
+ "PWR_CTRL": 0x1B,
+ "OSR": 0x1C,
+ "ORD": 0x1D,
+ "INT_CTRL": 0x19,
+ "CAL_1": 0x31,
+ "TEMP_MSB": 0x09,
+ "TEMP_LSB": 0x08,
+ "TEMP_XLSB": 0x07,
+ "PRESS_MSB": 0x06,
+ "PRESS_LSB": 0x05,
+ "PRESS_XLSB": 0x04,
+}
+BMP388_REG_VAL_PRESS_EN = 0x01
+BMP388_REG_VAL_TEMP_EN = 0x02
+BMP388_REG_VAL_PRESS_OS_NO = 0b000
+BMP388_REG_VAL_TEMP_OS_NO = 0b000000
+BMP388_REG_VAL_ODR_50_HZ = 0x02
+BMP388_REG_VAL_DRDY_EN = 0b100000
+BMP388_REG_VAL_NORMAL_MODE = 0x30
+
BME680_REGS = {
'RESET': 0xE0, 'CTRL_HUM': 0x72, 'CTRL_GAS_1': 0x71, 'CTRL_GAS_0': 0x70,
'GAS_WAIT_0': 0x64, 'RES_HEAT_0': 0x5A, 'IDAC_HEAT_0': 0x50,
@@ -68,9 +91,11 @@ MEASURE_DONE = 1 << 5
RESET_CHIP_VALUE = 0xB6
BME_CHIPS = {
- 0x58: 'BMP280', 0x60: 'BME280', 0x61: 'BME680', 0x55: 'BMP180'
+ 0x58: 'BMP280', 0x60: 'BME280', 0x61: 'BME680', 0x55: 'BMP180',
+ 0x50: 'BMP388'
}
BME_CHIP_ID_REG = 0xD0
+BMP3_CHIP_ID_REG = 0x00
def get_twos_complement(val, bit_size):
@@ -163,6 +188,29 @@ class BME280:
dig['P9'] = get_signed_short(calib_data_1[22:24])
return dig
+ def read_calibration_data_bmp388(calib_data_1):
+ dig = {}
+ dig["T1"] = get_unsigned_short(calib_data_1[0:2]) / 0.00390625
+ dig["T2"] = get_unsigned_short(calib_data_1[2:4]) / 1073741824.0
+ dig["T3"] = get_signed_byte(calib_data_1[4]) / 281474976710656.0
+
+ dig["P1"] = get_signed_short(calib_data_1[5:7]) - 16384
+ dig["P1"] /= 1048576.0
+ dig["P2"] = get_signed_short(calib_data_1[7:9]) - 16384
+ dig["P2"] /= 536870912.0
+ dig["P3"] = get_signed_byte(calib_data_1[9]) / 4294967296.0
+ dig["P4"] = get_signed_byte(calib_data_1[10]) / 137438953472.0
+ dig["P5"] = get_unsigned_short(calib_data_1[11:13]) / 0.125
+ dig["P6"] = get_unsigned_short(calib_data_1[13:15]) / 64.0
+ dig["P7"] = get_signed_byte(calib_data_1[15]) / 256.0
+ dig["P8"] = get_signed_byte(calib_data_1[16]) / 32768.0
+ dig["P9"] = get_signed_short(calib_data_1[17:19])
+ dig["P9"] /= 281474976710656.0
+ dig["P10"] = get_signed_byte(calib_data_1[19]) / 281474976710656.0
+ dig["P11"] = get_signed_byte(calib_data_1[20])
+ dig["P11"] /= 36893488147419103232.0
+ return dig
+
def read_calibration_data_bme280(calib_data_1, calib_data_2):
dig = read_calibration_data_bmp280(calib_data_1)
dig['H1'] = calib_data_1[25] & 0xFF
@@ -224,7 +272,7 @@ class BME280:
dig['MD'] = get_signed_short_msb(calib_data_1[20:22])
return dig
- chip_id = self.read_id()
+ chip_id = self.read_id() or self.read_bmp3_id()
if chip_id not in BME_CHIPS.keys():
logging.info("bme280: Unknown Chip ID received %#x" % chip_id)
else:
@@ -252,6 +300,24 @@ class BME280:
self.max_sample_time = (1.25 + ((2.3 * self.os_pres) + .575)) / 1000
self.sample_timer = self.reactor.register_timer(self._sample_bmp180)
self.chip_registers = BMP180_REGS
+ elif self.chip_type == 'BMP388':
+ self.max_sample_time = 0.5
+ self.chip_registers = BMP388_REGS
+ self.write_register(
+ "PWR_CTRL",
+ [
+ BMP388_REG_VAL_PRESS_EN
+ | BMP388_REG_VAL_TEMP_EN
+ | BMP388_REG_VAL_NORMAL_MODE
+ ],
+ )
+ self.write_register(
+ "OSR", [BMP388_REG_VAL_PRESS_OS_NO | BMP388_REG_VAL_TEMP_OS_NO]
+ )
+ self.write_register("ORD", [BMP388_REG_VAL_ODR_50_HZ])
+ self.write_register("INT_CTRL", [BMP388_REG_VAL_DRDY_EN])
+
+ self.sample_timer = self.reactor.register_timer(self._sample_bmp388)
else:
self.max_sample_time = \
(1.25 + (2.3 * self.os_temp) + ((2.3 * self.os_pres) + .575)
@@ -265,6 +331,8 @@ class BME280:
# Read out and calculate the trimming parameters
if self.chip_type == 'BMP180':
cal_1 = self.read_register('CAL_1', 22)
+ elif self.chip_type == 'BMP388':
+ cal_1 = self.read_register('CAL_1', 21)
else:
cal_1 = self.read_register('CAL_1', 26)
cal_2 = self.read_register('CAL_2', 16)
@@ -276,6 +344,8 @@ class BME280:
self.dig = read_calibration_data_bme680(cal_1, cal_2)
elif self.chip_type == 'BMP180':
self.dig = read_calibration_data_bmp180(cal_1)
+ elif self.chip_type == 'BMP388':
+ self.dig = read_calibration_data_bmp388(cal_1)
def _sample_bme280(self, eventtime):
# Enter forced mode
@@ -318,6 +388,79 @@ class BME280:
self._callback(self.mcu.estimated_print_time(measured_time), self.temp)
return measured_time + REPORT_TIME
+ def _sample_bmp388(self, eventtime):
+ status = self.read_register("STATUS", 1)
+ if status[0] & 0b100000:
+ self.temp = self._sample_bmp388_temp()
+ if self.temp < self.min_temp or self.temp > self.max_temp:
+ self.printer.invoke_shutdown(
+ "BME280 temperature %0.1f outside range of %0.1f:%.01f"
+ % (self.temp, self.min_temp, self.max_temp)
+ )
+
+ if status[0] & 0b010000:
+ self.pressure = self._sample_bmp388_press() / 100.0
+
+ measured_time = self.reactor.monotonic()
+ self._callback(self.mcu.estimated_print_time(measured_time), self.temp)
+ return measured_time + REPORT_TIME
+
+ def _sample_bmp388_temp(self):
+ xlsb = self.read_register("TEMP_XLSB", 1)
+ lsb = self.read_register("TEMP_LSB", 1)
+ msb = self.read_register("TEMP_MSB", 1)
+ adc_T = (msb[0] << 16) + (lsb[0] << 8) + (xlsb[0])
+
+ partial_data1 = adc_T - self.dig["T1"]
+ partial_data2 = self.dig["T2"] * partial_data1
+
+ self.t_fine = partial_data2
+ self.t_fine += (partial_data1 * partial_data1) * self.dig["T3"]
+
+ if self.t_fine < -40.0:
+ self.t_fine = -40.0
+
+ if self.t_fine > 85.0:
+ self.t_fine = 85.0
+
+ return self.t_fine
+
+ def _sample_bmp388_press(self):
+ xlsb = self.read_register("PRESS_XLSB", 1)
+ lsb = self.read_register("PRESS_LSB", 1)
+ msb = self.read_register("PRESS_MSB", 1)
+ adc_P = (msb[0] << 16) + (lsb[0] << 8) + (xlsb[0])
+
+ partial_data1 = self.dig["P6"] * self.t_fine
+ partial_data2 = self.dig["P7"] * (self.t_fine * self.t_fine)
+ partial_data3 = self.dig["P8"]
+ partial_data3 *= self.t_fine * self.t_fine * self.t_fine
+ partial_out1 = self.dig["P5"]
+ partial_out1 += partial_data1 + partial_data2 + partial_data3
+
+ partial_data1 = self.dig["P2"] * self.t_fine
+ partial_data2 = self.dig["P3"] * (self.t_fine * self.t_fine)
+ partial_data3 = self.dig["P4"]
+ partial_data3 *= (self.t_fine * self.t_fine * self.t_fine)
+ partial_out2 = adc_P * (
+ self.dig["P1"] + partial_data1 + partial_data2 + partial_data3
+ )
+
+ partial_data1 = adc_P * adc_P
+ partial_data2 = self.dig["P9"] + (self.dig["P10"] * self.t_fine)
+ partial_data3 = partial_data1 * partial_data2
+ partial_data4 = partial_data3 + adc_P * adc_P * adc_P * self.dig["P11"]
+
+ comp_press = partial_out1 + partial_out2 + partial_data4
+
+ if comp_press < 30000:
+ comp_press = 30000
+
+ if comp_press > 125000:
+ comp_press = 125000
+
+ return comp_press
+
def _sample_bme680(self, eventtime):
self.write_register('CTRL_HUM', self.os_hum & 0x07)
meas = self.os_temp << 5 | self.os_pres << 2
@@ -564,6 +707,12 @@ class BME280:
params = self.i2c.i2c_read(regs, 1)
return bytearray(params['response'])[0]
+ def read_bmp3_id(self):
+ # read chip id register
+ regs = [BMP3_CHIP_ID_REG]
+ params = self.i2c.i2c_read(regs, 1)
+ return bytearray(params['response'])[0]
+
def read_register(self, reg_name, read_len):
# read a single register
regs = [self.chip_registers[reg_name]]