from machine import Pin, I2C
import ssd1306
import time
import machine
# -------------------------
# OLED DISPLAY SETUP
# -------------------------
i2c = I2C(0, scl=Pin(5), sda=Pin(4))
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
# -------------------------
# ULTRASONIC SENSOR PINS
# -------------------------
trigger = Pin(3, Pin.OUT)
echo = Pin(2, Pin.IN)
# -------------------------
# OUTPUT DEVICES PINS
# -------------------------
led = Pin(15, Pin.OUT)
relay = Pin(16, Pin.OUT)
buzzer = Pin(17, Pin.OUT)
# -------------------------
# TANK PARAMETERS
# -------------------------
tank_height = 100
status = "STARTING"
# -------------------------
# MEASURE DISTANCE FUNCTION
# -------------------------
def measure_distance():
trigger.low()
time.sleep_us(2)
trigger.high()
time.sleep_us(10)
trigger.low()
# Safe pulse-timing function to keep Wokwi from freezing
time_passed = machine.time_pulse_us(echo, 1, 30000)
if time_passed < 0:
return tank_height # Timeout default (assumes empty tank)
distance = (time_passed * 0.0343) / 2
return distance
# -------------------------
# MAIN PROGRAM LOOP
# -------------------------
while True:
distance = measure_distance()
water_level = tank_height - distance
if water_level < 0:
water_level = 0
percentage = int((water_level / tank_height) * 100)
if percentage > 100:
percentage = 100
print("Water Level:", percentage, "%")
# LOW WATER CONDITION (Trigger Fill)
if percentage < 30:
led.on()
relay.on()
buzzer.on()
status = "FILLING"
# FULL TANK CONDITION (Stop Fill)
elif percentage >= 90:
led.off()
relay.off()
buzzer.off()
status = "FULL"
# NORMAL OPERATING CONDITION
else:
buzzer.off()
# Hysteresis: Keep pump running if filling, keep off if draining naturally
if relay.value() == 1:
status = "FILLING"
led.on()
else:
status = "NORMAL"
led.off()
# -------------------------
# OLED DISPLAY REFRESH
# -------------------------
oled.fill(0) # Clear Screen
oled.text("SMART TANK", 0, 0)
oled.text("LEVEL:", 0, 20)
oled.text(str(percentage) + "%", 60, 20)
oled.text("STATUS: " + status, 0, 45)
oled.show() # Update display hardware
time.sleep(1)