#— BME280 —#
class BME280
BME280_ADDRESS = 0x77
def initialize(wire)
@wire = wire
@osrs_t = 1
@osrs_p = 1
@osrs_h = 1
@mode = 3
@t_sb = 5
@filter = 0 #Filter off
@spi3w_en = 0 #3-wire SPI Disable
@ctrl_meas_reg = (@osrs_t << 5) | (@osrs_p << 2) | @mode
@config_reg = (@t_sb << 5) | (@filter << 2) | @spi3w_en
@ctrl_hum_reg = @osrs_h
digitalWrite(D2, 1)
# puts readReg(0xD0)
writeReg(0xF2,@ctrl_hum_reg)
writeReg(0xF4,@ctrl_meas_reg)
writeReg(0xF5,@config_reg)
readTrim
end
def readTrim
data = Array.new
i=0
@wire.beginTransmission(BME280_ADDRESS)
@wire.write(0x88)
@wire.endTransmission()
@wire.requestFrom(BME280_ADDRESS,24)
24.times do
data[i] = @wire.read
i += 1
end
@wire.beginTransmission(BME280_ADDRESS)
@wire.write(0xA1)
@wire.endTransmission()
@wire.requestFrom(BME280_ADDRESS,1)
data[i] = @wire.read
i += 1
@wire.beginTransmission(BME280_ADDRESS)
@wire.write(0xE1)
@wire.endTransmission()
@wire.requestFrom(BME280_ADDRESS,7)
7.times do
data[i] = @wire.read
i += 1
end
@dig_T1 = (data[1] << 8) | data[0]
@dig_T2 = (data[3] << 8) | data[2]
@dig_T3 = (data[5] << 8) | data[4]
@dig_P1 = (data[7] << 8) | data[6]
@dig_P2 = (data[9] << 8) | data[8]
@dig_P3 = (data[11]<< 8) | data[10]
@dig_P4 = (data[13]<< 8) | data[12]
@dig_P5 = (data[15]<< 8) | data[14]
@dig_P6 = (data[17]<< 8) | data[16]
@dig_P7 = (data[19]<< 8) | data[18]
@dig_P8 = (data[21]<< 8) | data[20]
@dig_P9 = (data[23]<< 8) | data[22]
@dig_H1 = data[24]
@dig_H2 = (data[26]<< 8) | data[25]
@dig_H3 = data[27]
@dig_H4 = (data[28]<< 4) | (0x0F & data[29])
@dig_H5 = (data[30] << 4) | (data[29] >> 4)
@dig_H6 = data[31]
end
def writeReg(reg_address, data)
@wire.beginTransmission(BME280_ADDRESS)
@wire.write(reg_address)
@wire.write(data)
@wire.endTransmission()
end
def readReg(reg_address)
@wire.beginTransmission(BME280_ADDRESS)
@wire.write( reg_address )
@wire.endTransmission()
@wire.requestFrom( BME280_ADDRESS, 1 )
@wire.read
end
def readData
i = 0
data = Array.new
@wire.beginTransmission(BME280_ADDRESS)
@wire.write(0xF7)
@wire.endTransmission()
@wire.requestFrom(BME280_ADDRESS,8)
8.times do
data[i] = @wire.read
i += 1
end
bar_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4)
temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4)
hum_raw = (data[6] << 8) | data[7]
[temp(temp_raw)/100.0, bar(bar_raw)/100.0, hum(hum_raw)/1024.0]
end
def temp(adc_T)
var1 = ((((adc_T.to_f >> 3) - (@dig_T1.to_f<<1))) * (@dig_T2).to_f) >> 11
var2 = (((((adc_T.to_f >> 4) - (@dig_T1).to_f) * ((adc_T.to_f>>4) - (@dig_T1).to_f)) >> 12) * (@dig_T3).to_f) >> 14
@t_fine = var1 + var2
(@t_fine * 5 + 128) >> 8
end
def bar(adc_P)
var1 = ((@t_fine).to_f>>1) - 64000
var2 = (((var1>>2) * (var1>>2)) >> 11) * (@dig_P6).to_f
var2 = var2 + ((var1*(@dig_P5).to_f)<<1)
var2 = (var2>>2)+((@dig_P4).to_f<<16)
var1 = (((@dig_P3.to_f * (((var1>>2)*(var1>>2)) >> 13)) >>3) + (((@dig_P2).to_f * var1)>>1))>>18
var1 = ((((32768+var1))*(@dig_P1).to_f)>>15)
if (var1 == 0)
return 0
end
P = ((((1048576)-adc_P.to_f)-(var2>>12)))*3125
if(P<0x80000000)
P = (P.to_f << 1) / var1
else
P = (P.to_f / var1) * 2
end
var1 = ((@dig_P9).to_f * ((((P.to_f>>3) * (P.to_f>>3))>>13)))>>12
var2 = (((P>>2)) * (@dig_P8).to_f)>>13
P + ((var1 + var2 + @dig_P7.to_f) >> 4)
end
def hum(adc_H)
v_x1 = (@t_fine.to_f - (76800).to_f)
v_x1 = (((((adc_H.to_f << 14)-((@dig_H4).to_f << 20).to_f - ((@dig_H5).to_f * v_x1.to_f).to_f).to_f + (16384).to_f) >> 15).to_f * (((((((v_x1 * (@dig_H6).to_f) >> 10).to_f * (((v_x1.to_f * (@dig_H3).to_f).to_f >> 11).to_f + ( 32768).to_f).to_f).to_f >> 10) + (2097152).to_f).to_f * ( @dig_H2).to_f + 8192) >> 14).to_f).to_f
v_x1 = (v_x1.to_f - (((((v_x1.to_f >> 15).to_f * (v_x1.to_f >> 15).to_f).to_f >> 7).to_f * (@dig_H1).to_f) >> 4).to_f).to_f
v_x1 = (v_x1.to_f < 0 ? 0 : v_x1.to_f)
v_x1 = (v_x1.to_f > 419430400.to_f ? 419430400.to_f : v_x1.to_f)
v_x1.to_f >> 12
end
end
# TWE command class
class TweCmd
attr_reader :srcdev, :command
def initialize(v)
@srcdev = v[1..2] # Source device
@command = v[3..4] # Command
end
end
# TWE 0x01 command class
class TweCmd01 < TweCmd
attr_reader :data
def initialize(v)
super(v)
@data = decode(v.strip[5...-2])
end
def decode(s)
s.scan(/.{1,2}/).inject([]) {|ary, v| ary << v.to_i(16)}.pack("c*")
end
def self.encode(s)
s.unpack("c*").inject("") {|str, c| str + ("0" + c.to_s(16))[-2,2]}
end
end
# TWE 0x81 command class
class TweCmd81 < TweCmd
attr_reader :lpi, :srcsdr, :tgtdev, :time
attr_reader :voltage, :di_sts, :di_chg, :ad
def initialize(v)
super(v)
@lqi = v[9..10].to_i(16) # LQI
@srcadr = v[11..18] # Source device
@tgtdev = v[19..20] # Target device
@time = v[21..24].to_i(16) # Time stamp
@relay = v[25..26].to_i(16) # Relay flag
@voltage = v[27..30].to_i(16) # Voltage
@di_sts = v[33..34].to_i(16) # DI status
@di_chg = v[35..36].to_i(16) # DI status change
ef = v[45..46].to_i(16) # AD1..AD4 bias
@ad = [
(v[37..38].to_i(16) * 4 + (ef & 0x03)) * 4, # AD1
(v[39..40].to_i(16) * 4 + ((ef & 0x0c) >> 2)) * 4, # AD2
(v[41..42].to_i(16) * 4 + ((ef & 0x30) >> 4)) * 4, # AD3
(v[43..44].to_i(16) * 4 + ((ef & 0xc0) >> 6)) * 4 # AD4
]
@prvDI = nil
end
def di
[ @di_sts & 0x01, (@di_sts >> 1) & 0x01,
(@di_sts >> 2) & 0x01, (@di_sts >> 3) & 0x01 ]
end
def relayed?
@relay > 0
end
end
class TweLite
attr_reader :target
def initialize
@ser = Serial.new(115200)
@sts = {}
@data = nil
@target = nil
end
def recv
v = @ser.gets
return nil if v == "" || v[0] != ":"
@data = v
case v[3..4]
when "81"
cmd = TweCmd81.new(v)
@target = cmd.srcdev unless @target
when "01"
cmd = TweCmd01.new(v)
else
cmd = v
end
cmd
end
def send(data)
data = data.to_s unless data.instance_of?(String)
if @target #!= "00"
body = ":#{@target}01"
body += TweCmd01.encode(data)
body += TweLite.sum(body)
body += "\r\n"
puts "SEND: #{body.inspect}" if $TWEDEBUG
@ser.puts body
end
end
def self.sum(v)
s = 0
v = v[1..-1] if v[0] == ":"
(v.size/2).to_i.times do |i|
s += v[i*2,2].to_i(16)
end
("0" + (256 - s % 256).to_s(16))[-2,2].upcase
end
def master?
@target && @target != '00'
end
end
#— main
sensor = BME280.new(Wire.new(0x0, Wire::DutyCycle_2))
twe = TweLite.new
di, count = nil, 1
loop do
while v = twe.recv
case v
when TweCmd01
puts "RECV(#{v.srcdev}): #{v.data}"
if v.data.to_f >= 29.0
digitalWrite(D8,1);
end
when TweCmd81
di = v.di
end
end
# idle
if twe.master?
temp, pres, humi = sensor.readData();
tempstr = temp.round(1).to_s;
puts tempstr
twe.send(tempstr)
count += 1
delay(1000)
end
end
loop do
# TODO
temp, pres, humi = sensor.readData();
puts "Temp: #{temp.round(1)} DegC " +
"Press: #{pres.round(1)} hPa " +
"Humi: #{humi.round(1)} %";
delay(1000)
end