Guías · 18 min de lectura

Raspberry Pi Pico W WiFi: crea un servidor web con MicroPython

Raspberry Pi Pico W WiFi: el UF2 correcto, network.WLAN y códigos de estado, servidor web para un LED, datos de sensores en vivo, API con urequests y hora NTP.

Usar el WiFi de la Raspberry Pi Pico W es una de las formas más baratas y sencillas de crear un pequeño dispositivo que controlas desde el móvil. La Pico W es la versión de la conocida Raspberry Pi Pico que añade WiFi de 2,4 GHz y Bluetooth: con unas pocas líneas de MicroPython se conecta a la red de casa, sirve su propia página web y descarga el tiempo y la hora de internet. En esta guía conectarás una Pico W al WiFi desde cero, montarás un servidor web que enciende un LED desde el móvil y después harás una página que muestra datos de un sensor en tiempo real.

Al terminar sabrás elegir el archivo UF2 correcto, conectarte con network.WLAN e interpretar sus códigos de estado, obtener datos de una API con urequests, poner la hora con NTP y hacer lo mismo desde el Arduino IDE. Si la Pico es nueva para ti, te ayudará leer primero ¿Qué es la Raspberry Pi Pico?, y los comandos básicos están en la guía ¿Qué es MicroPython?.

Raspberry Pi Pico WH: Pico W con WiFi y pines ya soldados
Raspberry Pi Pico WH: bajo el blindaje metálico está el chip inalámbrico Infineon CYW43439, y la antena impresa ocupa el extremo opuesto al conector USB. La "H" del nombre indica que los pines vienen soldados.

¿Qué es la Raspberry Pi Pico W y en qué se diferencia de la Pico?

La Pico W usa el mismo procesador RP2040, el mismo tamaño y la misma distribución de 40 pines que la Pico. La diferencia es el chip inalámbrico Infineon CYW43439 añadido a la placa: ofrece WiFi 802.11n a 2,4 GHz y Bluetooth 5.2. El procesador se comunica con este chip mediante un bus SPI interno; tú solo usas el módulo network de MicroPython. Más tarde Raspberry Pi lanzó la Pico 2 W con el procesador RP2350; como el chip inalámbrico es el mismo, todo el código de este artículo funciona también en ella.

CaracterísticaPico WPico 2 WESP32 (WROOM-32)
ProcesadorRP2040, doble núcleo Cortex-M0+, 133 MHzRP2350, doble núcleo Cortex-M33 (o RISC-V), 150 MHzXtensa LX6, doble núcleo, 240 MHz
RAM264 KB520 KB520 KB
Memoria flash2 MB4 MBNormalmente 4 MB
WiFi2,4 GHz, 802.11n (CYW43439)2,4 GHz, 802.11n (CYW43439)2,4 GHz, 802.11 b/g/n (integrado)
Bluetooth5.2 (Classic y BLE)5.2 (Classic y BLE)4.2 (Classic y BLE)
Entradas analógicas3 canales, 12 bits3 canales, 12 bits18 canales, 12 bits
Archivo de MicroPythonRPI_PICO_W (.uf2)RPI_PICO2_W (.uf2)ESP32_GENERIC (.bin)

Sobre el papel, el ESP32 es más rápido y tiene más ejemplos en el mundo Arduino. Los puntos fuertes de la Pico W son un soporte de MicroPython oficial y maduro, una documentación ordenada y unos pines sin trampas del tipo "debe estar a este nivel al arrancar". Si te gusta aprender con Python, la Pico W es una gran elección; si para ti priman el código Arduino y las librerías listas para usar, el ESP32 puede resultarte más cómodo. Si dudas entre las dos, la comparativa ¿Arduino o ESP32? te orientará.

El chip inalámbrico de la Pico W y las diferencias en los pines

Los pines accesibles de la Pico W son exactamente los mismos que en la Pico: GP0–GP22 y GP26–GP28 se pueden usar libremente, y las entradas analógicas siguen en GP26, GP27 y GP28. Lo que cambia son los cuatro pines que quedan dentro de la placa. En la Pico gestionan el LED integrado, el modo de la fuente y la detección de USB; en la Pico W están reservados para hablar con el chip inalámbrico, y el LED va conectado directamente a ese chip. Puedes ver el mapa completo de pines en la herramienta Pinout.

Pin internoFunción en la PicoFunción en la Pico W
GP23Modo de la fuente de alimentación (SMPS)Encendido del chip inalámbrico (WL_ON)
GP24Detección de tensión USB (VBUS)Línea de datos e interrupción inalámbrica (WL_D)
GP25LED integradoSelección del chip inalámbrico (WL_CS)
GP29Medida de la tensión VSYS (ADC3)Reloj inalámbrico (WL_CLK) y medida de VSYS
LED integradoGP25: Pin(25)WL_GPIO0 del chip inalámbrico: Pin("LED")
No intentes encender el LED integrado de la Pico W con Pin(25); ese pin es ahora la línea de selección del chip inalámbrico. La forma correcta es Pin("LED", Pin.OUT), y esa misma línea funciona en la Pico, la Pico W y la Pico 2 W. Además, no pongas metal, pilas ni un manojo de cables debajo o justo al lado de la zona de la antena, en el extremo de la placa; si la antena queda tapada, la señal se debilita bastante.

Paso 1: Cargar el archivo UF2 correcto para la Pico W

El error más habitual es cargar en la Pico W el archivo de MicroPython de la Pico normal. La placa funciona y ves el prompt en el Shell de Thonny, pero en cuanto escribes import network aparece "ImportError: no module named 'network'", porque la versión para la Pico normal no incluye el driver inalámbrico. Cada placa tiene su propio archivo UF2:

PlacaArchivo UF2 de MicroPythonUnidad que aparece con BOOTSEL
Raspberry Pi PicoRPI_PICO-….uf2RPI-RP2
Raspberry Pi Pico W / WHRPI_PICO_W-….uf2RPI-RP2
Raspberry Pi Pico 2RPI_PICO2-….uf2RP2350
Raspberry Pi Pico 2 WRPI_PICO2_W-….uf2RP2350
  1. En la página de descargas de micropython.org busca la placa RPI_PICO_W (RPI_PICO2_W para la Pico 2 W) y descarga el último archivo .uf2 estable, el que no pone "preview".
  2. Mantén pulsado el botón BOOTSEL de la Pico W mientras conectas el cable USB de datos al ordenador y luego suéltalo.
  3. En el ordenador aparece una unidad llamada RPI-RP2. Arrastra a ella el archivo descargado; al terminar la copia, la unidad desaparece sola y la placa se reinicia con MicroPython.
  4. Abre Thonny y elige MicroPython (Raspberry Pi Pico) en el menú del intérprete, abajo a la derecha. Si lo prefieres, la ventana "Install or update MicroPython" de Thonny hace la misma instalación con un clic si eliges la variante Pico W / Pico WH.
  5. Escribe import network en el Shell. Si no hay error, tienes instalado el firmware correcto con soporte inalámbrico.
Si no tienes claro qué placa y qué versión usas, escribe import os; print(os.uname()) en el Shell. Si el campo machine dice "Raspberry Pi Pico W with RP2040", vas bien; el campo release muestra la versión de MicroPython. Para actualizar el firmware basta con repetir los pasos del UF2; los archivos que guardaste en la Pico normalmente se conservan.

Paso 2: Conectarse al WiFi con network.WLAN

La Pico W tiene dos interfaces inalámbricas: en modo WLAN.IF_STA (estación) se conecta a tu router como un móvil, y en modo WLAN.IF_AP (punto de acceso) crea su propia red WiFi. Empecemos por el modo estación. Pega el código siguiente en un archivo nuevo de Thonny, escribe el nombre de tu red y la contraseña y guárdalo en la Pico como wifi.py. Todos los ejemplos siguientes usan este archivo con import wifi, así tu contraseña está en un solo sitio. Si usas una versión de MicroPython anterior a la 1.24, escribe estas constantes como network.STA_IF y network.AP_IF; los nombres antiguos también siguen funcionando en las versiones nuevas.

Python
1# wifi.py: Pico W'ye bu adla kaydet / save it to the Pico W with this name
2import network
3import time
4
5SSID = "AgAdi"            # Wi-Fi adın / your Wi-Fi name
6PASSWORD = "Sifre123"     # Wi-Fi şifren / your Wi-Fi password
7HOSTNAME = "picow"        # http://picow.local adresi için / for http://picow.local
8
9STATUS = {
10    0: "Boşta / idle",
11    1: "Ağa katılıyor / joining",
12    2: "IP bekleniyor / waiting for IP",
13    3: "Bağlandı / connected",
14    -1: "Bağlantı başarısız / connection failed",
15    -2: "Ağ bulunamadı / network not found",
16    -3: "Şifre hatalı / wrong password",
17}
18
19
20def connect(timeout=20):
21    network.country("TR")             # ülke kodu / country code
22    network.hostname(HOSTNAME)        # ağdaki adı / name on the network
23    wlan = network.WLAN(network.WLAN.IF_STA)
24    wlan.active(True)
25    wlan.config(pm=network.WLAN.PM_NONE)   # güç tasarrufunu kapat / disable power saving
26    if not wlan.isconnected():
27        wlan.connect(SSID, PASSWORD)
28        for _ in range(timeout):
29            code = wlan.status()
30            print(code, STATUS.get(code, "?"))
31            if code < 0 or code == 3:
32                break
33            time.sleep(1)
34    if wlan.status() != 3:
35        raise RuntimeError("Wi-Fi: " + STATUS.get(wlan.status(), "?"))
36    print("IP:", wlan.ifconfig()[0])
37    return wlan
38
39
40if __name__ == "__main__":
41    connect()

Veamos las líneas clave. network.country("TR") indica al chip inalámbrico qué normas de canales debe seguir; cambia TR por el código de tu país, por ejemplo ES, MX o AR. Si no lo haces, puede costarte ver redes en los canales 12 y 13, que usan algunos routers (en firmwares antiguos se hace con rp2.country()). wlan.config(pm=network.WLAN.PM_NONE) desactiva el ahorro de energía (los ejemplos antiguos escriben el mismo ajuste como pm=0xa11140): por defecto la Pico W ahorra energía, y eso puede hacer que el servidor web responda tarde o que la conexión se caiga al cabo de unas horas. El bucle muestra el código de estado cada segundo y se detiene al llegar a 3 o al recibir un código de error negativo. Así la placa nunca espera para siempre y ves en pantalla qué ha fallado.

¿Qué significan los códigos de wlan.status()?

La mayoría de los problemas de conexión se resuelven en segundos mirando el número que devuelve wlan.status(). MicroPython también ofrece constantes para estos números en el módulo network; tienes ambos en la tabla siguiente:

CódigoConstanteSignificadoQué hacer
0STAT_IDLESin conexión, no se ha iniciado nadaComprueba que se llamó a wlan.active(True) y wlan.connect()
1STAT_CONNECTINGUniéndose a la redEspera unos segundos
2(sin constante)Unida a la red, esperando una IP del routerSi tarda mucho, revisa el DHCP del router
3STAT_GOT_IPConectada y con dirección IPTodo listo
-1STAT_CONNECT_FAILFallo de conexiónRevisa la señal y la alimentación y vuelve a intentarlo
-2STAT_NO_AP_FOUNDRed no encontradaRevisa el nombre de la red, la banda de 2,4 GHz y la distancia
-3STAT_WRONG_PASSWORDError de autenticaciónVuelve a escribir la contraseña respetando mayúsculas y minúsculas

