from machine import Pin, ADC, PWM, time_pulse_us, I2C
import time
import dht
from i2c_lcd import I2cLcd
# Inisialisasi komponen
# Sensor DHT22 (AM2302)
dht_sensor = dht.DHT22(Pin(15))
# Sensor Cahaya (LDR)
ldr = ADC(Pin(34))
ldr.atten(ADC.ATTN_11DB) # Rentang 0-3.3V
# Sensor Gas MQ-135
mq135 = ADC(Pin(35))
mq135.atten(ADC.ATTN_11DB)
# Sensor Ultrasonik HC-SR04
trig = Pin(5, Pin.OUT)
echo = Pin(18, Pin.IN)
# LCD I2C
i2c = I2C(scl=Pin(22), sda=Pin(21), freq=400000)
lcd = I2cLcd(i2c, 0x27, 2, 16) # Alamat I2C 0x27, LCD 16x2
# Aktuator
servo = PWM(Pin(13), freq=50)
buzzer = PWM(Pin(12), freq=440, duty=0) # PWM untuk kontrol nada
led_green = Pin(2, Pin.OUT)
led_red = Pin(4, Pin.OUT)
# Parameter sistem
VENT_OPEN_ANGLE = 120 # Sudut bukaan ventilasi (derajat)
VENT_CLOSE_ANGLE = 0 # Sudut tutup ventilasi
WATER_LEVEL_MAX = 20 # Jarak maksimum air dari sensor (cm)
CO2_THRESHOLD = 800 # Threshold CO2 (ppm)
TEMP_THRESHOLD_HIGH = 30 # Suhu maksimum (C)
TEMP_THRESHOLD_LOW = 15 # Suhu minimum (C)
HUMIDITY_THRESHOLD_HIGH = 80 # Kelembaban maksimum (%)
HUMIDITY_THRESHOLD_LOW = 40 # Kelembaban minimum (%)
LIGHT_THRESHOLD_LOW = 2000 # Ambang batas intensitas cahaya rendah
LIGHT_THRESHOLD_HIGH = 3500 # Ambang batas intensitas cahaya tinggi
# Nada buzzer
BUZZER_NORMAL = 0
BUZZER_WARNING = 784 # G5
BUZZER_EMERGENCY = 1047 # C6
def map_value(x, in_min, in_max, out_min, out_max):
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
def set_servo_angle(angle):
duty = map_value(angle, 0, 180, 25, 115)
servo.duty(int(duty))
def play_buzzer(freq, duration_ms=200):
if freq == 0:
buzzer.duty(0)
else:
buzzer.freq(freq)
buzzer.duty(512) # 50% duty cycle
time.sleep_ms(duration_ms)
buzzer.duty(0)
def measure_distance():
trig.value(0)
time.sleep_us(2)
trig.value(1)
time.sleep_us(10)
trig.value(0)
duration = time_pulse_us(echo, 1, 30000) # Timeout 30ms
distance = (duration / 2) / 29.1 # Convert to cm
return distance if distance > 0 else 0
def read_mq135():
# Kalibrasi sederhana sensor MQ-135
sensor_value = mq135.read()
# Konversi ke ppm CO2 (perlu dikalibrasi lebih akurat)
ppm = sensor_value * (2000 / 4095) # ESP32 ADC 12-bit (0-4095)
return ppm
def read_ldr():
return ldr.read()
def check_emergency_conditions(temp, humidity, co2, water_level):
if (temp > TEMP_THRESHOLD_HIGH + 5 or
temp < TEMP_THRESHOLD_LOW - 5 or
humidity > HUMIDITY_THRESHOLD_HIGH + 15 or
humidity < HUMIDITY_THRESHOLD_LOW - 15 or
co2 > CO2_THRESHOLD + 800 or
water_level > WATER_LEVEL_MAX + 10):
return True
return False
def update_lcd(temp, humidity, co2, light, water_level):
lcd.clear()
# Baris pertama
lcd.putstr(f"T:{temp:.1f}C H:{humidity:.0f}%")
# Baris kedua
lcd.putstr(f"CO2:{co2:.0f} L:{light}")
# Tampilkan level air jika perlu
if water_level > WATER_LEVEL_MAX:
lcd.move_to(0, 1)
lcd.putstr(f"WATER HIGH! {water_level:.1f}cm")
def control_system(temp, humidity, co2, light, water_level):
emergency = check_emergency_conditions(temp, humidity, co2, water_level)
if emergency:
# Mode darurat - buka ventilasi penuh, nyalakan alarm
set_servo_angle(VENT_OPEN_ANGLE)
play_buzzer(BUZZER_EMERGENCY, 500)
led_red.on()
led_green.off()
print("EMERGENCY MODE!")
else:
led_red.off()
led_green.on()
# Kontrol ventilasi berdasarkan suhu, kelembaban dan CO2
temp_factor = max(0, temp - TEMP_THRESHOLD_HIGH) if temp > TEMP_THRESHOLD_HIGH else 0
humidity_factor = max(0, humidity - HUMIDITY_THRESHOLD_HIGH) if humidity > HUMIDITY_THRESHOLD_HIGH else 0
co2_factor = max(0, co2 - CO2_THRESHOLD)
control_factor = max(temp_factor, humidity_factor, co2_factor)
if control_factor > 0:
vent_angle = map_value(control_factor,
0,
max(10,
TEMP_THRESHOLD_HIGH + 10 - TEMP_THRESHOLD_HIGH,
HUMIDITY_THRESHOLD_HIGH + 30 - HUMIDITY_THRESHOLD_HIGH,
CO2_THRESHOLD + 1000 - CO2_THRESHOLD),
VENT_CLOSE_ANGLE,
VENT_OPEN_ANGLE)
set_servo_angle(int(vent_angle))
play_buzzer(BUZZER_WARNING) # Bunyikan warning
else:
set_servo_angle(VENT_CLOSE_ANGLE)
play_buzzer(BUZZER_NORMAL) # Matikan buzzer
def read_dht22():
try:
dht_sensor.measure()
temp = dht_sensor.temperature()
humidity = dht_sensor.humidity()
return temp, humidity
except Exception as e:
print("Error reading DHT22:", e)
return None, None
# Inisialisasi LCD
lcd.clear()
lcd.putstr("Greenhouse Monitor")
time.sleep(2)
while True:
try:
# Baca sensor DHT22
temp, humidity = read_dht22()
if temp is None or humidity is None:
time.sleep(2)
continue
# Baca sensor lainnya
co2 = read_mq135()
light = read_ldr()
water_level = measure_distance()
# Tampilkan data sensor
print("\n--- Sensor Readings ---")
print(f"Suhu: {temp:.1f}°C")
print(f"Kelembaban: {humidity:.1f}%")
print(f"CO2: {co2:.2f} ppm")
print(f"Cahaya: {light}")
print(f"Level Air: {water_level:.2f} cm")
# Update LCD
update_lcd(temp, humidity, co2, light, water_level)
# Kendalikan sistem
control_system(temp, humidity, co2, light, water_level)
except Exception as e:
print("System Error:", e)
play_buzzer(BUZZER_EMERGENCY, 1000)
time.sleep(2) # Delay antara pembacaan