¿Te imaginas controlar un LED, leer un sensor o prender la luz del living abriendo una página web desde el celular, sin depender de la nube ni de ningún servicio externo? Esa es la gracia de montar un servidor web dentro de una placa tan chica como la Raspberry Pi Pico W. En este tutorial vas a partir desde cero: levantar un servidor web básico en la Pico W (o en la Pico 2 W) programada con el Arduino IDE, usando la librería ESPAsyncWebServer. Al final vas a tener la placa entregando una página HTML simple que puedes abrir desde cualquier navegador de tu red local.

Este primer proyecto es a propósito minimalista: sirve un "Hola, mundo" en HTML. Pero es la base exacta sobre la que después se construyen los proyectos entretenidos: botones para controlar pines, sliders para regular PWM, lecturas de sensores en vivo. Si entiendes bien esta estructura, el resto es solo agregar rutas y contenido.

Raspberry Pi Pico W como servidor web sirviendo una página al navegador

Importante antes de empezar: este proyecto SOLO funciona con la Raspberry Pi Pico W y la Raspberry Pi Pico 2 W, que son las versiones con WiFi integrado. La Pico y la Pico 2 originales (sin la W) no tienen radio inalámbrica, así que no pueden actuar como servidor en la red.

Qué es un servidor web y por qué la Pico puede serlo

En términos simples, un servidor web es un "computador" que entrega páginas web. Guarda los archivos del sitio (documentos HTML, imágenes, hojas de estilo CSS, fuentes) y se los manda al navegador del usuario cuando este lo pide. Cuando usas la Pico como servidor, la estás convirtiendo en un mini computador que almacena y sirve páginas.

El intercambio funciona con el protocolo HTTP y sigue el modelo cliente y servidor:

  • El cliente eres tú con tu navegador: cuando escribes una dirección, mandas una petición (request) al servidor.
  • El servidor es la Pico: recibe la petición y responde (response) con la página solicitada.

La ventaja de hacer esto en un microcontrolador es que sus pines GPIO quedan disponibles para la web. El navegador puede pedirle a la Pico que encienda o apague un pin (un LED, un relé), y la Pico puede responder con datos de sus pines, como la lectura de un sensor. Todo eso ocurre adentro de tu red, sin salir a internet.

El detalle de la dirección IP

Una dirección IP es una etiqueta numérica que identifica a cada dispositivo en una red. Son cuatro valores separados por puntos, cada uno entre 0 y 255, por ejemplo 192.168.1.75. En tu casa, todos los dispositivos conectados al router forman tu red local y cada uno tiene su propia IP. Los equipos de la misma red se pueden hablar entre sí por esa dirección, pero alguien fuera de tu red local NO puede acceder a tus dispositivos usando esa IP privada.

Cuando conectas la Pico a tu router, pasa a ser parte de tu red local y recibe una IP única. Esa es la dirección que vas a escribir en el navegador para ver la página que sirve la placa. Por eso, más adelante, vamos a imprimir esa IP por el Monitor Serial.

Hardware: lo que necesitas

El montaje es casi inexistente, esa es otra gracia de este proyecto. No hay protoboard, no hay cables sueltos, no hay sensores todavía. Solo necesitas:

  • Una Raspberry Pi Pico W o Pico 2 W (con WiFi).
  • Un cable micro USB para conectarla al computador.
  • Un computador con el Arduino IDE instalado.

Eso es todo el hardware. El proyecto vive en el software.

Software, parte 1: el core de la Pico en el Arduino IDE

Antes de tocar este tutorial necesitas tener instalado el soporte (core) de la Raspberry Pi Pico en el Arduino IDE y saber subir código a la placa. Si todavía no lo tienes configurado, primero deja listo el entorno con la guía de instalación del core de la Pico que corresponda a tu placa (Pico/Pico W o Pico 2/Pico 2 W). Una vez que el Arduino IDE reconoce tu placa, sigue acá.

Software, parte 2: instalar las librerías

Para crear un servidor web asíncrono con la Pico programada desde el Arduino IDE vamos a usar la librería ESPAsyncWebServer, la misma que se usa con ESP32 y ESP8266. Lo interesante es que esa librería también es compatible con la RPi Pico (los chips RP2040 y RP2350) y otras placas relacionadas. Para la Pico, además, hay que instalar la librería RPAsyncTCP, que es la capa de transporte TCP asíncrona para el core arduino pico.

Entonces, son dos librerías a instalar desde el Gestor de Librerías:

  1. ESPAsyncWebServer by ESP32Async
  2. RPAsyncTCP by Ayush Sharma

Para instalarlas, anda a Programa > Incluir Librería > Administrar Bibliotecas, o haz clic en el ícono del Gestor de Librerías en la barra lateral izquierda. Busca ESPAsyncWebServer e instala la versión de ESP32Async (en la imagen aparece como "ESP Async WebServer by ESP32Async").

Instalar la librería ESP Async WebServer desde el Gestor de Librerías del Arduino IDE

Luego busca RPAsyncTCP e instala la librería de Ayush Sharma. Fíjate en la descripción: es la "Asynchronous TCP Library for RP2040+W, RP2350+W", justo lo que necesita nuestra placa.

Instalar la librería RPAsyncTCP de Ayush Sharma en el Arduino IDE

Por qué un servidor asíncrono (y no uno bloqueante)

Vale la pena entender la diferencia, porque marca cómo se escribe el resto del proyecto. En un servidor bloqueante clásico, el loop() está todo el rato preguntando "¿llegó un cliente?" y atendiéndolo paso a paso, lo que deja al microcontrolador ocupado y le cuesta hacer otras cosas al mismo tiempo. Un servidor asíncrono como ESPAsyncWebServer le da vuelta el enfoque: tú declaras qué hacer cuando llega una petición a tal ruta (con server.on(...)) y la librería se encarga de ejecutar esa respuesta en segundo plano cuando corresponde. ¿La consecuencia práctica? El loop() te queda libre para tu propia lógica, y la placa atiende la web sin trabarse.

El código: servir una página HTML

El siguiente sketch construye el servidor web que entrega la página de ejemplo. Cópialo completo en un nuevo programa del Arduino IDE:

C++
/*********
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at https://RandomNerdTutorials.com/raspberry-pi-pico-web-server-arduino/
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*********/
// Import required libraries
#include <WiFi.h>
#include <RPAsyncTCP.h>
#include <ESPAsyncWebServer.h>

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

const char index_html[] PROGMEM = R"rawliteral(
        <!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>
            <p>Hello, World!</p>
        </body>
        </html>
)rawliteral";

void setup(){
  Serial.begin(115200);
  
  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

  // Print Pico Local IP Address
  Serial.println(WiFi.localIP());

  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/html", index_html);
  });

  // Start server
  server.begin();
}

void loop() {

}

Lo único que TIENES que cambiar son tus credenciales de red. Reemplaza el nombre de tu red (SSID) y la contraseña en estas líneas, y recién ahí sube el código a la placa:

C++
// Replace with your network credentials
const char* ssid = "";
const char* password = "";

Cómo funciona el código, por partes

Librerías. Primero se incluyen las tres librerías necesarias: WiFi para conectar la Pico a tu red, más RPAsyncTCP y ESPAsyncWebServer para levantar el servidor.

C++
// Import required libraries
#include <WiFi.h>
#include <RPAsyncTCP.h>
#include <ESPAsyncWebServer.h>

Credenciales de red. Aquí pones el SSID y la contraseña para que la Pico pueda conectarse.

Servidor en el puerto 80. Se crea un objeto AsyncWebServer llamado server que escucha en el puerto 80, el puerto estándar de HTTP.

C++
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

El HTML. La variable index_html guarda el código HTML de la página. Está escrita como un raw string literal: va entre R"rawliteral( y )rawliteral". Esto te permite escribir un texto de varias líneas sin tener que escapar comillas ni saltos de línea, así que pegas el HTML tal cual. Además, la variable se guarda en la memoria flash gracias a PROGMEM, lo que ahorra RAM. Ese HTML es justo lo que se le sirve al navegador para armar la página.

setup(). En el setup() se inicia el Monitor Serial a 115200 baudios, se conecta la Pico a tu red con WiFi.begin(ssid, password) y se espera (con un while) hasta que el estado sea WL_CONNECTED. Después se imprime la IP local de la placa con Serial.println(WiFi.localIP()): esa es la dirección que vas a usar para acceder a la página.

Manejo de la petición. Estas líneas definen qué pasa cuando alguien pide la ruta raíz / (es decir, cuando escribes la IP de la Pico en el navegador). Al recibir esa petición, la placa devuelve el contenido de index_html.

C++
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send(200, "text/html", index_html);
});

Los parámetros de send() son: 200 (código HTTP que indica que la petición se recibió bien), text/html (le decimos al navegador que enviamos una página en formato HTML) e index_html (el contenido de la página). Finalmente, server.begin() arranca el servidor.

loop() vacío. Como el servidor es asíncrono (la función dentro de server.on() se ejecuta sola cuando llega una petición), no necesitas poner nada en el loop(). Igual, ahí puedes agregar tu propio código si tu proyecto lo requiere.

Cargar el código a la Pico y probar

Para subir el código, la Raspberry Pi Pico W necesita estar en modo bootloader. Si la placa está corriendo firmware de MicroPython, ponla manualmente en modo bootloader: conéctala al computador mientras mantienes presionado el botón BOOTSEL. Se va a abrir una ventana de almacenamiento masivo nuevo; ciérrala e ignórala. En las siguientes cargas con el Arduino IDE, la placa debería entrar sola en modo bootloader sin que tengas que presionar BOOTSEL.

En el menú desplegable de arriba elige Select other board and port… y selecciona Raspberry Pi Pico W o Raspberry Pi Pico 2W según tu placa. El puerto COM puede no aparecer en la primera carga, así que marca la opción Show all ports y elige la opción UF2 Board / UF2 Devices. Ahora sí, sube el código: deberías ver un mensaje de éxito.

Luego necesitas la IP de la Pico, que se imprime en el Monitor Serial. Ábrelo a 115200 baudios. Después desconecta la placa y vuelve a conectarla: tras unos segundos se conecta al Monitor Serial y muestra su IP. En el ejemplo original es 192.168.1.83.

Monitor Serial del Arduino IDE mostrando la dirección IP que recibió la Raspberry Pi Pico W

Finalmente, abre una ventana del navegador y escribe la IP de la Pico. Te va a servir el contenido de index_html y vas a ver esta página:

Página web servida por la Raspberry Pi Pico W mostrando Hola mundo en el navegador

Si llegaste hasta acá, oficialmente tienes un servidor web corriendo en una placa del porte de una memoria USB. Lo bueno es que casi todos los ejemplos de servidor web para ESP32 y ESP8266 se pueden aplicar a la Pico: los métodos y funciones para manejar el servidor son los mismos. La única diferencia es que la Pico requiere además la librería RPAsyncTCP.

Variantes y mejoras

Esta base te sirve para crecer en muchas direcciones. Algunas ideas concretas para el siguiente paso:

  • Controlar un GPIO desde la web: agrega una segunda ruta, por ejemplo server.on("/on", ...) y server.on("/off", ...), que cambien el estado de un pin con un LED conectado. Con eso prendes y apagas el LED escribiendo la IP seguida de /on o /off. Es el clásico salto desde "Hola mundo" a domótica real.

  • Mostrar la lectura de un sensor en vivo: conecta un sensor de temperatura (un DS18B20 o un DHT22) y reemplaza el texto fijo del HTML por el valor leído. Para que el dato se actualice solo sin recargar la página, conviene usar Server Sent Events (SSE), que ESPAsyncWebServer soporta.

  • IP fija para no perderla: como el router puede asignarle una IP distinta cada vez, puedes configurar una IP estática en el código con WiFi.config(...) antes de WiFi.begin(). Así siempre accedes a la misma dirección y no tienes que mirar el Monitor Serial cada vez.

  • Servir CSS para que se vea mejor: la página de ejemplo es HTML pelado. Puedes incrustar estilos CSS dentro del mismo index_html para darle colores, botones y una grilla decente, todo sin archivos externos.

Tip de debugging: si el while se queda pegado imprimiendo "Connecting to WiFi.." para siempre, casi siempre es por el SSID o la contraseña mal escritos, o porque intentas conectarte a una red de 5 GHz (la Pico W trabaja en 2.4 GHz). Revisa esos tres puntos antes que cualquier otra cosa.

Personalización para Chile

En Chile puedes conseguir la placa de este proyecto en MechatronicStore:

  • Raspberry Pi Pico 2 W (SKU GS3-4) a $15.990 CLP. Es la versión con WiFi del nuevo chip RP2350, totalmente compatible con este tutorial (en el Arduino IDE se selecciona como "Raspberry Pi Pico 2W").

Un par de aclaraciones útiles para no equivocarte al comprar:

  • Asegúrate de comprar una versión con WiFi (la "W"). La Raspberry Pi Pico y la Pico 2 a secas, sin la W, son más baratas pero NO tienen radio inalámbrica, así que no sirven para este servidor web. Para este proyecto necesitas la Pico W o la Pico 2 W.
  • El cable es un micro USB común y corriente, el mismo de muchos dispositivos; si ya tienes uno en casa, te sirve.

Recursos

  • Tutorial original (inglés): Raspberry Pi Pico: Web Server (Arduino IDE), por Rui Santos y Sara Santos en Random Nerd Tutorials.
  • Librería ESPAsyncWebServer: ESP Async WebServer by ESP32Async (Gestor de Librerías del Arduino IDE).
  • Librería RPAsyncTCP: RPAsyncTCP by Ayush Sharma (Gestor de Librerías del Arduino IDE).

Versión chilena con la placa en stock local en MechatronicStore. Tutorial basado en el original de Random Nerd Tutorials, re escrito y adaptado con contexto local.