Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
T
temperature-daemon
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
External wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
stustanet
temperature-daemon
Commits
042a5cb7
Commit
042a5cb7
authored
5 years ago
by
Stefan Huber
Browse files
Options
Downloads
Patches
Plain Diff
for branch maxbill
parent
d5aac7d5
Branches
maxbill
No related tags found
No related merge requests found
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
BME280.py
+292
-0
292 additions, 0 deletions
BME280.py
main.py
+58
-0
58 additions, 0 deletions
main.py
tempermon.ini
+30
-12
30 additions, 12 deletions
tempermon.ini
tempermonitor.py
+1
-1
1 addition, 1 deletion
tempermonitor.py
with
381 additions
and
13 deletions
BME280.py
0 → 100644
+
292
−
0
View file @
042a5cb7
"""
This code is designed to run on a ESP32 or ESP8266. It will
control one single BME280 via I2C.
"""
from
machine
import
I2C
import
time
# BME280 default address.
BME280_I2CADDR
=
0x76
# Operating Modes
BME280_OSAMPLE_1
=
1
BME280_OSAMPLE_2
=
2
BME280_OSAMPLE_4
=
3
BME280_OSAMPLE_8
=
4
BME280_OSAMPLE_16
=
5
# BME280 Registers
BME280_REGISTER_DIG_T1
=
0x88
# Trimming parameter registers
BME280_REGISTER_DIG_T2
=
0x8A
BME280_REGISTER_DIG_T3
=
0x8C
BME280_REGISTER_DIG_P1
=
0x8E
BME280_REGISTER_DIG_P2
=
0x90
BME280_REGISTER_DIG_P3
=
0x92
BME280_REGISTER_DIG_P4
=
0x94
BME280_REGISTER_DIG_P5
=
0x96
BME280_REGISTER_DIG_P6
=
0x98
BME280_REGISTER_DIG_P7
=
0x9A
BME280_REGISTER_DIG_P8
=
0x9C
BME280_REGISTER_DIG_P9
=
0x9E
BME280_REGISTER_DIG_H1
=
0xA1
BME280_REGISTER_DIG_H2
=
0xE1
BME280_REGISTER_DIG_H3
=
0xE3
BME280_REGISTER_DIG_H4
=
0xE4
BME280_REGISTER_DIG_H5
=
0xE5
BME280_REGISTER_DIG_H6
=
0xE6
BME280_REGISTER_DIG_H7
=
0xE7
BME280_REGISTER_CHIPID
=
0xD0
BME280_REGISTER_VERSION
=
0xD1
BME280_REGISTER_SOFTRESET
=
0xE0
BME280_REGISTER_CONTROL_HUM
=
0xF2
BME280_REGISTER_CONTROL
=
0xF4
BME280_REGISTER_CONFIG
=
0xF5
BME280_REGISTER_PRESSURE_DATA
=
0xF7
BME280_REGISTER_TEMP_DATA
=
0xFA
BME280_REGISTER_HUMIDITY_DATA
=
0xFD
class
Device
:
"""
Class for communicating with an I2C device.
Allows reading and writing 8-bit, 16-bit, and byte array values to
registers on the device.
"""
def
__init__
(
self
,
address
,
i2c
):
"""
Create an instance of the I2C device at the specified address using
the specified I2C interface object.
"""
self
.
_address
=
address
self
.
_i2c
=
i2c
def
writeRaw8
(
self
,
value
):
"""
Write an 8-bit value on the bus (without register).
"""
value
=
value
&
0xFF
self
.
_i2c
.
writeto
(
self
.
_address
,
value
)
def
write8
(
self
,
register
,
value
):
"""
Write an 8-bit value to the specified register.
"""
b
=
bytearray
(
1
)
b
[
0
]
=
value
&
0xFF
self
.
_i2c
.
writeto_mem
(
self
.
_address
,
register
,
b
)
def
write16
(
self
,
register
,
value
):
"""
Write a 16-bit value to the specified register.
"""
value
=
value
&
0xFFFF
b
=
bytearray
(
2
)
b
[
0
]
=
value
&
0xFF
b
[
1
]
=
(
value
>>
8
)
&
0xFF
self
.
i2c
.
writeto_mem
(
self
.
_address
,
register
,
value
)
def
readRaw8
(
self
):
"""
Read an 8-bit value on the bus (without register).
"""
return
int
.
from_bytes
(
self
.
_i2c
.
readfrom
(
self
.
_address
,
1
),
'
little
'
)
&
0xFF
def
readU8
(
self
,
register
):
"""
Read an unsigned byte from the specified register.
"""
return
int
.
from_bytes
(
self
.
_i2c
.
readfrom_mem
(
self
.
_address
,
register
,
1
),
'
little
'
)
&
0xFF
def
readS8
(
self
,
register
):
"""
Read a signed byte from the specified register.
"""
result
=
self
.
readU8
(
register
)
if
result
>
127
:
result
-=
256
return
result
def
readU16
(
self
,
register
,
little_endian
=
True
):
"""
Read an unsigned 16-bit value from the specified register, with the
specified endianness (default little endian, or least significant byte
first).
"""
result
=
int
.
from_bytes
(
self
.
_i2c
.
readfrom_mem
(
self
.
_address
,
register
,
2
),
'
little
'
)
&
0xFFFF
if
not
little_endian
:
result
=
((
result
<<
8
)
&
0xFF00
)
+
(
result
>>
8
)
return
result
def
readS16
(
self
,
register
,
little_endian
=
True
):
"""
Read a signed 16-bit value from the specified register, with the
specified endianness (default little endian, or least significant byte
first).
"""
result
=
self
.
readU16
(
register
,
little_endian
)
if
result
>
32767
:
result
-=
65536
return
result
def
readU16LE
(
self
,
register
):
"""
Read an unsigned 16-bit value from the specified register, in little
endian byte order.
"""
return
self
.
readU16
(
register
,
little_endian
=
True
)
def
readU16BE
(
self
,
register
):
"""
Read an unsigned 16-bit value from the specified register, in big
endian byte order.
"""
return
self
.
readU16
(
register
,
little_endian
=
False
)
def
readS16LE
(
self
,
register
):
"""
Read a signed 16-bit value from the specified register, in little
endian byte order.
"""
return
self
.
readS16
(
register
,
little_endian
=
True
)
def
readS16BE
(
self
,
register
):
"""
Read a signed 16-bit value from the specified register, in big
endian byte order.
"""
return
self
.
readS16
(
register
,
little_endian
=
False
)
class
BME280
:
def
__init__
(
self
,
mode
=
BME280_OSAMPLE_1
,
address
=
BME280_I2CADDR
,
i2c
=
None
,
**
kwargs
):
# Check that mode is valid.
if
mode
not
in
[
BME280_OSAMPLE_1
,
BME280_OSAMPLE_2
,
BME280_OSAMPLE_4
,
BME280_OSAMPLE_8
,
BME280_OSAMPLE_16
]:
raise
ValueError
(
'
Unexpected mode value {0}. Set mode to one of
'
'
BME280_ULTRALOWPOWER, BME280_STANDARD, BME280_HIGHRES, or
'
'
BME280_ULTRAHIGHRES
'
.
format
(
mode
))
self
.
_mode
=
mode
# Create I2C device.
if
i2c
is
None
:
raise
ValueError
(
'
An I2C object is required.
'
)
self
.
_device
=
Device
(
address
,
i2c
)
# Load calibration values.
self
.
_load_calibration
()
self
.
_device
.
write8
(
BME280_REGISTER_CONTROL
,
0x3F
)
self
.
t_fine
=
0
def
_load_calibration
(
self
):
self
.
dig_T1
=
self
.
_device
.
readU16LE
(
BME280_REGISTER_DIG_T1
)
self
.
dig_T2
=
self
.
_device
.
readS16LE
(
BME280_REGISTER_DIG_T2
)
self
.
dig_T3
=
self
.
_device
.
readS16LE
(
BME280_REGISTER_DIG_T3
)
self
.
dig_P1
=
self
.
_device
.
readU16LE
(
BME280_REGISTER_DIG_P1
)
self
.
dig_P2
=
self
.
_device
.
readS16LE
(
BME280_REGISTER_DIG_P2
)
self
.
dig_P3
=
self
.
_device
.
readS16LE
(
BME280_REGISTER_DIG_P3
)
self
.
dig_P4
=
self
.
_device
.
readS16LE
(
BME280_REGISTER_DIG_P4
)
self
.
dig_P5
=
self
.
_device
.
readS16LE
(
BME280_REGISTER_DIG_P5
)
self
.
dig_P6
=
self
.
_device
.
readS16LE
(
BME280_REGISTER_DIG_P6
)
self
.
dig_P7
=
self
.
_device
.
readS16LE
(
BME280_REGISTER_DIG_P7
)
self
.
dig_P8
=
self
.
_device
.
readS16LE
(
BME280_REGISTER_DIG_P8
)
self
.
dig_P9
=
self
.
_device
.
readS16LE
(
BME280_REGISTER_DIG_P9
)
self
.
dig_H1
=
self
.
_device
.
readU8
(
BME280_REGISTER_DIG_H1
)
self
.
dig_H2
=
self
.
_device
.
readS16LE
(
BME280_REGISTER_DIG_H2
)
self
.
dig_H3
=
self
.
_device
.
readU8
(
BME280_REGISTER_DIG_H3
)
self
.
dig_H6
=
self
.
_device
.
readS8
(
BME280_REGISTER_DIG_H7
)
h4
=
self
.
_device
.
readS8
(
BME280_REGISTER_DIG_H4
)
h4
=
(
h4
<<
24
)
>>
20
self
.
dig_H4
=
h4
|
(
self
.
_device
.
readU8
(
BME280_REGISTER_DIG_H5
)
&
0x0F
)
h5
=
self
.
_device
.
readS8
(
BME280_REGISTER_DIG_H6
)
h5
=
(
h5
<<
24
)
>>
20
self
.
dig_H5
=
h5
|
(
self
.
_device
.
readU8
(
BME280_REGISTER_DIG_H5
)
>>
4
&
0x0F
)
def
read_raw_temp
(
self
):
"""
Reads the raw (uncompensated) temperature from the sensor.
"""
meas
=
self
.
_mode
self
.
_device
.
write8
(
BME280_REGISTER_CONTROL_HUM
,
meas
)
meas
=
self
.
_mode
<<
5
|
self
.
_mode
<<
2
|
1
self
.
_device
.
write8
(
BME280_REGISTER_CONTROL
,
meas
)
sleep_time
=
1250
+
2300
*
(
1
<<
self
.
_mode
)
sleep_time
=
sleep_time
+
2300
*
(
1
<<
self
.
_mode
)
+
575
sleep_time
=
sleep_time
+
2300
*
(
1
<<
self
.
_mode
)
+
575
time
.
sleep_us
(
sleep_time
)
# Wait the required time
msb
=
self
.
_device
.
readU8
(
BME280_REGISTER_TEMP_DATA
)
lsb
=
self
.
_device
.
readU8
(
BME280_REGISTER_TEMP_DATA
+
1
)
xlsb
=
self
.
_device
.
readU8
(
BME280_REGISTER_TEMP_DATA
+
2
)
raw
=
((
msb
<<
16
)
|
(
lsb
<<
8
)
|
xlsb
)
>>
4
return
raw
def
read_raw_pressure
(
self
):
"""
Reads the raw (uncompensated) pressure level from the sensor.
"""
"""
Assumes that the temperature has already been read
"""
"""
i.e. that enough delay has been provided
"""
msb
=
self
.
_device
.
readU8
(
BME280_REGISTER_PRESSURE_DATA
)
lsb
=
self
.
_device
.
readU8
(
BME280_REGISTER_PRESSURE_DATA
+
1
)
xlsb
=
self
.
_device
.
readU8
(
BME280_REGISTER_PRESSURE_DATA
+
2
)
raw
=
((
msb
<<
16
)
|
(
lsb
<<
8
)
|
xlsb
)
>>
4
return
raw
def
read_raw_humidity
(
self
):
"""
Assumes that the temperature has already been read
"""
"""
i.e. that enough delay has been provided
"""
msb
=
self
.
_device
.
readU8
(
BME280_REGISTER_HUMIDITY_DATA
)
lsb
=
self
.
_device
.
readU8
(
BME280_REGISTER_HUMIDITY_DATA
+
1
)
raw
=
(
msb
<<
8
)
|
lsb
return
raw
def
read_temperature
(
self
):
"""
Get the compensated temperature in 0.01 of a degree celsius.
"""
adc
=
self
.
read_raw_temp
()
var1
=
((
adc
>>
3
)
-
(
self
.
dig_T1
<<
1
))
*
(
self
.
dig_T2
>>
11
)
var2
=
((
(((
adc
>>
4
)
-
self
.
dig_T1
)
*
((
adc
>>
4
)
-
self
.
dig_T1
))
>>
12
)
*
self
.
dig_T3
)
>>
14
self
.
t_fine
=
var1
+
var2
return
(
self
.
t_fine
*
5
+
128
)
>>
8
def
read_pressure
(
self
):
"""
Gets the compensated pressure in Pascals.
"""
adc
=
self
.
read_raw_pressure
()
var1
=
self
.
t_fine
-
128000
var2
=
var1
*
var1
*
self
.
dig_P6
var2
=
var2
+
((
var1
*
self
.
dig_P5
)
<<
17
)
var2
=
var2
+
(
self
.
dig_P4
<<
35
)
var1
=
(((
var1
*
var1
*
self
.
dig_P3
)
>>
8
)
+
((
var1
*
self
.
dig_P2
)
>>
12
))
var1
=
(((
1
<<
47
)
+
var1
)
*
self
.
dig_P1
)
>>
33
if
var1
==
0
:
return
0
p
=
1048576
-
adc
p
=
(((
p
<<
31
)
-
var2
)
*
3125
)
//
var1
var1
=
(
self
.
dig_P9
*
(
p
>>
13
)
*
(
p
>>
13
))
>>
25
var2
=
(
self
.
dig_P8
*
p
)
>>
19
return
((
p
+
var1
+
var2
)
>>
8
)
+
(
self
.
dig_P7
<<
4
)
def
read_humidity
(
self
):
adc
=
self
.
read_raw_humidity
()
# print 'Raw humidity = {0:d}'.format (adc)
h
=
self
.
t_fine
-
76800
h
=
(((((
adc
<<
14
)
-
(
self
.
dig_H4
<<
20
)
-
(
self
.
dig_H5
*
h
))
+
16384
)
>>
15
)
*
(((((((
h
*
self
.
dig_H6
)
>>
10
)
*
(((
h
*
self
.
dig_H3
)
>>
11
)
+
32768
))
>>
10
)
+
2097152
)
*
self
.
dig_H2
+
8192
)
>>
14
))
h
=
h
-
(((((
h
>>
15
)
*
(
h
>>
15
))
>>
7
)
*
self
.
dig_H1
)
>>
4
)
h
=
0
if
h
<
0
else
h
h
=
419430400
if
h
>
419430400
else
h
return
h
>>
12
@property
def
temperature
(
self
):
"
Return the temperature in degrees.
"
t
=
self
.
read_temperature
()
ti
=
t
//
100
td
=
t
-
ti
*
100
#return "{}.{:02d}C".format(ti, td)
return
"
{}.{:02d}
"
.
format
(
ti
,
td
)
@property
def
pressure
(
self
):
"
Return the temperature in hPa.
"
p
=
self
.
read_pressure
()
//
256
pi
=
p
//
100
pd
=
p
-
pi
*
100
#return "{}.{:02d}hPa".format(pi, pd)
return
"
{}.{:02d}
"
.
format
(
pi
,
pd
)
@property
def
humidity
(
self
):
"
Return the humidity in percent.
"
h
=
self
.
read_humidity
()
hi
=
h
//
1024
hd
=
h
*
100
//
1024
-
hi
*
100
#return "{}.{:02d}%".format(hi, hd)
return
"
{}.{:02d}
"
.
format
(
hi
,
hd
)
This diff is collapsed.
Click to expand it.
main.py
0 → 100644
+
58
−
0
View file @
042a5cb7
"""
This code is designed to run on an ESP8266 for grabbing temperature data from
ds18x20 sensors via the onewire protocol and sending them via serial to the
connected host. It should be trivial to port it to different platforms.
It also grabs data from one BME280 via I2C.
The Protocol is dead simple:
ONEWIRE-ID1 TEMPERATURE1 (in degree C)
ONEWIRE-ID2 TEMPERATURE2 (in degree C)
BME280-TEMPERATURE TEMPERATUREBME (in degree C)
BME280-PRESSURE PRESSUREBME (in hPa)
BME280-HUMIDITY HUMIDITYBME (in %rH)
...
<
Empty
Line
>
When a sensor has problems reading, it sends as temperature 9001.
New sensors are only detected upon powerup, so you have to reboot in order to
extend the sensor network.
The sensors have a parasitic-power-mode which is NOT TO BE USED here.
Please connect all three pins, and multiplex as you please.
"""
import
machine
import
time
import
onewire
,
ds18x20
import
ubinascii
import
BME280
di
=
machine
.
Pin
(
13
)
ds
=
ds18x20
.
DS18X20
(
onewire
.
OneWire
(
di
))
scl
=
machine
.
Pin
(
5
)
sda
=
machine
.
Pin
(
4
)
i2c
=
machine
.
I2C
(
scl
=
scl
,
sda
=
sda
,
freq
=
10000
)
bme
=
BME280
.
BME280
(
i2c
=
i2c
)
# scan for onewire sensors
roms
=
ds
.
scan
()
while
1
:
time
.
sleep_ms
(
240
)
ds
.
convert_temp
()
time
.
sleep_ms
(
750
)
for
rom
in
roms
:
print
(
ubinascii
.
hexlify
(
rom
).
decode
(
'
utf-8
'
),
end
=
'
'
)
try
:
print
(
ds
.
read_temp
(
rom
))
except
:
print
(
9001
)
print
(
"
BME280_temperature
"
,
bme
.
temperature
)
print
(
"
BME280_pressure
"
,
bme
.
pressure
)
print
(
"
BME280_humidity
"
,
bme
.
humidity
)
print
()
This diff is collapsed.
Click to expand it.
tempermon.ini
+
30
−
12
View file @
042a5cb7
[serial]
#port=/dev/ttyUSB0
port
=
/tmp/temperature_pts
port
=
/dev/ttyUSB0
baudrate
=
115200
timeout
=
100
...
...
@@ -12,23 +11,42 @@ interval=1
[mail]
from
=
Temperman <root@temperator.stusta.de>
to
=
jw@stusta.de,markus.hefele@stusta.de
to_urgent
=
jw@stusta.de,markus.hefele
@stusta.de
to
=
jw@stusta.de,markus.hefele@stusta.de
,suhu@stusta.de
to_urgent
=
vorstand
@stusta
net
.de
min_delay_between_messages
=
3600
[warning]
floor_sensors
=
Test
ceiling_sensors
=
Test2
floor_sensors
=
temp0
ceiling_sensors
=
temp1
min_ceiling_warning
=
35
floor_ceiling_diff
=
15
ceiling_warning_level
=
40
[28aaabf6531401a0]
name
=
temp0
calibration
=
0
[
testsensor
]
name
=
Test
calibration
=
5
[
28aab9ee5314017b
]
name
=
temp1
calibration
=
0
[sensortest]
name
=
Test2
calibration
=
5
[28aa82ec53140188]
name
=
temp2
calibration
=
0
[28aaec455414017b]
name
=
temp3
calibration
=
0
[BME280_temperature]
name
=
temp4
calibration
=
0
[BME280_pressure]
name
=
pressure
calibration
=
0
[BME280_humidity]
name
=
humidity
calibration
=
0
This diff is collapsed.
Click to expand it.
tempermonitor.py
+
1
−
1
View file @
042a5cb7
...
...
@@ -174,7 +174,7 @@ class TempMonitor:
config
=
self
.
_configname
,
owid
=
owid
,
temp
=
temp
)
elif
temp
>
1
000
or
temp
<
-
1000
:
elif
temp
>
9
000
or
temp
<
-
1000
:
sensor
.
valid
=
False
# if the sensor is giving bullshit data - notify the operators
await
self
.
call_plugin
(
"
err_problem_sensor
"
,
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment