Dalam panduan ini, Anda akan mempelajari cara mengimplementasikan web server lokal berbasis arsitektur asinkron pada Raspberry Pi Pico W menggunakan MicroPython dan modul asyncio. Pendekatan pemrograman asinkron memungkinkan Pico W memproses beberapa koneksi klien secara simultan, sekaligus menjalankan tugas paralel di latar belakang tanpa memblokir eksekusi utama.
Kita akan membangun antarmuka web yang menyediakan mekanisme kontrol untuk mengubah status LED (ON/OFF) dan menampilkan data numerik acak yang dihasilkan oleh Pico. Secara bersamaan, papan akan mengeksekusi rutinitas kedipan LED dan sejumlah background tasks dalam loop asinkron untuk mendemonstrasikan kemampuan concurrent task scheduling. Arsitektur ini dapat dengan mudah diadaptasi atau dikembangkan lebih lanjut untuk mengendalikan beberapa perangkat keluaran maupun melakukan akuisisi data sensor alih-alih sekadar menghasilkan nilai acak.
Firmware MicroPython
Untuk mengikuti tutorial ini, Anda perlu menginstal firmware MicroPython di papan Raspberry Pi Pico Anda. Anda juga memerlukan IDE untuk menulis dan mengunggah kode ke papan Anda.
IDE MicroPython yang direkomendasikan untuk Raspberry Pi Pico adalah Thonny IDE. Ikuti tutorial selanjutnya untuk mempelajari cara menginstal Thonny IDE, mem-flash firmware MicroPython, dan mengunggah kode ke papan.
Baca juga: Panduan Lengkap Memulai MQTT di Raspberry Pi Pico W dengan MicroPython
Konsep Dasar Web Server
Jika Anda belum familiar dengan konsep dasar server web, sebaiknya ikuti tutorial berikut terlebih dahulu:
Raspberry Pi Pico Asynchronous Web Server – Ikhtisar Proyek
Berikut adalah gambaran singkat mengenai proyek yang akan kita bangun untuk mempermudah pemahaman alur kode pada langkah selanjutnya. Web server ini memiliki fungsi yang sama dengan proyek sebelumnya, tetapi dirancang secara asynchronous dan non-blocking. Dengan pendekatan ini, server dapat menangani beberapa klien secara bersamaan serta tetap menjalankan tugas lain tanpa harus menunggu permintaan dari klien.
Contoh berikut menjalankan beberapa fungsi sekaligus:
- Menginisialisasi web server yang menampilkan halaman berisi:
- Dua tombol untuk mengendalikan LED pada GPIO 19 (ON/OFF).
- Satu bagian untuk menampilkan nilai acak, yang nantinya dapat diganti dengan data sensor.
- Menjalankan task terpisah secara bersamaan untuk membuat LED pada GPIO 20 berkedip.
- Tetap melaksanakan proses lain di dalam main loop sambil terus memantau dan merespons permintaan klien.
Modul asyncio pada MicroPython
Untuk membangun web server berbasis asynchronous, kita memanfaatkan modul asyncio bawaan MicroPython. Modul ini sudah termasuk dalam firmware secara default, sehingga tidak diperlukan instalasi tambahan.
Keunggulan Pemrograman Asinkron
Penggunaan modul asyncio memungkinkan eksekusi beberapa task secara bersamaan (concurrent execution), sehingga kode tidak terblokir oleh proses yang membutuhkan waktu lama dan tetap responsif terhadap operasi lain.
Sebagai contoh, program dapat menunggu respons dari sebuah server sambil tetap menjalankan proses lain secara paralel, seperti memantau status tombol atau mempertahankan siklus kedip pada sebuah LED. Pendekatan asynchronous sangat ideal ketika Raspberry Pi Pico digunakan sebagai web server, karena memungkinkan perangkat menangani beberapa klien secara bersamaan tanpa menghentikan eksekusi task lain dalam event loop.
Modul asyncio pada MicroPython merupakan kerangka kerja I/O asynchronous yang ringan dan diadaptasi dari modul asyncio pada Python standar. Dokumentasi lengkap mengenai modul ini dapat ditemukan pada halaman resmi MicroPython.
Rangkaian Pengujian
Untuk menguji proyek ini, siapkan dua LED yang akan dihubungkan ke Raspberry Pi Pico: satu LED pada GPIO 19 dan satu lagi pada GPIO 20. Gunakan diagram rangkaian sebagai acuan untuk memastikan koneksi yang benar.
Komponen yang Dibutuhkan
- Raspberry Pi Pico W
- 2× LED
- 2× Resistor 220Ω
- Breadboard
- Kabel jumper
Kode Web Server Asinkron Raspberry Pi Pico dengan MicroPython
Buat sebuah file baru di Thonny IDE, kemudian salin kode berikut ke dalam file tersebut.
# Rui Santos & Sara Santos - Random Nerd Tutorials
# Complete project details at https://RandomNerdTutorials.com/raspberry-pi-pico-w-asynchronous-web-server-micropython/
# Import necessary modules
import network
import asyncio
import socket
import time
import random
from machine import Pin
# Wi-Fi credentials
ssid = 'REPLACE_WITH_YOUR_SSID'
password = 'REPLACE_WITH_YOUR_PASSWORD'
# Create several LEDs
led_blink = Pin(20, Pin.OUT)
led_control = Pin(19, Pin.OUT)
# Initialize variables
state = "OFF"
random_value = 0
# HTML template for the webpage
def webpage(random_value, state):
html = f"""
<!DOCTYPE html>
<html>
<head>
<title>Pico Web Server</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h1>Raspberry Pi Pico Web Server</h1>
<h2>Led Control</h2>
<form action="./lighton">
<input type="submit" value="Light on" />
</form>
<br>
<form action="./lightoff">
<input type="submit" value="Light off" />
</form>
<p>LED state: {state}</p>
<h2>Fetch New Value</h2>
<form action="./value">
<input type="submit" value="Fetch value" />
</form>
<p>Fetched value: {random_value}</p>
</body>
</html>
"""
return str(html)
# Init Wi-Fi Interface
def init_wifi(ssid, password):
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
# Connect to your network
wlan.connect(ssid, password)
# Wait for Wi-Fi connection
connection_timeout = 10
while connection_timeout > 0:
print(wlan.status())
if wlan.status() >= 3:
break
connection_timeout -= 1
print('Waiting for Wi-Fi connection...')
time.sleep(1)
# Check if connection is successful
if wlan.status() != 3:
print('Failed to connect to Wi-Fi')
return False
else:
print('Connection successful!')
network_info = wlan.ifconfig()
print('IP address:', network_info[0])
return True
# Asynchronous functio to handle client's requests
async def handle_client(reader, writer):
global state
print("Client connected")
request_line = await reader.readline()
print('Request:', request_line)
# Skip HTTP request headers
while await reader.readline() != b"\r\n":
pass
request = str(request_line, 'utf-8').split()[1]
print('Request:', request)
# Process the request and update variables
if request == '/lighton?':
print('LED on')
led_control.value(1)
state = 'ON'
elif request == '/lightoff?':
print('LED off')
led_control.value(0)
state = 'OFF'
elif request == '/value?':
global random_value
random_value = random.randint(0, 20)
# Generate HTML response
response = webpage(random_value, state)
# Send the HTTP response and close the connection
writer.write('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
writer.write(response)
await writer.drain()
await writer.wait_closed()
print('Client Disconnected')
async def blink_led():
while True:
led_blink.toggle() # Toggle LED state
await asyncio.sleep(0.5) # Blink interval
async def main():
if not init_wifi(ssid, password):
print('Exiting program.')
return
# Start the server and run the event loop
print('Setting up server')
server = asyncio.start_server(handle_client, "0.0.0.0", 80)
asyncio.create_task(server)
asyncio.create_task(blink_led())
while True:
# Add other tasks that you might need to do in the loop
await asyncio.sleep(5)
print('This message will be printed every 5 seconds')
# Create an Event Loop
loop = asyncio.get_event_loop()
# Create a task to run the main function
loop.create_task(main())
try:
# Run the event loop indefinitely
loop.run_forever()
except Exception as e:
print('Error occurred: ', e)
except KeyboardInterrupt:
print('Program Interrupted by the user')
Kode ini membangun sebuah web server asinkron. Sebelum menjalankannya, pastikan Anda telah memasukkan kredensial jaringan Anda dengan benar.
# Wi-Fi credentials
ssid = 'REPLACE_WITH_YOUR_SSID'
password = 'REPLACE_WITH_YOUR_PASSWORD'
Cara Kerja Kode
Struktur program ini mirip dengan proyek sebelumnya. Pada penjelasan kali ini, kita hanya akan membahas bagian-bagian penting yang berkaitan dengan implementasi web server asinkron. Jika Anda belum memahami konsep dasar socket server, sebaiknya pelajari terlebih dahulu penjelasan kode pada proyek sebelumnya.
Mengimpor Modul asyncio
Langkah pertama adalah mengimpor modul asyncio, yang menyediakan fungsi dan mekanisme untuk menerapkan pemrograman asinkron di MicroPython.
import asyncio
Fungsi Asinkron
Fungsi handle_client() dan blink_led() dideklarasikan sebagai fungsi asinkron (menggunakan kata kunci `async def`), sehingga keduanya dapat dijalankan secara konkuren dan bekerja sama dengan coroutine lainnya tanpa saling menghalangi. Fungsi utama main() juga dibuat sebagai fungsi asinkron untuk mengatur proses inisialisasi server serta penjadwalan tugas-tugas lainnya. Sebuah event loop kemudian dibentuk menggunakan `asyncio.get_event_loop()` untuk mengelola, menjadwalkan, dan mengeksekusi seluruh tugas asinkron yang telah terdaftar.
loop = asyncio.get_event_loop()
Fungsi utama main() didaftarkan sebagai task pada event loop melalui pemanggilan `loop.create_task(main())`, sehingga coroutine tersebut dapat dijadwalkan dan dieksekusi secara asinkron oleh sistem penjadwalan event loop.
loop.create_task(main())
Konfigurasi Server Asinkron
Alih-alih menggunakan pemrograman soket konvensional, server TCP dibangun secara asinkron dengan memanfaatkan `asyncio.start_server()`, yang memungkinkan penanganan koneksi secara non-blocking dan terkelola oleh event loop.
server = asyncio.start_server(handle_client, "0.0.0.0", 80)
Korutin `handle_client()` ditetapkan sebagai callback untuk memproses setiap koneksi klien yang masuk. Pemanggilan `asyncio.start_server()` menginisialisasi server asinkron yang mendengarkan koneksi pada host dan port tertentu, serta mengembalikan objek server yang merepresentasikan task pemrosesan koneksi. Setiap kali koneksi baru diterima, event loop akan mengeksekusi korutin yang ditentukan sebagai handler (dalam hal ini `handle_client`).
Saat koneksi klien terbentuk, `asyncio.start_server()` menghasilkan sepasang objek stream—`StreamReader` untuk menerima data dan `StreamWriter` untuk mengirim respons. Kedua objek ini diteruskan sebagai argumen ke korutin handler untuk memungkinkan komunikasi dua arah.
async def handle_client(reader, writer):
Di dalam fungsi `handle_client()`, objek `reader` dan `writer` dimanfaatkan untuk melakukan operasi baca dan tulis secara asinkron pada koneksi klien.
Objek `reader` (`StreamReader`) menyediakan metode untuk mengambil data dari soket klien secara non-blocking, misalnya dengan memanggil `await reader.readline()` untuk membaca satu baris data.
print("Client connected")
request_line = await reader.readline()
print('Request:', request_line)
Objek `writer` (`StreamWriter`) menyediakan metode untuk mengirim data ke soket klien secara asinkron, misalnya melalui pemanggilan `writer.write()` untuk menuliskan buffer data ke koneksi.
writer.write('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
writer.write(response)
Objek `reader` dan `writer` dihasilkan oleh fungsi `asyncio.start_server()` setiap kali ada klien yang membuka koneksi. Kedua objek ini menyediakan antarmuka komunikasi asinkron antara server dan klien, memungkinkan proses pembacaan data masuk serta pengiriman respons berjalan tanpa blocking.
Menjalankan Tugas Secara Paralel
Fungsi `asyncio.create_task()` digunakan untuk membuat task yang menangani koneksi klien dan proses kedip LED secara bersamaan. Dengan cara ini, server dapat menerima banyak koneksi sekaligus dan tetap menjalankan tugas lainnya tanpa menghambat eksekusi program utama.
asyncio.create_task(server)
asyncio.create_task(blink_led())
Selain itu, di dalam fungsi main() kita juga menjalankan operasi asinkron lain menggunakan await asyncio.sleep(), yaitu versi non-blok dari time.sleep(). Pada contoh ini, kita hanya menampilkan pesan ke shell setiap 5 detik, tetapi Anda bebas menambahkan tugas lain sesuai kebutuhan. Anda juga dapat memperluas operasi tersebut jika diperlukan.
while True:
# Add other tasks that you might need to do in the loop
await asyncio.sleep(5)
print('This message will be printed every 5 seconds')
Event loop (loop.run_forever()) berjalan tanpa henti, terus memproses tugas serta menangani koneksi dari klien. Dengan cara ini, server tetap aktif dan responsif terhadap setiap permintaan yang masuk.
loop.run_forever() Secara keseluruhan, kode ini memanfaatkan operasi asinkron secara menyeluruh—mulai dari membaca data klien melalui await reader.readline(), mengirim respons menggunakan writer.write(), hingga melakukan aksi periodik seperti toggling LED melalui await asyncio.sleep(). Pendekatan non-blocking ini memungkinkan server menjalankan tugas lain saat menunggu operasi I/O selesai, sehingga meningkatkan efisiensi dan responsivitas sistem.
Pengujian Kode
Unggah dan jalankan kode tersebut pada Raspberry Pi Pico untuk melakukan verifikasi fungsional.
Setelah perangkat berhasil terhubung ke jaringan internet, buka peramban web pada perangkat yang berada dalam jaringan yang sama, kemudian masukkan alamat IP Pico untuk mengakses layanan web server.
Beberapa client dapat melakukan koneksi secara simultan—baik melalui beberapa tab pada peramban maupun melalui berbagai perangkat—tanpa menimbulkan konflik koneksi. Seluruh *client* tetap dapat mengirim perintah untuk mengendalikan status LED (ON/OFF) serta melakukan permintaan nilai acak terbaru secara bersamaan.
Seluruh proses tersebut dapat dijalankan secara paralel, bersamaan dengan operasi berkala lainnya seperti pengendalian kedipan LED dan pencetakan pesan ke shell pada interval yang berbeda, tanpa saling mengganggu berkat mekanisme eksekusi non-blocking.
Pada tahap ini, Anda seharusnya telah memahami bahwa, alih-alih sekadar menjalankan rutinitas sederhana seperti mengedipkan LED atau mencetak log, Anda dapat mengeksekusi asynchronous task yang jauh lebih kompleks. Berkat arsitektur event-driven dan eksekusi non-blocking, Raspberry Pi Pico tetap mampu mempertahankan kinerja web server dan melayani banyak klien secara bersamaan tanpa degradasi responsivitas.
Mengunggah Kode ke Raspberry Pi Pico
Agar Raspberry Pi Pico dapat menjalankan *web server* secara mandiri tanpa koneksi ke komputer, Anda harus mengunggah berkas kode sebagai **main.py** ke dalam sistem berkas Pico. Untuk melakukannya, salin kode ke file baru, kemudian pilih **File > Save As** dan arahkan tujuan penyimpanan ke **Raspberry Pi Pico**.
Berikan nama berkas main.py dan klik OK untuk menyimpannya ke dalam sistem berkas Raspberry Pi Pico. Setelah berkas tersebut berada pada direktori utama perangkat, Pico akan mengeksekusi main.py secara otomatis pada proses boot, sehingga tidak lagi memerlukan koneksi ke komputer untuk menjalankan program.
Baca juga: Panduan Lengkap Mengirim Email via SMTP pada Raspberry Pi Pico W (MicroPython)
Siap Untuk Membuat Proyek Impianmu Menjadi Kenyataan?
Klik di sini untuk chat langsung via WhatsApp dan dapatkan dukungan langsung dari tim ahli kami!




0 on: "Cara Membuat Web Server Asinkron di Raspberry Pi Pico W Menggunakan MicroPython"