Si obtienes el código -2, la Pico W no ve tu red. Listar las redes cercanas descubre el problema enseguida: si la tuya no aparece, o emite en 5 GHz o la señal es demasiado débil. Un RSSI mejor que -70 dBm (por ejemplo -55 dBm) es cómodo; hacia -80 dBm la conexión empieza a cortarse.

Python
1import network
2
3wlan = network.WLAN(network.WLAN.IF_STA)
4wlan.active(True)
5for ssid, bssid, channel, rssi, security, hidden in wlan.scan():
6    print(ssid.decode(), "| kanal / channel:", channel, "| RSSI:", rssi, "dBm")
La Pico W solo se conecta a redes de 2,4 GHz. Si tu router emite ambas bandas con el mismo nombre y no logras conectar, pon el punto de acceso personal de tu móvil en 2,4 GHz y prueba con él; si así funciona, el problema está en la configuración del router y no en tu código. Las redes de colegios y empresas que piden usuario (WPA2-Enterprise) no son compatibles con la Pico W. Para más consejos, la lista de comprobación de ESP32 no se conecta al WiFi también sirve para la Pico W.

Paso 3: Un servidor web sencillo con MicroPython (página para encender y apagar un LED)

Ahora convertiremos la Pico W en un pequeño servidor web que puedes abrir desde el móvil. No hace falta ninguna librería extra; basta con el módulo socket de MicroPython. Guarda el código siguiente como main.py y ejecútalo. Escribe la dirección que aparece en el Shell (por ejemplo http://192.168.1.42) en el navegador de un móvil conectado a la misma red WiFi; los botones ON y OFF de la página encienden y apagan el LED de la placa.

MicroPython
1import socket
2from machine import Pin
3import wifi
4
5wlan = wifi.connect()
6led = Pin("LED", Pin.OUT)              # Pico W dahili LED / Pico W onboard LED
7led_on = False
8
9
10def page(on):
11    state = "AÇIK / ON" if on else "KAPALI / OFF"
12    return """<!DOCTYPE html>
13<html><head><meta charset="utf-8">
14<meta name="viewport" content="width=device-width, initial-scale=1">
15<title>Pico W LED</title></head>
16<body style="font-family:sans-serif;text-align:center">
17<h1>Pico W LED</h1>
18<p>Durum / State: <b>""" + state + """</b></p>
19<p><a href="/on"><button style="font-size:24px">AÇ / ON</button></a>
20<a href="/off"><button style="font-size:24px">KAPAT / OFF</button></a></p>
21</body></html>"""
22
23
24addr = socket.getaddrinfo("0.0.0.0", 80)[0][-1]
25server = socket.socket()
26server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)   # EADDRINUSE hatasını önler / prevents EADDRINUSE
27server.bind(addr)
28server.listen(2)
29print("Tarayıcıda aç / open in browser: http://" + wlan.ifconfig()[0])
30
31while True:
32    client, remote = server.accept()           # bir tarayıcı bekle / wait for a browser
33    try:
34        request = client.recv(1024)            # b"GET /on HTTP/1.1 ..."
35        parts = request.split(b" ")
36        path = parts[1] if len(parts) > 1 else b"/"
37        if path == b"/on":
38            led.on()
39            led_on = True
40        elif path == b"/off":
41            led.off()
42            led_on = False
43        if path in (b"/", b"/on", b"/off"):
44            client.sendall("HTTP/1.0 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\n")
45            client.sendall(page(led_on))
46        else:
47            client.sendall("HTTP/1.0 404 Not Found\r\n\r\n")   # ör. /favicon.ico / e.g. /favicon.ico
48    except OSError as e:
49        print("Bağlantı hatası / connection error:", e)
50    finally:
51        client.close()

Veamos cómo funciona. Con bind y listen, la Pico W empieza a escuchar en el puerto 80 (HTTP), y accept() espera hasta que se conecta un navegador. La primera línea de la petición del navegador es del tipo "GET /on HTTP/1.1"; el código la divide por los espacios para encontrar la ruta pedida (/on) y ajusta el LED en consecuencia. Después envía la cabecera HTTP ("HTTP/1.0 200 OK" y el tipo de contenido), una línea en blanco y, por último, la página HTML, y cierra la conexión. La línea meta viewport hace que la página se adapte bien al móvil, y charset=utf-8 que los acentos y la ñ se vean correctamente.

RutaQué hace
/Muestra la página y el estado actual del LED
/onEnciende el LED y vuelve a enviar la página
/offApaga el LED y vuelve a enviar la página
/favicon.ico y otrasDevuelve 404; los navegadores piden esta ruta por su cuenta para el icono de la pestaña
Cuando detienes el código en Thonny y lo vuelves a ejecutar, puede aparecer "OSError: [Errno 98] EADDRINUSE": un socket de la ejecución anterior sigue ocupando el puerto 80. La línea SO_REUSEADDR del código lo evita casi siempre; si aun así lo ves, haz un reinicio suave con Ctrl+D en el Shell o desconecta y vuelve a conectar el cable USB de la placa.

Conectar un relé o un LED externo en lugar del LED integrado

Cuando funcione con el LED integrado, para controlar un aparato real desde la misma página solo cambias una línea: sustituye Pin("LED", Pin.OUT) por, por ejemplo, Pin(16, Pin.OUT). La resistencia adecuada para un LED externo la calculas con la herramienta Resistencia para LED; para un pin de 3,3 V bastan 220–330 Ω. Si usas un módulo de relé, aliméntalo desde el pin VBUS de 5 V y conecta su entrada IN al GPIO. Muchos módulos de relé se activan con una señal LOW; en ese caso intercambia las líneas led.on() y led.off(). Tienes los detalles del cableado en ¿Qué es un módulo de relé?.

