Raspberry Pi Pico PIO et double cœur : _thread, setup1, WS2812B
Guide Raspberry Pi Pico PIO : machines à états, signal carré et WS2812B, les deux cœurs avec MicroPython _thread et Arduino setup1/loop1, différences du Pico 2.
Le bloc PIO du Raspberry Pi Pico et ses deux cœurs sont les deux atouts qui distinguent cette petite carte de la plupart des microcontrôleurs du même prix. La puce RP2040, au cœur du Pico, possède deux cœurs de processeur distincts et 8 machines à états PIO. Grâce aux deux cœurs, tu peux lire des capteurs d'un côté pendant qu'un écran ou une animation de LED tourne sans à-coups de l'autre. Les PIO, eux, sont de minuscules moteurs de synchronisation qui fonctionnent indépendamment du processeur : ils produisent le signal précis à la nanoseconde qu'exigent les LED WS2812B, un UART supplémentaire ou un signal carré sans charger le CPU.
Dans ce guide, tu vas d'abord faire tourner les deux cœurs avec le module _thread de MicroPython, puis avec setup1() et loop1() dans l'Arduino IDE. Ensuite tu verras comment fonctionne le PIO, combien il y a de machines à états et quelles instructions elles comprennent, et tu écriras deux vrais programmes : un générateur de signal carré qui joue des notes sur un buzzer et un arc-en-ciel de WS2812B. Les dernières parties montrent ce que change le Pico 2 (RP2350) et quand tu as vraiment besoin de ces fonctions. Si tu débutes avec le Pico, lis d'abord Qu'est-ce que le Raspberry Pi Pico ? et Qu'est-ce que MicroPython ?.

Que sont les deux cœurs et le PIO du Raspberry Pi Pico ?
Le RP2040 contient deux processeurs Cortex-M0+ identiques appelés cœur 0 et cœur 1. Au démarrage du programme, seul le cœur 0 travaille ; le cœur 1 dort jusqu'à ce que tu le lances. Les deux cœurs partagent les mêmes 264 Ko de RAM et les mêmes broches : échanger des données est donc facile, mais ils ne doivent pas écrire la même variable au même instant. Pour cela, la puce dispose d'une petite file matérielle bidirectionnelle (FIFO, 8 mots dans chaque sens) et de 32 verrous matériels (spinlocks). Le PIO est un monde totalement à part : chacun des deux blocs PIO possède 4 machines à états, une mémoire de programme commune de 32 instructions et un accès direct aux broches. Une fois lancée, une machine à états exécute son programme cycle après cycle, même quand le processeur est occupé ailleurs.
| Ressource | RP2040 (Pico, Pico W) | À quoi ça sert ? |
|---|---|---|
| Cœur de processeur | 2 x Cortex-M0+, 133 MHz (jusqu'à 200 MHz dans la documentation actuelle) | Exécuter deux programmes distincts vraiment en même temps |
| FIFO entre les cœurs | 8 x 32 bits dans chaque sens | Envoyer des nombres et des ordres entre les cœurs |
| Verrou matériel (spinlock) | 32 | Accéder à tour de rôle aux données partagées |
| Bloc PIO | 2 (PIO0, PIO1) | Décharger le processeur du travail sur broches à timing critique |
| Machine à états | 4 par bloc, 8 au total | Chacune exécute son propre programme PIO |
| Mémoire de programme PIO | 32 instructions par bloc | Partagée par les 4 machines du bloc |
| FIFO PIO | TX 4 + RX 4 mots par machine (8 si fusionnées) | Données entre le processeur et la machine à états |
Le second cœur en MicroPython : le module _thread
En MicroPython, on utilise le cœur 1 avec l'appel _thread.start_new_thread(fonction, arguments). Sur le Pico, cet appel lance la fonction sur le second cœur, tandis que ton programme principal continue sur le cœur 0. Un seul thread supplémentaire peut tourner à la fois, puisqu'il n'y a pas de troisième cœur. Dans l'exemple ci-dessous, le cœur 0 lit un potentiomètre sur GP26 et affiche la valeur, pendant que le cœur 1 fait clignoter la LED intégrée à la vitesse fixée par le potentiomètre. L'attente sleep_ms() du cœur 1 n'affecte pas du tout le cœur 0 ; avec un seul cœur, il te faudrait un timer ou asyncio.
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)- Le verrou créé avec allocate_lock() garantit qu'à l'intérieur d'un bloc with lock: un seul cœur touche la variable partagée.
- Le drapeau running indique au cœur 1 de quitter sa boucle quand tu arrêtes le programme avec Ctrl+C ; sinon la LED continue de clignoter.
- L'écriture Pin("LED") trouve la LED intégrée sur le Pico comme sur le Pico W ; sur le Pico W la LED est reliée à la puce sans fil, donc Pin(25) ne marche pas.
- Un bon partage : les calculs longs, le dessin de l'écran ou les timings précis sur le cœur 1, le Wi-Fi, les menus et l'interaction avec l'utilisateur sur le cœur 0.
Deux cœurs dans l'Arduino IDE : setup1() et loop1()
Le paquet Pico le plus utilisé dans l'Arduino IDE est le core Raspberry Pi Pico/RP2040/RP2350 d'Earle Philhower (arduino-pico). Avec lui, utiliser les deux cœurs est étonnamment simple : les fonctions habituelles setup() et loop() tournent sur le cœur 0 ; si tu ajoutes setup1() et loop1() au croquis, le cœur 1 démarre tout seul et exécute ces deux fonctions. Les données passent d'un cœur à l'autre avec l'objet rp2040.fifo. Le paquet officiel "Arduino Mbed OS RP2040" ne gère pas setup1(), vérifie donc que tu as choisi le bon paquet dans le gestionnaire de cartes.
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}| Fonction | Ce qu'elle fait |
|---|---|
| rp2040.fifo.push(x) | Envoie une valeur 32 bits à l'autre cœur ; attend de la place si la file est pleine |
| rp2040.fifo.push_nb(x) | Essaie d'envoyer sans attendre ; renvoie false si la file est pleine |
| rp2040.fifo.pop() | Lit une valeur venant de l'autre cœur ; attend si la file est vide |
| rp2040.fifo.pop_nb(&x) | Écrit la valeur dans x et renvoie true s'il y en a une, sinon renvoie false tout de suite |
| rp2040.fifo.available() | Indique combien de valeurs attendent d'être lues |
| rp2040.idleOtherCore() / resumeOtherCore() | Met brièvement l'autre cœur en pause puis le relance (par exemple pendant une écriture en flash) |
Qu'est-ce que le PIO ? Fonctionnement des E/S programmables
Sur la plupart des microcontrôleurs, les blocs de communication et de signal comme l'UART, le SPI, l'I2C et la PWM sont figés dans le silicium ; si tu as besoin d'un protocole absent de la liste, le processeur s'en charge en allumant et éteignant les broches une à une (bit-banging). Cela occupe le processeur, et le timing se dégrade dès qu'une interruption s'intercale. Le PIO (Programmable Input/Output) règle le problème à la racine : chaque machine à états est un minuscule processeur à neuf instructions conçu uniquement pour piloter des broches. Chaque instruction s'exécute en exactement un cycle d'horloge, et on peut lui ajouter un délai de 0 à 31 cycles. Tu sais donc précisément, en comptant les cycles, au bout de combien de nanosecondes arrive chaque front du signal. La vitesse de la machine se règle en divisant l'horloge système par un diviseur compris entre 1 et 65536.
| Instruction | Rôle |
|---|---|
| set(pins, v) | Écrit une constante de 0 à 31 sur des broches ou dans les registres X/Y |
| out(dest, n) | Transfère n bits du registre de décalage de sortie (OSR) vers des broches ou X/Y |
| in_(src, n) | Fait entrer n bits venant de broches ou de registres dans le registre d'entrée (ISR) |
| pull() / push() | Tire un mot de la FIFO TX vers l'OSR, pousse le mot de l'ISR dans la FIFO RX |
| jmp(cond, label) | Saute selon une condition (X nul, broche haute, X-- etc.) |
| wait(polarité, src, n) | Attend qu'une broche ou un drapeau IRQ atteigne le niveau voulu |
| mov(dest, src) | Copie entre registres, avec inversion des bits si besoin |
| irq(n) | Envoie un drapeau d'interruption au CPU ou à une autre machine à états |
| nop() et .side(v) | Instruction vide ; le side-set change une broche dans le même cycle que n'importe quelle instruction |
En MicroPython, les programmes PIO sont des fonctions Python écrites avec le décorateur @rp2.asm_pio ; la fonction n'est pas appelée, MicroPython l'assemble en code machine. Tu la charges ensuite dans une machine à états avec rp2.StateMachine(n, programme, freq=..., set_base=...). Sur le Pico, les numéros 0 à 3 appartiennent au PIO0 et 4 à 7 au PIO1. La valeur freq est le nombre de cycles d'instruction par seconde et ne peut pas descendre sous 1/65536 de l'horloge système : à 125 MHz cela fait environ 1,9 kHz, à 150 MHz environ 2,3 kHz. Pour un signal plus lent, utilise des délais ou des boucles avec les compteurs X/Y.
Un signal carré avec le PIO : ton premier programme de machine à états
Dans le premier exemple, on joue une gamme sur un buzzer passif relié à GP15, puis on laisse tourner un signal carré continu de 1 kHz. Le programme ne contient que deux instructions : mettre la broche à HIGH et attendre 9 cycles, la mettre à LOW et attendre 9 cycles. Comme chaque instruction dure elle-même 1 cycle, une période fait 20 cycles : il suffit de donner à la machine à états 20 fois la fréquence voulue. Relie la patte positive du buzzer à GP15 et la négative à GND. À la place du buzzer, tu peux utiliser un oscilloscope ou une LED avec une résistance de 220 ohms ; choisis la résistance avec le calculateur de résistance pour LED.
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")La formule est simple : fréquence du son = fréquence de la machine à états / nombre de cycles. Pour 1000 Hz, la machine tourne à 20 000 Hz, bien au-dessus de la limite basse. Si tu supprimes les délais et ne gardes que les deux set(), une période tombe à 2 cycles ; avec la machine à 125 MHz, tu obtiens un signal carré de 62,5 MHz sur la broche. N'oublie pas que la PWM matérielle sait faire la même chose : pour un son simple ou la luminosité d'une LED, la PWM suffit. La différence du PIO, c'est que tu décides entièrement de la forme du signal ; en quelques lignes tu génères des impulsions de largeur variable, un nombre précis d'impulsions ou des sorties qui réagissent à une entrée.
Piloter des LED WS2812B (NeoPixel) avec le PIO

Les LED WS2812B attendent une impulsion d'environ 1,25 microseconde par bit ; la durée pendant laquelle l'impulsion reste à HIGH indique si le bit vaut 1 ou 0. C'est un cas d'école pour le PIO. Le programme ci-dessous s'inspire de l'exemple MicroPython officiel de Raspberry Pi : la machine à états tourne à 8 MHz et chaque bit dure exactement 10 cycles, soit 800 000 bits par seconde. Grâce à autopull, la machine récupère une nouvelle couleur dans la FIFO tous les 24 bits ; le processeur se contente de déposer le tableau dans la FIFO avec sm.put(). Adapte le nombre de LED à ton ruban ; pour le fonctionnement du WS2812B et son ordre des couleurs, consulte le guide WS2812B NeoPixel.
| Broche WS2812B | Broche du Pico | Remarque |
|---|---|---|
| DIN (entrée de données) | GP16 (broche physique 21) | Une résistance série de 330 ohms protège le signal |
| 5V / VCC | VBUS (broche 40) | 5 V de l'USB ; avec beaucoup de LED, utilise une alimentation 5 V externe |
| GND | GND (ex. broche 38) | Le GND de l'alimentation externe doit aussi être relié ici |
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 timeSuivons le programme ligne par ligne. out(x, 1) prend un bit de l'OSR dans le registre X pendant que le side-set maintient la ligne à LOW (3 cycles). Ensuite la ligne passe à HIGH et X est testé (2 cycles). Si le bit vaut 1, la ligne reste HIGH 5 cycles de plus ; s'il vaut 0, la ligne repasse à LOW et la machine attend 5 cycles. Les deux chemins totalisent 10 cycles, soit 1,25 µs. pull_thresh=24 indique à la machine de n'utiliser que 24 bits de chaque mot ; c'est pourquoi la couleur est décalée à gauche côté Python (sm.put(pixels, 8)). L'ordre des couleurs est GRB et non RGB ; si le rouge et le vert sont inversés, c'est pour ça. Comme 24 LED en blanc total peuvent tirer jusqu'à 1,4 A, la luminosité est limitée à 20 % dans l'exemple.
Qu'est-ce qui change avec le Pico 2 (RP2350) ?
Le Raspberry Pi Pico 2 est la nouvelle génération, de même taille et avec le même brochage, mais équipée d'une puce RP2350. Il a toujours deux cœurs, mais tu peux cette fois choisir au démarrage entre deux cœurs Arm Cortex-M33 ou deux cœurs RISC-V Hazard3. Tout le code de cet article fonctionne sans modification sur le Pico 2 : _thread est identique en MicroPython et, dans le core Arduino-Pico, setup1()/loop1() et rp2040.fifo gardent les mêmes noms. Côté PIO, un troisième bloc s'ajoute, ce qui donne 12 machines à états (0 à 11 en MicroPython), plus quelques nouvelles options d'instructions.
| Caractéristique | Pico (RP2040) | Pico 2 (RP2350) |
|---|---|---|
| Cœurs | 2 x Cortex-M0+ | 2 x Cortex-M33 ou 2 x Hazard3 RISC-V |
| Fréquence | 133 MHz | 150 MHz |
| RAM | 264 Ko | 520 Ko |
| Flash sur la carte | 2 Mo | 4 Mo |
| PIO | 2 blocs, 8 machines à états | 3 blocs, 12 machines à états |
| Virgule flottante | Logicielle (routines rapides en ROM) | FPU matérielle (simple précision) + coprocesseur double précision |
| Sécurité | Aucune | TrustZone, démarrage sécurisé, 8 Ko d'OTP |
| Fichier MicroPython | RPI_PICO (.uf2) | RPI_PICO2 (.uf2) |
En pratique, la différence la plus sensible du Pico 2 est la vitesse : grâce à la FPU matérielle, les calculs riches en flottants (filtres, fusion de capteurs, traitement audio) vont plusieurs fois plus vite, et le double de RAM laisse de la place pour de gros tampons d'écran. Il faut seulement flasher le bon fichier UF2 pour la carte ; celui du Pico ne fonctionne pas sur le Pico 2. Les premières versions du RP2350 avaient un défaut matériel connu (E9) avec les entrées utilisant le pull-down interne, corrigé dans la révision A4 ; une résistance externe pour câbler les boutons reste le choix sûr dans tous les cas.
Quand utiliser deux cœurs, et quand le PIO ?
| Ton besoin | Meilleure solution | Pourquoi ? |
|---|---|---|
| Luminosité de LED, servo, son simple | PWM matérielle | Bloc prêt à l'emploi, une ligne de code |
| Quelques capteurs + écran + bouton | Un cœur, millis() ou asyncio | Inutile d'ajouter de la complexité |
| Animation fluide pendant de longs calculs | Deux cœurs | Le calcul sur le cœur 1 ne fige pas l'écran |
| Mesure continue à côté du Wi-Fi | Deux cœurs | Les délais réseau ne perturbent pas l'intervalle de mesure |
| WS2812B, UART supplémentaire, émetteur IR, encodeur | PIO | Précision à la nanoseconde, CPU libre |
| Vidéo VGA/DVI, audio I2S, signaux très rapides | PIO + DMA | Débits que le CPU ne pourrait pas suivre |
En bref : pense au second cœur quand des tâches se gênent dans le logiciel, et au PIO quand les broches demandent une précision inférieure à la microseconde. La plupart des projets de loisir n'ont besoin ni de l'un ni de l'autre ; mais si un jour ton animation WS2812B saccade pendant une requête Wi-Fi ou que la carte manque d'UART, la solution t'attend déjà dans le Pico.
Idées de projets avec le PIO et les deux cœurs du Pico
- Anneau de LED réactif à la musique : le cœur 1 traite les échantillons du micro, le PIO pilote l'anneau WS2812B et le cœur 0 surveille les boutons.
- Générateur d'impulsions à huit voies : chaque machine à états produit un signal carré à une fréquence différente pour des drivers de moteurs pas à pas ou des bancs de test.
- Enregistreur de données sans trous : le cœur 1 lit l'ADC toutes les 10 ms pendant que le cœur 0 envoie les données en Wi-Fi ; même avec un réseau lent, aucune mesure n'est perdue.
- Ports série supplémentaires : ouvre un troisième et un quatrième UART avec le PIO pour brancher un GPS et un module Bluetooth en même temps.
- Compteur d'encodeur rotatif : le PIO compte les impulsions de l'encodeur sans en rater une seule ; le processeur lit seulement le résultat.
- Veilleuse qui respire : confie les fondus doux en PWM au cœur 1 et le capteur de lumière au cœur 0.
Erreurs fréquentes et solutions
| Symptôme | Cause | Solution |
|---|---|---|
| La carte ne répond plus après l'arrêt | La boucle du cœur 1 tourne encore | Utilise un drapeau d'arrêt ; au besoin, débranche et rebranche l'USB |
| start_new_thread échoue la deuxième fois | Le Pico n'accepte qu'un thread supplémentaire | N'en lance pas un nouveau avant la fin du précédent |
| Les variables prennent parfois des valeurs absurdes | Les deux cœurs écrivent sans verrou | Utilise allocate_lock() ou la FIFO |
| StateMachine lève une ValueError | freq est sous horloge système / 65536 | Augmente la fréquence et ralentis avec des délais |
| PIOASMError: delay too large | Les bits de side-set réduisent le champ de délai | Découpe le délai ou ajoute un nop() |
| Rouge et vert inversés sur les WS2812B | L'ordre des couleurs est GRB | Utilise le format (g << 16) | (r << 8) | b |
| setup1() ne s'exécute jamais | Le paquet Arduino Mbed RP2040 est sélectionné | Installe le paquet Raspberry Pi Pico/RP2040 d'Earle Philhower |
Les deux cœurs et le PIO transforment le Pico d'un simple clignoteur de LED en véritable système embarqué, mais tout repose sur la même base : bien connaître ses broches, ses timings et ses LED. Dans l'application BlueGrays, tu trouveras des projets Raspberry Pi Pico comme le clignotement de LED, le chenillard, l'effet K2000, une machine à états pilotée par bouton et un effet de respiration en PWM, chacun avec schéma et code MicroPython pas à pas, prêts à accueillir les techniques de cet article.
Questions fréquentes
Qu'est-ce que le PIO du Raspberry Pi Pico ?
Le PIO (E/S programmables) regroupe de petites machines à états des puces RP2040 et RP2350 qui fonctionnent indépendamment du processeur. Chacune exécute au cycle près un programme écrit dans un langage simple de neuf instructions. Il prend en charge les tâches à timing critique comme les LED WS2812B, des UART supplémentaires, l'émission IR ou la lecture d'encodeurs sans occuper le CPU.
Combien de cœurs a le Raspberry Pi Pico ?
La puce RP2040 du Pico et du Pico W possède deux cœurs Cortex-M0+. Le RP2350 du Pico 2 en a aussi deux, et l'on choisit au démarrage entre des cœurs Cortex-M33 et Hazard3 RISC-V. Au lancement du programme, seul le cœur 0 tourne ; c'est toi qui démarres le cœur 1.
Combien de machines à états PIO possède le Pico ?
Le RP2040 a deux blocs PIO de 4 machines à états chacun, soit 8 au total. La mémoire de programme de 32 instructions de chaque bloc est partagée entre ses machines. Le RP2350 du Pico 2 compte trois blocs PIO, donc 12 machines à états.
MicroPython peut-il utiliser les deux cœurs du Pico ?
Oui. Sur le Pico, une fonction lancée avec _thread.start_new_thread() s'exécute sur le second cœur. Un seul thread supplémentaire peut tourner à la fois, et les données partagées doivent être protégées par un verrou créé avec _thread.allocate_lock(). Le support multicœur restant expérimental dans MicroPython, mieux vaut éviter les grosses opérations mémoire dans ce thread.
Comment utiliser le second cœur du Pico dans l'Arduino IDE ?
Après avoir installé le paquet Raspberry Pi Pico/RP2040/RP2350 d'Earle Philhower, il suffit d'ajouter les fonctions setup1() et loop1() au croquis ; le cœur 1 les exécute automatiquement. Les valeurs 32 bits passent d'un cœur à l'autre avec rp2040.fifo.push() et rp2040.fifo.pop(). Le paquet RP2040 d'Arduino basé sur Mbed ne propose pas cette fonction.
Faut-il obligatoirement le PIO pour les LED WS2812B ?
Non. Le module neopixel intégré à MicroPython et la bibliothèque Adafruit NeoPixel sous Arduino fonctionnent très bien sur le Pico. L'intérêt d'écrire ta propre version PIO est de laisser le processeur libre pendant l'envoi et de pouvoir appliquer la même technique à d'autres protocoles à timing critique.
Projets à réaliser après cet article
Voir tous les projets
Clignotement LED Intégrée Raspberry Pi Pico (Pico et Pico W)
Le projet d'ouverture de la série Raspberry Pi Pico ! Nous faisons clignoter la LED verte intégrée pour vérifier que la carte fonctionne — une première expérience classique "Hello World". AUCUN composant externe, juste Pico et câble USB. Le code est écrit en MicroPython (le langage officiellement soutenu par la Raspberry Pi Foundation). Apprends la classe machine.Pin, le mode Pin.OUT, les méthodes led.on()/off() et time.sleep() dans Thonny IDE. Suis chaque basc

