In this guide, you’ll learn how to create a basic Raspberry Pi Pico local web server to control outputs and fetch data. As an example, we’ll create a web page to control an LED on and off and fetch some random values generated by the Pico. This example can be easily modified or extended to control multiple outputs and fetch data from sensors instead of random numbers.
This tutorial is only compatible with the Raspberry Pi Pico W that comes with Wi-Fi support. Throughout this tutorial whenever we refer to the Raspberry Pi Pico, we’re referring to the Raspberry Pi Pico W.
New to the Raspberry Pi Pico? Start here: Getting Started with Raspberry Pi Pico.
Table of Contents
This tutorial covers the following topics:
- Introducing Basic Web Server Concepts
- Project Overview
- Creating the HTML Page
- Raspberry Pi Pico Web Server – MicroPython Script
- Raspberry Pi Pico Web Server Demonstration
Prerequisites – MicroPython Firmware
To follow this tutorial you need MicroPython firmware installed in your Raspberry Pi Pico board. You also need an IDE to write and upload the code to your board.
The recommended MicroPython IDE for the Raspberry Pi Pico is Thonny IDE. Follow the next tutorial to learn how to install Thonny IDE, flash MicroPython firmware, and upload code to the board.
Introducing Basic Concepts
Already familiar with basic web server concepts? Jump to the Project Overview section.
The Raspberry Pi Pico as a Web Server
In simple terms, a web server is a “computer” that provides web pages. It stores the website’s files, including all HTML documents and related assets like images, CSS style sheets, fonts, and/or other files. It also brings those files to the user’s web browser device when the user makes a request to the server.
When using the Raspberry Pi Pico as a web server, you’re essentially turning it into a small computer that stores and provides web pages. As users access a web page, their browsers send requests to the Pico using Hypertext Transfer Protocol (HTTP). The Pico then responds by sending back the requested web page.
Client and Server
When you type a URL in your browser, in the background, you (the client) send a request via Hypertext Transfer Protocol (HTTP) to a server. When the server receives the request, it sends a response through HTTP, and you will see the web page requested in your browser. Clients and servers communicate over a computer network.
In simple terms, clients make requests to servers. Servers handle the clients’ requests. In this particular tutorial, the Raspberry Pi Pico will be the server, and you (your browser) will be the client.
Ip Address
An IP address is a numerical label assigned to each device connected to a computer network. It is a series of four values separated by periods with each value ranging from 0 to 255. Here’s an example:
192.168.1.75
At home, your devices are connected to a private network through your router (local network). All devices connected to your router are part of your local network. Inside this network, each device has its own IP address.
Devices that are connected to the same router can access each other via the IP address. Devices outside your local network can’t access your local devices using their local IP address.
When you connect your Raspberry Pi Pico to your router, it becomes part of your local network. So, it will be assigned a unique local IP address and you can access it from your computer on your local network.
Sockets
We’ll create our web server using sockets and the Python socket API.
Sockets and the socket API are used to send messages across a network. They provide a form of inter-process communication (IPC).
Sockets can be used in client-server applications, where one side acts as the server and waits for connections from clients – that’s what we’ll do here (the Raspberry Pi Pico is a server waiting for connections from clients).
Project Overview
Before going straight to the project, it is important to outline what our web server will do so that it is easier to understand how everything works.
We’ll create a simple web page with two buttons to control the Raspberry Pi Pico onboard LED on and off. The web page also has another button to request a new random value (this can easily be modified to request sensor readings).
Here’s a quick explanation of how everything works.
When you enter the Raspberry Pi Pico address on your web browser, you’re making a request to the Raspberry Pi Pico on the root (/) URL. When it receives that request, it responds with the HTML to build the web page we’ve seen previously.
When you click on the Light on button, it makes a request on the /lighton? URL. When it receives that request, it turns the onboard LED on and sends the web page with the updated LED state.
When you click on the Light off button, a request is made on the /lightoff? URL. When that happens, it will turn off the LED and send the web page with the current LED state.
Finally, we also have a button to request a random value from the Raspberry Pi Pico. This can be easily modified to request sensor readings or any other useful piece of information. That button sends a request on the /value? URL. When the Pico receives that request, it generates a new random value and sends the HTML page updated with that new value.
The HTML Page
Below you can find the HTML we’ll use to build the web page:
<!DOCTYPE html>
<html>
<head>
<title>Pico Web Server</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h1>Raspberry Pi Pico Web Server</h1>
<h2>Led Control</h2>
<form action="./lighton">
<input type="submit" value="Light on" />
</form>
<br>
<form action="./lightoff">
<input type="submit" value="Light off" />
</form>
<p>LED state: {state}</p>
<h2>Fetch New Value</h2>
<form action="./value">
<input type="submit" value="Fetch value" />
</form>
<p>Fetched value: {random_value}</p>
</body>
</html>
In this particular example, we’ll save the contents of the HTML file in a variable in our MicroPython script (but, it can also be saved in a file in the Raspberry Pi Pico filesystem—not covered in this tutorial).
This HTML structure creates a basic web page for controlling an LED and fetching a random value, for interaction with a Raspberry Pi Pico web server.
The {state} and {random_value} variables are meant to be dynamically populated with values from the server-side logic.
In summary, this HTML creates three different forms with buttons.
Raspberry Pi Pico Web Server – MicroPython Script
Create a new file in Thonny IDE and copy the following code.
# Complete project details at https://RandomNerdTutorials.com/raspberry-pi-pico-web-server-micropython/
# Import necessary modules
import network
import socket
import time
import random
from machine import Pin
# Create an LED object on pin 'LED'
led = Pin('LED', Pin.OUT)
# Wi-Fi credentials
ssid = 'REPLACE_WITH_YOUR_SSID'
password = 'REPLACE_WITH_YOUR_PASSWORD'
# HTML template for the webpage
def webpage(random_value, state):
html = f"""
<!DOCTYPE html>
<html>
<head>
<title>Pico Web Server</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h1>Raspberry Pi Pico Web Server</h1>
<h2>Led Control</h2>
<form action="./lighton">
<input type="submit" value="Light on" />
</form>
<br>
<form action="./lightoff">
<input type="submit" value="Light off" />
</form>
<p>LED state: {state}</p>
<h2>Fetch New Value</h2>
<form action="./value">
<input type="submit" value="Fetch value" />
</form>
<p>Fetched value: {random_value}</p>
</body>
</html>
"""
return str(html)
# Connect to WLAN
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(ssid, password)
# Wait for Wi-Fi connection
connection_timeout = 10
while connection_timeout > 0:
if wlan.status() >= 3:
break
connection_timeout -= 1
print('Waiting for Wi-Fi connection...')
time.sleep(1)
# Check if connection is successful
if wlan.status() != 3:
raise RuntimeError('Failed to establish a network connection')
else:
print('Connection successful!')
network_info = wlan.ifconfig()
print('IP address:', network_info[0])
# Set up socket and start listening
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(addr)
s.listen()
print('Listening on', addr)
# Initialize variables
state = "OFF"
random_value = 0
# Main loop to listen for connections
while True:
try:
conn, addr = s.accept()
print('Got a connection from', addr)
# Receive and parse the request
request = conn.recv(1024)
request = str(request)
print('Request content = %s' % request)
try:
request = request.split()[1]
print('Request:', request)
except IndexError:
pass
# Process the request and update variables
if request == '/lighton?':
print("LED on")
led.value(1)
state = "ON"
elif request == '/lightoff?':
led.value(0)
state = 'OFF'
elif request == '/value?':
random_value = random.randint(0, 20)
# Generate HTML response
response = webpage(random_value, state)
# Send the HTTP response and close the connection
conn.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
conn.send(response)
conn.close()
except OSError as e:
conn.close()
print('Connection closed')
You just need to insert your SSID and password on the following variables and the code should work straight away.
# Wi-Fi credentials
ssid = 'REPLACE_WITH_YOUR_SSID'
password = 'REPLACE_WITH_YOUR_PASSWORD'
How does the Code Work?
Continue reading to learn how the code works, or skip to the Demonstration section.
Importing Libraries
Start by importing the required modules, including network for Wi-Fi, socket for communication between client and server, time for delays, random for generating random numbers, and Pin from machine for GPIO pin control.
import network
import socket
import time
import random
from machine import Pin
Declaring the LED Pin
Create a Pin object named led that corresponds to the Raspberry Pi Pico onboard LED. It’s configured as an output pin. It will interpret ‘LED’ as the onboard LED.
led = Pin('LED', Pin.OUT)
Set the Wi-Fi credentials for the network you want to connect to. Modify these variables with your own credentials.
# Wi-Fi credentials
ssid = 'REPLACE_WITH_YOUR_SSID'
password = 'REPLACE_WITH_YOUR_PASSWORD'
Creating the Web Page
To generate the web page, we created a function called webpage() that accepts as arguments a random value and the LED state. We’re generating the web page in a function because it allows us to dynamically change its content at the time of sending it to the client. This way, we can send the page with the latest information about the GPIO state or random value.
# HTML template for the webpage
def webpage(random_value, state):
html = f"""
<!DOCTYPE html>
<html>
<head>
<title>Pico Web Server</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h1>Raspberry Pi Pico Web Server</h1>
<h2>Led Control</h2>
<form action="./lighton">
<input type="submit" value="Light on" />
</form>
<br>
<form action="./lightoff">
<input type="submit" value="Light off" />
</form>
<p>LED state: {state}</p>
<h2>Fetch New Value</h2>
<form action="./value">
<input type="submit" value="Fetch value" />
</form>
<p>Fetched value: {random_value}</p>
</body>
</html>
"""
return str(html)
To better understand how this works and the usage of f-strings along with curly braces {} to include variables in the HTML string, continue reading.
The triple quotes (“””) are used to create a multi-line string. This allows for easy formatting of the HTML content without needing to concatenate multiple strings. Our HTML content is more readable this way, but you can concatenate everything on the same line if you want to.
The f before the opening triple quote denotes an f-string, which is a way to embed expressions inside string literals. In this case, it allows the inclusion of variables (random_value and state) directly within the string.
html = f"""
The curly braces {} inside the f-string act as placeholders for variables. The variables inside the curly braces are replaced with their actual values during the string formatting.
In summary, the {state} and {random_value} within the HTML content are placeholders for the actual values of the state and random_value variables.
<p>LED state: {state}</p>
<p>Fetched value: {random_value}</p>
This dynamic string formatting makes it easy to incorporate variable values directly into the HTML content, providing a clean and readable way to generate dynamic web pages.
When we call this function, it will return an HTML page with the current random value and LED state.
Connecting to the Internet
The following lines are responsible for connecting your Raspberry Pi Pico to your local network using the SSID and password you defined earlier.
# Connect to WLAN
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(ssid, password)
Wait for the Wi-Fi connection to be established. It checks the connection status, and if it’s wlan.status() >= 3 (this means it has even connected to the network or failed to connect), the loop exits. It waits for a maximum of 10 seconds.
The method wlan.status, as the name suggests, checks the status of the Wi-Fi connection of the Raspberry Pi. This method returns an integer with the following meaning:
- 0: WLAN is not enabled
- 1: WLAN is currently scanning for networks
- 2: WLAN is connecting to a network
- 3: WLAN is connected to a network
- 4: WLAN failed to connect to a network
Then, we check if it’s connected or not (we know that status = 3 means it’s connected). If wlan.status() is different than 3, we know it failed to establish a connection.
Otherwise, it means we succeed. In case we succeed, we can get the network information using the ifconfig() method. This method returns a tupple with the following information:
network_info[0]: The IP address assigned to the Pico on the network.
network_info[1]: The subnet mask.
network_info[2]: The gateway IP address.
network_info[3]: The DNS (Domain Name System) server IP address.
We just need the IP address, so we just get the first element of the array (network_info[0]).
else:
print('Connection successful!')
network_info = wlan.ifconfig()
print('IP address:', network_info[0])
Creating a socket server
After establishing a connection with our network, we need to create a listening socket to listen for incoming requests and send the HTML text in response. For a better understanding, the following figure shows a diagram of how to create sockets for server-client interaction:
Set up a socket to listen on port 80. It uses the 0.0.0.0 address, indicating that it will listen on all available network interfaces. The SO_REUSEADDR option allows the socket to reuse the address (this way you won’t have problems with addresses already in use when you try to run the webserver after the first time).
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(addr)
s.listen()
The following line gets information about the socket address, specifically the address and port.
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
Create a socket using socket.socket().
s = socket.socket()
Next, bind the socket to an address (network interface and port number) using the bind() method. The bind() method accepts a tupple variable with the ip address, and port number, that we saved previously on the addr variable:
s.bind(addr)
Put the socket into listening mode. This means it’s now ready to accept incoming connections.
s.listen()
Initializing Variables
Initialize variables for the LED state (state) and for the random value (random_value).
# Initialize variables
state = "OFF"
random_value = 0
Listening for Connections
In the while loop, we listen for requests and send responses. When a client connects, the server calls the accept() method to accept the connection. When a client connects, it saves a new socket object to accept and send data on the conn variable, and saves the client address to connect to the server on the addr variable.
conn, addr = s.accept()
Then, print the address of the client saved on the addr variable.
print('Got a connection from', addr)
The data is exchanged between the client and server using the send() and recv() methods.
The following line gets the request received on the newly created socket and saves it in the request variable.
request = conn.recv(1024)
The recv() method receives the data from the client socket (remember that we’ve created a new socket object on the conn variable). The argument of the recv() method specifies the maximum amount of data that can be received at once in bytes.
The next line simply prints the content of the request:
print('Request content = %s' % request)
Get the Request Content
Then, we get the content of the request with request.split()[1]. It splits the received HTTP request string into a list of words and takes the second element (index 1) of the list. This is typically the path part of the HTTP request, which is the information that we need to know which button was clicked on the web interface.
try:
request = request.split()[1]
print('Request:', request)
except IndexError:
pass
Process the requests
We then check the contents of the request and act accordingly. If the request is on the /lighton? path, we turn the LED on and update the state variable to ‘ON’.
if request == '/lighton?':
print("LED on")
led.value(1)
state = "ON"
If the request is /lightoff?, we turn the LED off and update the state variable to ‘OFF’.
elif request == '/lightoff?':
led.value(0)
state = 'OFF'
Finally, if the request is on the /value? path, we generate a new random value and save it on the random_value variable.
elif request == '/value?':
random_value = random.randint(0, 20)
As we’ve mentioned previously, instead of generating a random value, you can get sensor readings.
Sending the Response
After processing the request, we’ll call the webpage() function with random_value and state as arguments to generate an HTML page with the updated values. The content to generate the web page is saved on the response variable.
response = webpage(random_value, state)
Finally, send the response to the socket client using the send() method:
conn.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
conn.send(response)
In the end, close the created socket.
conn.close()
Raspberry Pi Pico Web Server – Demonstration
Run the previous code on your Raspberry Pi Pico. You just need to click on the Thonny IDE green run button.
The Raspberry Pi IP address will be printed after a few seconds. In my case, it’s 192.168.1.82.
Open a web browser on your local network and type your Raspberry Pi Pico IP address. The following web page should load.
You can click the Light on and Light off buttons to turn the Raspberry Pi Pico onboard LED on and off.
You can also click on the Fetch value to request a new random generated value from the Raspberry Pi Pico. It should respond with the web page containing the newest value.
You can easily modify the web server to request sensor readings or any other useful information.
The web server is also accessible from your smartphone as long as it is connected to the same network.
If you want the Raspberry Pi Pico to run the webserver without being connected to your computer, you need to upload the code as main.py to the Raspberry Pi Pico filesystem. For that, after copying the code to a new file, go to File > Save as and select Raspberry Pi Pico.
Name the file main.py and click OK to save the file on the Raspberry Pi Pico. Now, it will run the main.py file on boot without the need to be connected to the computer.
Wrapping Up
In this tutorial, you learned the basics of building a web server with the Raspberry Pi Pico. As an example, we’ve built a simple page with buttons to control a GPIO and a section to request a new random value from the board.
This is just a basic example for you to understand how building a web server works. The idea is to modify the project to control GPIOs to activate relays, control motors, and display sensor readings or any other useful information.
We hope you’ve found this tutorial useful.
Learn more about the Raspberry Pi Pico with our eBook:
If you like the Raspberry Pi Pico, make sure you take a look at other tutorials on our blog:
- Raspberry Pi Pico and Pico W Pinout Guide: GPIOs Explained
- Raspberry Pi Pico: Control Digital Outputs and Read Digital Inputs (MicroPython)
- Raspberry Pi Pico: PWM Fading an LED (MicroPython)
- Raspberry Pi Pico: DHT11/DHT22 Temperature and Humidity Sensor (MicroPython)
Check out all our Raspberry Pi Pico Guides »
Thanks for reading.
As always, very informative.
I tried my hand at Micro Python over the past holiday season. I currently have a Pool Water Temperature controller system running (Arduino Nano) keeping my pool water WARM (35°C and more sometimes). The controller monitors the temperature of the water heater panels on the roof. Once they reach a threshold Set Point, the Pool pump is switched on. Then the water temperature is monitored going to the panels and returning from the panels. I calculate the Difference. If the returning water is not greater than a required set point value (e.g. 0.5°C) the pump is switched off, and the whole process repeats.
I wanted to use a Pi Pico W to have all the variables displayed on my phone via web server from the Pico W. The Web page part works 100%, but the control part (as mentioned above) does not execute unless a web page is required or refreshed.
I have the same code in the main loop. The problem with python “try:” is that it only seems to be triggered from the web page request.
# Main loop to listen for connections
while True:
try: (code here)
How can “Control” code be called cyclically in python without a web page request? The control code must run 24/7, vs a web page only being called say once or twice a day?
Hi.
I think you can add that logic to the while loop, but outside the try statement for the web server.
Did you try that?
Regards,
Sara
Hi.
Yes, I’ve tried nearly everything, BUT, it would never have worked.
I found this very informative YouTube channel by Bob Grant.
youtube.com/@BytesNBits
In there, Bob has a playlist “Web Control Panel for MicroPython”
youtube.com/watch?v=h18LMskRNMA&list=PLvOT6zBnJyYGLmvrJeYzRYwBFa44SVnLZ
He describes the calling of web pages as a “Blocking Function”. There is no way on earth that any other code will run unless you either do “Asynchronous calling (task management)” or using the second core of the Pico. A combination of the two is also possible and Bob explains that quite well.
I will play around with Bob’s suggestions and see what I manage to get going for my application.
Regards.
Hi again.
You’ll probably need to use the asyncio library for that, but I haven’t taken a look into that yet.
Regards,
Sara
Option 1. Use timer(s) to run routines like read temp and store it into a variable, do your comparison to turn on/off your pump. Then use the web page to read said variables and/or to control the pump manually. This way, running/displaying the web page will not condition your code.
Option 2. Use AJAX call to update the content of the page.
I got the program to run perfectly on the first try. I then copied it to the RP Pico as main.py . When I then plug the RP Pico into a USB power supply, the unit appears unresponsive. I’ve tried several times without luck. Any suggestions? Am I missing a step? Thanks
Hi.
Did you check that the file was actually uploaded to the Pi and that it is in the filesystem?
Regards,
Sara
Yes. A bit more info… I tried commenting out all of the print statements. Then I found that it works properly if, after I plug it into the usb power supply, I pull the run pin (Pin 30) to ground momentarily to force a reset. (However, unplugging and replugging the usb doesn’t seem to work). Hmmmm.
Hi Sara and Rui,
I have read several of your tutorials on the Raspberry Pi Pico and Raspberry Pi Pico W, but have no practical experience with either of these modules.
This tutorial constantly refers to the Raspberry Pi Pico, but my understanding is that none of this will work with the basic Pico. It will only work with a Pico W.
Perhaps you should update the tutorial to specify that a Pico W is essential and change all references from Pico to Pico W.
Hi.
Yes. You are right. You need a Pico W.
I added a note at the beginning of the tutorial mentioning that you need a Pico W, and that when we’re referring to the Raspberry Pi Pico, we mean a Raspberry Pi Pico W.
Thanks for pointing that out.
Regards,
Sara
Raspberry Pico is a dual core processor. Use one for web server and the other for the logic
Hi.
Alternatively, you can use asynchronous tasks using asyncio.
It works great. I’ve tried it already. Need to create a tutorial about that.
Regards,
Sara
It would be great if you could put together a little tutorial on how to do multithreading. Perhaps you could redo this same project using two threads to show us how.
Here you are with a sample of thread in Raspberry Pico. It’s inspired by the one I took from the book issued by Raspberry Pi (free on line).
It’s the simulation of a traffic light where the lights on/off are controlled by the simple delay instruction and there is a button for the pedestrians to ask their right to cross the road. If we use one single core, it cannot capture the click on the button because the delay is “killing” the CPU for some seconds. If this task is transferred to the second core, it’s completely independent and the click can be seen immediately and stored to be managed after the light is switched off. Obviously this task is still a task of the first core which also switches a buzzer on to signal the pedestrian crossing. Good work!
from machine import Pin, PWM
import time
import _thread
ledRed = Pin(13, Pin.OUT)
ledYellow = Pin(14, Pin.OUT)
ledGreen = Pin(15, Pin.OUT)
button = Pin( 7, Pin.IN, Pin.PULL_DOWN)
buzzer = PWM(8)
global buttonClick
buttonClick = False
def thread_Readbutton():
global buttonClick
while True:
if button.value() == 1:
buttonClick = True
print(“Click”)
_thread.start_new_thread(thread_Readbutton, ())
while (True):
ledRed.value(1)
print(“Red”)
if buttonClick == True:
for i in range(20):
buzzer.freq(500)
buzzer.duty_u16(16000)
ledYellow.on()
time.sleep(0.25)
ledYellow.off()
buzzer.freq(100)
time.sleep(0.25)
buttonClick = False
buzzer.freq(20)
buzzer.duty_u16(20)
time.sleep(5)
ledRed.value(0)
print(“Green”)
ledGreen.value(1)
time.sleep(5)
print(“Yellow”)
ledYellow.value(1)
time.sleep(2)
ledGreen.value(0)
ledYellow.value(0)
I have tried that.
Using ‘import _thread’ and adding this line to my code ….
run main control loop on second processor
second_thread = _thread.start_new_thread(main_loop, ())
did work for just a few seconds and then things go south real fast.
According to the “_thread” documentation it seems like development is still in Beta phase.
I have managed to get the “uasyncio” going very well.
Need to import uasyncio
Have one function setup as follow
#############
Call web server handling
#############
async def phew_server():
server.run()
await uasyncio.sleep_ms(50)
Have a second function setup as follow
#############
Call Control section
#############
async def main_loop():
while True:
And right at the end of the python file the following
#############
MAIN
#############
event_loop = uasyncio.get_event_loop()
event_loop.create_task(phew_server())
event_loop.create_task(main_loop())
event_loop.run_forever()
Runs like a dream. No hangups or failures.
You may want to take a peek here:
https://gist.github.com/aallan/3d45a062f26bc425b22a17ec9c81e3b6
Dear Sara:
Recently I have bought two Raspberry pi pico (original) not Chinese, well I have tried several times to install your RPIPIW Webserver in order to see how it works, well every try has been rejected with the “import network” instrucction, I have tried to solve installing the pluggin “network” in Thonny, and the the same result (f..y..!!), always network does not work( sh..!!). Solution the version of micropython in both microcontrollers is the latest micropython 1.24 and it does not work , I have read in https://forums.raspberrypi.com/viewtopic.php?t=359263 that version 1.20 works perfectly (https://github.com/micropython/micropython/releases/tag/v1.20.0). Well I will try to write the different steps of how to reinstall the software inside the Raspberry pi pico w, hope this lines will help ,also I have found something in order to run programs in the fake rpipw-esp8295 .
I am not going to surrender if I could make work an Esp01 this means nothing i only need the help of Madonna, Tears for fears, The cure, an U2 and will work.
Best regards
Visca Valencia
Luis
Hi.
Your problem is probably one of the following:
– you don’t have a Raspberry Pi Pico W (you have the Pico version without the W—without network, so it doesn’t work). OR:
– you uploaded micropython firmware for the Pico (which doesn’t have Wi-Fi support), instead of the Pico W, with Wi-Fi support.
When uploading the firmware, make sure you select the right one.
Regards,
Sara