ComponentePin del componentePin de la Pico W (n.º de pin físico)
LED externoÁnodo (+), a través de una resistencia de 220 ΩGP14 (19)
LED externoCátodo (−)GND (18)
DHT22VCC / DATA / GND3V3(OUT) (36) / GP15 (20) / GND (38)
Módulo de reléVCCVBUS, 5 V del USB (40)
Módulo de reléINGP16 (21)
Módulo de reléGNDGND (23)
Si vas a usar el relé para controlar una lámpara conectada a la red eléctrica (230 V), haz todo el cableado sin tensión, no dejes conductores al aire y monta el circuito en una caja cerrada; la tensión de red puede matar. Si no estás seguro, prueba primero con una tira LED de 12 V. Algunos módulos de relé de 5 V no conmutan bien con una señal de 3,3 V; si el relé no hace clic, añade un transistor o elige un módulo compatible con 3,3 V.

Paso 4: Mostrar datos de un sensor en directo en una página web

La página del LED se recargaba entera cada vez que pulsabas un botón. En una página que muestra medidas queda mucho mejor que los valores se actualicen sin recargar. Para eso usaremos dos rutas: / envía la propia página y /data solo las medidas en formato JSON. Un pequeño código JavaScript en la página lee /data cada dos segundos y cambia las cifras. El ejemplo muestra el sensor de temperatura interno, que no necesita componentes extra, y la intensidad de la señal WiFi (RSSI); además monta el servidor con el módulo asyncio de MicroPython, para que la Pico W siga midiendo mientras espera peticiones.

MicroPython
1import asyncio
2import json
3import time
4from machine import ADC, Pin
5import wifi
6
7wlan = wifi.connect()
8sensor = ADC(4)                        # dahili sıcaklık sensörü / internal temperature sensor
9led = Pin("LED", Pin.OUT)
10start = time.time()
11readings = {"temp": 0, "rssi": 0, "uptime": 0}
12
13HTML = """<!DOCTYPE html>
14<html><head><meta charset="utf-8">
15<meta name="viewport" content="width=device-width, initial-scale=1">
16<title>Pico W</title></head>
17<body style="font-family:sans-serif;text-align:center">
18<h1>Pico W</h1>
19<p>Sıcaklık / Temperature: <b id="t">-</b> °C</p>
20<p>Wi-Fi sinyali / signal: <b id="r">-</b> dBm</p>
21<p>Çalışma süresi / uptime: <b id="u">-</b> s</p>
22<script>
23async function update() {
24  try {
25    const d = await (await fetch("/data")).json();
26    document.getElementById("t").textContent = d.temp;
27    document.getElementById("r").textContent = d.rssi;
28    document.getElementById("u").textContent = d.uptime;
29  } catch (e) {}
30}
31update();
32setInterval(update, 2000);
33</script>
34</body></html>"""
35
36
37def read_temp():
38    volts = sensor.read_u16() * 3.3 / 65535
39    return round(27 - (volts - 0.706) / 0.001721, 1)
40
41
42async def measure():
43    while True:
44        readings["temp"] = read_temp()
45        readings["rssi"] = wlan.status("rssi")      # yalnız STA modunda / STA mode only
46        readings["uptime"] = time.time() - start
47        led.toggle()                                # kalp atışı / heartbeat
48        await asyncio.sleep(2)
49
50
51async def handle(reader, writer):
52    try:
53        line = await reader.readline()              # b"GET /data HTTP/1.1"
54        while True:                                 # başlıkları atla / skip the headers
55            header = await reader.readline()
56            if header in (b"\r\n", b""):
57                break
58        parts = line.split(b" ")
59        path = parts[1] if len(parts) > 1 else b"/"
60        if path == b"/":
61            writer.write(b"HTTP/1.0 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\n")
62            writer.write(HTML.encode())
63        elif path == b"/data":
64            writer.write(b"HTTP/1.0 200 OK\r\nContent-Type: application/json\r\n\r\n")
65            writer.write(json.dumps(readings).encode())
66        else:
67            writer.write(b"HTTP/1.0 404 Not Found\r\n\r\n")
68        await writer.drain()
69    except OSError as e:
70        print("Bağlantı hatası / connection error:", e)
71    finally:
72        writer.close()
73        await writer.wait_closed()
74
75
76async def main():
77    await asyncio.start_server(handle, "0.0.0.0", 80)
78    print("Tarayıcıda aç / open in browser: http://" + wlan.ifconfig()[0])
79    await measure()
80
81
82asyncio.run(main())

asyncio.start_server() ejecuta la función handle como una tarea aparte por cada nueva conexión del navegador, mientras la tarea measure() toma una medida cada dos segundos en segundo plano y hace parpadear el LED integrado. Por el parpadeo sabrás también que la placa no se ha colgado. Ojo: con asyncio, convierte el texto a bytes con .encode() antes de enviarlo, o las páginas con acentos darán error. El sensor de temperatura interno mide la temperatura del propio chip, así que da valores ruidosos y unos grados distintos de la temperatura ambiente; la fórmula 27 − (V − 0,706) / 0,001721 del código procede de la hoja de datos del RP2040. Para la temperatura real de la habitación, usa un sensor externo.

Módulo sensor de temperatura y humedad DHT22 (AM2302)
El módulo DHT22 tiene tres pines: VCC, DATA y GND. El orden puede variar según el fabricante, así que lee la serigrafía de la placa; el módulo funciona directamente con los 3,3 V de la Pico W.

Para medir de verdad temperatura y humedad, conecta un DHT22 (DATA a GP15). El driver de los sensores DHT viene incluido en el firmware de la Pico W, así que no tienes que subir nada más. En la función measure() del código del sensor, sustituye la línea readings["temp"] = read_temp() por una llamada a read_sensor(), que tienes abajo, y añade al HTML una línea para la humedad. El DHT22 no debe leerse más de una vez cada dos segundos, que es justo el ritmo del bucle. Tienes más detalles del sensor en Sensor de temperatura y humedad DHT11.

