Panduan · 10 mnt baca

Raspberry Pi Pico PIO dan Dua Inti: _thread, setup1, WS2812B

Panduan Raspberry Pi Pico PIO: state machine, contoh gelombang kotak dan WS2812B, dua inti dengan MicroPython _thread dan Arduino setup1/loop1, serta perubahan Pico 2.

Blok Raspberry Pi Pico PIO dan dua intinya adalah dua fitur yang membedakan board kecil ini dari kebanyakan mikrokontroler dalam kisaran harga yang sama. Chip RP2040 di jantung Pico memiliki dua inti prosesor terpisah dan 8 state machine PIO. Berkat kedua inti ini, kamu bisa membaca sensor di satu sisi sementara layar atau animasi LED tetap berjalan lancar di sisi lain. Sementara itu, PIO adalah sekumpulan mesin pewaktu kecil yang bekerja secara mandiri dari prosesor: mesin ini menghasilkan sinyal berakurasi nanodetik yang dibutuhkan LED WS2812B, UART tambahan, atau gelombang kotak tanpa membebani CPU sama sekali.

Dalam panduan ini, pertama kamu akan menjalankan kedua inti dengan modul _thread di MicroPython, lalu dengan setup1() dan loop1() di Arduino IDE. Setelah itu, kamu akan mempelajari cara kerja PIO, jumlah state machine dan instruksi yang dipahaminya, lalu menulis dua program nyata: pembangkit gelombang kotak yang memainkan nada lewat buzzer dan pelangi WS2812B. Bagian terakhir membahas perubahan pada Pico 2 (RP2350) dan kapan kamu benar-benar membutuhkan fitur ini. Jika kamu baru mengenal Pico, saya sarankan membaca Apa Itu Raspberry Pi Pico? dan dasar-dasar MicroPython terlebih dahulu.

Board pengembangan Raspberry Pi Pico
Raspberry Pi Pico: chip RP2040 di tengah berisi dua inti Cortex-M0+ dan dua blok PIO. Semua 26 pin GPIO dapat dihubungkan ke PIO.

Apa itu dua inti dan PIO pada Raspberry Pi Pico?

RP2040 memiliki dua prosesor Cortex-M0+ identik yang disebut inti 0 dan inti 1. Ketika programmu dimulai, hanya inti 0 yang berjalan; inti 1 tidur sampai kamu menjalankannya. Kedua inti berbagi RAM 264 KB dan pin yang sama, sehingga memindahkan data di antara keduanya mudah, tetapi keduanya tidak boleh menulis variabel yang sama secara bersamaan. Untuk itu, chip ini memiliki antrean perangkat keras kecil dua arah (FIFO, 8 word untuk setiap arah) dan 32 kunci perangkat keras (spinlock). PIO sepenuhnya terpisah: masing-masing dari dua blok PIO memiliki 4 state machine, memori program bersama berkapasitas 32 instruksi, serta akses langsung ke pin. Setelah state machine dijalankan, ia mengeksekusi programnya sendiri siklus demi siklus meskipun prosesor sibuk mengerjakan hal lain.

Sumber dayaRP2040 (Pico, Pico W)Untuk apa?
Inti prosesor2 x Cortex-M0+, 133 MHz (hingga 200 MHz dalam dokumen terbaru)Menjalankan dua program terpisah benar-benar secara bersamaan
FIFO antarinti8 x 32-bit untuk setiap arahMengirim angka dan perintah antarinti
Kunci perangkat keras (spinlock)32Mengakses data bersama secara bergantian
Blok PIO2 (PIO0, PIO1)Mengalihkan pekerjaan pin yang membutuhkan ketepatan waktu dari prosesor
State machine4 per blok, total 8Masing-masing menjalankan program PIO sendiri
Memori program PIO32 instruksi per blokDipakai bersama oleh 4 state machine dalam blok tersebut
FIFO PIOTX 4 + RX 4 word per state machine (8 jika digabung)Data antara prosesor dan state machine

Inti kedua di MicroPython: modul _thread

Di MicroPython, cara memakai inti 1 adalah dengan memanggil _thread.start_new_thread(function, args). Pada Pico, ini menjalankan fungsi di inti kedua, sementara program utamamu tetap berjalan di inti 0. Hanya satu thread tambahan yang dapat berjalan dalam satu waktu, karena tidak ada inti ketiga. Pada contoh di bawah, inti 0 membaca potensiometer di GP26 dan mencetak hasilnya, sementara inti 1 mengedipkan LED bawaan dengan kecepatan yang diatur oleh potensiometer. Jeda sleep_ms() pada inti 1 sama sekali tidak memengaruhi inti 0; pada satu inti, kamu membutuhkan timer atau asyncio untuk melakukannya.

