import uasyncio as asyncio
import time
from machine import Pin, ADC, I2C
import hcsr04

# Pin setup
anPin = ADC(Pin(28))  # ADC Pin for potentiometer
pbPin = Pin(16, Pin.IN, Pin.PULL_UP)  # Push button
ledR = Pin(12, Pin.OUT)  # Red LED
ledG = Pin(13, Pin.OUT)  # Green LED

# Ultrasonic sensor setup
sensor = hcsr04.HCSR04(trigger_pin=Pin(2, Pin.OUT), echo_pin=Pin(3, Pin.IN))

# LCD setup
class LCD:
    def __init__(self, addr=None, blen=1):
        self.bus = I2C(1, sda=Pin(6), scl=Pin(7), freq=400000)
        self.addr = self.scan_address(addr)
        self.blen = blen
        self.init_lcd()

    def scan_address(self, addr):
        devices = self.bus.scan()
        if not devices:
            raise Exception("No LCD found")
        return addr if addr in devices else devices[0]

    def init_lcd(self):
        cmds = [0x33, 0x32, 0x28, 0x0C, 0x01]
        for cmd in cmds:
            self.send_command(cmd)
            time.sleep(0.005)

    def write_word(self, data):
        self.bus.writeto(self.addr, bytearray([data | 0x08 if self.blen else data & 0xF7]))

    def send_command(self, cmd):
        for buf in [(cmd & 0xF0) | 0x04, (cmd & 0x0F) << 4 | 0x04]:
            self.write_word(buf)
            time.sleep(0.002)
            self.write_word(buf & 0xFB)

    def send_data(self, data):
        for buf in [(data & 0xF0) | 0x05, (data & 0x0F) << 4 | 0x05]:
            self.write_word(buf)
            time.sleep(0.002)
            self.write_word(buf & 0xFB)

    def clear(self):
        self.send_command(0x01)

    def write(self, x, y, text):
        self.send_command(0x80 + 0x40 * y + min(max(x, 0), 15))
        for char in text:
            self.send_data(ord(char))

# Initialize the LCD
lcd = LCD()

# Global variables
threshold = 50  # Default threshold value in cm
scanning = False

# Async functions
async def blink_led_g():
    while True:
        ledG.on()
        await asyncio.sleep(0.05)
        ledG.off()
        await asyncio.sleep(0.05)

async def read_potentiometer():
    while True:
        if not scanning:
            pot_value = anPin.read_u16()
            distance = int(10 + (pot_value * (100 - 10) / 65535))
            lcd.write(0, 1, f"Dist: {distance:02} cm")
        await asyncio.sleep(0.1)

async def monitor_button():
    global scanning, threshold
    while True:
        if not pbPin.value():  # Button pressed
            await asyncio.sleep(0.2)  # Debounce delay
            if not scanning:
                scanning = True
                await scan_distance()
                scanning = False
            else:
                await set_threshold()
        await asyncio.sleep(0.1)

async def set_threshold():
    global threshold
    lcd.clear()
    lcd.write(0, 0, "Set Threshold")
    while pbPin.value():
        await asyncio.sleep(0.1)
    await asyncio.sleep(0.2)  # Debounce delay
    while True:
        pot_value = anPin.read_u16()
        threshold = int(10 + (pot_value * (100 - 10) / 65535))
        lcd.write(0, 1, f"Thresh: {threshold:02} cm")
        if not pbPin.value():  # Button pressed
            await asyncio.sleep(0.2)  # Debounce delay
            break

async def scan_distance():
    lcd.clear()
    lcd.write(0, 0, "Scanning")
    while pbPin.value():
        distance = sensor.distance_cm()
        lcd.write(0, 0, f"Distance: {distance:02} cm")
        lcd.write(0, 1, "Object: Yes" if distance < threshold else "Object: No")
        ledR.value(distance < threshold)
        await asyncio.sleep(0.5)
    lcd.clear()
    lcd.write(0, 0, "User Input")

# Main function to schedule tasks
async def main():
    lcd.clear()
    lcd.write(0, 0, "Distance Counter")
    await asyncio.sleep(2)
    asyncio.create_task(blink_led_g())
    asyncio.create_task(read_potentiometer())
    asyncio.create_task(monitor_button())
    while True:
        await asyncio.sleep(1)

# Run the main function
asyncio.run(main())
BOOTSELLED1239USBRaspberryPiPico©2020RP2-8020/21P64M15.00TTT