MicroPython
1import dht
2from machine import Pin
3
4dht_sensor = dht.DHT22(Pin(15))        # DATA ucu GP15'te / DATA pin on GP15
5
6
7def read_sensor():
8    try:
9        dht_sensor.measure()            # ölçümü başlat / trigger a reading
10        readings["temp"] = dht_sensor.temperature()   # °C
11        readings["hum"] = dht_sensor.humidity()       # % bağıl nem / % relative humidity
12    except OSError as e:
13        print("DHT22 okunamadı / read failed:", e)

Paso 5: Llamar a una API con urequests (traer datos de internet)

La Pico W puede ser cliente además de servidor: envía una petición a un servicio en línea y lee la respuesta. El módulo requests viene incluido en el firmware de la Pico W; el nombre urequests que verás en ejemplos antiguos apunta al mismo módulo, así que funcionan las dos formas. El ejemplo siguiente obtiene la temperatura, la humedad y la velocidad del viento actuales en Estambul desde el servicio meteorológico gratuito Open-Meteo, que no necesita clave de API. Solo tienes que cambiar LAT y LON por los de tu ciudad, por ejemplo 40.42 y -3.70 para Madrid.

Python
1import requests
2import wifi
3
4wifi.connect()
5
6# İstanbul; kendi konumunu yaz / Istanbul; put your own location
7LAT, LON = 41.01, 28.98
8URL = ("https://api.open-meteo.com/v1/forecast?latitude={}&longitude={}"
9       "&current=temperature_2m,relative_humidity_2m,wind_speed_10m").format(LAT, LON)
10
11response = requests.get(URL)
12try:
13    if response.status_code == 200:
14        current = response.json()["current"]
15        print("Sıcaklık / temperature:", current["temperature_2m"], "°C")
16        print("Nem / humidity:", current["relative_humidity_2m"], "%")
17        print("Rüzgâr / wind:", current["wind_speed_10m"], "km/h")
18    else:
19        print("HTTP hatası / HTTP error:", response.status_code)
20finally:
21    response.close()                   # soketi ve belleği serbest bırak / free the socket and memory

En este código hay tres cosas a tener en cuenta. Primero, llama a response.close() después de cada respuesta; las respuestas sin cerrar consumen sockets y memoria, y tras unas cuantas peticiones aparecerá "OSError: [Errno 12] ENOMEM". Segundo, response.json() carga toda la respuesta en memoria; la Pico W tiene 264 KB de RAM en total, así que con APIs que devuelven JSON grandes usa direcciones que pidan solo los campos necesarios (como el parámetro current de aquí). Tercero, una conexión HTTPS necesita memoria extra para el cifrado; si haces peticiones periódicas en un bucle, añadir gc.collect() entre ellas reduce la fragmentación de la memoria. Con el mismo método puedes enviar mensajes de Telegram, escribir datos en una hoja de cálculo o consultar el tipo de cambio; la configuración del bot de Telegram es la misma que en Bot de Telegram con ESP32.

Paso 6: La hora exacta de internet con NTP

La Pico W tiene un reloj en tiempo real (RTC) interno, pero sin pila de respaldo: cada vez que se enciende, el reloj vuelve al 1 de enero de 2021. Con WiFi es muy fácil obtener la hora correcta de los servidores NTP de internet: la función settime() del módulo integrado ntptime pone el reloj interno en UTC. Para la hora local el código suma un desfase fijo; el ejemplo usa 3 horas (10 800 segundos) para Turquía. En España peninsular pon UTC_OFFSET a 1 * 3600 en invierno y 2 * 3600 en verano; en México, -6 * 3600.

Python
1import time
2import ntptime
3import wifi
4
5wifi.connect()
6ntptime.host = "pool.ntp.org"          # varsayılan sunucu / default server
7UTC_OFFSET = 3 * 3600                  # Türkiye UTC+3; kendi saat dilimini yaz / set your own time zone
8
9for attempt in range(5):
10    try:
11        ntptime.settime()              # dahili saati UTC'ye ayarlar / sets the internal clock to UTC
12        print("Saat ayarlandı / time set")
13        break
14    except OSError as e:
15        print("NTP hatası / NTP error:", e)
16        time.sleep(2)
17
18DAYS = ("Pzt/Mon", "Sal/Tue", "Çar/Wed", "Per/Thu", "Cum/Fri", "Cmt/Sat", "Paz/Sun")
19
20while True:
21    y, mo, d, h, mi, s, wd, yd = time.localtime(time.time() + UTC_OFFSET)
22    print("%02d.%02d.%d %s %02d:%02d:%02d" % (d, mo, y, DAYS[wd], h, mi, s))
23    time.sleep(1)

Por defecto ntptime usa el servidor pool.ntp.org y espera un segundo la respuesta; si no llega, lanza "OSError: [Errno 110] ETIMEDOUT", por eso el código lo intenta cinco veces. El reloj interno puede desviarse unos segundos con el tiempo, así que en proyectos que funcionan mucho tiempo vuelve a llamar a settime() una vez al día. En los países con horario de verano el desfase cambia dos veces al año; tendrás que gestionarlo en el código con una comprobación de la fecha. Si quieres mostrar la hora en una pantalla, combina este código con los ejemplos de MicroPython de los artículos sobre la pantalla OLED o la LCD I2C; la versión para ESP32 está en ESP32 NTP.

Crear tu propia red (modo AP) y la dirección picow.local

Donde no hay router, por ejemplo en el puesto de una feria de ciencias o en el jardín, la Pico W puede emitir su propia red WiFi. En modo punto de acceso conectas el móvil directamente a la red "PicoW-BlueGrays" y abres la página en http://192.168.4.1. El código del servidor web funciona sin cambios; solo escribe las líneas siguientes en lugar de wlan = wifi.connect() y añade wlan = ap. La contraseña debe tener al menos 8 caracteres. La línea del RSSI del ejemplo del sensor solo funciona en modo estación, así que bórrala en modo AP. En este modo la Pico W no tiene acceso a internet, por lo que los ejemplos de NTP y de la API no funcionan.

