import math
import machine, time
from ssd1306 import SSD1306_I2C
import onewire, ds18x20
from machine import ADC
# === PMV Calculation ===
def calculate_pmv(Ta, Tr, RH, Va):
Met = 1.2
Icl = 0.5
M = Met * 58.15
W = 0
Icl_m2 = Icl * 0.155
Pa = RH * 10 * math.exp(16.6536 - 4030.183 / (Ta + 235))
fcl = 1 + 1.29*Icl if Icl <= 0.078 else 1.05 + 0.645*Icl
Tcla = Ta + (35.5 - Ta)/(3.5*Icl + 0.1)
xf = Tcla
eps = 0.00015
for _ in range(150):
xn = xf
hc = 12.1 * math.sqrt(Va)
xf = ((35.7 - 0.028*(M - W)) + Icl_m2*fcl*hc*(Ta - xn)) / (1 + Icl_m2*fcl*hc)
if abs(xn - xf) < eps:
break
tcl = xf
Ta_K = Ta + 273.0
Tr_K = Tr + 273.0
hl1 = 3.05 * 0.001 * (5733 - (6.99*(M - W)) - Pa)
hl2 = 0.42 * ((M - W) - 58.15)
hl3 = 1.7 * 0.00001 * M * (5867 - Pa)
hl4 = 0.0014 * M * (34 - Ta)
hl5 = 3.96e-8 * fcl * ((tcl + 273.0)**4 - Tr_K**4)
hl6 = fcl * hc * (tcl - Ta)
L = M - W - hl1 - hl2 - hl3 - hl4 - hl5 - hl6
PMV = (0.303 * math.exp(-0.036*M) + 0.028) * L
return PMV
def pmv_to_ppd(pmv):
return 100.0 - 95.0 * math.exp(-0.03353 * pmv**4 - 0.2179 * pmv**2)
# === DS18B20 Setup ===
DS_PIN = 4
ow = onewire.OneWire(machine.Pin(DS_PIN))
ds = ds18x20.DS18X20(ow)
roms = ds.scan()
if not roms:
raise RuntimeError("No DS18B20 sensors found on pin {}".format(DS_PIN))
sensor = roms[0]
def read_ds18b20_c():
ds.convert_temp()
time.sleep_ms(750) # max conversion time at 12-bit
return ds.read_temp(sensor)
# === OLED Setup ===
i2c = machine.I2C(0, scl=machine.Pin(22), sda=machine.Pin(21))
oled = SSD1306_I2C(128, 64, i2c)
# === Potentiometer Setup ===
pot_rh = ADC(machine.Pin(34)) # potentiometer 1 → humidity
pot_rh.atten(ADC.ATTN_11DB)
pot_va = ADC(machine.Pin(35)) # potentiometer 2 → air velocity
pot_va.atten(ADC.ATTN_11DB)
# === Main Loop ===
while True:
Ta = read_ds18b20_c() # air temp from DS18B20 (°C)
Tr = Ta # assume mean radiant ≈ air temp
# Humidity from potentiometer
raw_rh = pot_rh.read() # 0–4095
RH = (raw_rh / 4095) * 100.0 # 0–100 %RH
# Air velocity from potentiometer
raw_va = pot_va.read() # 0–4095
Va = (raw_va / 4095) # 0–1.0 m/s
pmv = calculate_pmv(Ta, Tr, RH, Va)
ppd = pmv_to_ppd(pmv)
# Display on OLED
oled.fill(0)
oled.text("Thermal Comfort", 0, 0)
oled.text("Ta: {:.1f}C".format(Ta), 0, 12)
oled.text("RH: {:.0f}%".format(RH), 0, 24)
oled.text("Va: {:.2f}m/s".format(Va), 0, 36)
oled.text("PMV: {:.2f}".format(pmv), 0, 48)
oled.show()
time.sleep(2)
Loading
ds18b20
ds18b20