Raspberry Pi Pico W Wi-Fi: tutorial de servidor web com MicroPython
Guia de Wi-Fi do Raspberry Pi Pico W: o UF2 certo, network.WLAN e códigos de status, servidor web para LED, página de sensor ao vivo, APIs com urequests e hora via NTP.
Usar o Wi-Fi do Raspberry Pi Pico W é um dos jeitos mais baratos e fáceis de montar um pequeno dispositivo que você controla pelo celular. O Pico W é a versão do conhecido Raspberry Pi Pico que traz Wi-Fi de 2,4 GHz e Bluetooth: com poucas linhas de MicroPython, ele entra na sua rede doméstica, serve a própria página web e busca a previsão do tempo e a hora na internet. Neste guia, você vai conectar um Pico W ao Wi-Fi do zero, montar um servidor web que acende um LED pelo celular e, depois, criar uma página que mostra dados de sensores ao vivo.
No final, você vai saber escolher o arquivo UF2 certo, conectar com network.WLAN e ler os códigos de status, buscar dados de uma API com urequests, acertar o relógio com NTP e fazer o mesmo trabalho na Arduino IDE. Se o Pico é novidade para você, ler antes O que é o Raspberry Pi Pico? vai facilitar as coisas, e o guia O que é MicroPython? cobre os comandos básicos.

O que é o Raspberry Pi Pico W e qual a diferença para o Pico?
O Pico W usa o mesmo processador RP2040, o mesmo tamanho e a mesma disposição de 40 pinos do Pico. A diferença é o chip sem fio Infineon CYW43439 adicionado à placa: ele oferece Wi-Fi 802.11n de 2,4 GHz e Bluetooth 5.2. O processador conversa com esse chip por uma ligação SPI dentro da placa; você só usa o módulo network do MicroPython. Mais tarde, a Raspberry Pi lançou o Pico 2 W, com o processador RP2350; como o chip sem fio é o mesmo, todo o código deste artigo também roda nele.
| Característica | Pico W | Pico 2 W | ESP32 (WROOM-32) |
|---|---|---|---|
| Processador | RP2040, Cortex-M0+ dual-core, 133 MHz | RP2350, Cortex-M33 dual-core (ou RISC-V), 150 MHz | Xtensa LX6, dual-core, 240 MHz |
| RAM | 264 KB | 520 KB | 520 KB |
| Memória flash | 2 MB | 4 MB | Geralmente 4 MB |
| Wi-Fi | 2,4 GHz, 802.11n (CYW43439) | 2,4 GHz, 802.11n (CYW43439) | 2,4 GHz, 802.11 b/g/n (no próprio chip) |
| Bluetooth | 5.2 (Clássico e BLE) | 5.2 (Clássico e BLE) | 4.2 (Clássico e BLE) |
| Entradas analógicas | 3 canais, 12 bits | 3 canais, 12 bits | 18 canais, 12 bits |
| Arquivo do MicroPython | RPI_PICO_W (.uf2) | RPI_PICO2_W (.uf2) | ESP32_GENERIC (.bin) |
No papel, o ESP32 é mais rápido e tem mais exemplos no mundo Arduino. Os pontos fortes do Pico W são o suporte oficial e maduro ao MicroPython, a documentação organizada e pinos sem armadilhas do tipo “precisa estar neste nível na inicialização”. Se você gosta de aprender com Python, o Pico W é uma ótima escolha; se código Arduino e bibliotecas prontas são o que mais importa para você, o ESP32 pode ser mais confortável. Se não consegue decidir entre os dois, a comparação Arduino ou ESP32? vai ajudar.
O chip sem fio do Pico W e as diferenças nos pinos
Os pinos expostos no Pico W são exatamente os mesmos do Pico: GP0–GP22 e GP26–GP28 estão livres para uso, e as entradas analógicas continuam em GP26, GP27 e GP28. O que muda são os quatro pinos que ficam dentro da placa. No Pico, eles cuidam do LED integrado, do modo de alimentação e da detecção do USB; no Pico W, ficam reservados para a comunicação com o chip sem fio, e o próprio LED é ligado diretamente ao chip sem fio. Você vê o mapa completo de pinos da placa na ferramenta Pinagem.
| Pino interno | Função no Pico | Função no Pico W |
|---|---|---|
| GP23 | Modo da fonte de alimentação (SMPS) | Habilitação do chip sem fio (WL_ON) |
| GP24 | Detecção da tensão do USB (VBUS) | Linha de dados e interrupção sem fio (WL_D) |
| GP25 | LED integrado | Seleção do chip sem fio (WL_CS) |
| GP29 | Medição da tensão VSYS (ADC3) | Linha de clock sem fio (WL_CLK) e medição de VSYS |
| LED integrado | GP25: Pin(25) | WL_GPIO0 do chip sem fio: Pin("LED") |
Passo 1: grave o arquivo UF2 certo para o Pico W
O erro mais comum é gravar o arquivo de MicroPython do Pico comum em um Pico W. A placa funciona e você vê o prompt no Shell do Thonny, mas assim que digita import network aparece “ImportError: no module named 'network'”, porque a versão do Pico comum não tem driver sem fio. Cada placa tem o próprio arquivo UF2:
| Placa | Arquivo UF2 do MicroPython | Unidade exibida no modo BOOTSEL |
|---|---|---|
| Raspberry Pi Pico | RPI_PICO-….uf2 | RPI-RP2 |
| Raspberry Pi Pico W / WH | RPI_PICO_W-….uf2 | RPI-RP2 |
| Raspberry Pi Pico 2 | RPI_PICO2-….uf2 | RP2350 |
| Raspberry Pi Pico 2 W | RPI_PICO2_W-….uf2 | RP2350 |
- Na página de download do micropython.org, encontre a placa RPI_PICO_W (RPI_PICO2_W para o Pico 2 W) e baixe o arquivo .uf2 estável mais recente, aquele que não está marcado como “preview”.
- Mantenha pressionado o botão BOOTSEL do Pico W enquanto conecta o cabo USB de dados ao computador e depois solte o botão.
- Uma unidade chamada RPI-RP2 aparece no computador. Arraste o arquivo baixado para ela; quando a cópia terminar, a unidade some sozinha e a placa reinicia com o MicroPython.
- Abra o Thonny e escolha MicroPython (Raspberry Pi Pico) no menu do interpretador, no canto inferior direito. Se preferir, a janela “Install or update MicroPython” (Instalar ou atualizar o MicroPython) do Thonny faz a mesma instalação com um clique quando você escolhe a variante Pico W / Pico WH.
- Digite import network no Shell. Se não aparecer erro, o firmware certo, com suporte sem fio, está instalado.
Passo 2: conecte ao Wi-Fi com network.WLAN
O Pico W tem duas interfaces sem fio: no modo WLAN.IF_STA (estação), ele entra no roteador de casa como um celular, e no modo WLAN.IF_AP (ponto de acesso), cria a própria rede Wi-Fi. Vamos começar pelo modo estação. Cole o código abaixo em um arquivo novo no Thonny, coloque o nome e a senha da sua rede e salve no Pico como wifi.py. Todos os exemplos seguintes usam esse arquivo com import wifi, assim a sua senha fica em um lugar só. Se você usa uma versão do MicroPython anterior à 1.24, escreva essas constantes como network.STA_IF e network.AP_IF; os nomes antigos continuam funcionando nas versões novas.
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()Vamos ver as linhas principais. network.country("TR") diz ao chip sem fio quais regras de canal de qual país seguir; troque TR pelo código de duas letras do seu país, como BR ou US. Se você pular essa linha, pode ter dificuldade para ver redes nos canais 12 e 13, que alguns roteadores usam (firmwares mais antigos fazem o mesmo com rp2.country()). wlan.config(pm=network.WLAN.PM_NONE) desliga a economia de energia (exemplos mais antigos escrevem a mesma configuração como pm=0xa11140): por padrão o Pico W economiza energia, o que pode fazer o servidor web responder com atraso ou perder a conexão depois de algumas horas. O laço imprime o código de status a cada segundo e para quando chega a 3 ou recebe um código de erro negativo. Assim a placa nunca espera para sempre, e você vê na tela o que deu errado.
O que significam os códigos de wlan.status()?
A maioria dos problemas de conexão se resolve em segundos olhando o número que wlan.status() retorna. O MicroPython também oferece constantes prontas para esses números no módulo network; você encontra os dois na tabela abaixo:
| Código | Constante | Significado | O que fazer |
|---|---|---|---|
| 0 | STAT_IDLE | Sem conexão, nada foi iniciado | Confira se wlan.active(True) e wlan.connect() foram chamados |
| 1 | STAT_CONNECTING | Entrando na rede | Aguarde alguns segundos |
| 2 | (sem constante) | Entrou na rede, aguardando um endereço IP do roteador | Se demorar, verifique as configurações de DHCP do roteador |
| 3 | STAT_GOT_IP | Conectado, com endereço IP | Tudo pronto |
| -1 | STAT_CONNECT_FAIL | A conexão falhou | Verifique o sinal e a alimentação e tente de novo |
| -2 | STAT_NO_AP_FOUND | Rede não encontrada | Verifique o nome da rede, a banda de 2,4 GHz e a distância |
| -3 | STAT_WRONG_PASSWORD | A autenticação falhou | Digite a senha de novo, prestando atenção a maiúsculas e minúsculas |
Se você recebe o código -2, o Pico W não está vendo a sua rede. Listar as redes ao redor revela o problema na hora: se a sua não está na lista, ou ela transmite em 5 GHz ou o sinal está fraco demais. Um RSSI melhor que -70 dBm (por exemplo, -55 dBm) é confortável; perto de -80 dBm a conexão começa a cair.
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")Passo 3: um servidor web simples com MicroPython (página para ligar e desligar o LED)
Agora vamos transformar o Pico W em um pequeno servidor web que você abre pelo celular. Não precisa de nenhuma biblioteca extra; o módulo socket do MicroPython basta. Salve o código abaixo como main.py e execute. Digite o endereço mostrado no Shell (por exemplo, http://192.168.1.42) no navegador de um celular conectado à mesma rede Wi-Fi; os botões ON e OFF da página ligam e desligam o LED da placa.
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()Veja como funciona. Com bind e listen, o Pico W começa a escutar na porta 80 (HTTP), e accept() espera até um navegador se conectar. A primeira linha da requisição do navegador é parecida com “GET /on HTTP/1.1”; o código divide essa linha nos espaços para achar o caminho pedido (/on) e ajusta o LED de acordo. Depois envia o cabeçalho HTTP (“HTTP/1.0 200 OK” e o tipo de conteúdo), uma linha em branco e, por fim, a página HTML, e fecha a conexão. A linha meta viewport faz a página se ajustar direito à tela do celular, e charset=utf-8 faz os caracteres especiais aparecerem corretamente.
| Caminho | O que faz |
|---|---|
| / | Mostra a página e o estado atual do LED |
| /on | Liga o LED e envia a página de novo |
| /off | Desliga o LED e envia a página de novo |
| /favicon.ico e outros | Retorna 404; os navegadores pedem esse caminho por conta própria para o ícone da aba |
Ligando um relé ou um LED externo no lugar
Depois que funcionar com o LED integrado, controlar um dispositivo de verdade pela mesma página exige mudar só uma linha: troque Pin("LED", Pin.OUT) por, por exemplo, Pin(16, Pin.OUT). Você calcula o resistor certo para um LED externo com a ferramenta Resistor para LED; 220–330 Ω bastam para um pino de 3,3 V. Se usar um módulo relé, alimente-o pelo pino VBUS de 5 V e ligue o pino IN dele ao GPIO. Muitos módulos relé acionam com sinal LOW; nesse caso, inverta as linhas led.on() e led.off(). Para detalhes da ligação do relé, veja O que é um módulo relé?
| Componente | Pino do componente | Pino do Pico W (nº do pino físico) |
|---|---|---|
| LED externo | Ânodo (+), por um resistor de 220 Ω | GP14 (19) |
| LED externo | Cátodo (−) | GND (18) |
| DHT22 | VCC / DATA / GND | 3V3(OUT) (36) / GP15 (20) / GND (38) |
| Módulo relé | VCC | VBUS, 5 V do USB (40) |
| Módulo relé | IN | GP16 (21) |
| Módulo relé | GND | GND (23) |
Passo 4: mostre dados de sensores ao vivo em uma página web
A página do LED recarregava inteira sempre que você apertava um botão. Em uma página que mostra medições, é bem melhor que os valores se atualizem sem recarregar. Para isso, vamos usar dois caminhos: / envia a própria página e /data envia só as medições em formato JSON. Um pequeno trecho de JavaScript na página lê /data a cada dois segundos e atualiza os números. O exemplo mostra o sensor de temperatura interno, que não precisa de peças extras, e a intensidade do sinal Wi-Fi (RSSI); ele também monta o servidor com o módulo asyncio do MicroPython, assim o Pico W continua medindo enquanto espera requisições.
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() executa a função handle como uma tarefa separada a cada nova conexão do navegador, enquanto a tarefa measure() faz uma leitura a cada dois segundos em segundo plano e alterna o LED integrado. O LED piscando também mostra que a placa não travou. Atenção: ao programar com asyncio, converta o texto em bytes com .encode() antes de enviar, senão páginas com caracteres especiais vão dar erro. O sensor de temperatura interno mede a temperatura do próprio chip, então as leituras têm ruído e ficam alguns graus acima ou abaixo da temperatura ambiente; a fórmula 27 − (V − 0.706) / 0.001721 do código vem do datasheet do RP2040. Para a temperatura ambiente real, use um sensor externo.

Para temperatura e umidade reais, ligue um DHT22 (pino DATA no GP15). O driver do sensor DHT já vem no firmware do Pico W, então não há nada extra para carregar. Na função measure() do código do sensor, troque a linha readings["temp"] = read_temp() por uma chamada a read_sensor(), abaixo, e acrescente mais uma linha no HTML para a umidade. O DHT22 não deve ser lido com intervalo menor que dois segundos, que é justamente o ritmo do laço. Para saber mais sobre o sensor, veja Sensor de temperatura e umidade DHT11.
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)Passo 5: chame uma API com urequests (busque dados na internet)
O Pico W pode ser cliente além de servidor: ele envia uma requisição a um serviço online e lê a resposta. O módulo requests já vem no firmware do Pico W; o nome urequests, que você vê em exemplos mais antigos, aponta para o mesmo módulo, então as duas grafias funcionam. O exemplo abaixo busca a temperatura, a umidade e a velocidade do vento atuais de Istambul no serviço de previsão do tempo gratuito Open-Meteo, que não exige chave de API. Basta mudar LAT e LON para a sua cidade, por exemplo 51.51 e -0.13 para Londres.
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 "¤t=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 memoryHá três pontos de atenção neste código. Primeiro, chame response.close() depois de cada resposta; respostas não fechadas consomem sockets e memória, e depois de algumas requisições aparece “OSError: [Errno 12] ENOMEM”. Segundo, response.json() carrega a resposta inteira na memória; o Pico W tem 264 KB de RAM no total, então, com APIs que devolvem JSON grande, use URLs que peçam só os campos necessários (como o parâmetro current aqui). Terceiro, uma conexão HTTPS precisa de memória extra para a criptografia; se você envia requisições regularmente em um laço, acrescentar gc.collect() entre elas reduz a fragmentação da memória. O mesmo método permite enviar mensagens no Telegram, gravar dados em uma planilha ou buscar cotações de câmbio; a configuração do bot do Telegram é igual à de Bot do Telegram com ESP32.
Passo 6: hora exata da internet com NTP
O Pico W tem um relógio de tempo real (RTC) interno, mas sem bateria de backup: sempre que a placa é ligada, o relógio volta para 1º de janeiro de 2021. Enquanto você está no Wi-Fi, obter a hora certa dos servidores NTP da internet é fácil: a função settime() do módulo embutido ntptime ajusta o relógio interno em UTC. O código soma um deslocamento fixo para chegar à hora local; o exemplo usa 3 horas (10.800 segundos) para a Turquia, então ajuste UTC_OFFSET para o seu fuso horário, por exemplo -3 * 3600 para Brasília, 0 para Londres no inverno ou -5 * 3600 para Nova York.
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 padrão, o ntptime usa o servidor pool.ntp.org e espera um segundo pela resposta; se ela não chegar, gera “OSError: [Errno 110] ETIMEDOUT”, e é por isso que o código tenta cinco vezes. O relógio interno pode se desviar alguns segundos com o tempo, então, em projetos que ficam ligados por muito tempo, chame settime() de novo uma vez por dia. Em países com horário de verão, o deslocamento muda duas vezes por ano; você vai precisar tratar isso no código com uma verificação de data. Se quiser mostrar a hora em um display, combine este código com os exemplos de MicroPython dos artigos sobre o display OLED de 0,96 polegada ou o LCD I2C; a versão para ESP32 está em ESP32 NTP.
Criando a própria rede (modo AP) e o endereço picow.local
Onde não há roteador, por exemplo no estande de uma feira de ciências ou no jardim, o Pico W pode transmitir a própria rede Wi-Fi. No modo ponto de acesso, você conecta o celular direto na rede “PicoW-BlueGrays” e abre a página em http://192.168.4.1. O código do servidor web roda sem mudanças; basta escrever as linhas abaixo no lugar de wlan = wifi.connect() e acrescentar wlan = ap. A senha precisa ter pelo menos 8 caracteres. A linha do RSSI no exemplo do sensor só funciona no modo estação, então apague-a no modo AP. Nesse modo o Pico W não tem acesso à internet, por isso os exemplos de NTP e de API não vão funcionar.
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.1Se ler o endereço IP no Shell toda vez dá trabalho, você pode usar um nome no lugar. As versões recentes do MicroPython têm suporte a mDNS no Pico W: graças à linha network.hostname("picow") do wifi.py, a placa também pode ser acessada em http://picow.local. Esse endereço costuma funcionar no Windows, macOS, Linux e iPhone; alguns celulares Android não abrem endereços .local, então use o endereço IP neles. Se quiser que o endereço IP nunca mude, o jeito mais confiável é reservar um IP fixo para o endereço MAC do Pico W nas configurações do roteador (uma reserva de DHCP).
Nota sobre o Pico 2 W: o que muda?
O Pico 2 W tem o mesmo tamanho e a mesma disposição de pinos do Pico W e usa o mesmo chip sem fio CYW43439, mas o processador é o RP2350, mais rápido. No software, a única diferença é o firmware: baixe o arquivo RPI_PICO2_W no micropython.org e, quando você conectar com o BOOTSEL, a unidade aparece como RP2350. Todo o código MicroPython deste artigo roda sem mudanças. Com 520 KB de RAM, requisições HTTPS, respostas JSON grandes e páginas HTML longas cabem com muito mais folga no Pico 2 W. Na Arduino IDE, escolha Raspberry Pi Pico 2W como placa. Uma observação: as primeiras versões do RP2350 têm uma errata conhecida do chip (E9) que afeta os resistores de pull-down internos; para botões, ligar ao GND e usar PULL_UP é a opção mais livre de problemas. Para recursos avançados como os dois núcleos e o PIO, veja PIO e dois núcleos no Pico.
Alternativa: programar o Pico W na Arduino IDE (arduino-pico)
Se C++ e bibliotecas Arduino são mais familiares para você, dá para programar o Pico W pela Arduino IDE com o core arduino-pico de Earle Philhower. Ele traz bibliotecas WiFi e WebServer compatíveis com as do ESP32, então um código de servidor web escrito para o ESP32 roda no Pico W com pequenas mudanças.
- Na Arduino IDE, abra Arquivo > Preferências e adicione https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json ao campo “URLs do Gerenciador de Placas Adicionais”.
- Busque pico no Gerenciador de Placas e instale o pacote Raspberry Pi Pico/RP2040/RP2350 de Earle F. Philhower.
- Escolha Raspberry Pi Pico W em Ferramentas > Placa (Raspberry Pi Pico 2W para o Pico 2 W).
- No primeiro carregamento, conecte a placa segurando o BOOTSEL; a Arduino IDE a reconhece como uma unidade UF2. Nos carregamentos seguintes, basta escolher a porta serial que aparece em Ferramentas > Porta.
- Depois de carregar, abra o Monitor Serial em 115200 baud e leia o endereço IP.
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 faz o mesmo que a página do LED em MicroPython e acrescenta a temperatura interna lida com analogReadTemp(). No Pico W, LED_BUILTIN aciona automaticamente o LED do chip sem fio, e a linha MDNS.begin("picow") deixa a página acessível também em http://picow.local. O driver de Wi-Fi acrescenta cerca de 220 KB ao programa compilado, então a primeira compilação pode demorar um pouco. Na hora de escolher entre MicroPython e Arduino, lembre-se disto: com MicroPython você salva o código e testa na hora; com Arduino você espera a compilação, mas ganha código mais rápido e amplo suporte de bibliotecas.
Ideias de projetos com o Raspberry Pi Pico W
- Termômetro Wi-Fi: acompanhe pelo celular a temperatura e a umidade medidas por um DHT11 ou DHT22.
- Luminária controlada pelo celular: acrescente um módulo relé à página do LED deste artigo e ligue e desligue a luminária da sua mesa.
- Monitor de umidade de plantas: mostre na página a leitura do sensor de umidade do solo e receba um aviso quando a terra secar.
- Alerta de movimento: quando um sensor PIR detectar alguém, envie uma mensagem no Telegram para o seu celular com urequests.
- Relógio pela internet: mostre a hora do NTP com a data e o dia da semana em um display OLED de 0,96 polegada.
- Automação residencial: instale a biblioteca umqtt.simple com o mip e envie suas leituras ao Home Assistant via MQTT; a ideia é explicada em ESP32 MQTT.
- Painel em tempo real: para páginas que se atualizam mais rápido, adapte ao Pico W as ideias do artigo Servidor web assíncrono com ESP32, baseado em WebSocket.
Erros comuns e soluções
| Sintoma ou erro | Causa | Solução |
|---|---|---|
| ImportError: no module named 'network' (módulo network não encontrado) | Firmware do Pico comum gravado em um Pico W | Grave o arquivo UF2 RPI_PICO_W (RPI_PICO2_W para o Pico 2 W) |
| wlan.status() fica em -2 | Rede não visível: 5 GHz, nome de rede errado ou sinal fraco | Ative a banda de 2,4 GHz, procure a rede com wlan.scan(), aproxime a placa do roteador |
| wlan.status() retorna -3 | Senha errada | Digite a senha de novo, prestando atenção a maiúsculas, minúsculas e espaços |
| OSError: [Errno 98] EADDRINUSE | O socket do servidor anterior ainda ocupa a porta 80 | Use SO_REUSEADDR, reinicie com Ctrl+D |
| A página não abre no celular | O celular está nos dados móveis ou em uma rede de convidados, ou o roteador está com isolamento de clientes ativado | Conecte o celular ao mesmo Wi-Fi e digite o endereço com http, não https |
| OSError: -2 (urequests) | Não foi possível resolver o nome do host: sem Wi-Fi ou problema de DNS | Chame wifi.connect() antes e verifique a URL |
| OSError: [Errno 12] ENOMEM | Memória esgotada | Use response.close() e gc.collect(), peça respostas menores |
| A conexão cai depois de algumas horas | Economia de energia ou o roteador reiniciando | Use pm=network.WLAN.PM_NONE, verifique wlan.isconnected() no laço e reconecte |
| Não funciona quando desconectado do computador | O código não foi salvo como main.py, ou o wifi.py não está no Pico | Salve os dois arquivos no Pico |
Como você viu, conectar o Raspberry Pi Pico W ao Wi-Fi, servir uma página web e buscar dados na internet exige só um par de arquivos: o wifi.py cuida da conexão e o main.py executa o projeto em si. Para reforçar a base no Pico, o app BlueGrays tem projetos com o Raspberry Pi Pico de LEDs piscando, semáforo, PWM e LEDs RGB e, do lado do ESP32, projetos de conexão Wi-Fi, servidor web assíncrono, relógio NTP e API de previsão do tempo, cada um com esquema do circuito e código passo a passo.
Perguntas frequentes
O Raspberry Pi Pico W tem suporte a Wi-Fi de 5 GHz?
Não. O chip CYW43439 do Pico W e do Pico 2 W só funciona na banda de 2,4 GHz e não enxerga redes de 5 GHz. Confira se a banda de 2,4 GHz do roteador está ativada; se as duas bandas usam o mesmo nome e você tiver problemas, dar um nome próprio à banda de 2,4 GHz ajuda.
Como instalo o MicroPython no Pico W?
Baixe o arquivo .uf2 da placa RPI_PICO_W no micropython.org. Segure o botão BOOTSEL enquanto conecta o Pico W ao computador e arraste o arquivo para a unidade RPI-RP2 que aparecer. A placa reinicia e fica pronta para usar com o Thonny; a janela “Install or update MicroPython” do Thonny faz o mesmo trabalho.
Como descubro o endereço IP do Pico W?
Depois de conectado, wlan.ifconfig()[0] dá o endereço IP, e o arquivo wifi.py deste artigo o imprime no Shell. Quando a placa não está ligada a um computador, consulte a lista de dispositivos conectados nas configurações do roteador ou tente http://picow.local em dispositivos com suporte a mDNS.
Por que o LED integrado do Pico W não acende com Pin(25)?
No Pico W, o LED integrado está ligado ao chip sem fio, não ao processador, e o GP25 é usado como linha de seleção desse chip. Use Pin("LED", Pin.OUT) no MicroPython ou LED_BUILTIN na Arduino IDE, e o LED acende corretamente. Essa forma também funciona no Pico comum, então você pode usá-la sempre.
Posso acessar o servidor web do Pico W pela internet?
Tecnicamente sim, com redirecionamento de portas no roteador, mas não é recomendado, porque um servidor MicroPython simples não tem criptografia nem autenticação. Para controle remoto, um intermediário como MQTT, um bot do Telegram ou um serviço de IoT na nuvem é muito mais seguro.
Pico W ou ESP32: qual é melhor para projetos com Wi-Fi?
Os dois oferecem Wi-Fi de 2,4 GHz e Bluetooth. Se você quer trabalhar em MicroPython com documentação organizada e pinos sem surpresas, escolha o Pico W; se quer mais velocidade, muitas entradas analógicas e amplo suporte de bibliotecas Arduino, o ESP32 se encaixa melhor. Para projetos simples de servidor web, sensores e APIs, os dois dão conta com folga.
Projetos para montar depois desta leitura
Ver todos os projetos
Piscar o LED integrado do Raspberry Pi Pico (Pico e Pico W)
O primeiro projeto da série Raspberry Pi Pico! Fazemos o LED verde integrado piscar para verificar se a placa funciona — um primeiro experimento no estilo clássico "Hello World". SEM componentes externos, apenas o Pico e um cabo USB. O código foi escrito em MicroPython (a linguagem com suporte oficial da Raspberry Pi Foundation). Aprenda a usar a classe machine.Pin, o modo Pin.OUT, os métodos led.on()/off() e time.sleep() no Thonny IDE.

Raspberry Pi Pico: controle de LED externo (protoboard)
O próximo passo após o LED integrado do Pico: conectar um LED externo à protoboard e controlá-lo pelo pino GP14. Neste projeto, você aprende a usar qualquer pino GPIO de uso geral do Pico como saída, a polaridade do LED (terminal longo = ânodo/+, terminal curto = cátodo/–) e por que um resistor limitador de corrente (220Ω) é necessário. Sem o resistor, uma corrente excessiva passa pelo LED e pode queimá-lo. O circuito é muito simples: Pico GP14 → resistor de 220Ω → LE

Raspberry Pi Pico: semáforo (3 LEDs em sequência)
Simulamos um semáforo real com LEDs vermelho, amarelo e verde — o primeiro projeto com 3 LEDs da série Pico! Verde por 4 segundos: "siga"; amarelo por 1,5 segundo: "prepare-se"; vermelho por 3 segundos: "pare"; e vermelho+amarelo por 1 segundo: "saída" (padrão de semáforo europeu). Aprenda definição de funções (def all_off()), lógica de máquina de estados (sequência) e sincronização de vários GPIOs.

Raspberry Pi Pico: variação de brilho do LED com PWM (efeito de respiração)
O LED não só pisca — ele respira! Com o PWM (modulação por largura de pulso) do Raspberry Pi Pico, o brilho do LED aumenta e diminui lentamente, como a luz de um MacBook em repouso. Aprenda a usar a classe machine.PWM, duty_u16() (brilho de 16 bits, de 0–65535), frequência PWM (freq(1000) — 1.000 ciclos de ligar/desligar por segundo, sem cintilação visível), laços com passos usando range() (crescentes e decrescentes) e saída semelhante à analógica em um pino digital.

Servidor web assíncrono com ESP32 (IP no LCD)
Neste projeto, transformamos o ESP32 em um servidor web assíncrono que você pode controlar pelo celular ou computador na mesma rede Wi-Fi. Com a biblioteca ESPAsyncWebServer, o servidor processa várias requisições ao mesmo tempo (ao contrário do WebServer.h tradicional, que bloqueia a execução ao processar uma requisição). Você poderá abrir o endereço IP do ESP32 no navegador e clicar nos botões ON/OFF (as rotas /on e /off) para ligar e desligar o LED conectado ao GPIO 5.

Conexão Wi-Fi STA com ESP32 e display LCD
Neste projeto, conectamos o ESP32 à rede Wi-Fi de casa no modo estação (STA), de forma segura e tolerante a falhas. Guardamos o SSID e a senha em um arquivo secrets.h separado para evitar que sejam expostos no Git, configuramos um mecanismo de reconexão automática e exibimos o nível de sinal RSSI e o endereço IP em um display LCD I2C. O LED integrado funciona como indicador de status. É um gerenciador de conexão pronto para uso em produção.

Hora exata pela internet com ESP32 e NTP
O ESP32 se conecta ao Wi-Fi e obtém a hora exata com precisão de milissegundos de servidores NTP (Network Time Protocol). Com a função configTzTime(), o fuso horário configurado (TRT, UTC+3 neste exemplo) é aplicado automaticamente, e as mudanças nos países que adotam horário de verão são gerenciadas automaticamente por uma string POSIX TZ. A hora é exibida tanto no Monitor Serial quanto em um LCD I2C opcional.

ESP32 HTTPClient + API de clima (com display LCD)
Neste projeto, usamos o ESP32 para fazer uma chamada REST à API de clima wttr.in pela internet com HTTPClient.h. Interpretamos a resposta JSON com ArduinoJson v7 e mostramos cidade, temperatura, umidade, condições do tempo e vento em um display LCD I2C, em turco e inglês. O wttr.in é grátis e não exige chave de API — basta informar o nome de uma cidade para consultar o clima atual. Os dados se atualizam sozinhos a cada 30 minutos, e o LED dá um retorno visual diferente para cada tela.
Mais artigos
App BlueGrays
Monte este circuito passo a passo pelo celular
Esquema do circuito, código e lista de componentes em uma só tela. Mais de 200 projetos com Arduino, ESP32 e Pico prontos para montar.
Escaneie com seu celular
Aponte a câmera para o código para abrir a loja de aplicativos do seu celular.
ou abrir a loja

