Raspberry Pi Pico PIO ve İki Çekirdek: _thread, setup1, WS2812B
Raspberry Pi Pico PIO rehberi: durum makineleri, kare dalga ve WS2812B örneği, MicroPython _thread ve Arduino setup1/loop1 ile iki çekirdek, Pico 2 farkları.
Raspberry Pi Pico PIO birimi ve iki çekirdeği, bu küçük kartı aynı fiyattaki çoğu mikrodenetleyiciden ayıran iki özelliktir. Pico'nun kalbindeki RP2040 yongasında iki ayrı işlemci çekirdeği ve 8 adet PIO durum makinesi bulunur. Çekirdekler sayesinde bir yanda sensör okurken öbür yanda ekranı ya da LED animasyonunu hiç takılmadan sürdürebilirsin. PIO ise işlemciden bağımsız çalışan minik zamanlama motorlarıdır: WS2812B LED'lerinin istediği nanosaniye hassasiyetindeki sinyali, ek bir UART'ı ya da kare dalgayı işlemciye hiç yük bindirmeden üretir.
Bu rehberde önce iki çekirdeği MicroPython'da _thread modülüyle, sonra Arduino IDE'de setup1() ve loop1() ile çalıştıracaksın. Ardından PIO'nun nasıl çalıştığını, kaç durum makinesi olduğunu ve hangi komutları bildiğini öğrenip iki gerçek program yazacaksın: buzzer'dan nota çalan bir kare dalga üreteci ve bir WS2812B gökkuşağı. Son bölümde Pico 2'nin (RP2350) getirdiği farklara ve bu özelliklere gerçekten ne zaman ihtiyaç duyduğuna bakacağız. Pico'ya yeniysen önce Raspberry Pi Pico Nedir? ve MicroPython Nedir? yazılarını okumanı öneririm.