Allumage d'une LED externe sur le Raspberry Pi Pico (plaque d'essai)
Après la LED intégrée du Pico : connecter une LED externe à la maquette et la contrôler via la broche GP14. Ce projet vous permet d’apprendre comment utiliser n’importe quelle broche GPIO à usage général du Pico en sortie, de comprendre la polarité de la LED (grande patte = anode/+, petite patte = cathode/–) et de découvrir pourquoi une résistance de limitation de courant (220 Ω) est indispensable. Si vous n'installez pas cette résistance, un courant excessif traversera la LED et celle-ci risque

Simulateur de Feu de Circulation Raspberry Pi Pico (3 LEDs séquentielles)
Nous simulons un vrai feu de circulation avec des LEDs rouge, jaune et verte. Vert 4 sec "passez", jaune 1,5 sec "préparez", rouge 3 sec "arrêtez" et rouge+jaune 1 sec "départ" (motif européen). Apprends la définition de fonction, la logique de machine à états et la synchronisation multi-GPIO. Circuit simple : 3 LEDs sur GP11/GP12/GP13, chacune avec 220Ω.

Raspberry Pi Pico Chenillard LED (6 LEDs)
Animation chenillard classique avec Pico — version 6 LEDs ! 6 LEDs s'allument séquentiellement de gauche à droite. Apprends la liste Python, la compréhension de liste ([Pin(p, Pin.OUT) for p in LED_PINS]), la boucle for avec contrôle de broches et enumerate(). 6 LEDs sur GP9-GP14, chacune avec résistance 220Ω. Code très propre : au lieu de définir 6 LEDs une par une, nous utilisons une liste — tu peux ajouter des LED dans la limite des GPIO libres et utilisables, chacune avec sa propre résistanc

