BME280を用いたPro Microの温湿度・気圧測定 プログラムで環境センサモジュール「BME280」を用いたPro Microのアプリを作成しましたが、NodeMCUで動作するアプリをLuaで作成しました。

温湿度・気圧測定 プログラムの作成

BME280のプログラムは、ESP8266 NodeMCU mini WiFi module ESP-12 data logger with BME280を使用しています。ビン番号とI2Cポートを次に示します。それぞれのBME280の仕様に従って変更してください。

local sda = 2
local scl = 1
local i2cport = 0x76

bme280.lua

bme280.luaは、BME280のセンサ情報を取り出す部分を関数化し、外部の関数から呼び出せるようにします。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
local M
do
-- cache
local i2c, tmr = i2c, tmr
 
local sda = 2
local scl = 1
local i2cport = 0x76
 
-- helpers
local function r8(reg)
    local r = { }
    i2c.start(0)
    i2c.address(0, i2cport, i2c.TRANSMITTER)
    i2c.write(0, reg)
    i2c.stop(0)
    i2c.start(0)
    i2c.address(0, i2cport, i2c.RECEIVER)
    r = i2c.read(0, 1)
    i2c.stop(0)
    return r:byte(1)
    end
local function w8(reg, val)
    i2c.start(0)
    i2c.address(0, i2cport, i2c.TRANSMITTER)
    i2c.write(0, reg)
    i2c.write(0, val)
    i2c.stop(0)
    end
local function r16u(reg)
    local r = { }
    i2c.start(0)
    i2c.address(0, i2cport, i2c.TRANSMITTER)
    i2c.write(0, reg)
    i2c.stop(0)
    i2c.start(0)
    i2c.address(0, i2cport, i2c.RECEIVER)
    r = i2c.read(0, 2)
    i2c.stop(0)
    return r:byte(1) + r:byte(2) * 256
    end
    --return r8(reg) + r8(reg + 1) * 256
    --end
local function r16(reg)
    local r = r16u(reg)
    if r > 32767 then r = r - 65536 end
    return r
    end
local function rRaw()
    local t, p, h
    local r = { }
    i2c.start(0)
    i2c.address(0, i2cport, i2c.TRANSMITTER)
    i2c.write(0, 0xF7)
    i2c.stop(0)
    i2c.start(0)
    i2c.address(0, i2cport, i2c.RECEIVER)
    r = i2c.read(0, 8)
    i2c.stop(0)
    p = r:byte(1) * 4096 + r:byte(2) * 16 + r:byte(3) / 16
    t = r:byte(4) * 4096 + r:byte(5) * 16 + r:byte(6) / 16
    h = r:byte(7) * 256 + r:byte(8)
    r = nil
    return t, p, h
    end
 
-- calibration data
local T1, T2, T3, P1, P2, P3, P4, P5, P6, P7, P8, P9, H1, H2, H3, H4, H5, H6
-- read t, p, h [mC, Pa, m%]
local function read()
print ("start")
    i2c.setup(0, sda, scl, i2c.SLOW)
    -- Initial setup
    w8(0xF2, 0x01)    -- H oversampling x1
    w8(0xF4, 0x27)  -- P oversampling x1, T oversampling x1, mode Normal
    w8(0xF5, 0xA8)  -- 1000ms, IIR 4, I2C
    -- Calibration coefficients
    T1 = r16u(0x88)
    T2 = r16(0x8A)
    T3 = r16(0x8C)
    P1 = r16u(0x8E)
    P2 = r16(0x90)
    P3 = r16(0x92)
    P4 = r16(0x94)
    P5 = r16(0x96)
    P6 = r16(0x98)
    P7 = r16(0x9A)
    P8 = r16(0x9C)
    P9 = r16(0x9E)
    H1 = r8(0xA1)
    H2 = r16(0xE1)
    H3 = r8(0xE3)
    H4 = (r8(0xE4) * 16) + (r8(0xE5) % 16)
    H5 = (r8(0xE6) * 16) + (r8(0xE5) / 16)
    H6 = r8(0xE7)
 
    -- Raw Data
    local t, p, h
    t, p, h = rRaw()
 
    -- Temperature
    --print("T=",T1,T2,T3)
    --local t = r8(0xFA) * 4096 + r8(0xFB) * 16 + r8(0xFC) / 16
    --print("t",t)
    local v1 = ((t/8 - T1*2) * T2) / 2048
    local v2 = ((((t/16 - T1) * (t/16 - T1)) / 4096) * T3) / 16384
    local tfine = v1 + v2
    --print("tf",tfine)
    --t = (tfine * 5 + 128) / 256
    t = (tfine * 5 + 128) / 256
    t = 10 * t
    --print("t=",t)
 
    -- Pressure (32bit version)
    --print("P=",P1,P2,P3,P4,P5,P6,P7,P8,P9)
    --local p = r8(0xF7) * 4096 + r8(0xF8) * 16 + r8(0xF9) / 16
    --print("p",p)
    v1 = (tfine - 128000) / 2
    v2 = (((v1 / 4) * (v1 / 4)) / 2048) * P6
    v2 = v2 + v1 * P5 * 2
    v2 = v2 / 4 + P4 * 65536
    v1 = ((P3 * (((v1 / 4) * (v1 / 4)) / 8192)) / 8 + (P2 * v1) / 2) / 262144
    v1 = ((32768 + v1) * P1) / 32768
    p = ((1048576 - p) - (v2 / 4096)) * 3125;
    if v1 ~= 0 then
    p = (p / v1) * 2
    else
    p = 0
    end
    v1 = (P9 * (((p / 8) * (p / 8)) / 8192)) / 4096
    v2 = ((p / 4) * P8) / 8192
    p = p + (v1 + v2 + P7) / 16
    --print("p=",p)
 
    -- Humidity
    --print("H=",H1,H2,H3,H4,H5,H6)
    --local h = r8(0xFD) * 256 + r8(0xFE)
    --print("h",h)
    v1 = tfine - 76800
    v1 = ((h * 16384 - H4 * 1024 * 1024 - H5 * v1 + 16384) / 32768) * ((((((v1 * H6 / 1024) * (v1 * H3 / 2048) + 32768) / 1024) + 2097152) * H2 + 8192) / 16384)
    v1 = v1 - ((((v1/32768) * (v1/32768)) / 128 ) * H1) / 16
    if v1 < 0 then
    v1 = 0
    end
    if v1 > 419430400 then
    v1 = 419430400
    end
    h = v1 / 4096
    --print("h=",h)
    return t, p, h
    end
-- expose
M = { read = read }
end
return M

main.lua

BME280のセンサ情報を取り出すbme280.luaを呼び出し、取り出したセンサ情報を表示します。Tは温度、Pは気圧、Hは湿度を示します。各単位は、温度はm°C、気圧はPa、湿度は、m%となっています。

1
2
t, p, h = dofile("bme280.lua").read()
print (string.format("T:%d P:%d H:%d",t,p,h))

プログラムの実行結果

作成したプログラムをESPlorerで実行した結果を次に示します。温湿度・気圧が、「T:18440 P:101958 H:50611」になっています。

BME28000