Raspberry Pi Pico'nun iki çekirdeği ve PIO birimi nedir?
RP2040'ta çekirdek 0 ve çekirdek 1 adında iki eş Cortex-M0+ işlemci vardır. Program açıldığında yalnız çekirdek 0 çalışır; çekirdek 1 sen onu başlatana kadar uyur. İki çekirdek aynı 264 KB RAM'i ve aynı pinleri paylaşır, bu yüzden aralarında veri taşımak kolaydır ama aynı değişkene aynı anda yazmamaları gerekir. Bunun için yongada iki yönlü küçük bir donanım kuyruğu (FIFO, her yönde 8 sözcük) ve 32 adet donanım kilidi (spinlock) bulunur. PIO ise çekirdeklerden tamamen ayrı bir dünyadır: iki PIO bloğunun her birinde 4 durum makinesi, ortak 32 komutluk program belleği ve pinlere doğrudan erişim vardır. Durum makinesi bir kez başlatıldıktan sonra işlemci başka işle uğraşırken bile kendi programını döngü döngü yürütür.
| Kaynak | RP2040 (Pico, Pico W) | Ne işe yarar? |
|---|---|---|
| İşlemci çekirdeği | 2 x Cortex-M0+, 133 MHz (güncel belgelerde 200 MHz'e kadar) | İki ayrı programı gerçekten aynı anda çalıştırmak |
| Çekirdekler arası FIFO | Her yönde 8 x 32 bit | Çekirdekler arasında sayı ve komut göndermek |
| Donanım kilidi (spinlock) | 32 adet | Ortak veriye sırayla erişmek |
| PIO bloğu | 2 adet (PIO0, PIO1) | Zamanlaması hassas pin işlerini işlemciden almak |
| Durum makinesi | Blok başına 4, toplam 8 | Her biri ayrı bir PIO programı yürütür |
| PIO program belleği | Blok başına 32 komut | O bloktaki 4 durum makinesi paylaşır |
| PIO FIFO | Makine başına TX 4 + RX 4 sözcük (birleştirilince 8) | İşlemci ile durum makinesi arasında veri |
MicroPython'da ikinci çekirdek: _thread modülü
MicroPython'da çekirdek 1'i kullanmanın yolu _thread.start_new_thread(fonksiyon, argümanlar) çağrısıdır. Pico'da bu çağrı fonksiyonu ikinci çekirdekte başlatır; ana programın ise çekirdek 0'da devam eder. Aynı anda yalnız bir ek iş parçacığı çalışabilir, çünkü ikinci bir çekirdek yoktur. Aşağıdaki örnekte çekirdek 0 GP26'ya bağlı bir potansiyometreyi okuyup sonucu ekrana yazar, çekirdek 1 ise dahili LED'i potansiyometrenin belirlediği hızda yakıp söndürür. Çekirdek 1'deki sleep_ms() beklemesi çekirdek 0'ı hiç etkilemez; tek çekirdekte bunu yapmak için zamanlayıcı ya da asyncio gerekirdi.
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)- allocate_lock() ile oluşturulan kilit, with lock: bloğu içinde yalnız bir çekirdeğin ortak değişkene dokunmasını sağlar.
- running bayrağı, Ctrl+C ile programı durdurduğunda çekirdek 1'e döngüden çıkmasını söyler; aksi halde LED yanıp sönmeye devam eder.
- Pin("LED") yazımı hem Pico'da hem Pico W'de dahili LED'i bulur; Pico W'de LED kablosuz yongaya bağlı olduğu için Pin(25) çalışmaz.
- Çekirdek 1'de uzun süren hesap, ekran çizimi ya da hassas zamanlama gibi işler, çekirdek 0'da ise Wi-Fi, menü ve kullanıcı etkileşimi tutmak iyi bir paylaşımdır.
Arduino IDE'de iki çekirdek: setup1() ve loop1()
Arduino IDE'de Pico için en yaygın kullanılan paket, Earle Philhower'ın hazırladığı Raspberry Pi Pico/RP2040/RP2350 çekirdeğidir (arduino-pico). Bu pakette iki çekirdeği kullanmak şaşırtıcı derecede kolaydır: alışık olduğun setup() ve loop() çekirdek 0'da çalışır; çizime setup1() ve loop1() eklersen çekirdek 1 otomatik olarak başlar ve bu iki fonksiyonu yürütür. Çekirdekler arasında veri göndermek için rp2040.fifo nesnesi kullanılır. Arduino'nun resmî "Arduino Mbed OS RP2040" paketinde setup1() desteği yoktur; bu yüzden Kart Yöneticisi'nde doğru paketi seçtiğinden emin ol.
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}| Fonksiyon | Ne yapar? |
|---|---|
| rp2040.fifo.push(x) | 32 bitlik değeri öbür çekirdeğe gönderir; kuyruk doluysa yer açılana kadar bekler |
| rp2040.fifo.push_nb(x) | Beklemeden göndermeyi dener; kuyruk doluysa false döndürür |
| rp2040.fifo.pop() | Öbür çekirdekten gelen değeri okur; kuyruk boşsa bekler |
| rp2040.fifo.pop_nb(&x) | Değer varsa x'e yazar ve true döndürür, yoksa hemen false döndürür |
| rp2040.fifo.available() | Okunmayı bekleyen değer sayısını verir |
| rp2040.idleOtherCore() / resumeOtherCore() | Öbür çekirdeği kısa süreliğine durdurur ve yeniden başlatır (ör. flaşa yazarken) |
PIO nedir? Programlanabilir giriş-çıkış nasıl çalışır?
Çoğu mikrodenetleyicide UART, SPI, I2C ve PWM gibi haberleşme ve sinyal birimleri yongaya sabitlenmiştir; listede olmayan bir protokol gerekirse işlemci pinleri tek tek açıp kapatarak (bit-banging) idare eder. Bu yöntem işlemciyi meşgul eder ve kesmeler araya girince zamanlama bozulur. PIO (Programmable Input/Output) bu sorunu kökten çözer: her durum makinesi, yalnız pin işleri için tasarlanmış dokuz komutluk minik bir işlemcidir. Her komut tam olarak bir saat döngüsünde çalışır ve istenirse sonuna 0–31 döngülük gecikme eklenir. Böylece bir sinyalin her kenarının kaç nanosaniyede geleceğini döngü sayarak kesin olarak bilirsin. Durum makinesinin hızı, sistem saatinin bir bölücüyle (1 ile 65536 arası) bölünmesiyle ayarlanır.
| Komut | Görevi |
|---|---|
| set(pins, v) | Pinlere ya da X/Y yazmaçlarına 0–31 arası sabit değer yazar |
| out(hedef, n) | Çıkış kaydırma yazmacından (OSR) n biti pinlere ya da X/Y'ye aktarır |
| in_(kaynak, n) | Pinlerden ya da yazmaçlardan n biti giriş kaydırma yazmacına (ISR) alır |
| pull() / push() | TX FIFO'dan OSR'ye sözcük çeker, ISR'deki sözcüğü RX FIFO'ya iter |
| jmp(koşul, etiket) | Koşula göre (X sıfır mı, pin yüksek mi, X-- vb.) atlar |
| wait(kutup, kaynak, no) | Bir pin ya da IRQ bayrağı istenen seviyeye gelene kadar bekler |
| mov(hedef, kaynak) | Yazmaçlar arasında kopyalar, istenirse bitleri ters çevirir |
| irq(no) | İşlemciye ya da başka bir durum makinesine kesme bayrağı gönderir |
| nop() ve .side(v) | Boş komut; side-set ile her komutla birlikte bir pini aynı döngüde değiştirmek |
MicroPython'da PIO programları @rp2.asm_pio süslemesiyle yazılan Python fonksiyonlarıdır; fonksiyon çağrılmaz, MicroPython onu derleyip makine koduna çevirir. Sonra rp2.StateMachine(no, program, freq=..., set_base=...) ile bir durum makinesine yüklersin. Pico'da makine numaraları 0–3 PIO0'a, 4–7 PIO1'e aittir. freq değeri saniyedeki komut döngüsü sayısıdır ve sistem saatinin 65536'da birinden düşük olamaz; 125 MHz'de bu yaklaşık 1,9 kHz, 150 MHz'de 2,3 kHz eder. Daha yavaş bir sinyal gerekiyorsa gecikmeleri ya da X/Y sayaçlı döngüleri kullanırsın.
PIO ile kare dalga: ilk durum makinesi programın
İlk örnekte GP15'e bağlı pasif bir buzzer'dan sırayla notalar çalıp sonunda 1 kHz'lik sürekli bir kare dalga bırakacağız. Program yalnız iki komuttan oluşur: pini HIGH yap ve 9 döngü bekle, pini LOW yap ve 9 döngü bekle. Her komut kendisi 1 döngü sürdüğü için bir periyot 20 döngüdür; yani istediğin ton frekansının 20 katını durum makinesine vermen yeterli. Buzzer'ın artı ucunu GP15'e, eksi ucunu GND'ye bağla. Buzzer yerine osiloskop ya da bir LED ile 220 ohm direnç de kullanabilirsin; direnci LED direnci hesaplayıcısıyla seçebilirsin.
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")Burada formül basittir: ton frekansı = durum makinesi frekansı / döngü sayısı. 1000 Hz için makine 20.000 Hz'de çalışır, bu da alt sınırın oldukça üstündedir. Gecikmeleri kaldırıp yalnız iki set() komutu bırakırsan bir periyot 2 döngüye iner; makineyi 125 MHz'de çalıştırınca pinde 62,5 MHz'lik bir kare dalga elde edersin. Aynı işi donanım PWM'iyle de yapabileceğini unutma: basit bir ton ya da LED parlaklığı için PWM yeterlidir. PIO'nun farkı, sinyalin biçimini tamamen senin belirlemendir; birkaç satırla değişken genişlikli darbeler, belirli sayıda darbe ya da bir girişe tepki veren çıkışlar üretebilirsin.
PIO ile WS2812B (NeoPixel) LED sürmek

