Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adjust temperature under usb power #142

Merged
merged 22 commits into from
Feb 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion enviro/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,11 @@ def stop_activity_led():
from machine import RTC, ADC
import phew
from pcf85063a import PCF85063A
import enviro.config_defaults as config_defaults
import enviro.helpers as helpers

config_defaults.add_missing_config_settings()

# read the state of vbus to know if we were woken up by USB
vbus_present = Pin("WL_GPIO2", Pin.IN).value()

Expand Down Expand Up @@ -351,7 +354,7 @@ def get_sensor_readings():
logging.info(f" - seconds since last reading: {seconds_since_last}")


readings = get_board().get_sensor_readings(seconds_since_last)
readings = get_board().get_sensor_readings(seconds_since_last, vbus_present)
# readings["voltage"] = 0.0 # battery_voltage #Temporarily removed until issue is fixed

# write out the last time log
Expand Down
2 changes: 1 addition & 1 deletion enviro/boards/grow.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def water(moisture_levels):
drip_noise()
time.sleep(0.5)

def get_sensor_readings(seconds_since_last):
def get_sensor_readings(seconds_since_last, is_usb_power):
# bme280 returns the register contents immediately and then starts a new reading
# we want the current reading so do a dummy read to discard register contents first
bme280.read()
Expand Down
17 changes: 14 additions & 3 deletions enviro/boards/indoor.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import enviro.helpers as helpers
import math
from breakout_bme68x import BreakoutBME68X
from breakout_bh1745 import BreakoutBH1745

from enviro import config
from enviro import i2c

bme688 = BreakoutBME68X(i2c, address=0x77)
Expand Down Expand Up @@ -40,12 +42,21 @@ def colour_temperature_from_rgbc(r, g, b, c):
ct = 10000
return round(ct)

def get_sensor_readings(seconds_since_last):
def get_sensor_readings(seconds_since_last, is_usb_power):
data = bme688.read()

temperature = round(data[0], 2)
pressure = round(data[1] / 100.0, 2)
humidity = round(data[2], 2)

# Compensate for additional heating when on usb power - this also changes the
# relative humidity value.
if is_usb_power:
adjusted_temperature = temperature - config.usb_power_temperature_offset
macifell marked this conversation as resolved.
Show resolved Hide resolved
absolute_humidity = helpers.relative_to_absolute_humidity(humidity, temperature)
humidity = helpers.absolute_to_relative_humidity(absolute_humidity, adjusted_temperature)
temperature = adjusted_temperature

pressure = round(data[1] / 100.0, 2)
gas_resistance = round(data[3])
# an approximate air quality calculation that accounts for the effect of
# humidity on the gas sensor
Expand All @@ -64,4 +75,4 @@ def get_sensor_readings(seconds_since_last):
"aqi": aqi,
"luminance": lux_from_rgbc(r, g, b, c),
"color_temperature": colour_temperature_from_rgbc(r, g, b, c)
})
})
2 changes: 1 addition & 1 deletion enviro/boards/urban.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def particulates(particulate_data, measure):
multiplier = 10 if measure >= PM0_3_PER_LITRE else 1
return ((particulate_data[measure * 2] << 8) | particulate_data[measure * 2 + 1]) * multiplier

def get_sensor_readings(seconds_since_last):
def get_sensor_readings(seconds_since_last, is_usb_power):
# bme280 returns the register contents immediately and then starts a new reading
# we want the current reading so do a dummy read to discard register contents first
bme280.read()
Expand Down
2 changes: 1 addition & 1 deletion enviro/boards/weather.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ def rainfall(seconds_since_last):

return amount, per_second

def get_sensor_readings(seconds_since_last):
def get_sensor_readings(seconds_since_last, is_usb_power):
# bme280 returns the register contents immediately and then starts a new reading
# we want the current reading so do a dummy read to discard register contents first
bme280.read()
Expand Down
23 changes: 23 additions & 0 deletions enviro/config_defaults.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import config
from phew import logging

DEFAULT_USB_POWER_TEMPERATURE_OFFSET = 4.5


