import machine
import utime
import onewire
import ds18x20
from lcd_parallel import LCD
# ── Sensor ───────────────────────────────────────
ow = onewire.OneWire(machine.Pin(2))
ds = ds18x20.DS18X20(ow)
rom = None
def init_sensor():
global rom
try:
roms = ds.scan()
if roms:
rom = roms[0]
return True
except Exception:
pass
return False
# ── LCD (Parallel 4-bit) ─────────────────────────
lcd = LCD(7, 8, 9, 10, 11, 12)
# ── Button ───────────────────────────────────────
button = machine.Pin(15, machine.Pin.IN, machine.Pin.PULL_UP)
# ── Variables ────────────────────────────────────
mode = 0 # 0=Celsius 1=Fahrenheit 2=Kelvin 3=MIN/MAX
temp_c = 25.0 # default starting temperature
min_c = 25.0 # ← start at default temp (not 999)
max_c = 25.0 # ← start at default temp (not -999)
min_set = False # ← track if real reading received
DEGREE = chr(223)
# ── Conversion Functions ─────────────────────────
def c_to_f(c):
return c * 9 / 5 + 32
def c_to_k(c):
return c + 273.15
# ── Display Function ─────────────────────────────
def update_display():
lcd.clear()
if mode == 0:
# ── Celsius ──────────────────────────────
lcd.move_to(0, 0)
lcd.putstr("Temp:{:.1f}{}C ".format(temp_c, DEGREE))
lcd.move_to(0, 1)
lcd.putstr("Mode: Celsius ")
elif mode == 1:
# ── Fahrenheit ───────────────────────────
lcd.move_to(0, 0)
lcd.putstr("Temp:{:.1f}{}F ".format(c_to_f(temp_c), DEGREE))
lcd.move_to(0, 1)
lcd.putstr("Mode:Fahrenheit ")
elif mode == 2:
# ── Kelvin ───────────────────────────────
lcd.move_to(0, 0)
lcd.putstr("Temp:{:.1f}K ".format(c_to_k(temp_c)))
lcd.move_to(0, 1)
lcd.putstr("Mode: Kelvin ")
else:
# ── MIN / MAX ────────────────────────────
if not min_set:
# no real reading yet
lcd.move_to(0, 0)
lcd.putstr("MIN: --.-{}C ".format(DEGREE))
lcd.move_to(0, 1)
lcd.putstr("MAX: --.-{}C ".format(DEGREE))
else:
lcd.move_to(0, 0)
lcd.putstr("MIN:{:.1f}{}C ".format(min_c, DEGREE))
lcd.move_to(0, 1)
lcd.putstr("MAX:{:.1f}{}C ".format(max_c, DEGREE))
# ── Safe Sensor Read ─────────────────────────────
def read_sensor():
global temp_c, min_c, max_c, min_set
try:
t = ds.read_temp(rom)
# ✅ validate reading (ignore garbage values)
if -55 <= t <= 125:
temp_c = t
if not min_set:
min_c = t
max_c = t
min_set = True
else:
if t < min_c: min_c = t
if t > max_c: max_c = t
return True
except Exception:
# ✅ CRC error caught here — skip bad reading
pass
return False
# ── Splash Screen ────────────────────────────────
lcd.clear()
lcd.move_to(0, 0)
lcd.putstr(" Thermometer ")
lcd.move_to(0, 1)
lcd.putstr(" ANBU ARASAN V ")
utime.sleep(2)
lcd.clear()
lcd.move_to(0, 0)
lcd.putstr(" ID:2403917711 ")
lcd.move_to(0, 1)
lcd.putstr(" 521002 ")
utime.sleep(2)
lcd.clear()
# ── Init Sensor ──────────────────────────────────
if not init_sensor():
lcd.clear()
lcd.move_to(0, 0)
lcd.putstr("Sensor Error! ")
lcd.move_to(0, 1)
lcd.putstr("Check Wiring.. ")
utime.sleep(3)
init_sensor()
if rom:
ds.convert_temp()
# ── Timing ───────────────────────────────────────
conversion_start = utime.ticks_ms()
CONVERSION_MS = 1000 # ← increased to 1 second (reduces CRC errors)
update_display()
# ── Main Loop ────────────────────────────────────
while True:
now = utime.ticks_ms()
# ✅ Button Check
if button.value() == 0:
utime.sleep_ms(50)
if button.value() == 0:
mode = (mode + 1) % 4
update_display()
while button.value() == 0:
utime.sleep_ms(10)
# ✅ Sensor Read Every 1000ms
if utime.ticks_diff(now, conversion_start) >= CONVERSION_MS:
if rom:
read_sensor() # ← safe read with CRC protection
update_display()
try:
ds.convert_temp()
except Exception:
pass
conversion_start = now
else:
init_sensor()
utime.sleep_ms(10)