Code:
THANK YOU!!! With your tips I managed to figure it out. It's very stable now. Thank you!Although 'asyncio' looks difficult at first glance, I'd propose you write your solution using asyncio.
The 'sweep' routine for your servo needs some time (too much time in terms of a web request) and should run in background.
Unfortunately multithreading is not yet stable in micropython.
But in asyncio, you can start a Task 'in parallel'.
Starting point https://gist.github.com/aallan/3d45a062 ... ec9c81e3b6
If you detect that a "sweep" is needed by checking the request, you can start a task asyncio.create_task(sweep())
Next step is to connect a battery shield to run also when power is down. If you have any awesome tip on linking all together, I'd appreciate it.
Code:
import networkimport socketimport timefrom picozero import pico_temp_sensor, pico_ledfrom machine import Pin, PWMimport uasyncio as asyncio# led = Pin(15, Pin.OUT)# onboard = Pin("LED", Pin.OUT, value=0)ssid = 'myssid'password = 'mypwd'wlan = network.WLAN(network.STA_IF)servo_state = 'Servo is idle.'servo_running = False # Global flagled_state = 'LED is OFF.'pico_led.off()led_is_on = False # Global flagdef webpage(temperature): global servo_running global servo_state global led_is_on global led_state html_top = """<!DOCTYPE html> <html> <head> <title>Lazy Project</title> <script> function redirectToRoot(event) { event.preventDefault(); // Prevent the default form submission window.location.href = '/'; // Redirect to the root URL } // Refresh the page every 5 seconds setTimeout(function() { window.location.href = '/'; }, 5000); </script> </head> <body> <h1>Pico WH </h1> """ if not servo_running: html_servo = """<form action="./activateservo" onsubmit="redirectToRoot()"> <input type="submit" value="Activate Servo" /> </form> """ else: html_servo = """<form action="./activateservo" onsubmit="redirectToRoot()"> <input type="submit" value="Activate Servo" disabled /> </form> """ if led_is_on: html_led = f"""<form action="./lighton" onsubmit="redirectToRoot()"> <input type="submit" value="Light on" disabled /> </form> <form action="./lightoff" onsubmit="redirectToRoot()"> <input type="submit" value="Light off" /> </form> """ else: html_led = f"""<form action="./lighton" onsubmit="redirectToRoot()"> <input type="submit" value="Light on" /> </form> <form action="./lightoff" onsubmit="redirectToRoot()"> <input type="submit" value="Light off" disabled /> </form> """ html_bottom = f"""<p>Temperature is {temperature}</p> <p>{led_state}</p> <p>{servo_state}</p> </body> </html> """ html = html_top + html_servo + html_led + html_bottom return (html)def lighton(): global led_is_on global led_state print("led on") pico_led.on() led_is_on = True led_state = "LED is ON." returndef lightoff(): global led_is_on global led_state print("led off") pico_led.off() led_is_on = False led_state = "LED is OFF." returnasync def activate_servo(): global servo_running global servo_state if servo_running: print("Servo is running, further requests discarded.") return servo_running = True servo_state = 'Servo is running, further requests discarded.' print("Servo is running, further requests discarded.") print("PWM up") # Define the servo pin (change the pin number as per your connection) servo_pin = Pin(0) # Create a PWM instance servo = PWM(servo_pin) # Set the frequency of the PWM signal servo.freq(50) # 50 Hz for standard servos (20ms) # code found https://www.waveshare.com/wiki/Pico-Servo-Driver # https://files.waveshare.com/upload/3/31/Pico_Servo_Driver_Code.7z # duty_u16 max 65535 # servo.duty_u16(0) # for i in range(0,6553,100): # servo.duty_u16(i) # await asyncio.sleep(0.01) # for i in range(6553,0,-10): # servo.duty_u16(i) # await asyncio.sleep(0.01) # servo.duty_u16(0) # Define the pulse widths for -90, 0, and +90 degrees min_pulse = 65535 // 20 # Approximately 1 ms pulse width mid_pulse = 65535 // 20 + (65535 // 40) # Approximately 1.5 ms pulse width max_pulse = 65535 // 10 # Approximately 2 ms pulse width # Move to -90 degrees servo.duty_u16(min_pulse) await asyncio.sleep(2) # Wait for 2 second # Move to 0 degrees (neutral) servo.duty_u16(mid_pulse) await asyncio.sleep(2) # Move to +90 degrees servo.duty_u16(max_pulse) await asyncio.sleep(2) # Move back to 0 degrees servo.duty_u16(mid_pulse) await asyncio.sleep(2) print("PWM down") # Stop the PWM servo.deinit() servo_state = 'Servo is idle.' servo_running = False return def connect_to_network(): wlan.active(True) wlan.config(pm = 0xa11140) # Disable power-save mode wlan.connect(ssid, password) max_wait = 10 while max_wait > 0: if wlan.status() < 0 or wlan.status() >= 3: break max_wait -= 1 print('waiting for connection...') time.sleep(1) if wlan.status() != 3: print('wlan.status: ', wlan.status) raise RuntimeError('network connection failed') else: print('connected') status = wlan.ifconfig() print('ip = ' + status[0])async def serve_client(reader, writer): print("Client connected") temperature = 0 temperature = pico_temp_sensor.temp request_line = await reader.readline() print("Request:", request_line) # Request it's either # GET /favicon.ico HTTP/1.1\r\n # or something like # GET /lighton? HTTP/1.1\r\n # so by analysing request, we understand what the client requested # We are not interested in HTTP request headers, skip them # discard each line of the header until it's only \r\n (last line of HTTP headers) while await reader.readline() != b"\r\n": pass request = str(request_line) led_on = request.find('/lighton') #search /lighton in the Request led_off = request.find('/lightoff') #search /lightoff in the Request servo = request.find('/activateservo') print( 'led on = ' + str(led_on)) # this is -1 if /lighton was not in the request, else is 6 print( 'led off = ' + str(led_off)) print( 'servo = ' + str(servo)) if led_on == 6: lighton() if led_off == 6: lightoff() if servo == 6: asyncio.create_task(activate_servo()) # state = activate_servo() print('temp: '+str(temperature)) response = webpage(temperature) # print(str(response)) writer.write('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n') writer.write(response) await writer.drain() await writer.wait_closed() print("Client disconnected")async def main(): print('Connecting to Network...') connect_to_network() print('Setting up webserver...') asyncio.create_task(asyncio.start_server(serve_client, "0.0.0.0", 80)) counter = 0 while True: # Toggle LED for 250 milliseconds pico_led.toggle() await asyncio.sleep(0.25) # onboard.on() # print("heartbeat") counter += 1 # Increment the counter if counter == 12: print("heartbeat") # print every 60 secs counter = 0 # Reset the counter # onboard.off() pico_led.toggle() await asyncio.sleep(5) try: asyncio.run(main())finally: asyncio.new_event_loop()
Statistics: Posted by fiore42 — Mon Jan 22, 2024 11:10 pm