Raspberry Pi Pico Knight Rider LED Scanner (6 LED Aller-Retour)
Effet scanner LED "Knight Rider" classique avec Pico ! 6 LEDs vont de gauche à droite, puis de droite à gauche, à l'infini. Apprends reversed() et deux boucles for séparées pour motif aller-retour.

Feu de signalisation Raspberry Pi Pico avec sélecteur à 4 modes (machine à états)
4 modes différents pour le feu tricolore avec un seul bouton ! À chaque pression sur le bouton, le mode change : Cycle normal (rouge → orange → vert dans cet ordre), Rouge uniquement (ordre d'arrêt), Orange clignotant (attention/mode nuit), Éteint (entretien). Notions : state machine (machine à états — la variable mode détermine le comportement à adopter), modulo mod cycling ((mode + 1) % 4 → 0→1→2→3→0, boucle infinie), synchronisation non bloquante (les phases de

Raspberry Pi Pico Bouton Debounce : IRQ vs Software Polling
Une pression, le code compte 3-4 ? C'est le contact bounce ! Compare 2 méthodes de comptage dans Serial : RAW polling (attrape bounce, compte faux) vs IRQ + software debounce (précis). Apprends physique du bounce, software debounce, Pin.irq() interrupt, IRQ_FALLING trigger, ISR handlers, sécurité des variables globales ISR.

Raspberry Pi Pico PWM LED Fade (Effet Respiration)
La LED ne clignote plus — elle respire ! Grâce au PWM (modulation de largeur d'impulsion) du Raspberry Pi Pico, la luminosité monte puis descend lentement. Apprends la classe machine.PWM, duty_u16() (luminosité 16 bits 0–65535), la fréquence PWM, les boucles range() et la sortie quasi analogique. Base du mélange de couleurs RGB, du contrôle moteur, des servos et du buzzer.
Autres articles
- Qu'est-ce que le Raspberry Pi Pico ? Installation de MicroPython, brochage et premiers projets
- Qu'est-ce que MicroPython ? Bases, REPL et premiers programmes
- Ruban LED WS2812B NeoPixel avec Arduino : guide des LED RGB adressables
- Qu'est-ce que le PWM ? Guide d'analogWrite, du rapport cyclique et de la fréquence sur Arduino
Application BlueGrays
Réalise ce montage pas à pas sur ton téléphone
Schéma, code et liste des composants sur un seul écran. Plus de 200 projets Arduino, ESP32 et Pico à réaliser.
Scanne avec ton téléphone
Pointe l’appareil photo vers le code : la boutique d’applications de ton téléphone s’ouvre.
ou ouvre la boutique

