Skip to content

Instantly share code, notes, and snippets.

@k-takata
Created July 23, 2023 03:22
Show Gist options
  • Save k-takata/16dfca7faebe38a30bb592c1d70bf0cc to your computer and use it in GitHub Desktop.
Save k-takata/16dfca7faebe38a30bb592c1d70bf0cc to your computer and use it in GitHub Desktop.
Using AE-BME680 with GR-CITRUS
#!mruby
class BME680
ID = 0x77
#REG_COEFF3 = 0x00
REG_FIELD0 = 0x1D
REG_IDAC_HEAT0 = 0x50
REG_RES_HEAT0 = 0x5A
REG_GAS_WAIT0 = 0x64
REG_SHD_HEATR_DUR = 0x6E
REG_CTRL_GAS_0 = 0x70
REG_CTRL_GAS_1 = 0x71
REG_CTRL_HUM = 0x72
REG_CTRL_MEAS = 0x74
REG_CONFIG = 0x75
REG_UNIQUE_ID = 0x83
REG_COEFF1 = 0x8A
REG_CHIP_ID = 0xD0
REG_RESET = 0xE0
REG_COEFF2 = 0xE1
REG_VARIANT_ID = 0xF0
LEN_COEFF1 = 23
LEN_COEFF2 = 14
#LEN_COEFF3 = 5
#LEN_COEFF_ALL = LEN_COEFF1 + LEN_COEFF2 + LEN_COEFF3
LEN_FIELD = 17
def initialize
@i2c = I2c.new(1)
end
def init
@i2c.write(ID, REG_RESET, 0xB6)
#delay(100)
if @i2c.read(ID, REG_CHIP_ID) != 0x61 then
puts "BME680 not found."
end
#puts(["ctrl_meas", @i2c.read(ID, REG_CTRL_MEAS)])
get_calib_data()
#puts(["@coeff", @coeff])
end
def u16(msb, lsb)
return (msb << 8) + lsb
end
def s16(msb, lsb)
return (msb << 8) + lsb + (((msb & 0x80) == 0) ? 0 : ~0xffff)
end
def u8(b)
return b
end
def s8(b)
return b + (((b & 0x80) == 0) ? 0 : ~0xff)
end
def get_calib_data
@coeff = []
delay 10
@i2c.begin(ID)
@i2c.lwrite(REG_COEFF1)
@i2c.end(0)
@i2c.request(ID, LEN_COEFF1)
LEN_COEFF1.times do
@coeff << @i2c.lread()
end
@i2c.begin(ID)
@i2c.lwrite(REG_COEFF2)
@i2c.end(0)
@i2c.request(ID, LEN_COEFF2)
LEN_COEFF2.times do
@coeff << @i2c.lread()
end
#@i2c.begin(ID)
#@i2c.lwrite(REG_COEFF3)
#@i2c.end(0)
#@i2c.request(ID, LEN_COEFF3)
#LEN_COEFF3.times do
# @coeff << @i2c.lread()
#end
@par_t1 = u16(@coeff[32], @coeff[31])
@par_t2 = s16(@coeff[1], @coeff[0])
@par_t3 = s8(@coeff[2])
@par_p1 = u16(@coeff[5], @coeff[4])
@par_p2 = s16(@coeff[7], @coeff[6])
@par_p3 = s8(@coeff[8])
@par_p4 = s16(@coeff[11], @coeff[10])
@par_p5 = s16(@coeff[13], @coeff[12])
@par_p6 = s8(@coeff[15])
@par_p7 = s8(@coeff[14])
@par_p8 = s16(@coeff[19], @coeff[18])
@par_p9 = s16(@coeff[21], @coeff[20])
@par_p10 = u8(@coeff[22])
@par_h1 = (@coeff[25] << 4) + (@coeff[24] & 0x0f)
@par_h2 = (@coeff[23] << 4) + ((@coeff[24] >> 4) & 0x0f)
@par_h3 = s8(@coeff[26])
@par_h4 = s8(@coeff[27])
@par_h5 = s8(@coeff[28])
@par_h6 = u8(@coeff[29])
@par_h7 = s8(@coeff[30])
@par_g1 = s8(@coeff[35])
@par_g2 = s16(@coeff[34], @coeff[33])
@par_g3 = s8(@coeff[36])
end
def set_op_mode(mode)
# Wait until it becomes to sleep mode.
cur_mode = 0
loop do
cur_mode = @i2c.read(ID, REG_CTRL_MEAS)
break if (cur_mode & 0x03) == 0
delay 10
end
if mode != 0 then
@i2c.write(ID, REG_CTRL_MEAS, (cur_mode & ~0x03) | (mode & 0x03))
end
end
def set_conf(osrs_t, osrs_p, osrs_h, filter)
set_op_mode(0)
tmp = @i2c.read(ID, REG_CTRL_MEAS)
@i2c.write(ID, REG_CTRL_MEAS, ((osrs_t & 0x07) << 5) | ((osrs_p & 0x07) << 2) | (tmp & 0x03))
tmp = @i2c.read(ID, REG_CTRL_HUM)
@i2c.write(ID, REG_CTRL_HUM, (tmp & ~0x07) | (osrs_h & 0x07))
tmp = @i2c.read(ID, REG_CONFIG)
@i2c.write(ID, REG_CONFIG, (tmp & ~0x1C) | ((filter & 0x07) << 2))
end
def set_heatr_conf(osrs_t, osrs_p, osrs_h, filter)
# TODO
end
def read_field_data
data = []
@i2c.begin(ID)
@i2c.lwrite(REG_FIELD0)
@i2c.end(0)
@i2c.request(ID, LEN_FIELD)
LEN_FIELD.times do
data << @i2c.lread()
end
@adc_pres = (data[2] << 12) | (data[3] << 4) | (data[4] >> 4)
@adc_temp = (data[5] << 12) | (data[6] << 4) | (data[7] >> 4)
@adc_hum = (data[8] << 8) | data[9]
end
def calc_temp
var1 = (@adc_temp >> 3) - (@par_t1 << 1)
var2 = (var1 * @par_t2) >> 11
var3 = ((((var1 >> 1) * (var1 >> 1)) >> 12) * (@par_t3 << 4)) >> 14
@t_fine = var2 + var3
@temp_comp = ((@t_fine * 5) + 128) >> 8
return @temp_comp
end
def calc_pres
var1 = (@t_fine >> 1) - 64000
var2 = ((((var1 >> 2) * (var1 >> 2)) >> 11) * @par_p6) >> 2
var2 = var2 + ((var1 * @par_p5) << 1)
var2 = (var2 >> 2) + (@par_p4 << 16)
var1 = (((((var1 >> 2) * (var1 >> 2)) >> 13) * (@par_p3 << 5)) >> 3) + ((@par_p2 * var1) >> 1)
var1 = var1 >> 18
var1 = ((32768 + var1) * @par_p1) >> 15
press_comp = 1048576 - @adc_pres
press_comp = (press_comp - (var2 >> 12)) * 3125
if press_comp >= (1 << 30) then
press_comp = (press_comp / var1) << 1
else
press_comp = (press_comp << 1) / var1
end
var1 = (@par_p9 * (((press_comp >> 3) * (press_comp >> 3)) >> 13)) >> 12
var2 = ((press_comp >> 2) * @par_p8) >> 13
var3 = ((press_comp >> 8) * (press_comp >> 8) * (press_comp >> 8) * @par_p10) >> 17
press_comp = press_comp + ((var1 + var2 + var3 + (@par_p7 << 7)) >> 4)
return press_comp
end
def calc_hum
temp_scaled = @temp_comp
var1 = @adc_hum - (@par_h1 << 4) - (((temp_scaled * @par_h3) / 100) >> 1)
var2 = (@par_h2 * (((temp_scaled * @par_h4) / 100) + (((temp_scaled * ((temp_scaled * @par_h5) / 100)) >> 6) / 100) + (1 << 14))) >> 10
var3 = var1 * var2
var4 = ((@par_h6 << 7) + ((temp_scaled * @par_h7) / 100)) >> 4
var5 = ((var3 >> 14) * (var3 >> 14)) >> 10
var6 = (var4 * var5) >> 1
comp_hum = (((var3 + var6) >> 10) * 1000) >> 12
if comp_hum > 100000
comp_hum = 100000
elsif comp_hum < 0
comp_hum = 0
end
return comp_hum
end
end
bme680 = BME680.new
bme680.init
bme680.set_conf(5, 5, 5, 3)
5.times do
bme680.set_op_mode(1)
bme680.set_op_mode(0)
bme680.read_field_data
s = bme680.calc_temp.to_s
s[-2,0] = '.'
puts("temp: #{s} C")
s = bme680.calc_pres.to_s
s[-2,0] = '.'
puts("pres: #{s} hPa")
s = bme680.calc_hum.to_s
s[-3,0] = '.'
puts("hum: #{s} %")
puts
delay 1000
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment