Following various examples, I’ve created a MicroPython script that does the following:
- Create an access point on the Raspberry Pi Pico W.
- Create a web server.
- Serve a simple page on that web server.
- Toggle/flash the on-board LED when that page is loaded/refreshed.
TL;DR – see the code here
Download MicroPython and install it
First of all, you’ll need to download the latest MicroPython UF2. The one I’m using is v1.19.1-108-g474c47d59 (2022-07-08) .uf2 from this page. I found out via the Raspberry Pi forums that there was something broken on versions earlier than the 07-05 one – check out the thread here.
Next, you will need to put the Pico into bootloader mode and then drag the UF2 file to the external device that comes up.
Initial access point
Use Thonny to program the initial code:
import socket import network ssid = "PicoW" password = "123456789" ap = network.WLAN(network.AP_IF) ap.config(essid=ssid, password=password) ap.active(True) while ap.active == False: pass print("Access point active") print(ap.ifconfig())
Despite setting the SSID, to start with I got a generic wi-fi name starting with “PICO”. In order to get PicoW working, I had to power cycle the Pico (rather than just CTRL-D and run again). This is behaviour described here on the RP forums.
I tried connecting to it using my mobile and success – I could connect to the access point, but had no Internet (as expected, obviously).
Serving a web page
Now, I want to serve a web page of some kind from the Pico W, otherwise it’s pretty useless. What’s the point in having an access point that does nothing?
I found this MicroPython library called tinyweb which is like Flask, but for MicroPython instead of full-blown Python. This I can use to establish “routes” which will deliver specific content via the web browser.
tinyweb requires, as it says in the README, the logging library. I had to scratch around to find that, so here it is.
I uploaded the tinyweb folder and the logging.py file to the PicoW and added
import tinyweb
at the top of the code. This ran correctly, so I then looked at the tinyweb documentation for how to create a web server.
I added some more code (which you can see on my own GitHub repo – WordPress is doing VERY weird things if I paste it in here!)
I connected to the AP again using my phone, turned off mobile data to make sure it didn’t try and serve content from the Internet, and then accessed http://192.168.4.1/ (which had been printed to the REPL which I could see because I was using Thonny).
To my surprise, I got Hello world! on the browser. Yay! It works!
Flash the onboard LED
I added the definition of the onboard LED:
led = Pin("LED", Pin.OUT)
and set the / path of the tinyweb web server to toggle it on and off.
Now, when I refresh the Hello World page, the LED goes on and off. Wonderful!
Hi Michael,
Thonny shows that the access point is active. How can I connect to the access point on Windows 10. It doesn’t work with chrome.
Greetings Konrad
Hi Konrad,
First of all, you’ll need to use the Windows wi-fi connection tool to connect TO your new access point. Let me know if you still get probs.
Hi Michael,
the access point is not displayed in the windows wi-fi connection tool. What can I do?
Hi Michael,
now it’s working. thanks for the example
Excellent work Michael, need this for my electric gates on my property
How do you upload the tinyweb folder and the logging.py file to the picoW? I opened the picoW with bootsel and copied the files over and it said couldn’t find tinyweb when i tried to import. I booted again with bootsel and the files are gone?
Wonderful example and it worked for me. I also edited the HTML a bit, added few buttons and linked them to different URLs like ”192.168.4.1/led_on or /led_off”. But I cannot wrap my head around how to make Pico do things when these URLs are visited.
Hi Cagan,
Okay, if you look at the code here: https://github.com/recantha/PicoWAccessPoint/blob/main/main.py
…you will see a bit that starts:
@app.route(‘/’)
…then a function
This defines the behaviour when you hit / – you will see it prints something to the screen and then does led.toggle() to turn the LED on or off.
What you’d need to do is to define your own route:
@app.route(‘/led_on’)
and then create a new function below it (similar to the one for /) which would turn the LED on – led.on().
Then, create your led_off route and function to do led.off()
Hope that makes sense!
—
Mike
Have you had any luck running this with external power supply? When I run connected to my computer everything works smoothly, but when I run it as main.py on startup not connected to my laptop it gets stuck setting up the AP. Thanks for the great tutorial.
I seem to remember having a similar problem, but I can’t remember what I did to resolve it. Sorry. However, it’s possible there’s a better example out there for doing the same thing, maybe with a different library?