Python
1import network
2
3ap = network.WLAN(network.WLAN.IF_AP)
4ap.config(ssid="PicoW-BlueGrays", password="bluegrays123")   # şifre en az 8 karakter / at least 8 characters
5ap.active(True)
6while not ap.active():
7    pass
8print("Ağ hazır / network ready:", ap.ifconfig()[0])          # genellikle 192.168.4.1 / usually 192.168.4.1

Si te resulta pesado leer la IP en el Shell cada vez, puedes usar un nombre. Las versiones actuales de MicroPython admiten mDNS en la Pico W: gracias a la línea network.hostname("picow") de wifi.py, la placa también responde en http://picow.local. Esta dirección suele funcionar en Windows, macOS, Linux y iPhone; algunos móviles Android no abren direcciones .local, así que allí usa la IP. Si quieres que la IP no cambie nunca, lo más fiable es asignar una IP fija a la dirección MAC de la Pico W desde la configuración del router (reserva DHCP).

Nota sobre la Pico 2 W: ¿qué cambia?

La Pico 2 W tiene el mismo tamaño y la misma distribución de pines que la Pico W y usa el mismo chip inalámbrico CYW43439, pero su procesador es el RP2350, más rápido. En el software, la única diferencia es el firmware: descarga el archivo RPI_PICO2_W de micropython.org, y al conectarla con BOOTSEL la unidad aparece como RP2350. Todo el código MicroPython de este artículo funciona sin cambios. Con 520 KB de RAM, las peticiones HTTPS, las respuestas JSON grandes y las páginas HTML largas caben mucho más holgadas en la Pico 2 W. En el Arduino IDE se elige la placa Raspberry Pi Pico 2W. Una nota: las primeras versiones del RP2350 tienen una errata conocida del chip (E9) que afecta a las resistencias pull-down internas; para los pulsadores, conectarlos a GND y usar PULL_UP es la opción más segura. Para funciones avanzadas como los dos núcleos y el PIO, consulta PIO y doble núcleo de la Pico.

Alternativa: programar la Pico W con el Arduino IDE (arduino-pico)

Si te resultan más familiares C++ y las librerías de Arduino, puedes programar la Pico W desde el Arduino IDE con el core arduino-pico de Earle Philhower. Incluye librerías WiFi y WebServer compatibles con las del ESP32, así que el código de servidor web escrito para el ESP32 funciona en la Pico W con pequeños cambios.

  1. En el Arduino IDE abre Archivo > Preferencias y añade https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json en el campo «Gestor de URLs adicionales de tarjetas».
  2. En el Gestor de tarjetas busca pico e instala el paquete Raspberry Pi Pico/RP2040/RP2350 de Earle F. Philhower.
  3. Elige Raspberry Pi Pico W en Herramientas > Placa (Raspberry Pi Pico 2W para la Pico 2 W).
  4. En la primera carga, conecta la placa manteniendo pulsado BOOTSEL; el Arduino IDE la detecta como unidad UF2. En las siguientes cargas basta con elegir el puerto serie que aparece en Herramientas > Puerto.
  5. Tras cargar el código, abre el Monitor Serie a 115200 baudios y lee la dirección IP.
C++ (Arduino IDE)
1#include <WiFi.h>
2#include <WebServer.h>
3#include <LEAmDNS.h>
4
5const char* ssid = "AgAdi";          // Wi-Fi adın / your Wi-Fi name
6const char* password = "Sifre123";   // Wi-Fi şifren / your Wi-Fi password
7
8WebServer server(80);
9bool ledOn = false;
10
11void sendPage() {
12  String html = "<!DOCTYPE html><html><head><meta charset='utf-8'>"
13                "<meta name='viewport' content='width=device-width, initial-scale=1'>"
14                "<title>Pico W</title></head>"
15                "<body style='font-family:sans-serif;text-align:center'><h1>Pico W LED</h1>";
16  html += "<p>Durum / State: <b>";
17  html += ledOn ? "AÇIK / ON" : "KAPALI / OFF";
18  html += "</b></p><p><a href='/on'><button>AÇ / ON</button></a> ";
19  html += "<a href='/off'><button>KAPAT / OFF</button></a></p>";
20  html += "<p>Sıcaklık / Temp: ";
21  html += String(analogReadTemp(), 1);   // dahili sensör / internal sensor
22  html += " °C</p></body></html>";
23  server.send(200, "text/html", html);
24}
25
26void setup() {
27  Serial.begin(115200);
28  pinMode(LED_BUILTIN, OUTPUT);          // Pico W'de kablosuz yongadaki LED / the LED on the wireless chip
29  WiFi.mode(WIFI_STA);
30  WiFi.begin(ssid, password);
31  while (WiFi.status() != WL_CONNECTED) {
32    delay(500);
33    Serial.print(".");
34  }
35  Serial.println();
36  Serial.print("IP: ");
37  Serial.println(WiFi.localIP());        // bu adresi telefonda aç / open this address on your phone
38
39  MDNS.begin("picow");                   // http://picow.local
40  server.on("/", sendPage);
41  server.on("/on", []() { ledOn = true;  digitalWrite(LED_BUILTIN, HIGH); sendPage(); });
42  server.on("/off", []() { ledOn = false; digitalWrite(LED_BUILTIN, LOW);  sendPage(); });
43  server.onNotFound([]() { server.send(404, "text/plain", "404"); });
44  server.begin();
45}
46
47void loop() {
48  server.handleClient();
49  MDNS.update();
50}

