Raspberry Pi Pico W WLAN: Webserver mit MicroPython einrichten
Raspberry Pi Pico W WLAN-Anleitung: die richtige UF2, network.WLAN und Statuscodes, LED-Webserver, Live-Sensorseite, API-Abfragen mit urequests und NTP-Zeit.
WLAN mit dem Raspberry Pi Pico W zu nutzen, ist einer der günstigsten und einfachsten Wege, ein kleines Gerät zu bauen, das du vom Handy aus steuerst. Der Pico W ist die Version des bekannten Raspberry Pi Pico mit 2,4-GHz-WLAN und Bluetooth: Mit ein paar Zeilen MicroPython verbindet er sich mit deinem Heimnetz, liefert eine eigene Webseite aus und holt Wetter und Uhrzeit aus dem Internet. In dieser Anleitung verbindest du einen Pico W von Grund auf mit dem WLAN, baust einen Webserver, mit dem du eine LED vom Handy aus einschaltest, und danach eine Seite, die Sensordaten live anzeigt.
Am Ende weißt du, wie du die richtige UF2-Datei auswählst, dich mit network.WLAN verbindest und die Statuscodes liest, mit urequests Daten von einer API abrufst, die Uhr per NTP stellst und dasselbe in der Arduino IDE umsetzt. Wenn der Pico neu für dich ist, hilft dir zuerst der Artikel Was ist der Raspberry Pi Pico?; die Grundbefehle findest du in der Anleitung Was ist MicroPython?.

Was ist der Raspberry Pi Pico W und was unterscheidet ihn vom Pico?
Der Pico W nutzt denselben RP2040-Prozessor, dieselbe Größe und dieselbe 40-polige Pinbelegung wie der Pico. Der Unterschied ist der zusätzliche Funkchip Infineon CYW43439: Er liefert 2,4-GHz-WLAN nach 802.11n und Bluetooth 5.2. Der Prozessor spricht mit diesem Chip über eine interne SPI-Verbindung; du selbst nutzt nur das network-Modul von MicroPython. Später brachte Raspberry Pi den Pico 2 W mit dem RP2350-Prozessor heraus; da der Funkchip derselbe ist, läuft der gesamte Code dieses Artikels auch dort.
| Merkmal | Pico W | Pico 2 W | ESP32 (WROOM-32) |
|---|---|---|---|
| Prozessor | RP2040, Dual-Core Cortex-M0+, 133 MHz | RP2350, Dual-Core Cortex-M33 (oder RISC-V), 150 MHz | Xtensa LX6, Dual-Core, 240 MHz |
| RAM | 264 KB | 520 KB | 520 KB |
| Flash-Speicher | 2 MB | 4 MB | Meist 4 MB |
| WLAN | 2,4 GHz, 802.11n (CYW43439) | 2,4 GHz, 802.11n (CYW43439) | 2,4 GHz, 802.11 b/g/n (im Chip) |
| Bluetooth | 5.2 (Classic und BLE) | 5.2 (Classic und BLE) | 4.2 (Classic und BLE) |
| Analoge Eingänge | 3 Kanäle, 12 Bit | 3 Kanäle, 12 Bit | 18 Kanäle, 12 Bit |
| MicroPython-Datei | RPI_PICO_W (.uf2) | RPI_PICO2_W (.uf2) | ESP32_GENERIC (.bin) |
Auf dem Papier ist der ESP32 schneller und hat in der Arduino-Welt mehr Beispiele. Die Stärken des Pico W sind die offizielle, ausgereifte MicroPython-Unterstützung, eine aufgeräumte Dokumentation und Pins ohne Fallen wie "muss beim Booten diesen Pegel haben". Wenn du gern mit Python lernst, ist der Pico W eine tolle Wahl; sind dir Arduino-Code und fertige Bibliotheken wichtiger, ist der ESP32 vielleicht bequemer. Kannst du dich nicht entscheiden, hilft der Vergleich Arduino oder ESP32?.
Der Funkchip des Pico W und die Unterschiede bei den Pins
Die herausgeführten Pins des Pico W sind exakt dieselben wie beim Pico: GP0–GP22 und GP26–GP28 sind frei nutzbar, die analogen Eingänge liegen weiterhin auf GP26, GP27 und GP28. Anders sind nur die vier Pins, die auf der Platine bleiben. Beim Pico steuern sie die Onboard-LED, den Netzteilmodus und die USB-Erkennung; beim Pico W sind sie für die Kommunikation mit dem Funkchip reserviert, und die LED hängt direkt am Funkchip. Die komplette Pinbelegung findest du im Tool Pinout.
| Interner Pin | Funktion beim Pico | Funktion beim Pico W |
|---|---|---|
| GP23 | Netzteilmodus (SMPS) | Funkchip einschalten (WL_ON) |
| GP24 | USB-Spannungserkennung (VBUS) | Daten- und Interrupt-Leitung des Funkchips (WL_D) |
| GP25 | Onboard-LED | Chip-Select des Funkchips (WL_CS) |
| GP29 | Messung der VSYS-Spannung (ADC3) | Taktleitung des Funkchips (WL_CLK) und VSYS-Messung |
| Onboard-LED | GP25: Pin(25) | WL_GPIO0 des Funkchips: Pin("LED") |
Schritt 1: Die richtige UF2-Datei für den Pico W aufspielen
Der häufigste Fehler ist, die MicroPython-Datei des normalen Pico auf einen Pico W zu spielen. Die Platine läuft dann zwar und du siehst die Eingabeaufforderung in der Shell von Thonny, aber sobald du import network eingibst, erscheint "ImportError: no module named 'network'", weil der normalen Pico-Version der WLAN-Treiber fehlt. Jede Platine hat ihre eigene UF2-Datei:
| Platine | MicroPython-UF2-Datei | Laufwerk im BOOTSEL-Modus |
|---|---|---|
| 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 |
- Suche auf der Download-Seite von micropython.org die Platine RPI_PICO_W (RPI_PICO2_W für den Pico 2 W) und lade die neueste stabile .uf2-Datei herunter, also die ohne "preview".
- Halte die BOOTSEL-Taste des Pico W gedrückt, während du das USB-Datenkabel am Computer einsteckst, und lass die Taste dann los.
- Auf dem Computer erscheint ein Laufwerk namens RPI-RP2. Zieh die heruntergeladene Datei darauf; nach dem Kopieren verschwindet das Laufwerk von selbst und die Platine startet mit MicroPython neu.
- Öffne Thonny und wähle im Interpreter-Menü unten rechts MicroPython (Raspberry Pi Pico). Alternativ erledigt das Fenster "Install or update MicroPython" in Thonny dieselbe Installation mit einem Klick, wenn du die Variante Pico W / Pico WH auswählst.
- Gib in der Shell import network ein. Kommt keine Fehlermeldung, ist die richtige Firmware mit WLAN-Unterstützung installiert.
Schritt 2: Mit network.WLAN ins WLAN
Der Pico W hat zwei Funkschnittstellen: Im Modus WLAN.IF_STA (Station) meldet er sich wie ein Handy an deinem Router an, im Modus WLAN.IF_AP (Access Point) baut er ein eigenes WLAN auf. Wir beginnen mit dem Stationsmodus. Füge den folgenden Code in Thonny in eine neue Datei ein, trage Netzwerkname und Passwort ein und speichere ihn auf dem Pico als wifi.py. Alle weiteren Beispiele nutzen diese Datei mit import wifi, so steht dein Passwort nur an einer Stelle. Nutzt du eine MicroPython-Version vor 1.24, schreibst du diese Konstanten als network.STA_IF und network.AP_IF; die alten Namen funktionieren auch in neueren Versionen weiter.
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()Schauen wir uns die wichtigen Zeilen an. network.country("TR") teilt dem Funkchip mit, nach den Kanalregeln welches Landes er sich richten soll; ersetze TR durch dein eigenes Länderkürzel, etwa DE, AT oder CH. Lässt du das weg, findest du Netze auf den Kanälen 12 und 13, die manche Router nutzen, eventuell nur schwer (ältere Firmware macht dasselbe mit rp2.country()). wlan.config(pm=network.WLAN.PM_NONE) schaltet den Stromsparmodus aus (ältere Beispiele schreiben dieselbe Einstellung als pm=0xa11140): Standardmäßig spart der Pico W Energie, was dazu führen kann, dass der Webserver verzögert antwortet oder die Verbindung nach ein paar Stunden abbricht. Die Schleife gibt jede Sekunde den Statuscode aus und endet bei 3 oder bei einem negativen Fehlercode. So wartet die Platine nie endlos, und du siehst auf dem Bildschirm, woran es liegt.
Was bedeuten die Statuscodes von wlan.status()?
Die meisten Verbindungsprobleme lassen sich in Sekunden lösen, wenn du dir die Zahl ansiehst, die wlan.status() zurückgibt. MicroPython bietet für diese Zahlen im network-Modul auch fertige Konstanten; beides findest du in der folgenden Tabelle:
| Code | Konstante | Bedeutung | Was tun? |
|---|---|---|---|
| 0 | STAT_IDLE | Keine Verbindung, nichts gestartet | Prüfe, ob wlan.active(True) und wlan.connect() aufgerufen wurden |
| 1 | STAT_CONNECTING | Meldet sich am Netz an | Ein paar Sekunden warten |
| 2 | (keine Konstante) | Angemeldet, wartet auf eine IP-Adresse vom Router | Dauert es lange, prüfe die DHCP-Einstellungen des Routers |
| 3 | STAT_GOT_IP | Verbunden, IP-Adresse erhalten | Alles bereit |
| -1 | STAT_CONNECT_FAIL | Verbindung fehlgeschlagen | Signal und Stromversorgung prüfen, erneut versuchen |
| -2 | STAT_NO_AP_FOUND | Netz nicht gefunden | Netzwerkname, 2,4-GHz-Band und Entfernung prüfen |
| -3 | STAT_WRONG_PASSWORD | Authentifizierung fehlgeschlagen | Passwort neu eingeben, auf Groß- und Kleinschreibung achten |
Bekommst du den Code -2, sieht der Pico W dein Netz nicht. Eine Liste der Netze in der Umgebung zeigt das Problem sofort: Fehlt dein Netz, sendet es entweder auf 5 GHz oder das Signal ist zu schwach. Ein RSSI besser als -70 dBm (zum Beispiel -55 dBm) ist komfortabel; um -80 dBm herum beginnt die Verbindung abzubrechen.
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")Schritt 3: Ein einfacher MicroPython-Webserver (LED an/aus)
Jetzt machen wir aus dem Pico W einen kleinen Webserver, den du mit dem Handy aufrufen kannst. Eine zusätzliche Bibliothek brauchst du nicht; das socket-Modul von MicroPython reicht. Speichere den folgenden Code als main.py und starte ihn. Gib die in der Shell angezeigte Adresse (zum Beispiel http://192.168.1.42) im Browser eines Handys ein, das im selben WLAN ist; die Tasten ON und OFF auf der Seite schalten die LED auf der Platine.
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()So funktioniert es: Mit bind und listen lauscht der Pico W auf Port 80 (HTTP), und accept() wartet, bis sich ein Browser verbindet. Die erste Zeile der Browser-Anfrage sieht aus wie "GET /on HTTP/1.1"; der Code teilt sie an den Leerzeichen, findet so den angefragten Pfad (/on) und schaltet die LED entsprechend. Danach sendet er den HTTP-Header ("HTTP/1.0 200 OK" und den Inhaltstyp), eine Leerzeile und zuletzt die HTML-Seite und schließt die Verbindung. Die Zeile meta viewport sorgt dafür, dass die Seite auf dem Handy richtig skaliert, und charset=utf-8 dafür, dass Umlaute und Sonderzeichen korrekt erscheinen.
| Pfad | Was passiert? |
|---|---|
| / | Zeigt die Seite und den aktuellen Zustand der LED |
| /on | Schaltet die LED ein und sendet die Seite erneut |
| /off | Schaltet die LED aus und sendet die Seite erneut |
| /favicon.ico und andere | Liefert 404; Browser fragen diesen Pfad für das Tab-Symbol von selbst an |
Statt der LED ein Relais oder eine externe LED anschließen
Klappt es mit der Onboard-LED, steuerst du mit derselben Seite ein echtes Gerät, indem du nur eine Zeile änderst: Ersetze Pin("LED", Pin.OUT) zum Beispiel durch Pin(16, Pin.OUT). Den passenden Vorwiderstand für eine externe LED berechnest du mit dem Tool LED-Vorwiderstand; an einem 3,3-V-Pin reichen 220–330 Ω. Für ein Relaismodul versorgst du das Modul über den 5-V-Pin VBUS und verbindest IN mit dem GPIO. Viele Relaismodule schalten bei LOW; dann musst du die Zeilen led.on() und led.off() vertauschen. Details zur Verdrahtung findest du unter Was ist ein Relaismodul?.
| Bauteil | Pin am Bauteil | Pin am Pico W (physische Pin-Nr.) |
|---|---|---|
| Externe LED | Anode (+), über einen 220-Ω-Widerstand | GP14 (19) |
| Externe LED | Kathode (−) | GND (18) |
| DHT22 | VCC / DATA / GND | 3V3(OUT) (36) / GP15 (20) / GND (38) |
| Relaismodul | VCC | VBUS, 5 V vom USB (40) |
| Relaismodul | IN | GP16 (21) |
| Relaismodul | GND | GND (23) |
Schritt 4: Sensordaten live auf einer Webseite anzeigen
Die LED-Seite wurde bei jedem Tastendruck komplett neu geladen. Bei einer Seite mit Messwerten ist es viel schöner, wenn sich die Werte ohne Neuladen aktualisieren. Dafür nutzen wir zwei Pfade: / liefert die Seite selbst, /data nur die Messwerte im JSON-Format. Ein kleines JavaScript auf der Seite liest alle zwei Sekunden /data und aktualisiert die Zahlen. Das Beispiel zeigt den internen Temperatursensor, der keine Zusatzteile braucht, und die WLAN-Signalstärke (RSSI); den Server baut es mit dem asyncio-Modul von MicroPython, damit der Pico W weiter misst, während er auf Anfragen wartet.
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() startet die Funktion handle für jede neue Browser-Verbindung als eigenen Task, während der Task measure() im Hintergrund alle zwei Sekunden misst und die Onboard-LED umschaltet. Am Blinken erkennst du auch, dass die Platine nicht hängt. Achtung: Wandle Text bei asyncio vor dem Senden mit .encode() in Bytes um, sonst gibt es bei Seiten mit Umlauten einen Fehler. Der interne Temperatursensor misst die Temperatur des Chips selbst, seine Werte rauschen und weichen ein paar Grad von der Raumtemperatur ab; die Formel 27 − (V − 0,706) / 0,001721 im Code stammt aus dem RP2040-Datenblatt. Für die echte Raumtemperatur nimmst du einen externen Sensor.

Für echte Temperatur und Luftfeuchtigkeit schließt du einen DHT22 an (DATA an GP15). Der Treiber für DHT-Sensoren ist in der Pico-W-Firmware bereits enthalten, du musst nichts zusätzlich hochladen. Ersetze in der Funktion measure() des Sensorcodes die Zeile readings["temp"] = read_temp() durch einen Aufruf von read_sensor() unten und ergänze im HTML eine Zeile für die Luftfeuchtigkeit. Den DHT22 solltest du nicht öfter als alle zwei Sekunden auslesen, und genau in diesem Takt läuft die Schleife. Mehr zum Sensor erfährst du in DHT11 Temperatur- und Feuchtigkeitssensor.
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)Schritt 5: APIs mit urequests abfragen (Daten aus dem Internet holen)
Der Pico W kann nicht nur Server, sondern auch Client sein: Er schickt eine Anfrage an einen Onlinedienst und liest die Antwort. Das Modul requests ist in der Pico-W-Firmware bereits enthalten; der Name urequests aus älteren Beispielen verweist auf dasselbe Modul, beide Schreibweisen funktionieren also. Das folgende Beispiel holt die aktuelle Temperatur, Luftfeuchtigkeit und Windgeschwindigkeit für Istanbul vom kostenlosen Wetterdienst Open-Meteo, der keinen API-Schlüssel braucht. Ändere einfach LAT und LON für deine Stadt, für Berlin etwa 52.52 und 13.41.
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 memoryBei diesem Code musst du auf drei Dinge achten. Erstens: Ruf nach jeder Antwort response.close() auf; nicht geschlossene Antworten belegen Sockets und Speicher, und nach ein paar Anfragen kommt "OSError: [Errno 12] ENOMEM". Zweitens: response.json() lädt die gesamte Antwort in den Speicher; der Pico W hat insgesamt 264 KB RAM, also nutze bei APIs mit großen JSON-Antworten Adressen, die nur die benötigten Felder abfragen (wie hier der Parameter current). Drittens: Eine HTTPS-Verbindung braucht zusätzlichen Speicher für die Verschlüsselung; schickst du in einer Schleife regelmäßig Anfragen, verringert ein gc.collect() dazwischen die Speicherfragmentierung. Auf dieselbe Weise kannst du Telegram-Nachrichten senden, Daten in eine Tabelle schreiben oder Wechselkurse abrufen; die Einrichtung des Telegram-Bots ist dieselbe wie in ESP32 Telegram-Bot.
Schritt 6: Die genaue Uhrzeit per NTP aus dem Internet
Der Pico W hat eine eingebaute Echtzeituhr (RTC), aber keine Batteriepufferung: Bei jedem Einschalten springt die Uhr auf den 1. Januar 2021 zurück. Mit WLAN holst du die richtige Zeit ganz einfach von NTP-Servern im Internet: Die Funktion settime() des eingebauten Moduls ntptime stellt die interne Uhr auf UTC. Für die Ortszeit addiert der Code einen festen Versatz; im Beispiel sind es 3 Stunden (10.800 Sekunden) für die Türkei. In Deutschland, Österreich und der Schweiz setzt du UTC_OFFSET im Winter auf 1 * 3600 und im Sommer auf 2 * 3600.
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)ntptime nutzt standardmäßig den Server pool.ntp.org und wartet eine Sekunde auf die Antwort; kommt keine, erscheint "OSError: [Errno 110] ETIMEDOUT", deshalb versucht es der Code fünfmal. Die interne Uhr kann mit der Zeit ein paar Sekunden abweichen, ruf settime() in Projekten mit langer Laufzeit daher einmal am Tag erneut auf. In Ländern mit Sommerzeit ändert sich der Versatz zweimal im Jahr; das musst du im Code mit einer Datumsprüfung berücksichtigen. Willst du die Uhrzeit auf einem Display zeigen, kombiniere diesen Code mit den MicroPython-Beispielen aus den Artikeln zum OLED-Display oder I2C-LCD; die ESP32-Variante steht in ESP32 NTP.
Ein eigenes Netz aufbauen (AP-Modus) und die Adresse picow.local
Wo es keinen Router gibt, etwa an einem Messestand oder im Garten, kann der Pico W sein eigenes WLAN aufspannen. Im Access-Point-Modus verbindest du dein Handy direkt mit dem Netz "PicoW-BlueGrays" und öffnest die Seite unter http://192.168.4.1. Der Webserver-Code läuft unverändert; schreib einfach die folgenden Zeilen statt wlan = wifi.connect() und ergänze wlan = ap. Das Passwort muss mindestens 8 Zeichen lang sein. Die RSSI-Zeile im Sensorbeispiel funktioniert nur im Stationsmodus, lösche sie im AP-Modus. In diesem Modus hat der Pico W keinen Internetzugang, die NTP- und API-Beispiele funktionieren also nicht.
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.1Ist dir das ständige Ablesen der IP-Adresse in der Shell zu mühsam, kannst du einen Namen verwenden. Aktuelle MicroPython-Versionen unterstützen auf dem Pico W mDNS: Dank der Zeile network.hostname("picow") in wifi.py ist die Platine auch unter http://picow.local erreichbar. Diese Adresse funktioniert meist unter Windows, macOS, Linux und auf iPhones; manche Android-Handys öffnen keine .local-Adressen, dort nimmst du die IP-Adresse. Soll sich die IP-Adresse nie ändern, ist der zuverlässigste Weg, der MAC-Adresse des Pico W in den Router-Einstellungen eine feste IP zuzuweisen (DHCP-Reservierung).
Hinweis zum Pico 2 W: Was ändert sich?
Der Pico 2 W hat dieselbe Größe und Pinbelegung wie der Pico W und denselben Funkchip CYW43439, nur der Prozessor ist der schnellere RP2350. Softwareseitig ist der einzige Unterschied die Firmware: Lade von micropython.org die Datei RPI_PICO2_W herunter; im BOOTSEL-Modus erscheint das Laufwerk als RP2350. Der gesamte MicroPython-Code dieses Artikels läuft unverändert. Dank 520 KB RAM passen HTTPS-Anfragen, große JSON-Antworten und lange HTML-Seiten auf dem Pico 2 W viel entspannter in den Speicher. In der Arduino IDE wählst du als Board Raspberry Pi Pico 2W. Ein Hinweis: Frühe Versionen des RP2350 haben ein bekanntes Chip-Erratum (E9), das die internen Pull-down-Widerstände betrifft; bei Tastern ist der Anschluss gegen GND mit PULL_UP die problemloseste Lösung. Zu fortgeschrittenen Funktionen wie den zwei Kernen und PIO lies Pico PIO und zwei Kerne.
Alternative: Den Pico W mit der Arduino IDE (arduino-pico) programmieren
Sind dir C++ und Arduino-Bibliotheken vertrauter, programmierst du den Pico W mit dem arduino-pico-Core von Earle Philhower aus der Arduino IDE. Er bringt zu den ESP32-Versionen kompatible WiFi- und WebServer-Bibliotheken mit, sodass Webserver-Code für den ESP32 mit kleinen Änderungen auf dem Pico W läuft.
- Öffne in der Arduino IDE Datei > Voreinstellungen und trage https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json unter "Zusätzliche Boardverwalter-URLs" ein.
- Suche im Boardverwalter nach pico und installiere das Paket Raspberry Pi Pico/RP2040/RP2350 von Earle F. Philhower.
- Wähle unter Werkzeuge > Board den Raspberry Pi Pico W (für den Pico 2 W Raspberry Pi Pico 2W).
- Beim ersten Hochladen steckst du die Platine mit gedrückter BOOTSEL-Taste ein; die Arduino IDE findet sie als UF2-Laufwerk. Bei späteren Uploads wählst du einfach den seriellen Port unter Werkzeuge > Port.
- Öffne nach dem Hochladen den seriellen Monitor mit 115200 Baud und lies die IP-Adresse ab.
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}Dieser Sketch macht dasselbe wie die MicroPython-LED-Seite und zeigt zusätzlich die interne Temperatur an, die analogReadTemp() liefert. LED_BUILTIN steuert beim Pico W automatisch die LED am Funkchip, und dank der Zeile MDNS.begin("picow") ist die Seite auch unter http://picow.local erreichbar. Der WLAN-Treiber vergrößert das kompilierte Programm um etwa 220 KB, der erste Build kann also etwas dauern. Bei der Wahl zwischen MicroPython und Arduino gilt: Mit MicroPython speicherst du den Code und probierst ihn sofort aus; mit Arduino wartest du aufs Kompilieren, bekommst dafür aber schnelleren Code und eine große Bibliotheksauswahl.
Projektideen mit dem Raspberry Pi Pico W
- WLAN-Thermometer: Behalte die mit einem DHT11 oder DHT22 gemessene Temperatur und Luftfeuchtigkeit auf dem Handy im Blick.
- Lampe per Handy: Ergänze die LED-Seite aus diesem Artikel um ein Relaismodul und schalte deine Schreibtischlampe.
- Pflanzenfeuchte-Monitor: Zeig den Wert eines Bodenfeuchtesensors auf der Seite an und lass dich warnen, wenn die Erde austrocknet.
- Bewegungsalarm: Erkennt ein PIR-Sensor jemanden, schickt der Pico W mit urequests eine Telegram-Nachricht an dein Handy.
- Internetuhr: Zeig die NTP-Zeit mit Datum und Wochentag auf einem OLED-Display.
- Hausautomation: Installiere mit mip die Bibliothek umqtt.simple und schick deine Messwerte per MQTT an Home Assistant; das Prinzip erklärt ESP32 MQTT.
- Echtzeit-Dashboard: Für schneller aktualisierte Seiten übertrage die Ideen aus dem WebSocket-Artikel ESP32 Async-Webserver auf den Pico W.
Häufige Fehler und Lösungen
| Symptom oder Fehler | Ursache | Lösung |
|---|---|---|
| ImportError: no module named 'network' | Firmware des normalen Pico auf dem Pico W | UF2-Datei RPI_PICO_W aufspielen (RPI_PICO2_W für den Pico 2 W) |
| wlan.status() bleibt bei -2 | Netz nicht sichtbar: 5 GHz, falscher Netzwerkname oder schwaches Signal | 2,4-GHz-Band einschalten, Netz mit wlan.scan() suchen, Platine näher an den Router |
| wlan.status() liefert -3 | Falsches Passwort | Passwort neu eingeben, auf Groß-/Kleinschreibung und Leerzeichen achten |
| OSError: [Errno 98] EADDRINUSE | Der vorige Server-Socket belegt noch Port 80 | SO_REUSEADDR nutzen, mit Strg+D neu starten |
| Seite öffnet sich auf dem Handy nicht | Handy im Mobilfunknetz, im Gastnetz oder Client-Isolation im Router aktiv | Handy ins selbe WLAN bringen, Adresse mit http statt https eingeben |
| OSError: -2 (urequests) | Hostname nicht auflösbar: kein WLAN oder DNS-Problem | Zuerst wifi.connect() aufrufen, URL prüfen |
| OSError: [Errno 12] ENOMEM | Speicher voll | response.close() und gc.collect() nutzen, kleinere Antworten anfordern |
| Verbindung bricht nach Stunden ab | Stromsparmodus oder Neustart des Routers | pm=network.WLAN.PM_NONE setzen, in der Schleife wlan.isconnected() prüfen und neu verbinden |
| Läuft nicht ohne Computer | Code nicht als main.py gespeichert oder wifi.py fehlt auf dem Pico | Beide Dateien auf dem Pico speichern |
Wie du gesehen hast, braucht es nur ein paar Dateien, um den Raspberry Pi Pico W mit dem WLAN zu verbinden, eine Webseite bereitzustellen und Daten aus dem Internet zu holen: wifi.py kümmert sich um die Verbindung, main.py um das eigentliche Projekt. Um deine Pico-Grundlagen zu festigen, findest du in der BlueGrays-App Raspberry-Pi-Pico-Projekte zu LEDs, Ampel, PWM und RGB-LED und auf der ESP32-Seite Projekte zu WLAN-Verbindung, Async-Webserver, NTP-Uhr und Wetter-API, jeweils mit Schaltplan und Code Schritt für Schritt.
Häufige Fragen
Unterstützt der Raspberry Pi Pico W 5-GHz-WLAN?
Nein. Der Chip CYW43439 auf dem Pico W und dem Pico 2 W arbeitet nur im 2,4-GHz-Band und sieht keine 5-GHz-Netze. Achte darauf, dass das 2,4-GHz-Band deines Routers eingeschaltet ist; teilen sich beide Bänder einen Namen und gibt es Probleme, hilft ein eigener Name für das 2,4-GHz-Band.
Wie installiere ich MicroPython auf dem Pico W?
Lade von micropython.org die .uf2-Datei für die Platine RPI_PICO_W herunter. Halte die BOOTSEL-Taste gedrückt, während du den Pico W an den Computer anschließt, und zieh die Datei auf das erscheinende Laufwerk RPI-RP2. Die Platine startet neu und ist mit Thonny einsatzbereit; das Fenster "Install or update MicroPython" in Thonny erledigt dasselbe.
Wie finde ich die IP-Adresse des Pico W heraus?
Nach dem Verbinden liefert wlan.ifconfig()[0] die IP-Adresse; die wifi.py aus diesem Artikel gibt sie in der Shell aus. Ist die Platine nicht am Computer angeschlossen, schau in der Liste der verbundenen Geräte deines Routers nach oder probiere auf mDNS-fähigen Geräten http://picow.local.
Warum leuchtet die Onboard-LED des Pico W mit Pin(25) nicht?
Beim Pico W hängt die Onboard-LED am Funkchip und nicht am Prozessor, und GP25 dient als Chip-Select-Leitung dieses Chips. Mit Pin("LED", Pin.OUT) in MicroPython oder LED_BUILTIN in der Arduino IDE leuchtet die LED korrekt. Diese Schreibweise funktioniert auch beim normalen Pico, du kannst sie also immer verwenden.
Kann ich aus dem Internet auf den Webserver des Pico W zugreifen?
Technisch geht das per Portweiterleitung im Router, es ist aber nicht zu empfehlen, weil ein einfacher MicroPython-Server weder Verschlüsselung noch Anmeldung hat. Für die Fernsteuerung ist ein Vermittler wie MQTT, ein Telegram-Bot oder ein Cloud-IoT-Dienst deutlich sicherer.
Pico W oder ESP32: Was ist besser für WLAN-Projekte?
Beide bieten 2,4-GHz-WLAN und Bluetooth. Willst du mit MicroPython, sauberer Dokumentation und Pins ohne Überraschungen arbeiten, nimm den Pico W; brauchst du mehr Tempo, viele analoge Eingänge und eine große Auswahl an Arduino-Bibliotheken, passt der ESP32 besser. Für einfache Webserver-, Sensor- und API-Projekte sind beide bestens geeignet.
Projekte, die du danach bauen kannst
Alle Projekte ansehen
Raspberry Pi Pico Onboard-LED Blinken (Pico und Pico W)
Das Eröffnungsprojekt der Raspberry Pi Pico-Serie! Wir bringen die grüne interne LED zum Blinken, um zu überprüfen, ob die Platine funktioniert — ein klassisches "Hello World"-Erstexperiment. Keine externen Komponenten, nur Pico und USB-Kabel. Der Code ist in MicroPython geschrieben (die offiziell von der Raspberry Pi Foundation unterstützte Sprache). Lerne die machine.Pin-Klasse, Pin.OUT-Modus, led.on()/off()-Methoden und time.sleep() in Thonny IDE. Verfolge jede Umsch

Raspberry Pi Pico: Externe LED zum Leuchten bringen (Steckbrett)
Der nächste Schritt nach der integrierten LED des Pico: Eine externe LED an das Breadboard anschließen und über den GP14-Pin steuern. In diesem Projekt lernst du, wie du einen beliebigen universellen GPIO-Pin des Pico als Ausgang nutzen kannst, welche Polarität die LED hat (langes Bein = Anode/+, kurzes Bein = Kathode/–) und warum ein Strombegrenzungswiderstand (220 Ω) erforderlich ist. Wenn du den Widerstand weglässt, fließt zu viel Strom durch die LED und sie kann durchbrennen. Die Schaltung i

Raspberry Pi Pico Ampel-Simulator (3 LEDs sequenziell)
Wir simulieren eine echte Ampel mit roten, gelben und grünen LEDs. Grün 4 Sek "gehen", gelb 1,5 Sek "bereit", rot 3 Sek "stopp" und rot+gelb 1 Sek "starten" (europäisches Ampelmuster). Lerne Funktionsdefinition, Zustandsmaschinen-Logik und Multi-GPIO-Synchronisation. Sehr einfache Schaltung: 3 LEDs an GP11/GP12/GP13, jeweils mit 220Ω Widerstand.

Raspberry Pi Pico PWM LED Fade (Atem-Effekt)
Die LED blinkt nicht mehr nur — sie atmet! Mit der PWM (Pulsweitenmodulation) des Raspberry Pi Pico steigt die Helligkeit langsam an und fällt wieder ab. Lerne die machine.PWM-Klasse, duty_u16() (16-Bit-Helligkeit 0–65535), PWM-Frequenz, range()-Schleifen und analogähnliche Ausgabe. Grundlage für RGB-Farbmischung, Motorsteuerung, Servos und Buzzer.

ESP32 Async-Webserver (mit IP-Anzeige auf dem LCD)
In diesem Projekt verwandeln wir den ESP32 in einen asynchronen Webserver, den Sie über Ihr Smartphone oder Ihren Computer im selben WLAN-Netzwerk steuern können. Dank der ESPAsyncWebServer-Bibliothek kann der Server mehrere Anfragen gleichzeitig bearbeiten (im Gegensatz zum klassischen WebServer.h, der bei einer einzigen Anfrage blockiert). Sie können über den Browser die IP-Adresse des ESP32 öffnen und durch Drücken der ON/OFF-Schaltflächen (Routen /on und /off) die an GPIO 5 anges

ESP32-WLAN-STA-Verbindung (mit LCD-Display)
In diesem Projekt verbinden wir den ESP32 im Station-Modus (STA) sicher und fehlertolerant mit dem heimischen WLAN. Wir lagern SSID und Passwort in eine separate secrets.h-Datei aus, um Leaks zu Git zu verhindern, richten einen Auto-Reconnect-Mechanismus ein und zeigen RSSI-Signalpegel und IP-Adresse auf einem I2C-LCD-Display an. Die interne LED dient als Statusanzeige. Ein Verbindungsmanager auf Produktionsniveau.

ESP32: Echtzeit aus dem Internet per NTP
Der ESP32 verbindet sich mit dem WLAN und ruft die Echtzeit mit Millisekunden-Genauigkeit von NTP-Servern (Network Time Protocol) ab. Dank configTzTime() wird die türkische Zeitzone (TRT, UTC+3) automatisch angewendet, und der DST-Wechsel wird per POSIX-TZ-String verwaltet. Die Uhrzeit wird auf dem Serial Monitor und einem optionalen I2C-LCD ausgegeben. configTzTime() startet den SNTP-Dienst; bei verfügbarem Netzwerkzugang erfolgt regelmäßig eine erneute Synchronisierung, und zwischen den Sy

ESP32 HTTPClient + Wetter-API (mit LCD-Display)
In diesem Projekt führen wir mit dem ESP32 über das Internet mithilfe von HTTPClient.h einen REST-API-Aufruf an die Wetter-API (wttr.in) durch. Mit ArduinoJson v7 analysieren wir die zurückgegebenen JSON-Daten und zeigen Informationen zu Stadt, Temperatur, Luftfeuchtigkeit, Wetter und Wind sowohl auf Türkisch als auch auf Englisch auf einem I2C-LCD-Display an. wttr.in ist kostenlos und erfordert keinen API-Schlüssel – Sie können den aktuellen Wetterbericht einer beliebigen Stadt abrufen, indem
Weitere Artikel
BlueGrays-App
Diese Schaltung Schritt für Schritt auf dem Handy nachbauen
Schaltplan, Code und Teileliste auf einem Bildschirm. Über 200 Arduino-, ESP32- und Pico-Projekte zum Nachbauen.
Mit dem Handy scannen
Richte die Kamera auf den Code, dann öffnet sich der App-Store deines Handys.
oder im Store öffnen