WS2812B LED'ler her bit için yaklaşık 1,25 mikrosaniyelik bir darbe bekler; bitin 1 mi 0 mı olduğu, darbenin HIGH kalma süresinden anlaşılır. Bu, PIO için ders kitabı örneğidir. Aşağıdaki program Raspberry Pi'nin resmî MicroPython örneğine dayanır: durum makinesi 8 MHz'de çalışır ve her bit tam 10 döngü sürer, böylece saniyede 800.000 bit gönderilir. autopull sayesinde makine her 24 bitte bir FIFO'dan yeni renk çeker; işlemci yalnız diziyi sm.put() ile FIFO'ya bırakır. LED sayısını kendi şeridine göre değiştir; WS2812B'nin çalışma mantığı ve renk sırası için WS2812B NeoPixel rehberine bakabilirsin.
| WS2812B ucu | Pico pini | Not |
|---|---|---|
| DIN (veri girişi) | GP16 (fiziksel pin 21) | Araya 330 ohm direnç koymak sinyali korur |
| 5V / VCC | VBUS (pin 40) | USB'den 5 V; çok LED'de harici 5 V kaynak kullan |
| GND | GND (ör. pin 38) | Harici kaynağın GND'si de buraya bağlanmalı |
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 timeProgramın mantığını satır satır izleyelim. out(x, 1) OSR'den bir biti X yazmacına alır ve bu sırada side-set ile hat LOW tutulur (3 döngü). Ardından hat HIGH yapılır ve X'e bakılır (2 döngü). Bit 1 ise hat 5 döngü daha HIGH kalır; bit 0 ise hat LOW'a çekilip 5 döngü beklenir. Her iki yol da toplam 10 döngüdür, yani 1,25 µs. pull_thresh=24 makineye her sözcükten yalnız 24 bit kullanmasını söyler; bu yüzden Python tarafında renk sola kaydırılır (sm.put(pixels, 8)). Renk sırası RGB değil GRB'dir; kırmızı ve yeşil yer değiştirmişse sorun buradadır. 24 LED tam beyazda 1,4 A'e kadar çekebileceği için örnekte parlaklık %20 ile sınırlandı.
Pico 2 (RP2350) ile neler değişti?
Raspberry Pi Pico 2, aynı boyut ve aynı pin düzeniyle gelen ama içinde RP2350 yongası taşıyan yeni nesildir. İki çekirdek yine vardır, ancak bu kez açılışta iki Arm Cortex-M33 ya da iki Hazard3 RISC-V çekirdeği arasında seçim yapılabilir. Bu yazıdaki kodların hepsi Pico 2'de değişmeden çalışır: MicroPython'da _thread aynı, Arduino-Pico çekirdeğinde setup1()/loop1() ve rp2040.fifo aynı adlarla kullanılır. PIO tarafında üçüncü bir blok eklendiği için durum makinesi sayısı 12'ye çıkar (MicroPython'da 0–11) ve birkaç yeni komut seçeneği gelir.
| Özellik | Pico (RP2040) | Pico 2 (RP2350) |
|---|---|---|
| Çekirdekler | 2 x Cortex-M0+ | 2 x Cortex-M33 ya da 2 x Hazard3 RISC-V |
| Saat hızı | 133 MHz | 150 MHz |
| RAM | 264 KB | 520 KB |
| Kart üstü flaş | 2 MB | 4 MB |
| PIO | 2 blok, 8 durum makinesi | 3 blok, 12 durum makinesi |
| Kayan nokta | Yazılımla (ROM'daki hızlı rutinler) | Donanım FPU (tek hassasiyet) + çift hassasiyet yardımcı işlemcisi |
| Güvenlik | Yok | TrustZone, güvenli açılış, 8 KB OTP |
| MicroPython dosyası | RPI_PICO (.uf2) | RPI_PICO2 (.uf2) |
Pratikte Pico 2'nin en hissedilir farkı hızdır: donanım FPU'su sayesinde float ağırlıklı hesaplar (filtreler, sensör füzyonu, ses işleme) birkaç kat hızlanır, iki kat RAM de büyük ekran tamponlarına yer açar. Dikkat etmen gereken tek şey, karta uygun UF2 dosyasını yüklemektir; Pico için olan dosya Pico 2'de çalışmaz. İlk RP2350 sürümlerinde dahili pull-down dirençli girişlerle ilgili bilinen bir donanım hatası (E9) vardı ve A4 revizyonunda giderildi; buton bağlarken harici direnç kullanmak her iki durumda da güvenli yoldur.
Ne zaman iki çekirdek, ne zaman PIO gerekir?
| İhtiyacın | En uygun çözüm | Neden? |
|---|---|---|
| LED parlaklığı, servo, basit ton | Donanım PWM | Hazır birim, tek satır kod |
| Birkaç sensör + ekran + buton | Tek çekirdek, millis() ya da asyncio | Ek karmaşıklığa gerek yok |
| Uzun hesap sürerken akıcı animasyon | İki çekirdek | Hesap çekirdek 1'de ekranı dondurmaz |
| Wi-Fi yanında kesintisiz ölçüm | İki çekirdek | Ağ gecikmeleri ölçüm aralığını bozmaz |
| WS2812B, ek UART, IR verici, enkoder | PIO | Nanosaniye hassasiyeti, işlemci serbest |
| VGA/DVI görüntü, I2S ses, çok hızlı sinyal | PIO + DMA | İşlemcinin yetişemeyeceği veri hızı |
Kısacası: işler yazılımda çakışıyorsa ikinci çekirdeği, pinlerde mikrosaniyenin altında hassasiyet gerekiyorsa PIO'yu düşün. Hobi projelerinin çoğunda ikisine de gerek kalmaz; ama bir gün WS2812B animasyonu Wi-Fi isteği sırasında takılmaya başlarsa ya da kartın UART'ları yetmezse, çözüm zaten Pico'nun içinde seni bekliyor demektir.
Pico PIO ve iki çekirdek ile proje fikirleri
- Müziğe tepki veren LED halka: Çekirdek 1 mikrofon örneklerini işler, PIO WS2812B halkasını sürer, çekirdek 0 düğmeleri dinler.
- Sekiz kanallı darbe üreteci: Her durum makinesi farklı frekansta kare dalga üretir; step motor sürücülerine ya da test düzeneklerine sinyal verir.
- Kesintisiz veri kaydedici: Çekirdek 1 her 10 ms'de ADC okur, çekirdek 0 verileri Wi-Fi ile gönderir; ağ yavaşlasa da ölçüm kaçmaz.
- Ek seri portlar: PIO ile üçüncü ve dördüncü UART'ı açıp GPS ve Bluetooth modülünü aynı anda bağla.
- Döner enkoder sayacı: PIO, enkoder darbelerini hiç kaçırmadan sayar; işlemci yalnız sonucu okur.
- Nefes alan gece lambası: PWM ile yumuşak geçişleri çekirdek 1'e, ışık sensörünü çekirdek 0'a ver.
Sık yapılan hatalar ve çözümleri
| Belirti | Neden | Çözüm |
|---|---|---|
| Durdurduktan sonra kart yanıt vermiyor | Çekirdek 1'deki döngü hâlâ çalışıyor | Durdurma bayrağı kullan; gerekirse USB'yi çıkarıp tak |
| start_new_thread ikinci kez hata veriyor | Pico'da yalnız bir ek iş parçacığı olabilir | Önceki iş bitmeden yenisini başlatma |
| Değişkenler arada saçma değer alıyor | İki çekirdek aynı veriye kilitsiz yazıyor | allocate_lock() ya da FIFO kullan |
| StateMachine ValueError veriyor | freq, sistem saati / 65536'dan küçük | Frekansı artır, yavaşlatmayı gecikmeyle yap |
| PIOASMError: delay too large | Side-set bitleri gecikme alanını küçülttü | Gecikmeyi böl ya da nop() ekle |
| WS2812B'de kırmızı ve yeşil ters | Renk sırası GRB | (g << 16) | (r << 8) | b biçimini kullan |
| setup1() hiç çalışmıyor | Arduino Mbed RP2040 paketi seçili | Earle Philhower'ın Raspberry Pi Pico/RP2040 paketini kur |
İki çekirdek ve PIO, Pico'yu basit bir LED yakıcıdan ciddi bir gömülü sisteme dönüştüren özelliklerdir; ama hepsi aynı temel üzerine kurulur: pinleri, zamanlamayı ve LED'leri iyi tanımak. BlueGrays uygulamasında Raspberry Pi Pico ile LED yakma, yürüyen LED, karaşimşek, buton ile durum makinesi ve PWM nefes efekti gibi projeleri devre şeması ve MicroPython koduyla adım adım bulabilir, bu yazıdaki teknikleri onların üzerine ekleyebilirsin.
Sıkça sorulan sorular
Raspberry Pi Pico PIO nedir?
PIO (programlanabilir giriş-çıkış), RP2040 ve RP2350 yongalarındaki, işlemciden bağımsız çalışan küçük durum makineleridir. Her biri dokuz komutluk basit bir dilde yazılan programı döngü hassasiyetinde yürütür. WS2812B LED, ek UART, IR gönderme ya da enkoder okuma gibi zamanlaması hassas işleri işlemciyi meşgul etmeden yapar.
Raspberry Pi Pico kaç çekirdekli?
Pico ve Pico W'deki RP2040 yongasında iki adet Cortex-M0+ çekirdeği vardır. Pico 2'deki RP2350'de de iki çekirdek bulunur ve açılışta Cortex-M33 ya da Hazard3 RISC-V çekirdekleri seçilebilir. Program başladığında yalnız çekirdek 0 çalışır, çekirdek 1'i sen başlatırsın.
Pico'da kaç tane PIO durum makinesi var?
RP2040'ta iki PIO bloğu ve her blokta 4 durum makinesi olmak üzere toplam 8 durum makinesi vardır. Her bloğun 32 komutluk program belleği o bloktaki makineler arasında paylaşılır. Pico 2'deki RP2350'de üç PIO bloğu, yani 12 durum makinesi bulunur.
MicroPython'da Pico'nun iki çekirdeği kullanılabilir mi?
Evet. _thread.start_new_thread() ile başlatılan fonksiyon Pico'da ikinci çekirdekte çalışır. Aynı anda yalnız bir ek iş parçacığı açılabilir ve ortak veriler için _thread.allocate_lock() ile kilit kullanmak gerekir. Çok çekirdek desteği MicroPython'da hâlâ deneysel olduğundan ek iş parçacığında ağır bellek işlemlerinden kaçınmak iyi olur.
Arduino IDE'de Pico'nun ikinci çekirdeği nasıl kullanılır?
Earle Philhower'ın Raspberry Pi Pico/RP2040/RP2350 paketini kurduktan sonra çizime setup1() ve loop1() fonksiyonlarını eklemen yeterlidir; çekirdek 1 bunları kendiliğinden çalıştırır. Çekirdekler arasında rp2040.fifo.push() ve rp2040.fifo.pop() ile 32 bitlik değerler gönderilir. Arduino'nun Mbed tabanlı RP2040 paketinde bu özellik yoktur.
WS2812B LED için PIO kullanmak şart mı?
Hayır. MicroPython'un hazır neopixel modülü ve Arduino'daki Adafruit NeoPixel kütüphanesi Pico'da sorunsuz çalışır. PIO ile kendin yazmanın faydası, gönderim sırasında işlemcinin serbest kalması ve aynı tekniği başka zamanlama hassas protokollere uygulayabilmendir.
Bu yazıdan sonra yapabileceğin projeler
Tüm projeleri gör
Raspberry Pi Pico Dahili LED Yakma (Pico ve Pico W)
Raspberry Pi Pico serisinin açılış projesi! Pico'nun üzerindeki yeşil dahili LED'i yakıp söndürerek kartın çalıştığını doğruluyoruz — klasik "Hello World" tarzı ilk deney. Harici bileşene ihtiyaç YOK, sadece Pico ve USB kablosu yeterli. Kod MicroPython ile yazıldı (Raspberry Pi Vakfı'nın resmi olarak desteklediği dil). Thonny IDE ile Pico'yu programlarken machine.Pin sınıfı, Pin.OUT mode, led.on()/off() metodları ve time.sleep() fonksiyonlarını kavrarsın. Seri

Raspberry Pi Pico Harici LED Yakma (Breadboard)
Pico'nun dahili LED'inden sonraki adım: breadboard'a harici LED bağlayıp GP14 pini üzerinden kontrol etmek. Bu proje ile Pico'nun herhangi bir genel amaçlı GPIO pinini output olarak nasıl kullanacağını, LED'in polaritesini (uzun bacak = anot/+, kısa bacak = katot/–) ve neden akım sınırlama direnci (220Ω) şart olduğunu öğreniyorsun. Direnci koymazsan LED'e aşırı akım gider ve yanabilir. Devre çok basit: Pico GP14 → 220Ω direnç → LED (+) → LED (–) → Pico GND. Wokwi'de simüle edebilir, gerçek bread

Raspberry Pi Pico Trafik Lambası (3 LED Sıralı)
Kırmızı, sarı ve yeşil LED'lerle gerçek trafik ışığı mantığını simüle ediyoruz — Pico serisinin 3 LED'e geçen ilk projesi! Yeşil 4 saniye "geç", sarı 1.5 saniye "hazırlan", kırmızı 3 saniye "dur" ve kırmızı+sarı 1 saniye "kalkış" (Avrupa trafik lambası pattern'i). Bu proje ile fonksiyon tanımlama (def all_off()), durum makinesi mantığı (sequence) ve coklu GPIO senkronizasyonu kavramlarını öğreneceksin. Devre çok basit: GP11 (Yeşil), GP12 (Sarı), GP13 (Kırmızı) pinlerine 3 LE

Raspberry Pi Pico Yürüyen LED / Chasing LED (6 LED)
Pico ile klasik "yürüyen LED" animasyonu — 6 LED versiyonu! 6 LED soldan sağa sırayla yanıp sönüyor, sanki ışık dizi boyunca yürüyor. Bu proje ile Python list yapısı (LED_PINS = [14, 13, 12, 11, 10, 9]), list comprehension ([Pin(p, Pin.OUT) for p in LED_PINS]), for döngüsü ile pin kontrolü ve enumerate() kavramlarını öğreneceksin. GP9-GP14 pinlerine 6 LED, her birinde 220Ω akım sınırlama direnci. Kod çok temiz: 6 LED'i tek tek tanımlamak yerine liste ile toplu tanımlıyoruz

Raspberry Pi Pico Karaşimşek / Knight Rider (6 LED Git-Gel)
Pico ile klasik "Karaşimşek" (Knight Rider) LED efekti! 6 LED önce soldan sağa yürür, sonra sağdan sola geri döner, sonsuza kadar. 80'lerin ikonik dizisindeki KITT arabasının ön ızgarası gibi. Bu proje Yürüyen LED projesinin bir üst versiyonu: aynı 6 LED devresi (GP9-GP14), farklı kod pattern'i. Yeni öğrenme: reversed() fonksiyonu ile liste ters çevirme, iki ayrı for döngüsü ile git-gel pattern, ve aynı devrede birden fazla animasyon yaratma.

Raspberry Pi Pico Trafik Lambası 4 Mod Buton Seçici (State Machine)
1 buton ile trafik lambasının 4 farklı modu! Butona her basışta mod değişir: Normal döngü (kırmızı → sarı → yeşil sırayla), Sadece Kırmızı (dur emri), Sarı Flash (dikkat/gece modu), Kapalı (bakım). Öğrenme: state machine (durum makinesi — mode değişkeni hangi davranışın çalışacağını belirler), modulo mod cycling ((mode + 1) % 4 → 0→1→2→3→0 sonsuz döngü), non-blocking timing (LED fazları time.ticks_ms() + time.ticks_diff() ile zamanlanır; ancak kod mod değişimi

Raspberry Pi Pico Buton Debounce Karşılaştırma: IRQ vs Software Polling
Butona bir kere bastığında kod 3-4 kere saydırdıysa nedeni contact bounce — buton metal kontakları temas anında mikrosaniyelerde defalarca aç-kapa yapar! Bu projede aynı butonu 2 farklı yöntemle sayıp Serial'da yan yana karşılaştırıyoruz: RAW polling (bounce'u yakalar, hatalı sayar) vs IRQ + software debounce (doğru sayar). Öğrenme: contact bounce fiziği (metal titreşim), software debounce (ticks_diff() > 50ms), Pin.irq() interrupt kaydı, IRQ_FALLING trigger tipi,

Raspberry Pi Pico PWM ile LED Fade (Nefes Efekti)
LED artık sadece yanıp sönmüyor — nefes alıyor! Raspberry Pi Pico'nun PWM (Pulse Width Modulation — darbe genişlik modülasyonu) özelliğiyle LED'in parlaklığı yavaş yavaş artar, sonra yavaş yavaş azalır. Uyku modundaki MacBook ışığı gibi sakin bir "nefes" efekti. Öğrenme: machine.PWM sınıfı (pini PWM çıkışına çevirme), duty_u16() (0–65535 arası 16-bit parlaklık değeri), PWM frekansı (freq(1000) — saniyede 1000 kez aç-kapa, göz titremeyi görmez), range() ile adım adım döngü
Diğer yazılar
BlueGrays uygulaması
Bu devreyi telefonunda adım adım kur
Devre şeması, kod ve parça listesi tek ekranda. 200'den fazla Arduino, ESP32 ve Pico projesi seni bekliyor.
Telefonunla tara
Kamerayı koda tut; telefonunun uygulama mağazası açılır.
ya da mağazada aç