Este sketch hace lo mismo que la página del LED en MicroPython y añade la temperatura interna leída con analogReadTemp(). En la Pico W, LED_BUILTIN controla automáticamente el LED conectado al chip inalámbrico, y gracias a la línea MDNS.begin("picow") la página también se abre en http://picow.local. El driver WiFi añade unos 220 KB al programa compilado, así que la primera compilación puede tardar un poco. Para elegir entre MicroPython y Arduino, piensa en esto: con MicroPython guardas el código y lo pruebas al instante; con Arduino esperas a que compile, pero obtienes un código más rápido y un gran catálogo de librerías.

Ideas de proyectos con la Raspberry Pi Pico W

  • Termómetro WiFi: consulta desde el móvil la temperatura y la humedad medidas con un DHT11 o DHT22.
  • Lámpara desde el móvil: añade un módulo de relé a la página del LED de este artículo y enciende y apaga la lámpara del escritorio.
  • Control de humedad de plantas: muestra en la página el valor del sensor de humedad del suelo y avisa cuando la tierra se seque.
  • Aviso de movimiento: cuando un sensor PIR detecte a alguien, envía un mensaje de Telegram a tu móvil con urequests.
  • Reloj de internet: muestra la hora NTP con la fecha y el día de la semana en una pantalla OLED.
  • Domótica: instala la librería umqtt.simple con mip y envía tus medidas a Home Assistant por MQTT; la idea se explica en ESP32 MQTT.
  • Panel en tiempo real: para páginas que se actualicen más rápido, adapta a la Pico W las ideas del artículo servidor web asíncrono con ESP32, que usa WebSocket.

Errores frecuentes y soluciones

Síntoma o errorCausaSolución
ImportError: no module named 'network'Se cargó el firmware de la Pico normal en la Pico WCarga el UF2 RPI_PICO_W (RPI_PICO2_W para la Pico 2 W)
wlan.status() se queda en -2La red no se ve: 5 GHz, nombre de red incorrecto o señal débilActiva la banda de 2,4 GHz, busca la red con wlan.scan(), acerca la placa al router
wlan.status() devuelve -3Contraseña incorrectaVuelve a escribirla respetando mayúsculas, minúsculas y espacios
OSError: [Errno 98] EADDRINUSEEl socket del servidor anterior sigue ocupando el puerto 80Usa SO_REUSEADDR y reinicia con Ctrl+D
La página no se abre en el móvilEl móvil está con datos móviles, en la red de invitados o el router tiene el aislamiento de clientes activadoConecta el móvil al mismo WiFi y escribe la dirección con http, no https
OSError: -2 (urequests)No se pudo resolver el nombre: sin WiFi o problema de DNSLlama primero a wifi.connect() y revisa la URL
OSError: [Errno 12] ENOMEMMemoria llenaUsa response.close() y gc.collect(), pide respuestas más pequeñas
La conexión se cae al cabo de horasAhorro de energía o reinicio del routerUsa pm=network.WLAN.PM_NONE, comprueba wlan.isconnected() en el bucle y reconecta
No funciona al desconectarla del ordenadorEl código no está guardado como main.py o falta wifi.py en la PicoGuarda los dos archivos en la Pico
Los servidores de este artículo no tienen contraseña ni HTTPS; cualquiera conectado a la misma red puede abrir la página. Para probar en casa es suficiente, pero no expongas la Pico W directamente a internet abriendo puertos en el router. Si necesitas acceso remoto, un servicio intermedio como MQTT o Telegram es mucho más seguro. Y cuando compartas tu código, acuérdate de borrar la contraseña del WiFi de wifi.py.

Como has visto, conectar la Raspberry Pi Pico W al WiFi, servir una página web y traer datos de internet es cuestión de un par de archivos: wifi.py se encarga de la conexión y main.py del proyecto en sí. Para afianzar lo básico de la Pico, en la app BlueGrays tienes proyectos con la Raspberry Pi Pico para encender LEDs, un semáforo, PWM y LED RGB, y en el lado del ESP32 proyectos de conexión WiFi, servidor web asíncrono, reloj NTP y API del tiempo, todos con esquema del circuito y código paso a paso.

Preguntas frecuentes

¿La Raspberry Pi Pico W se conecta a WiFi de 5 GHz?

No. El chip CYW43439 de la Pico W y la Pico 2 W solo funciona en la banda de 2,4 GHz y no ve las redes de 5 GHz. Asegúrate de que la banda de 2,4 GHz de tu router está activada; si ambas bandas comparten nombre y tienes problemas, dar un nombre propio a la de 2,4 GHz suele solucionarlo.

¿Cómo se instala MicroPython en la Pico W?

Descarga de micropython.org el archivo .uf2 de la placa RPI_PICO_W. Mantén pulsado BOOTSEL mientras conectas la Pico W al ordenador y arrastra el archivo a la unidad RPI-RP2 que aparece. La placa se reinicia y queda lista para usar con Thonny; la ventana "Install or update MicroPython" de Thonny hace lo mismo.

¿Cómo averiguo la dirección IP de la Pico W?

Una vez conectada, wlan.ifconfig()[0] te da la IP, y el archivo wifi.py de este artículo la muestra en el Shell. Si la placa no está conectada al ordenador, mira la lista de dispositivos conectados en la configuración del router o prueba http://picow.local en dispositivos compatibles con mDNS.

¿Por qué el LED integrado de la Pico W no se enciende con Pin(25)?

En la Pico W el LED integrado está conectado al chip inalámbrico, no al procesador, y GP25 se usa como línea de selección de ese chip. Con Pin("LED", Pin.OUT) en MicroPython o LED_BUILTIN en el Arduino IDE, el LED se enciende correctamente. Esta forma también funciona en la Pico normal, así que puedes usarla siempre.

¿Puedo acceder al servidor web de la Pico W desde internet?

Técnicamente sí, abriendo puertos en el router, pero no se recomienda, porque un servidor MicroPython sencillo no tiene cifrado ni autenticación. Para controlarla desde fuera, un intermediario como MQTT, un bot de Telegram o un servicio IoT en la nube es mucho más seguro.

¿Pico W o ESP32: cuál es mejor para proyectos WiFi?

Las dos ofrecen WiFi de 2,4 GHz y Bluetooth. Si quieres trabajar con MicroPython, con documentación ordenada y pines sin sorpresas, elige la Pico W; si necesitas más velocidad, muchas entradas analógicas y un amplio catálogo de librerías Arduino, el ESP32 encaja mejor. Para proyectos sencillos de servidor web, sensores y APIs, ambas cumplen de sobra.

Ver todos los proyectos
Parpadeo LED Integrado Raspberry Pi Pico (Pico y Pico W)
#147Principiante

Parpadeo LED Integrado Raspberry Pi Pico (Pico y Pico W)

¡El proyecto de apertura de la serie Raspberry Pi Pico! Hacemos parpadear el LED verde integrado para verificar que la placa funciona — un experimento clásico "Hello World". SIN componentes externos, solo Pico y cable USB. El código está escrito en MicroPython (el lenguaje oficialmente respaldado por la Raspberry Pi Foundation). Aprende la clase machine.Pin, el modo Pin.OUT, los métodos led.on()/off() y time.sleep() en Thonny IDE. Sigue cada cambio en vivo en l

5.0(1)
10
Encendido de un LED externo con la Raspberry Pi Pico (placa de pruebas)
#148Principiante

Encendido de un LED externo con la Raspberry Pi Pico (placa de pruebas)

El siguiente paso tras el LED integrado de Pico: conectar un LED externo a la placa de pruebas y controlarlo a través del pin GP14. Con este proyecto aprenderás a utilizar cualquier pin GPIO de uso general del Pico como salida, la polaridad del LED (patilla larga = ánodo/+, patilla corta = cátodo/–) y por qué es imprescindible utilizar una resistencia limitadora de corriente (220 Ω). Si no colocas la resistencia, el LED recibirá una corriente excesiva y podría quemarse. El circuito es muy sencil

4.5(2)
7
Simulador de Semáforo Raspberry Pi Pico (3 LEDs Secuenciales)
#150Principiante

Simulador de Semáforo Raspberry Pi Pico (3 LEDs Secuenciales)

Simulamos un semáforo real con LEDs rojo, amarillo y verde. Verde 4 seg "pase", amarillo 1,5 seg "prepárese", rojo 3 seg "detenga" y rojo+amarillo 1 seg "arranque" (patrón europeo). Aprende definición de función, lógica de máquina de estados y sincronización multi-GPIO. Circuito simple: 3 LEDs en GP11/GP12/GP13.

4.0(1)
12
Raspberry Pi Pico PWM LED Fade (Efecto Respiración)
#160Principiante

Raspberry Pi Pico PWM LED Fade (Efecto Respiración)

¡El LED ya no solo parpadea — respira! Con el PWM (modulación por ancho de pulso) del Raspberry Pi Pico, el brillo sube y baja lentamente. Aprende la clase machine.PWM, duty_u16() (brillo de 16 bits 0–65535), la frecuencia PWM, bucles range() y salida tipo analógica. Base para mezcla de color RGB, control de motores, servos y buzzer.

0.0(0)
4
Servidor web asíncrono ESP32 (con indicación de IP en la pantalla LCD)
#129Avanzado

Servidor web asíncrono ESP32 (con indicación de IP en la pantalla LCD)

En este proyecto, convertimos el ESP32 en un servidor web asíncrono que puedes controlar desde tu teléfono o tu ordenador, siempre que estén conectados a la misma red Wi-Fi. Gracias a la biblioteca ESPAsyncWebServer, el servidor puede procesar varias solicitudes al mismo tiempo (a diferencia del clásico WebServer.h, que se bloquea con una sola solicitud).

4.8(16)
26
Conexión Wi-Fi STA con ESP32 (con pantalla LCD)
#127Avanzado

Conexión Wi-Fi STA con ESP32 (con pantalla LCD)

En este proyecto, conectamos el ESP32 a la red Wi-Fi doméstica en modo Station (STA) de forma segura y tolerante a fallos. Separamos el SSID y la contraseña en el archivo secrets.h para evitar que se filtren a Git, configuramos un mecanismo de reconexión automática y mostramos el nivel de señal RSSI y la dirección IP en una pantalla LCD I2C. El LED interno actúa como indicador de estado.

4.4(21)
34
ESP32: hora real desde Internet con NTP
#128Avanzado
Premium

ESP32: hora real desde Internet con NTP

El ESP32 se conecta a Wi-Fi y obtiene la hora real con precisión de milisegundos desde servidores NTP (Network Time Protocol). Gracias a configTzTime(), se aplica automáticamente la zona horaria de Turquía (TRT, UTC+3) y el cambio DST se gestiona mediante la cadena POSIX TZ. La hora se muestra en el monitor serie y en una pantalla LCD I2C opcional. configTzTime() inicia el servicio SNTP; se realizan resincronizaciones periódicas mientras hay acceso a la red, y el reloj del sistema sigue avan

4.5(13)
21
ESP32 HTTPClient + API del tiempo (con pantalla LCD)
#133Avanzado
Premium

ESP32 HTTPClient + API del tiempo (con pantalla LCD)

En este proyecto, utilizamos el ESP32 para realizar una llamada a la API REST de la página web de información meteorológica (wttr.in) a través de Internet, utilizando HTTPClient.h. Analizamos la respuesta JSON devuelta con ArduinoJson v7 y mostramos la información sobre la ciudad, la temperatura, la humedad, el tiempo y el viento en una pantalla LCD I2C, tanto en turco como en inglés. wttr.in es gratuito y no requiere clave API: basta con escribir el nombre de cualquier ciudad para obtener su

4.7(13)
20