def add_missing_config_settings():
try:
# check if ca file parameter is set, if not set it to not use SSL by setting to None
config.mqtt_broker_ca_file
except AttributeError:
warn_missing_config_setting("mqtt_broker_ca_file")
config.mqtt_broker_ca_file = None

try:
config.usb_power_temperature_offset
except AttributeError:
warn_missing_config_setting("usb_power_temperature_offset")
config.usb_power_temperature_offset = DEFAULT_USB_POWER_TEMPERATURE_OFFSET


def warn_missing_config_setting(setting):
logging.warn(f"> config setting '{setting}' missing, please add it to config.py")
5 changes: 4 additions & 1 deletion enviro/config_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,7 @@
auto_water = False
moisture_target_a = 50
moisture_target_b = 50
moisture_target_c = 50
moisture_target_c = 50

# compensate for usb power
usb_power_temperature_offset = 4.5
5 changes: 5 additions & 0 deletions enviro/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,8 @@
UPLOAD_RATE_LIMITED = 2
UPLOAD_LOST_SYNC = 3
UPLOAD_SKIP_FILE = 4

# humidity
WATER_VAPOR_SPECIFIC_GAS_CONSTANT = 461.5
CRITICAL_WATER_TEMPERATURE = 647.096
CRITICAL_WATER_PRESSURE = 22064000
6 changes: 0 additions & 6 deletions enviro/destinations/mqtt.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,6 @@ def upload_reading(reading):
password = config.mqtt_broker_password
nickname = reading["nickname"]

# check if ca file paramter is set, if not set it to not use SSL by setting to None
try:
config.mqtt_broker_ca_file
except AttributeError:
config.mqtt_broker_ca_file = None

try:
if config.mqtt_broker_ca_file:
# Using SSL
Expand Down
43 changes: 42 additions & 1 deletion enviro/helpers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from enviro.constants import *
import machine, os, time
import machine, math, os, time

# miscellany
# ===========================================================================
Expand Down Expand Up @@ -57,3 +57,44 @@ def copy_file(source, target):
if not chunk:
break
outfile.write(chunk)

# temperature and humidity helpers
# ===========================================================================

# https://www.calctool.org/atmospheric-thermodynamics/absolute-humidity#what-is-and-how-to-calculate-absolute-humidity
def relative_to_absolute_humidity(relative_humidity, temperature_in_c):
temperature_in_k = celcius_to_kelvin(temperature_in_c)
actual_vapor_pressure = get_actual_vapor_pressure(relative_humidity, temperature_in_k)

return actual_vapor_pressure / (WATER_VAPOR_SPECIFIC_GAS_CONSTANT * temperature_in_k)

def absolute_to_relative_humidity(absolute_humidity, temperature_in_c):
temperature_in_k = celcius_to_kelvin(temperature_in_c)
saturation_vapor_pressure = get_saturation_vapor_pressure(temperature_in_k)

return (WATER_VAPOR_SPECIFIC_GAS_CONSTANT * temperature_in_k * absolute_humidity) / saturation_vapor_pressure * 100

def celcius_to_kelvin(temperature_in_c):
return temperature_in_c + 273.15

# https://www.calctool.org/atmospheric-thermodynamics/absolute-humidity#actual-vapor-pressure
# http://cires1.colorado.edu/~voemel/vp.html
def get_actual_vapor_pressure(relative_humidity, temperature_in_k):
return get_saturation_vapor_pressure(temperature_in_k) * (relative_humidity / 100)

def get_saturation_vapor_pressure(temperature_in_k):
v = 1 - (temperature_in_k / CRITICAL_WATER_TEMPERATURE)

# empirical constants
a1 = -7.85951783
a2 = 1.84408259
a3 = -11.7866497
a4 = 22.6807411
a5 = -15.9618719
a6 = 1.80122502

return CRITICAL_WATER_PRESSURE * math.exp(
CRITICAL_WATER_TEMPERATURE /
temperature_in_k *
(a1*v + a2*v**1.5 + a3*v**3 + a4*v**3.5 + a5*v**4 + a6*v**7.5)
)