MicroPython
1# Pico - iki çekirdek (MicroPython _thread) / two cores (MicroPython _thread)
2import _thread
3import time
4from machine import Pin, ADC
5
6led = Pin("LED", Pin.OUT)          # Pico ve Pico W dahili LED / onboard LED on Pico and Pico W
7pot = ADC(26)                      # GP26 = ADC0, potansiyometre / potentiometer
8
9lock = _thread.allocate_lock()     # ortak veri kilidi / shared data lock
10blink_ms = 500                     # çekirdek 0 yazar, çekirdek 1 okur / core 0 writes, core 1 reads
11running = True                     # durdurma bayrağı / stop flag
12
13
14def core1_task():
15    # Çekirdek 1: LED'i kendi hızında yakıp söndürür / Core 1: blinks the LED at its own pace
16    while running:
17        with lock:
18            period = blink_ms
19        led.toggle()
20        time.sleep_ms(period)
21    led.off()
22
23
24_thread.start_new_thread(core1_task, ())   # ikinci çekirdekte başlat / start on the second core
25
26try:
27    while True:
28        # Çekirdek 0: sensörü okur ve hızı ayarlar / Core 0: reads the sensor and sets the speed
29        raw = pot.read_u16()                     # 0-65535
30        with lock:
31            blink_ms = 50 + raw * 950 // 65535   # 50-1000 ms
32        print("ham / raw:", raw, "ms:", blink_ms)
33        time.sleep_ms(200)
34except KeyboardInterrupt:
35    running = False                              # çekirdek 1'e dur de / tell core 1 to stop
36    time.sleep_ms(1100)
  • Kunci yang dibuat dengan allocate_lock() memastikan bahwa di dalam blok with lock:, hanya satu inti yang mengakses variabel bersama.
  • Flag running memberi tahu inti 1 untuk keluar dari perulangannya ketika kamu menghentikan program dengan Ctrl+C; jika tidak, LED terus berkedip.
  • Menulis Pin("LED") akan menemukan LED bawaan pada Pico maupun Pico W; pada Pico W, LED terhubung ke chip nirkabel, sehingga Pin(25) tidak berfungsi.
  • Pembagian yang baik adalah menempatkan perhitungan panjang, penggambaran layar, atau pewaktuan presisi di inti 1, serta Wi-Fi, menu, dan interaksi pengguna di inti 0.
Tombol Stop di Thonny hanya menghentikan program pada inti 0. Jika perulangan tanpa akhir tetap berjalan di inti 1, board terlihat sibuk dan kode baru tidak bisa di-upload. Dalam kondisi ini, cabut dan pasang kembali kabel USB atau reset board dengan menghubungkan pin RUN ke GND sebentar. Selalu gunakan flag penghentian seperti pada contoh, dan hindari alokasi memori yang berat (list besar, penggabungan string panjang) di thread tambahan; dukungan multiinti di MicroPython masih dianggap eksperimental.

Dua inti di Arduino IDE: setup1() dan loop1()

Paket Pico yang paling banyak dipakai untuk Arduino IDE adalah core Raspberry Pi Pico/RP2040/RP2350 karya Earle Philhower (arduino-pico). Memakai kedua inti dengannya ternyata sangat mudah: setup() dan loop() yang sudah familier berjalan di inti 0; jika kamu menambahkan setup1() dan loop1() ke sketch, inti 1 otomatis mulai dan menjalankan kedua fungsi tersebut. Data dikirim antarinti dengan objek rp2040.fifo. Paket resmi Arduino “Arduino Mbed OS RP2040” tidak mendukung setup1(), jadi pastikan kamu memilih paket yang tepat di Boards Manager.

C++ (Arduino IDE)
1// Raspberry Pi Pico - iki çekirdek (Arduino-Pico çekirdeği) / two cores (Arduino-Pico core)
2const int POT_PIN = 26;        // GP26 = ADC0, potansiyometre / potentiometer
3
4// ---- Çekirdek 0 / Core 0 ----
5void setup() {
6  Serial.begin(115200);
7}
8
9void loop() {
10  int raw = analogRead(POT_PIN);   // 0-1023 (varsayılan 10 bit / default 10-bit)
11  rp2040.fifo.push_nb(raw);        // FIFO doluysa bekleme, değeri atla / skip the value if the FIFO is full
12  Serial.print("pot: ");
13  Serial.println(raw);
14  delay(100);
15}
16
17// ---- Çekirdek 1 / Core 1 ----
18void setup1() {
19  pinMode(LED_BUILTIN, OUTPUT);
20}
21
22void loop1() {
23  static uint32_t periodMs = 500;
24  uint32_t value;
25  while (rp2040.fifo.pop_nb(&value)) {           // FIFO'yu boşalt, sonuncuyu kullan / drain the FIFO, keep the last one
26    periodMs = map(value, 0, 1023, 50, 1000);
27  }
28  digitalWrite(LED_BUILTIN, HIGH);
29  delay(periodMs);                               // yalnız çekirdek 1'i bekletir / only blocks core 1
30  digitalWrite(LED_BUILTIN, LOW);
31  delay(periodMs);
32}
FungsiKegunaan
rp2040.fifo.push(x)Mengirim nilai 32-bit ke inti lain; menunggu ruang kosong jika antrean penuh
rp2040.fifo.push_nb(x)Mencoba mengirim tanpa menunggu; mengembalikan false jika antrean penuh
rp2040.fifo.pop()Membaca nilai dari inti lain; menunggu jika antrean kosong
rp2040.fifo.pop_nb(&x)Menulis nilai ke x dan mengembalikan true jika ada nilai, jika tidak langsung mengembalikan false
rp2040.fifo.available()Mengembalikan jumlah nilai yang menunggu untuk dibaca
rp2040.idleOtherCore() / resumeOtherCore()Menjeda sebentar dan melanjutkan inti lain (misalnya ketika menulis ke flash)
Jangan memakai satu perangkat keras seperti port serial, layar, atau bus SPI dari kedua inti secara bersamaan. Seperti pada contoh, serahkan setiap periferal ke satu inti dan biarkan inti lain mengirim angka kepadanya melalui FIFO. Dengan begitu, kamu menghindari teks berantakan dan tampilan rusak tanpa membutuhkan kunci.

Apa itu PIO? Cara kerja I/O yang bisa diprogram

Pada kebanyakan mikrokontroler, blok komunikasi dan sinyal seperti UART, SPI, I2C, dan PWM sudah ditetapkan di silikon; jika kamu membutuhkan protokol di luar daftar tersebut, prosesor menanganinya dengan menyalakan dan mematikan pin satu per satu (bit-banging). Hal ini membuat prosesor sibuk, dan pewaktuan terganggu setiap kali ada interrupt yang menyela. PIO (Programmable Input/Output) mengatasi masalah ini dari akarnya: setiap state machine adalah prosesor kecil dengan sembilan instruksi yang dirancang khusus untuk pekerjaan pin. Setiap instruksi berjalan tepat selama satu siklus clock, dan jeda 0 hingga 31 siklus dapat ditambahkan di akhirnya. Jadi, kamu tahu persis berapa nanodetik yang dibutuhkan setiap tepi sinyal hanya dengan menghitung siklus. Kecepatan state machine diatur dengan membagi clock sistem menggunakan pembagi antara 1 dan 65.536.

InstruksiKegunaan
set(pins, v)Menulis konstanta 0-31 ke pin atau register X/Y
out(dest, n)Memindahkan n bit dari output shift register (OSR) ke pin atau X/Y
in_(src, n)Menggeser n bit dari pin atau register ke input shift register (ISR)
pull() / push()Menarik satu word dari FIFO TX ke OSR, mendorong word ISR ke FIFO RX
jmp(cond, label) (instruksi lompat bersyarat)Melompat berdasarkan kondisi (X nol, pin high, X--, dan sebagainya)
wait(polarity, src, idx) (instruksi tunggu)Menunggu sampai pin atau flag IRQ mencapai level yang diinginkan
mov(dest, src) (instruksi salin antar register)Menyalin antarregister, dengan opsi membalik bit
irq(idx)Mengirim flag interrupt ke CPU atau state machine lain
nop() dan .side(v)Instruksi kosong; side-set mengubah pin dalam siklus yang sama dengan instruksi apa pun

Di MicroPython, program PIO adalah fungsi Python yang ditulis dengan dekorator @rp2.asm_pio; fungsi itu tidak dipanggil, melainkan dirakit oleh MicroPython menjadi kode mesin. Kamu lalu memuatnya ke state machine dengan rp2.StateMachine(id, program, freq=..., set_base=...). Pada Pico, state machine bernomor 0-3 termasuk PIO0 dan 4-7 termasuk PIO1. Nilai freq adalah jumlah siklus instruksi per detik dan tidak boleh lebih rendah dari 1/65536 clock sistem; pada 125 MHz nilainya sekitar 1,9 kHz, pada 150 MHz sekitar 2,3 kHz. Jika membutuhkan sinyal lebih lambat, gunakan jeda atau perulangan dengan penghitung X/Y.

Gelombang kotak dengan PIO: program state machine pertamamu

Pada contoh pertama, kita akan memainkan tangga nada pada buzzer pasif yang terhubung ke GP15, lalu membiarkan gelombang kotak 1 kHz berjalan terus-menerus. Program ini hanya memiliki dua instruksi: atur pin HIGH dan tunggu 9 siklus, atur pin LOW dan tunggu 9 siklus. Karena setiap instruksi sendiri membutuhkan 1 siklus, satu periode adalah 20 siklus, jadi kamu cukup memberi state machine frekuensi 20 kali frekuensi nada yang diinginkan. Hubungkan kaki positif buzzer ke GP15 dan kaki negatifnya ke GND. Sebagai pengganti buzzer, kamu juga bisa memakai osiloskop atau LED dengan resistor 220 ohm; pilih resistornya dengan kalkulator resistor LED.

MicroPython
1# PIO ile kare dalga ve buzzer notaları / square wave and buzzer notes with PIO
2import time
3import rp2
4from machine import Pin
5
6
7@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
8def square():
9    wrap_target()
10    set(pins, 1)   [9]     # 1 + 9 = 10 döngü HIGH / 10 cycles HIGH
11    set(pins, 0)   [9]     # 1 + 9 = 10 döngü LOW / 10 cycles LOW
12    wrap()                 # başa dön, işlemci karışmaz / loop back, no CPU involved
13
14
15def tone(freq_hz):
16    # Bir periyot 20 döngü: durum makinesi frekansı = 20 x ton
17    # One period is 20 cycles: state machine frequency = 20 x tone
18    sm = rp2.StateMachine(0, square, freq=freq_hz * 20, set_base=Pin(15))
19    sm.active(1)
20    return sm
21
22
23notes = [262, 294, 330, 349, 392, 440, 494, 523]   # Do-Re-Mi ... / C4 ... C5
24for n in notes:
25    sm = tone(n)
26    time.sleep_ms(300)        # işlemci boşta, ses PIO'dan / CPU is idle, PIO makes the sound
27    sm.active(0)
28
29sm = tone(1000)               # 1 kHz sürekli kare dalga / continuous 1 kHz square wave
30print("GP15: 1 kHz kare dalga / square wave")

Rumusnya sederhana: frekuensi nada = frekuensi state machine / jumlah siklus. Untuk 1000 Hz, state machine berjalan pada 20.000 Hz, jauh di atas batas bawahnya. Jika kamu menghapus jeda dan hanya menyisakan dua instruksi set(), satu periode turun menjadi 2 siklus; menjalankan state machine pada 125 MHz lalu menghasilkan gelombang kotak 62,5 MHz pada pin. Ingat bahwa PWM perangkat keras bisa melakukan pekerjaan yang sama: untuk nada sederhana atau kecerahan LED, PWM sudah cukup. Yang membedakan PIO adalah kamu menentukan bentuk sinyal secara tepat; dengan beberapa baris, kamu bisa menghasilkan pulsa dengan lebar yang berubah, jumlah pulsa yang presisi, atau output yang bereaksi terhadap input.

Mengendalikan LED WS2812B (NeoPixel) dengan PIO

Cincin RGB WS2812B dengan 24 LED
Cincin WS2812B dengan 24 LED: setiap LED memiliki pengendali sendiri di dalamnya dan menerima warnanya dalam 24 bit melalui satu jalur data.

LED WS2812B membutuhkan pulsa sekitar 1,25 mikrodetik per bit; nilai bit 1 atau 0 ditentukan oleh lamanya pulsa tetap HIGH. Ini contoh yang sangat cocok untuk PIO. Program di bawah didasarkan pada contoh MicroPython resmi Raspberry Pi: state machine berjalan pada 8 MHz dan setiap bit membutuhkan tepat 10 siklus, sehingga 800.000 bit dikirim per detik. Berkat autopull, state machine mengambil warna baru dari FIFO setiap 24 bit; prosesor cukup memasukkan array ke FIFO dengan sm.put(). Ubah jumlah LED agar sesuai dengan strip-mu; untuk cara kerja WS2812B dan urutan warnanya, lihat panduan WS2812B NeoPixel.

Pin WS2812BPin PicoCatatan
DIN (input data)GP16 (pin fisik 21)Resistor seri 330 ohm melindungi sinyal
5V / VCCVBUS (pin 40)5 V dari USB; gunakan catu daya eksternal 5 V untuk banyak LED
GNDGND (misalnya pin 38)GND catu daya eksternal juga harus dihubungkan ke sini
MicroPython
1# PIO ile WS2812B (NeoPixel) gökkuşağı / WS2812B (NeoPixel) rainbow with PIO
2import array
3import time
4import rp2
5from machine import Pin
6
7NUM_LEDS = 24          # halka ya da şeritteki LED sayısı / LEDs in the ring or strip
8LED_PIN = 16           # DIN bağlantısı / DIN connection
9BRIGHTNESS = 0.2       # 0.0-1.0, akımı düşük tutar / keeps current low
10
11
12@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT,
13             autopull=True, pull_thresh=24)
14def ws2812():
15    T1 = 2
16    T2 = 5
17    T3 = 3
18    wrap_target()
19    label("bitloop")
20    out(x, 1)               .side(0)    [T3 - 1]   # 1 biti al, hat LOW / take 1 bit, line LOW
21    jmp(not_x, "do_zero")   .side(1)    [T1 - 1]   # hat HIGH / line HIGH
22    jmp("bitloop")          .side(1)    [T2 - 1]   # bit 1: uzun HIGH / long HIGH
23    label("do_zero")
24    nop()                   .side(0)    [T2 - 1]   # bit 0: kısa HIGH / short HIGH
25    wrap()
26
27
28# Bit başına 10 döngü x 8 MHz = 800 kHz / 10 cycles per bit x 8 MHz = 800 kHz
29sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(LED_PIN))
30sm.active(1)
31
32pixels = array.array("I", [0] * NUM_LEDS)
33
34
35def set_pixel(i, r, g, b):
36    r = int(r * BRIGHTNESS)
37    g = int(g * BRIGHTNESS)
38    b = int(b * BRIGHTNESS)
39    pixels[i] = (g << 16) | (r << 8) | b    # WS2812B sırası GRB / byte order is GRB
40
41
42def show():
43    sm.put(pixels, 8)      # 24 biti sola hizala / left-align the 24 bits
44
45
46def wheel(pos):
47    # 0-255 arası değeri renge çevir / turn 0-255 into a colour
48    pos %= 255
49    if pos < 85:
50        return 255 - pos * 3, pos * 3, 0
51    if pos < 170:
52        pos -= 85
53        return 0, 255 - pos * 3, pos * 3
54    pos -= 170
55    return pos * 3, 0, 255 - pos * 3
56
57
58step = 0
59while True:
60    for i in range(NUM_LEDS):
61        set_pixel(i, *wheel(i * 255 // NUM_LEDS + step))
62    show()
63    step = (step + 3) % 255
64    time.sleep_ms(30)      # kare arası bekleme, aynı zamanda reset / frame gap, also the reset time

Mari ikuti programnya baris demi baris. out(x, 1) mengambil satu bit dari OSR ke register X sementara side-set menahan jalur LOW (3 siklus). Lalu jalur menjadi HIGH dan X diperiksa (2 siklus). Jika bitnya 1, jalur tetap HIGH selama 5 siklus lagi; jika 0, jalur ditarik LOW dan state machine menunggu 5 siklus. Kedua jalur eksekusi berjumlah 10 siklus, yaitu 1,25 µs. pull_thresh=24 memberi tahu state machine untuk memakai hanya 24 bit dari setiap word, sehingga warna digeser ke kiri di sisi Python (sm.put(pixels, 8)). Urutan warnanya GRB, bukan RGB; itulah penyebabnya jika merah dan hijau tertukar. Karena 24 LED pada putih penuh bisa menarik arus hingga 1,4 A, kecerahan pada contoh dibatasi menjadi 20%.

Jika kamu hanya ingin menyalakan LED, modul neopixel bawaan MicroPython juga bisa melakukannya: np = neopixel.NeoPixel(Pin(16), 24), np[0] = (255, 0, 0), np.write(). Keuntungan menulis versi PIO adalah prosesor tetap bebas selama transmisi dan kamu bisa menyesuaikan teknik yang sama untuk protokol lain.

Apa yang berubah pada Pico 2 (RP2350)?

Raspberry Pi Pico 2 adalah generasi baru dengan ukuran dan pinout yang sama, tetapi memakai chip RP2350 di dalamnya. Jumlah intinya tetap dua, tetapi kali ini kamu bisa memilih ketika boot antara dua inti Arm Cortex-M33 atau dua inti Hazard3 RISC-V. Semua kode dalam artikel ini berjalan tanpa perubahan di Pico 2: _thread tetap sama di MicroPython, dan pada core Arduino-Pico, setup1()/loop1() serta rp2040.fifo tetap memakai nama yang sama. Di sisi PIO, ada tambahan blok ketiga, sehingga tersedia 12 state machine (0-11 di MicroPython), ditambah beberapa opsi instruksi baru.

FiturPico (RP2040)Pico 2 (RP2350)
Inti2 x Cortex-M0+2 x Cortex-M33 atau 2 x Hazard3 RISC-V
Kecepatan clock133 MHz150 MHz
RAM264 KB520 KB
Flash bawaan2 MB4 MB
PIO2 blok, 8 state machine3 blok, 12 state machine
Floating pointMelalui perangkat lunak (rutin ROM cepat)FPU perangkat keras (presisi tunggal) + koprosesor presisi ganda
KeamananTidak adaTrustZone, secure boot, OTP 8 KB
File MicroPythonRPI_PICO (.uf2)RPI_PICO2 (.uf2)

Dalam praktiknya, perbedaan Pico 2 yang paling terasa adalah kecepatan: berkat FPU perangkat keras, pekerjaan yang banyak memakai float (filter, fusi sensor, pemrosesan audio) berjalan beberapa kali lebih cepat, dan RAM dua kali lipat memberi ruang untuk buffer layar besar. Hal yang perlu diperhatikan adalah menulis file UF2 yang sesuai dengan board; file Pico tidak berjalan di Pico 2. Versi awal RP2350 memiliki masalah perangkat keras yang sudah diketahui (E9) pada input yang memakai pull-down internal, dan masalah ini diperbaiki pada revisi A4; memakai resistor eksternal ketika menghubungkan tombol tetap menjadi pilihan aman untuk keduanya.

Kapan kamu membutuhkan dua inti, dan kapan PIO?

KebutuhanmuPilihan paling cocokMengapa?
Kecerahan LED, servo, nada sederhanaPWM perangkat kerasBlok siap pakai, satu baris kode
Beberapa sensor + layar + tombolSatu inti, millis() atau asyncioTidak perlu kerumitan tambahan
Animasi lancar selama perhitungan panjangDua intiPerhitungan di inti 1 tidak membuat layar macet
Pengukuran terus-menerus bersamaan dengan Wi-FiDua intiJeda jaringan tidak mengganggu interval sampling
WS2812B, UART tambahan, pemancar IR, encoderPIOAkurasi nanodetik, CPU tetap bebas
Video VGA/DVI, audio I2S, sinyal sangat cepatPIO + DMALaju data yang tidak bisa diimbangi CPU

Singkatnya: pertimbangkan inti kedua ketika pekerjaan saling berbenturan di perangkat lunak, dan PIO ketika pin membutuhkan akurasi di bawah satu mikrodetik. Kebanyakan proyek hobi tidak membutuhkan keduanya; tetapi jika suatu hari animasi WS2812B-mu mulai tersendat selama request Wi-Fi, atau UART pada board habis terpakai, solusinya sudah tersedia di dalam Pico.

Ide proyek dengan PIO dan dua inti Pico

  • Cincin LED yang bereaksi terhadap musik: inti 1 memproses sampel mikrofon, PIO mengendalikan cincin WS2812B, dan inti 0 memantau tombol.
  • Pembangkit pulsa delapan kanal: setiap state machine menghasilkan gelombang kotak dengan frekuensi berbeda untuk memasok sinyal ke driver motor stepper atau perangkat pengujian.
  • Pencatat data tanpa celah: inti 1 membaca ADC setiap 10 ms sementara inti 0 mengirim data melalui Wi-Fi; jaringan lambat tidak akan membuatmu kehilangan sampel.
  • Port serial tambahan: buka UART ketiga dan keempat dengan PIO, lalu hubungkan modul GPS dan Bluetooth secara bersamaan.
  • Penghitung rotary encoder: PIO menghitung pulsa encoder tanpa melewatkan satu pun; prosesor hanya membaca hasilnya.
  • Lampu tidur dengan efek bernapas: serahkan perubahan kecerahan PWM yang halus ke inti 1 dan sensor cahaya ke inti 0.

Kesalahan umum dan cara mengatasinya

GejalaPenyebabSolusi
Board tidak merespons setelah program dihentikanPerulangan di inti 1 masih berjalanGunakan flag penghentian; cabut dan pasang kembali USB jika perlu
start_new_thread gagal pada percobaan keduaPico hanya mengizinkan satu thread tambahanJangan mulai thread baru sebelum yang sebelumnya berakhir
Variabel terkadang mendapat nilai yang tidak masuk akalKedua inti menulis data bersama tanpa kunciGunakan allocate_lock() atau FIFO
StateMachine memunculkan ValueErrorfreq di bawah clock sistem / 65536Naikkan frekuensi dan perlambat dengan jeda
“PIOASMError: delay too large”Bit side-set memperkecil bidang jedaBagi jeda atau tambahkan nop()
Merah dan hijau tertukar pada WS2812BUrutan warnanya GRBGunakan format (g << 16) | (r << 8) | b
setup1() tidak pernah berjalanPaket Arduino Mbed RP2040 dipilihInstal paket Raspberry Pi Pico/RP2040 karya Earle Philhower
Ketika menulis program PIO, catat jumlah siklus setiap instruksi dan pastikan totalnya sesuai dengan waktu yang kamu inginkan. Jika kamu memiliki osiloskop atau logic analyser murah, itu sangat membantu; jika tidak, turunkan sementara frekuensi state machine ke 2-3 kHz dan pantau pin dengan LED agar kamu bisa melihat kesalahannya sendiri.

Dua inti dan PIO mengubah Pico dari sekadar pengedip LED menjadi sistem embedded yang serius, tetapi semuanya bertumpu pada fondasi yang sama: mengenal pin, pewaktuan, dan LED dengan baik. Di aplikasi BlueGrays, kamu akan menemukan proyek Raspberry Pi Pico seperti LED berkedip, LED berjalan, pemindai Knight Rider, state machine yang dikendalikan tombol, dan efek bernapas PWM, masing-masing dengan skema rangkaian dan kode MicroPython, langkah demi langkah, siap untuk kamu tambahkan teknik dari artikel ini.

Pertanyaan umum

Apa itu PIO pada Raspberry Pi Pico?

PIO (I/O yang bisa diprogram) adalah sekumpulan state machine kecil dalam chip RP2040 dan RP2350 yang berjalan secara mandiri dari prosesor. Masing-masing mengeksekusi program yang ditulis dalam bahasa sederhana dengan sembilan instruksi dan pewaktuan yang akurat hingga tingkat siklus. PIO menangani pekerjaan yang membutuhkan ketepatan waktu seperti LED WS2812B, UART tambahan, transmisi IR, atau pembacaan encoder tanpa menyibukkan CPU.

Berapa inti yang dimiliki Raspberry Pi Pico?

Chip RP2040 pada Pico dan Pico W memiliki dua inti Cortex-M0+. RP2350 pada Pico 2 juga memiliki dua inti, dan ketika boot kamu bisa memilih antara inti Cortex-M33 dan Hazard3 RISC-V. Ketika programmu dimulai, hanya inti 0 yang berjalan; kamu menjalankan inti 1 sendiri.

Berapa jumlah state machine PIO pada Pico?

RP2040 memiliki dua blok PIO dengan masing-masing 4 state machine, sehingga totalnya 8 state machine. Memori program berkapasitas 32 instruksi pada setiap blok dipakai bersama oleh state machine di blok tersebut. RP2350 pada Pico 2 memiliki tiga blok PIO, yang berarti 12 state machine.

Bisakah MicroPython memakai kedua inti Pico?

Ya. Pada Pico, fungsi yang dimulai dengan _thread.start_new_thread() berjalan di inti kedua. Hanya satu thread tambahan yang bisa aktif dalam satu waktu, dan data bersama perlu dilindungi dengan kunci dari _thread.allocate_lock(). Dukungan multiinti masih eksperimental di MicroPython, jadi sebaiknya hindari pekerjaan memori yang berat di thread tambahan.

Bagaimana cara memakai inti kedua Pico di Arduino IDE?

Setelah menginstal paket Raspberry Pi Pico/RP2040/RP2350 karya Earle Philhower, cukup tambahkan fungsi setup1() dan loop1() ke sketch-mu; inti 1 menjalankannya secara otomatis. Nilai 32-bit diteruskan antarinti dengan rp2040.fifo.push() dan rp2040.fifo.pop(). Paket RP2040 berbasis Mbed dari Arduino tidak memiliki fitur ini.

Apakah saya harus memakai PIO untuk LED WS2812B?

Tidak. Modul neopixel bawaan MicroPython dan library Adafruit NeoPixel di Arduino sama-sama berjalan dengan baik pada Pico. Manfaat menulisnya sendiri dengan PIO adalah prosesor tetap bebas selama transmisi dan kamu bisa menerapkan teknik yang sama pada protokol lain yang membutuhkan ketepatan waktu.

Lihat semua proyek
Kedip LED Bawaan Raspberry Pi Pico (Pico dan Pico W)
#147Pemula

Kedip LED Bawaan Raspberry Pi Pico (Pico dan Pico W)

Proyek pembuka seri Raspberry Pi Pico! Kita mengedipkan LED hijau bawaan untuk memastikan board bekerja; percobaan "Hello World" klasik. TANPA komponen eksternal, hanya Pico dan kabel USB. Kodenya ditulis dalam MicroPython (bahasa resmi dari Raspberry Pi Foundation). Pelajari kelas machine.Pin, mode Pin.OUT, metode led.on()/off(), dan time.sleep() di Thonny IDE, dan ikuti setiap perubahan di output Serial (REPL). Juga pas untuk menguji firmware MicroPython.

5.0(1)
10
Raspberry Pi Pico: Mengendalikan LED Eksternal (Breadboard)
#148Pemula

Raspberry Pi Pico: Mengendalikan LED Eksternal (Breadboard)

Langkah berikutnya setelah LED bawaan Pico: menyambungkan LED eksternal ke breadboard dan mengendalikannya lewat pin GP14. Di proyek ini, kamu belajar memakai pin GPIO serbaguna Pico mana pun sebagai output, polaritas LED (kaki panjang = anoda/+, kaki pendek = katoda/–), dan kenapa resistor pembatas arus (220Ω) diperlukan. Tanpa resistor, arus berlebih mengalir melalui LED dan LED bisa terbakar. Rangkaiannya sangat sederhana: Pico GP14 → resistor 220Ω → LED → GND.

4.5(2)
7
Simulator Lampu Lalu Lintas Raspberry Pi Pico (3 LED Berurutan)
#150Pemula

Simulator Lampu Lalu Lintas Raspberry Pi Pico (3 LED Berurutan)

Kita menyimulasikan lampu lalu lintas sungguhan dengan LED merah, kuning, dan hijau; proyek 3 LED pertama di seri Pico! Hijau 4 detik "jalan", kuning 1,5 detik "siap", merah 3 detik "berhenti", dan merah+kuning 1 detik "bersiap" (pola Eropa). Pelajari pendefinisian fungsi (def all_off()), logika state machine, dan sinkronisasi beberapa GPIO. 3 LED di GP11 (Hijau), GP12 (Kuning), GP13 (Merah), masing-masing dengan resistor 220Ω, berdampingan di board.

4.0(1)
12
LED Berjalan Raspberry Pi Pico (6 LED)
#153Pemula

LED Berjalan Raspberry Pi Pico (6 LED)

Animasi "LED berjalan" klasik dengan Pico, versi 6 LED! 6 LED menyala berurutan dari kiri ke kanan, seperti cahaya yang berjalan. Pelajari list Python, list comprehension ([Pin(p, Pin.OUT) for p in LED_PINS]), loop for dengan kendali pin, dan enumerate(). 6 LED di GP9-GP14, masing-masing dengan resistor 220Ω. Alih-alih mendefinisikan LED satu per satu, kita memakai list; kamu bisa menambah LED sebanyak pin GPIO yang bebas. Untuk 100 LED, pakai LED beralamat seperti WS2812B.

0.0(0)
8
Pemindai LED Knight Rider Raspberry Pi Pico (6 LED Bolak-balik)
#154Pemula

Pemindai LED Knight Rider Raspberry Pi Pico (6 LED Bolak-balik)

Efek pemindai LED "Knight Rider" klasik dengan Pico! 6 LED bergerak dari kiri ke kanan, lalu kembali, selamanya, seperti gril depan mobil KITT dari serial TV tahun 80-an. Ini pengembangan dari proyek LED Berjalan: rangkaian 6 LED yang sama (GP9-GP14), pola kode berbeda. Pelajari reversed() untuk membalik list, dua loop for untuk pola bolak-balik, dan cara membuat beberapa animasi di rangkaian yang sama. Perangkat keras sama, efek yang sama sekali berbeda.

0.0(0)
13
Lampu Lalu Lintas Raspberry Pi Pico dengan Pemilih 4 Mode lewat Tombol (State Machine)
#158Menengah

Lampu Lalu Lintas Raspberry Pi Pico dengan Pemilih 4 Mode lewat Tombol (State Machine)

4 mode lampu lalu lintas dengan 1 tombol! Setiap tekanan mengganti mode: Siklus normal (merah → kuning → hijau), Hanya Merah (tanda berhenti), Kuning Berkedip (mode malam), Mati (perawatan). Konsep: state machine (variabel mode menentukan perilaku), perputaran mode dengan modulo ((mode + 1) % 4 → 0→1→2→3→0), waktu non-blocking (fase LED dengan time.ticks_ms() + time.ticks_diff(); jeda debounce singkat tetap memakai sleep_ms).

5.0(1)
15
Debounce Tombol Raspberry Pi Pico: IRQ vs Polling Perangkat Lunak
#159Menengah
Premium

Debounce Tombol Raspberry Pi Pico: IRQ vs Polling Perangkat Lunak

Tekan tombol sekali, kode menghitung 3-4? Itu pantulan kontak: kontak logam bergetar beberapa mikrodetik! Bandingkan 2 metode di Serial: polling MENTAH (ikut menghitung pantulan) vs IRQ + debounce perangkat lunak (akurat). Pelajari pantulan kontak, debounce perangkat lunak (ticks_diff() > 50ms), interrupt Pin.irq(), pemicu IRQ_FALLING, handler ISR, serta global + keamanan ISR. LED berbalik lewat IRQ, dan Serial menampilkan kedua penghitung.

0.0(0)
12
LED Fade PWM Raspberry Pi Pico (Efek Bernapas)
#160Pemula

LED Fade PWM Raspberry Pi Pico (Efek Bernapas)

LED tidak lagi sekadar berkedip, ia bernapas! Dengan PWM (Pulse Width Modulation) Pico, kecerahan LED naik lalu turun perlahan, seperti lampu MacBook yang tidur. Pelajari kelas machine.PWM, duty_u16() (kecerahan 16-bit 0–65535), frekuensi PWM (freq(1000): 1000 siklus per detik, tanpa kedipan terlihat), loop range() bertahap, dan output mirip analog dari pin digital. PWM juga dipakai untuk warna RGB, motor, servo, dan buzzer.

0.0(0)
4