# from machine import Pin, I2C, time_pulse_us
# import time
# # ----------------------------
# # PIN CONFIGURATION
# # ----------------------------
# TRIG_PIN = 4
# ECHO_PIN = 16
# BUTTON_PIN = 13
# LED_PIN = 2
# BUZZER_PIN = 27
# # ----------------------------
# # COMPONENT SETUP
# # ----------------------------
# trig = Pin(TRIG_PIN, Pin.OUT)
# echo = Pin(ECHO_PIN, Pin.IN)
# button = Pin(BUTTON_PIN, Pin.IN, Pin.PULL_UP)
# led = Pin(LED_PIN, Pin.OUT)
# buzzer = Pin(BUZZER_PIN, Pin.OUT)
# led.value(0)
# buzzer.value(0)
# # ----------------------------
# # LCD LOW-LEVEL DRIVER
# # ----------------------------
# I2C_ADDR = 0x27
# i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=400000)
# def lcd_write(cmd):
# i2c.writeto(I2C_ADDR, bytes([cmd]))
# def lcd_clear():
# lcd_write(0x01)
# time.sleep_ms(2)
# def lcd_print(text):
# for char in text:
# lcd_write(ord(char))
# def lcd_init():
# time.sleep_ms(50)
# lcd_write(0x33)
# lcd_write(0x32)
# lcd_write(0x28)
# lcd_write(0x0C)
# lcd_write(0x06)
# lcd_clear()
# lcd_init()
# lcd_print("Warehouse Ready")
# time.sleep(2)
# lcd_clear()
# # ----------------------------
# # FUNCTIONS
# # ----------------------------
# def beep():
# buzzer.value(1)
# time.sleep(0.1)
# buzzer.value(0)
# def read_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)
# if duration < 0:
# return 999
# return (duration * 0.0343) / 2
# # ----------------------------
# # MAIN LOOP
# # ----------------------------
# OCCUPIED_THRESHOLD = 12
# last_btn = 1
# while True:
# # -------- BUTTON --------
# btn = button.value()
# if btn == 0 and last_btn == 1:
# lcd_clear()
# lcd_print("SCAN DETECTED")
# beep()
# time.sleep(1)
# lcd_clear()
# last_btn = btn
# # -------- ULTRASONIC --------
# distance = read_distance()
# if distance < OCCUPIED_THRESHOLD:
# led.value(1)
# lcd_clear()
# lcd_print("Shelf OCCUPIED")
# else:
# led.value(0)
# lcd_clear()
# lcd_print("Shelf EMPTY")
# time.sleep(0.7)
# from machine import Pin, I2C
# import time
# i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=400000)
# print("Scanning I2C...")
# devices = i2c.scan()
# print("Found:", [hex(d) for d in devices])
# while True:
# time.sleep(1)
# from machine import Pin, I2C, time_pulse_us
# import time
# # ----------------------------
# # PINS
# # ----------------------------
# TRIG_PIN = 4
# ECHO_PIN = 16
# BUTTON_PIN = 13
# LED_PIN = 2
# BUZZER_PIN = 27
# # LCD I2C pins: SDA=21, SCL=22
# I2C_ADDR = 0x27 # keep this unless your scan shows different
# # ----------------------------
# # SETUP IO
# # ----------------------------
# trig = Pin(TRIG_PIN, Pin.OUT)
# echo = Pin(ECHO_PIN, Pin.IN)
# button = Pin(BUTTON_PIN, Pin.IN, Pin.PULL_UP)
# led = Pin(LED_PIN, Pin.OUT)
# buzzer = Pin(BUZZER_PIN, Pin.OUT)
# led.value(0)
# buzzer.value(0)
# # ----------------------------
# # LCD (PCF8574) DRIVER
# # ----------------------------
# i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=400000)
# # PCF8574 -> LCD pin mapping (common for 0x27 I2C backpacks)
# # P0 RS, P1 RW, P2 E, P3 Backlight, P4 D4, P5 D5, P6 D6, P7 D7
# RS = 0x01
# RW = 0x02
# EN = 0x04
# BL = 0x08 # backlight
# def _write_pcf(val):
# i2c.writeto(I2C_ADDR, bytes([val]))
# def _pulse_enable(data):
# _write_pcf(data | EN)
# time.sleep_us(2)
# _write_pcf(data & ~EN)
# time.sleep_us(50)
# def _write4bits(data):
# _write_pcf(data | BL)
# _pulse_enable(data | BL)
# def _send(value, mode):
# # mode: RS=0 command, RS=1 data
# high = (value & 0xF0)
# low = ((value << 4) & 0xF0)
# _write4bits(high | mode)
# _write4bits(low | mode)
# def lcd_cmd(cmd):
# _send(cmd, 0)
# def lcd_data(ch):
# _send(ch, RS)
# def lcd_init():
# time.sleep_ms(50)
# # init in 4-bit mode
# _write4bits(0x30)
# time.sleep_ms(5)
# _write4bits(0x30)
# time.sleep_us(150)
# _write4bits(0x30)
# _write4bits(0x20)
# lcd_cmd(0x28) # 4-bit, 2 line, 5x8
# lcd_cmd(0x0C) # display on, cursor off
# lcd_cmd(0x06) # entry mode
# lcd_cmd(0x01) # clear
# time.sleep_ms(2)
# def lcd_clear():
# lcd_cmd(0x01)
# time.sleep_ms(2)
# def lcd_goto(row, col):
# # row 0 -> 0x80, row 1 -> 0xC0
# addr = 0x80 + col if row == 0 else 0xC0 + col
# lcd_cmd(addr)
# def lcd_print_line(row, text):
# lcd_goto(row, 0)
# s = text[:16]
# s = s + (" " * (16 - len(s))) # pad to clear old chars
# for c in s:
# lcd_data(ord(c))
# # Initialize LCD
# try:
# lcd_init()
# except OSError as e:
# print("LCD I2C error:", e)
# print("Run I2C scan to confirm address.")
# raise
# lcd_print_line(0, "Warehouse Ready")
# lcd_print_line(1, "")
# time.sleep(1.5)
# # ----------------------------
# # HELPERS
# # ----------------------------
# def beep(ms=120):
# buzzer.value(1)
# time.sleep_ms(ms)
# buzzer.value(0)
# def read_distance_cm():
# trig.value(0)
# time.sleep_us(2)
# trig.value(1)
# time.sleep_us(10)
# trig.value(0)
# dur = time_pulse_us(echo, 1, 30000)
# if dur < 0:
# return 999.0
# return (dur * 0.0343) / 2.0
# # ----------------------------
# # MAIN LOOP
# # ----------------------------
# OCCUPIED_THRESHOLD = 12.0
# last_btn = 1
# last_state = None # None/True/False
# while True:
# # Button press -> scan detected
# btn = button.value()
# if btn == 0 and last_btn == 1:
# lcd_print_line(0, "SCAN DETECTED")
# lcd_print_line(1, "")
# beep(120)
# time.sleep(5.0)
# last_state = None # force refresh after scan
# last_btn = btn
# # Ultrasonic -> shelf state
# dist = read_distance_cm()
# occupied = (dist < OCCUPIED_THRESHOLD)
# # update LCD only if state changed (prevents flicker)
# if last_state is None or occupied != last_state:
# if occupied:
# led.value(1)
# lcd_print_line(0, "Shelf: OCCUPIED")
# lcd_print_line(1, "LED: ON")
# else:
# led.value(0)
# lcd_print_line(0, "Shelf: EMPTY")
# lcd_print_line(1, "LED: OFF")
# last_state = occupied
# time.sleep(0.2)
# from machine import Pin, I2C, time_pulse_us
# import time
# # import network
# # import urequests
# from umqtt.simple import MQTTClient
# import ubinascii
# import machine
# MQTT_BROKER = "broker.hivemq.com"
# MQTT_TOPIC = b"warehouse/neelray/occupied"
# CLIENT_ID = b"wokwi-" + ubinascii.hexlify(machine.unique_id())
# # ----------------------------
# # NGROK / FLASK SERVER CONFIG
# # ----------------------------
# # WIFI_SSID = "Wokwi-GUEST"
# # WIFI_PASS = ""
# # SERVER_BASE = "http://janell-meaningless-crammingly.ngrok-free.dev" # <-- your ngrok URL
# def wifi_connect():
# wlan = network.WLAN(network.STA_IF)
# wlan.active(True)
# if not wlan.isconnected():
# wlan.connect(WIFI_SSID, WIFI_PASS)
# while not wlan.isconnected():
# time.sleep(0.2)
# print("WiFi connected:", wlan.ifconfig())
# def post_update(payload):
# # payload example: {"occupied": True} or {"scan": True}
# try:
# r = urequests.post(SERVER_BASE + "/update", json=payload)
# r.close()
# print("POST OK:", payload)
# except Exception as e:
# print("POST failed:", e)
# # ----------------------------
# # PINS
# # ----------------------------
# TRIG_PIN = 4
# ECHO_PIN = 16
# BUTTON_PIN = 13
# LED_PIN = 2
# BUZZER_PIN = 27
# # LCD I2C pins: SDA=21, SCL=22
# I2C_ADDR = 0x27 # keep this unless your scan shows different
# # ----------------------------
# # SETUP IO
# # ----------------------------
# trig = Pin(TRIG_PIN, Pin.OUT)
# echo = Pin(ECHO_PIN, Pin.IN)
# button = Pin(BUTTON_PIN, Pin.IN, Pin.PULL_UP)
# led = Pin(LED_PIN, Pin.OUT)
# buzzer = Pin(BUZZER_PIN, Pin.OUT)
# led.value(0)
# buzzer.value(0)
# # ----------------------------
# # LCD (PCF8574) DRIVER
# # ----------------------------
# i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=400000)
# # PCF8574 -> LCD pin mapping (common for 0x27 I2C backpacks)
# # P0 RS, P1 RW, P2 E, P3 Backlight, P4 D4, P5 D5, P6 D6, P7 D7
# RS = 0x01
# RW = 0x02
# EN = 0x04
# BL = 0x08 # backlight
# def _write_pcf(val):
# i2c.writeto(I2C_ADDR, bytes([val]))
# def _pulse_enable(data):
# _write_pcf(data | EN)
# time.sleep_us(2)
# _write_pcf(data & ~EN)
# time.sleep_us(50)
# def _write4bits(data):
# _write_pcf(data | BL)
# _pulse_enable(data | BL)
# def _send(value, mode):
# # mode: RS=0 command, RS=1 data
# high = (value & 0xF0)
# low = ((value << 4) & 0xF0)
# _write4bits(high | mode)
# _write4bits(low | mode)
# def lcd_cmd(cmd):
# _send(cmd, 0)
# def lcd_data(ch):
# _send(ch, RS)
# def lcd_init():
# time.sleep_ms(50)
# # init in 4-bit mode
# _write4bits(0x30)
# time.sleep_ms(5)
# _write4bits(0x30)
# time.sleep_us(150)
# _write4bits(0x30)
# _write4bits(0x20)
# lcd_cmd(0x28) # 4-bit, 2 line, 5x8
# lcd_cmd(0x0C) # display on, cursor off
# lcd_cmd(0x06) # entry mode
# lcd_cmd(0x01) # clear
# time.sleep_ms(2)
# def lcd_clear():
# lcd_cmd(0x01)
# time.sleep_ms(2)
# def lcd_goto(row, col):
# # row 0 -> 0x80, row 1 -> 0xC0
# addr = 0x80 + col if row == 0 else 0xC0 + col
# lcd_cmd(addr)
# def lcd_print_line(row, text):
# lcd_goto(row, 0)
# s = text[:16]
# s = s + (" " * (16 - len(s))) # pad to clear old chars
# for c in s:
# lcd_data(ord(c))
# # Initialize LCD
# try:
# lcd_init()
# except OSError as e:
# print("LCD I2C error:", e)
# print("Run I2C scan to confirm address.")
# raise
# lcd_print_line(0, "Warehouse Ready")
# lcd_print_line(1, "")
# time.sleep(1.0)
# # ----------------------------
# # CONNECT WIFI (IMPORTANT)
# # ----------------------------
# wifi_connect()
# # ----------------------------
# # HELPERS
# # ----------------------------
# def beep(ms=120):
# buzzer.value(1)
# time.sleep_ms(ms)
# buzzer.value(0)
# def read_distance_cm():
# trig.value(0)
# time.sleep_us(2)
# trig.value(1)
# time.sleep_us(10)
# trig.value(0)
# dur = time_pulse_us(echo, 1, 30000)
# if dur < 0:
# return 999.0
# return (dur * 0.0343) / 2.0
# # ----------------------------
# # MAIN LOOP
# # ----------------------------
# OCCUPIED_THRESHOLD = 12.0
# last_btn = 1
# last_state = None # for LCD updates (None/True/False)
# last_sent_occupied = None # for server updates
# while True:
# # Button press -> scan detected
# btn = button.value()
# if btn == 0 and last_btn == 1:
# lcd_print_line(0, "SCAN DETECTED")
# lcd_print_line(1, "")
# beep(120)
# # Send scan event to server (pulse)
# post_update({"scan": True})
# time.sleep(2.0) # keep message long enough for you to see
# post_update({"scan": False})
# # force LCD refresh after scan
# last_state = None
# last_btn = btn
# # Ultrasonic -> shelf state
# dist = read_distance_cm()
# occupied = (dist < OCCUPIED_THRESHOLD)
# # update LCD only if state changed (prevents flicker)
# if last_state is None or occupied != last_state:
# if occupied:
# led.value(1)
# lcd_print_line(0, "Shelf: OCCUPIED")
# lcd_print_line(1, "LED: ON")
# else:
# led.value(0)
# lcd_print_line(0, "Shelf: EMPTY")
# lcd_print_line(1, "LED: OFF")
# last_state = occupied
# # Send to server only if occupied changed (reduces spam)
# if last_sent_occupied is None or occupied != last_sent_occupied:
# post_update({"occupied": occupied})
# last_sent_occupied = occupied
# time.sleep(0.2)
from machine import Pin, I2C, time_pulse_us
import time
import network
from umqtt.simple import MQTTClient
import ubinascii
import machine
# ----------------------------
# WIFI + MQTT CONFIG
# ----------------------------
WIFI_SSID = "Wokwi-GUEST"
WIFI_PASS = ""
MQTT_BROKER = "broker.hivemq.com"
MQTT_PORT = 1883
MQTT_TOPIC = b"warehouse/neelray/occupied"
CLIENT_ID = b"wokwi-" + ubinascii.hexlify(machine.unique_id())
def wifi_connect():
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
print("Connecting WiFi...")
wlan.connect(WIFI_SSID, WIFI_PASS)
while not wlan.isconnected():
time.sleep(0.2)
print("WiFi connected:", wlan.ifconfig())
def mqtt_connect():
client = MQTTClient(CLIENT_ID, MQTT_BROKER, port=MQTT_PORT, keepalive=60)
client.connect()
print("MQTT connected to", MQTT_BROKER)
return client
def mqtt_publish(client, data_dict):
# Publish JSON string like {"occupied": true}
try:
# Manual JSON (keeps it MicroPython-friendly)
if "occupied" in data_dict:
payload = '{"occupied": %s}' % ("true" if data_dict["occupied"] else "false")
elif "scan" in data_dict:
payload = '{"scan": %s}' % ("true" if data_dict["scan"] else "false")
else:
return
client.publish(MQTT_TOPIC, payload)
print("Published:", payload)
except Exception as e:
print("MQTT publish failed:", e)
# ----------------------------
# PINS
# ----------------------------
TRIG_PIN = 4
ECHO_PIN = 16
BUTTON_PIN = 13
LED_PIN = 2
BUZZER_PIN = 27
# LCD I2C pins: SDA=21, SCL=22
I2C_ADDR = 0x27
# ----------------------------
# SETUP IO
# ----------------------------
trig = Pin(TRIG_PIN, Pin.OUT)
echo = Pin(ECHO_PIN, Pin.IN)
button = Pin(BUTTON_PIN, Pin.IN, Pin.PULL_UP)
led = Pin(LED_PIN, Pin.OUT)
buzzer = Pin(BUZZER_PIN, Pin.OUT)
led.value(0)
buzzer.value(0)
# ----------------------------
# LCD (PCF8574) DRIVER
# ----------------------------
i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=400000)
RS = 0x01
EN = 0x04
BL = 0x08 # backlight
def _write_pcf(val):
i2c.writeto(I2C_ADDR, bytes([val]))
def _pulse_enable(data):
_write_pcf(data | EN)
time.sleep_us(2)
_write_pcf(data & ~EN)
time.sleep_us(50)
def _write4bits(data):
_write_pcf(data | BL)
_pulse_enable(data | BL)
def _send(value, mode):
high = (value & 0xF0)
low = ((value << 4) & 0xF0)
_write4bits(high | mode)
_write4bits(low | mode)
def lcd_cmd(cmd):
_send(cmd, 0)
def lcd_data(ch):
_send(ch, RS)
def lcd_init():
time.sleep_ms(50)
_write4bits(0x30)
time.sleep_ms(5)
_write4bits(0x30)
time.sleep_us(150)
_write4bits(0x30)
_write4bits(0x20)
lcd_cmd(0x28)
lcd_cmd(0x0C)
lcd_cmd(0x06)
lcd_cmd(0x01)
time.sleep_ms(2)
def lcd_goto(row, col):
addr = 0x80 + col if row == 0 else 0xC0 + col
lcd_cmd(addr)
def lcd_print_line(row, text):
lcd_goto(row, 0)
s = text[:16]
s = s + (" " * (16 - len(s)))
for c in s:
lcd_data(ord(c))
# Init LCD
lcd_init()
lcd_print_line(0, "Warehouse Ready")
lcd_print_line(1, "")
time.sleep(1.0)
# ----------------------------
# CONNECT WIFI + MQTT
# ----------------------------
wifi_connect()
mqtt = mqtt_connect()
# ----------------------------
# HELPERS
# ----------------------------
def beep(ms=120):
buzzer.value(1)
time.sleep_ms(ms)
buzzer.value(0)
def read_distance_cm():
trig.value(0)
time.sleep_us(2)
trig.value(1)
time.sleep_us(10)
trig.value(0)
dur = time_pulse_us(echo, 1, 30000)
if dur < 0:
return 999.0
return (dur * 0.0343) / 2.0
# ----------------------------
# MAIN LOOP
# ----------------------------
OCCUPIED_THRESHOLD = 12.0
last_btn = 1
last_state = None
last_sent_occupied = None
while True:
# keep MQTT alive (safe call)
try:
mqtt.check_msg()
except:
pass
# Button press -> scan detected
btn = button.value()
if btn == 0 and last_btn == 1:
lcd_print_line(0, "SCAN DETECTED")
lcd_print_line(1, "")
beep(120)
mqtt_publish(mqtt, {"scan": True})
time.sleep(2.0)
mqtt_publish(mqtt, {"scan": False})
last_state = None
last_btn = btn
# Ultrasonic -> shelf state
dist = read_distance_cm()
occupied = (dist < OCCUPIED_THRESHOLD)
# LCD + LED update
if last_state is None or occupied != last_state:
if occupied:
led.value(1)
lcd_print_line(0, "Shelf: OCCUPIED")
lcd_print_line(1, "LED: ON")
else:
led.value(0)
lcd_print_line(0, "Shelf: EMPTY")
lcd_print_line(1, "LED: OFF")
last_state = occupied
# Publish occupied only when it changes
if last_sent_occupied is None or occupied != last_sent_occupied:
mqtt_publish(mqtt, {"occupied": occupied})
last_sent_occupied = occupied
time.sleep(0.2)