# main.py
import time
import machine
import ssd1306
import urequests
from config import (
API_URL,
BUZZER_PIN,
DIST_CLOSE_THRESHOLD,
DIST_OPEN_THRESHOLD,
ECHO_PIN,
I2C_SCL,
I2C_SDA,
JWT_TOKEN,
LED1_PIN,
LED2_PIN,
LED3_PIN,
SERVO_PIN,
TRIG_PIN,
)
# ======== Inisialisasi Hardware ========
# HC-SR04 Ultrasonic
trig = machine.Pin(TRIG_PIN, machine.Pin.OUT)
echo = machine.Pin(ECHO_PIN, machine.Pin.IN)
# Servo (50Hz PWM)
servo_pwm = machine.PWM(machine.Pin(SERVO_PIN), freq=50, duty=0)
def set_servo_angle(angle):
# Konversi sudut 0–180 ke duty_u16 (0–65535)
# duty u16 untuk PWM 50 Hz: nilai minimal ~26 untuk 0°, ~115 utk 180°
duty = int((angle / 180) * (115 - 26) + 26)
servo_pwm.duty_u16(duty)
# Buzzer (pin digital)
buzzer = machine.Pin(BUZZER_PIN, machine.Pin.OUT)
def buzz(duration_ms=200):
buzzer.on()
time.sleep_ms(duration_ms)
buzzer.off()
# LEDs
led1 = machine.Pin(LED1_PIN, machine.Pin.OUT) # Open indicator
led2 = machine.Pin(LED2_PIN, machine.Pin.OUT) # Close indicator
led3 = machine.Pin(LED3_PIN, machine.Pin.OUT) # Error/status
# SSD1306 OLED via I2C
i2c = machine.I2C(0, scl=machine.Pin(I2C_SCL), sda=machine.Pin(I2C_SDA))
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
def oled_clear():
oled.fill(0)
oled.show()
def oled_display(text, line=0):
# text = string, line = baris 0–7 (font 8px tinggi)
oled.text(text, 0, line * 8)
oled.show()
# ======== Fungsi Bantu ========
# Baca jarak ultrasonic (cm)
def read_distance():
trig.off()
time.sleep_us(2)
trig.on()
time.sleep_us(10)
trig.off()
# Tunggu echo naik
while echo.value() == 0:
pass
t1 = time.ticks_us()
while echo.value() == 1:
pass
t2 = machine.time_pulse_us(echo, 1, 30000) # timeout 30 ms
# Alternatif jika time_pulse_us tidak tersedia:
# t2 = time.ticks_us()
# dist = ((t2 - t1) / 2) / 29.1
dist = t2 / 58.0 # Rumus HC-SR04 (microseconds → cm)
return dist
# Kirim HTTP POST ke API
def send_gate_command(action="open"):
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer " + JWT_TOKEN,
}
payload = '{"gateId":"G1","action":"%s"}' % action
try:
resp = urequests.post(API_URL, data=payload, headers=headers)
code = resp.status_code
resp.close()
return code == 200
except Exception as e:
print("HTTP Error:", e)
return False
# ======== Loop Utama ========
def main():
state = "closed"
set_servo_angle(0) # Pastikan servo di posisi tutup
led1.off()
led2.off()
led3.off()
oled_clear()
oled_display("Gate System Ready", 0)
while True:
try:
dist = read_distance()
except Exception as e:
print("Sensor Error:", e)
led3.on()
oled_clear()
oled_display("Sensor Error", 0)
time.sleep(1)
continue
# Tampilkan jarak di OLED
oled_clear()
oled_display("Distance: %.1f cm" % dist, 0)
oled_display("State: %s" % state, 1)
# Logic buka, tutup
if dist < DIST_OPEN_THRESHOLD and state == "closed":
oled_display("Opening Gate...", 2)
success = send_gate_command("open")
if success:
set_servo_angle(90)
led1.on()
buzz(150)
state = "open"
oled_display("Gate Opened", 3)
else:
led3.on()
oled_display("Open Failed", 3)
elif dist > DIST_CLOSE_THRESHOLD and state == "open":
oled_display("Closing Gate...", 2)
success = send_gate_command("close")
if success:
set_servo_angle(0)
led2.on()
buzz(150)
state = "closed"
oled_display("Gate Closed", 3)
else:
led3.on()
oled_display("Close Failed", 3)
# Matikan LED indikator jika tidak aktif
if state == "open":
led2.off()
else:
led1.off()
# jeda 1 detik
time.sleep(1)
if __name__ == "__main__":
main()