Guides · 16 min de lecture

Chenillard LED Arduino (effet K2000) : montage, code et vitesse

Chenillard LED Arduino façon K2000 : 8 LED et 220 Ω, code avec tableau et boucle for, vitesse au potentiomètre, millis, 74HC595, WS2812B, ESP32 et Pico.

Le chenillard LED Arduino façon K2000 est un effet lumineux classique : une rangée de LED s'allume l'une après l'autre, la lumière file d'un bout à l'autre puis revient, comme le balayage rouge à l'avant de KITT, la voiture qui parle de la célèbre série des années 80 K 2000 (Knight Rider en anglais). Il te suffit d'un Arduino Uno, de 6 ou 8 LED, d'une résistance de 220 Ω par LED et de quelques fils de connexion. Si la lumière avance dans un seul sens puis repart du début, on parle de chenillard simple. Ce sont deux grands classiques que l'on réalise juste après le feu tricolore, et la façon la plus amusante d'apprendre deux des outils les plus importants de la programmation : les tableaux et la boucle for.

Dans ce guide, tu vas monter le circuit et écrire d'abord le code du chenillard simple, puis celui de l'effet K2000 en aller-retour. Ensuite, tu régleras la vitesse avec un potentiomètre, tu ajouteras un effet où les LED s'empilent à une extrémité et tu feras tourner le même effet avec millis(), sans jamais bloquer le code. Dans les dernières parties, tu verras comment piloter 8 LED avec seulement 3 broches grâce au circuit 74HC595, comment faire un K2000 avec traînée lumineuse sur une seule broche avec des LED adressables WS2812B, les versions ESP32 et Raspberry Pi Pico (MicroPython) et les solutions aux erreurs les plus fréquentes.

LED de 5 mm rouges, jaunes, bleues, vertes et blanches
Pour le look K2000 classique, utilise 6 ou 8 LED de 5 mm de la même couleur (rouges de préférence) ; la patte longue est l'anode (+), la patte courte la cathode (−).

Qu'est-ce que l'effet K2000, et quelle différence avec un chenillard ?

Dans la série, la lumière rouge sur le pare-chocs avant de KITT balaie sans arrêt de gauche à droite, comme un œil qui scrute. En électronique, cet effet s'appelle aussi scanner Larson (Larson scanner), du nom du producteur de la série, Glen A. Larson ; les yeux des robots cylons de son autre série, Galactica, fonctionnent de la même manière. Sur le vrai scanner, on voit derrière le point allumé une trace rouge qui s'éteint lentement, une traînée. Dans un circuit à LED simple, chaque LED est soit complètement allumée, soit complètement éteinte ; pour imiter la traînée, il faut baisser progressivement la luminosité des LED en PWM. C'est ce que nous ferons plus loin avec les WS2812B et l'ESP32. Le tableau ci-dessous résume les effets que tu vas coder dans cet article et le nombre de pas d'un cycle avec 8 LED.

EffetCe qu'il faitUn cycle avec 8 LEDDans cet article
Chenillard simpleUne seule lumière file de gauche à droite, puis repart du début8 pasÉtape 1
K2000Une seule lumière fait l'aller-retour entre les deux extrémités14 pasÉtapes 2 et 3
EmpilementChaque lumière court jusqu'à la dernière place libre à droite et y reste36 pasÉtape 4
Rencontre au centreDeux lumières arrivent des extrémités vers le centre, puis s'écartent8 pasPartie 74HC595
K2000 avec traînéeLa LED de tête brille à fond, celles derrière s'éteignent peu à peu14 pasParties WS2812B et ESP32

Matériel et choix de la résistance

MatérielQuantitéRemarque
Arduino Uno (ou Nano)1Un ESP32 ou un Raspberry Pi Pico conviennent aussi
LED 5 mm6–8Même couleur et même lot pour une luminosité identique
Résistance 220 Ω6–8Une par LED ; 330 Ω sur le Pico
Potentiomètre 10 kΩ (B10K)1Uniquement pour les versions à vitesse réglable
Breadboard (plaque d'essai)1Une demi-plaque (400 trous) suffit
Fils de connexion (jumpers)12–15Mâle-mâle
74HC595 ou barrette WS2812B de 8 LED1En option : pour les parties sur l'économie de broches et la traînée

Une LED ne limite pas elle-même son courant : chaque LED reçoit donc une résistance en série. On calcule sa valeur avec la loi d'Ohm : R = (tension d'alimentation − tension directe de la LED) / courant. Une LED rouge a une tension directe d'environ 2 V, donc à 5 V avec 220 Ω le courant vaut (5 − 2) / 220 ≈ 13,6 mA. La LED brille bien et tu restes sous les 20 mA recommandés pour une broche d'Arduino. Dans l'effet d'empilement, quand les huit LED sont allumées en même temps, le courant total est d'environ 109 mA, ce qui reste dans la limite de 200 mA que l'Uno accepte pour l'ensemble des broches. Pour reconnaître une résistance de 220 Ω à ses anneaux, utilise l'outil code couleur des résistances ; pour d'autres couleurs et tensions, le calculateur de résistance pour LED.

Câblage : 8 LED et un potentiomètre

La patte longue (anode) de chaque LED va vers une broche numérique de la carte à travers une résistance, et la patte courte (cathode) va au GND. Sur la breadboard, le plus propre est de relier la broche GND de l'Arduino à la ligne bleue (−) et d'y ramener les pattes courtes des huit LED. Place les LED à intervalles réguliers, de gauche à droite dans l'ordre des broches : ainsi, l'ordre du tableau dans le code correspond à l'ordre réel de la lumière. Les deux pattes extérieures du potentiomètre vont au 5V et au GND, la patte du milieu (le curseur) va sur A0. Le tableau ci-dessous indique les broches utilisées par tous les codes de cet article ; avec 6 LED, saute les deux dernières lignes de LED et supprime les deux dernières broches du tableau dans le code. Tu peux voir le brochage de ta carte avec l'outil Pinout.

FonctionArduino UnoESP32Raspberry Pi Pico
LED 1 (tout à gauche)D2GPIO 18GP8
LED 2D3GPIO 19GP9
LED 3D4GPIO 21GP10
LED 4D5GPIO 22GP11
LED 5D6GPIO 23GP12
LED 6D7GPIO 25GP13
LED 7D8GPIO 26GP14
LED 8 (tout à droite)D9GPIO 27GP15
Patte du milieu du potentiomètreA0GPIO 34GP26 (ADC0)
Pattes extérieures du potentiomètre5V et GND3V3 et GND3V3(OUT) et AGND
Cathodes des LED (patte courte)GNDGNDGND
Résistance série220 Ω220 Ω330 Ω
Ne branche pas de LED sur les broches D0 et D1 : elles servent au téléversement par USB et au moniteur série ; avec des LED branchées, le téléversement peut échouer et les LED clignotent au hasard. C'est pour cela que le tableau commence à D2. Si aucune LED ne s'allume, vérifie d'abord que la ligne bleue de la breadboard est bien reliée à la broche GND de l'Arduino.
Arduino Uno
Arduino Uno
Breadboard
Breadboard
R · Ω
R · Ω
Jumper
Jumper

Étape 1 : code du chenillard avec un tableau et une boucle for

Tu pourrais écrire huit lignes pinMode et seize lignes digitalWrite pour huit LED, mais le code devient long et changer le nombre de LED devient pénible. À la place, tu ranges les numéros de broches dans un tableau et tu le parcours dans l'ordre avec une boucle for. Le premier élément du tableau est LEDS[0], c'est-à-dire D2 ; le dernier est LEDS[7], c'est-à-dire D9. Ainsi, le même code fonctionne sans modification avec 6, 8 ou 12 LED ; tu modifies seulement le tableau. Les bases des tableaux et des boucles sont expliquées plus en détail dans Les bases de la programmation Arduino.

C++ (Arduino IDE)
1// Yürüyen LED: 8 LED sırayla yanar / Running light: 8 LEDs light up one after another
2const int LEDS[] = {2, 3, 4, 5, 6, 7, 8, 9};             // LED pinleri / LED pins
3const int LED_SAYISI = sizeof(LEDS) / sizeof(LEDS[0]);  // dizideki LED sayısı (8) / number of LEDs (8)
4const int BEKLE = 100;                                  // adım süresi (ms) / step time (ms)
5
6void setup() {
7  for (int i = 0; i < LED_SAYISI; i++) {
8    pinMode(LEDS[i], OUTPUT);                           // tüm LED pinleri çıkış / all LED pins as outputs
9  }
10}
11
12void loop() {
13  for (int i = 0; i < LED_SAYISI; i++) {
14    digitalWrite(LEDS[i], HIGH);                        // sıradaki LED'i yak / light the next LED
15    delay(BEKLE);
16    digitalWrite(LEDS[i], LOW);                         // söndür ve devam et / turn it off and move on
17  }
18}
LigneCe qu'elle fait
const int LEDS[] = {2, ..., 9};Tableau qui contient les broches des LED dans l'ordre, de gauche à droite ; LEDS[0] = 2, LEDS[7] = 9
sizeof(LEDS) / sizeof(LEDS[0])Calcule le nombre d'éléments : sur l'Uno, 16 octets / 2 octets = 8 ; se met à jour tout seul quand tu ajoutes ou retires des broches
for (int i = 0; i < LED_SAYISI; i++)Compte la variable i de 0 à 7 ; chaque tour traite un élément du tableau
pinMode(LEDS[i], OUTPUT)Met les huit broches en sortie avec une seule boucle
digitalWrite, delay(BEKLE), digitalWriteAllume la LED, attend BEKLE millisecondes, l'éteint et passe à la suivante

Avec BEKLE (le temps par pas) à 100 ms, la lumière parcourt les huit LED en 0,8 seconde et repart aussitôt. Descends à 30 ms et le défilement devient très rapide ; monte à 300 ms et il paraît lent, comme des lampes qui s'allument une à une. Pour téléverser le code, choisis la carte et le port dans le menu Outils puis clique sur Téléverser ; si le téléversement échoue, suis la liste de contrôle de Arduino : le téléversement ne fonctionne pas.

Étape 2 : code de l'effet K2000 (aller-retour)

Pour l'effet K2000, la lumière doit faire demi-tour en arrivant à l'extrémité droite. Tu le fais avec deux boucles : la première compte de gauche à droite, la seconde de droite à gauche. Le point délicat, ce sont les LED des extrémités. Si les deux boucles comptent entièrement de 0 à 7 puis de 7 à 0, la LED de droite s'allume une fois à la fin de la boucle aller et une seconde fois au début de la boucle retour ; la lumière reste deux fois plus longtemps aux extrémités et le mouvement semble saccadé. C'est pourquoi la boucle aller s'arrête à 6 et la boucle retour à 1. Chaque cycle dure alors exactement 14 pas et la lumière reste aussi longtemps aux extrémités qu'au centre. Nous avons aussi déplacé les trois lignes qui allument et éteignent une LED dans une petite fonction appelée yakSondur() (« allumer et éteindre ») ; le code est plus court et plus lisible.

C++ (Arduino IDE)
1// Karaşimşek (Knight Rider): ışık iki uç arasında gidip gelir / light bounces between the two ends
2const int LEDS[] = {2, 3, 4, 5, 6, 7, 8, 9};
3const int LED_SAYISI = sizeof(LEDS) / sizeof(LEDS[0]);
4const int BEKLE = 80;                                   // adım süresi (ms) / step time (ms)
5
6void yakSondur(int i) {
7  digitalWrite(LEDS[i], HIGH);
8  delay(BEKLE);
9  digitalWrite(LEDS[i], LOW);
10}
11
12void setup() {
13  for (int i = 0; i < LED_SAYISI; i++) pinMode(LEDS[i], OUTPUT);
14}
15
16void loop() {
17  for (int i = 0; i < LED_SAYISI - 1; i++) {           // soldan sağa: 0..6 / left to right: 0..6
18    yakSondur(i);
19  }
20  for (int i = LED_SAYISI - 1; i > 0; i--) {           // sağdan sola: 7..1 / right to left: 7..1
21    yakSondur(i);
22  }
23}
La vitesse la plus proche de celle de la série est d'environ 60 à 120 ms par pas. Avec 8 LED et 80 ms, un aller-retour complet dure 14 × 80 = 1,12 seconde. Quand tu descends vers 20 ms, l'œil voit plusieurs LED allumées en même temps et la lumière se transforme en un trait flou.

Étape 3 : régler la vitesse avec un potentiomètre

Plutôt que de modifier le code et de le téléverser à nouveau à chaque changement de vitesse, tu peux utiliser un potentiomètre. Un potentiomètre est un pont diviseur de tension : la tension sur la patte du milieu varie entre 0 et 5 V selon la position de l'axe, et analogRead() la convertit en un nombre entre 0 et 1023. map(deger, 0, 1023, 400, 20) transforme ce nombre en un temps par pas compris entre 400 et 20 ms ; comme la plage est écrite à l'envers, plus la valeur lue est grande, plus le pas est court et plus la lumière va vite. Le sens dans lequel il faut tourner pour accélérer dépend de la patte extérieure reliée au 5V ; si cela te semble inversé, échange les deux fils extérieurs ou intervertis 400 et 20 dans map(). Tu peux lire comment fonctionne un potentiomètre de l'intérieur dans Qu'est-ce qu'un potentiomètre ?.

Potentiomètre 10 kΩ
Potentiomètre 10 kΩ : les pattes extérieures vont au 5V et au GND, la patte centrale du curseur va sur A0.
C++ (Arduino IDE)
1// Hız ayarlı karaşimşek: potansiyometre adım süresini belirler / Speed-adjustable Knight Rider: the pot sets the step time
2const int LEDS[] = {2, 3, 4, 5, 6, 7, 8, 9};
3const int LED_SAYISI = sizeof(LEDS) / sizeof(LEDS[0]);
4const int POT = A0;                                     // potansiyometrenin orta bacağı / pot wiper
5
6int adimSuresi() {
7  int deger = analogRead(POT);                          // 0–1023
8  return map(deger, 0, 1023, 400, 20);                  // değer büyüdükçe hızlanır / faster as the value rises
9}
10
11void yakSondur(int i) {
12  digitalWrite(LEDS[i], HIGH);
13  delay(adimSuresi());                                  // her adımda yeniden okunur / read again on every step
14  digitalWrite(LEDS[i], LOW);
15}
16
17void setup() {
18  for (int i = 0; i < LED_SAYISI; i++) pinMode(LEDS[i], OUTPUT);
19}
20
21void loop() {
22  for (int i = 0; i < LED_SAYISI - 1; i++) yakSondur(i);   // sağa / to the right
23  for (int i = LED_SAYISI - 1; i > 0; i--) yakSondur(i);   // sola / to the left
24}

Dans cette version, le temps par pas est relu à chaque LED, donc la vitesse change dès que tu tournes l'axe. Mais pendant que delay() s'exécute, l'Arduino ne peut rien faire d'autre : même si tu tournes l'axe au milieu d'un pas lent de 400 ms, la nouvelle vitesse ne s'applique qu'au pas suivant. Pour un effet avec quelques LED, ce n'est pas un problème, mais dès que tu ajoutes un bouton de changement de mode ou des lectures de capteurs, il faut passer à la méthode millis() de l'étape 5.

Étape 4 : l'effet d'empilement

Dans l'effet d'empilement, la première lumière court jusqu'au bout à droite et y reste allumée. La deuxième court aussi, mais s'arrête cette fois une place plus à gauche ; à chaque tour, la cible se décale d'une LED vers la gauche jusqu'à ce que toute la barre soit remplie. Dans le code, tu le fais avec deux boucles imbriquées : la boucle extérieure compte combien de LED se sont empilées (dolu, « plein »), la boucle intérieure combien de pas la lumière parcourt à ce tour. La LED qui atteint sa cible (hedef) n'est pas éteinte ; c'est exactement le rôle de la ligne if (i < hedef). Avec huit LED, remplir toute la barre prend 8 + 7 + 6 + ... + 1 = 36 pas.

C++ (Arduino IDE)
1// Birikerek dolan efekt: her ışık en boş uca kadar gider ve orada kalır / Stacking effect: each light runs to the last free spot and stays
2const int LEDS[] = {2, 3, 4, 5, 6, 7, 8, 9};
3const int LED_SAYISI = sizeof(LEDS) / sizeof(LEDS[0]);
4const int BEKLE = 60;
5
6void setup() {
7  for (int i = 0; i < LED_SAYISI; i++) pinMode(LEDS[i], OUTPUT);
8}
9
10void loop() {
11  for (int dolu = 0; dolu < LED_SAYISI; dolu++) {       // dolu: sağda birikmiş LED sayısı / LEDs already stacked on the right
12    int hedef = LED_SAYISI - 1 - dolu;                  // bu turda ışığın duracağı yer / where the light stops this round
13    for (int i = 0; i <= hedef; i++) {
14      digitalWrite(LEDS[i], HIGH);
15      delay(BEKLE);
16      if (i < hedef) digitalWrite(LEDS[i], LOW);        // hedefte yanık kalır / stays lit at the target
17    }
18  }
19  delay(600);                                           // dolu çubuğu göster / show the full bar
20  for (int i = LED_SAYISI - 1; i >= 0; i--) {           // sağdan sola boşalt / empty from right to left
21    digitalWrite(LEDS[i], LOW);
22    delay(BEKLE);
23  }
24  delay(300);
25}

À la fin du code, la barre pleine est affichée pendant 0,6 seconde, puis les LED s'éteignent une à une de droite à gauche et l'effet recommence. Si tu veux une barre qui se remplit plus simple, il suffit de supprimer la boucle intérieure et d'allumer les LED dans l'ordre sans jamais les éteindre ; cet aspect est idéal pour un indicateur de charge ou un niveau sonore. N'oublie pas que, dans cet effet, les huit LED sont allumées en même temps : tant que chaque LED a sa propre résistance, la luminosité ne baisse pas.

Étape 5 : effet K2000 non bloquant avec millis()

Dans un code qui utilise delay(), l'Arduino se fige pendant la durée indiquée à chaque pas ; si quelqu'un appuie sur un bouton pendant ce temps, il ne s'en rend pas compte. millis(), au contraire, renvoie le temps écoulé en millisecondes depuis la mise sous tension de la carte. La logique est la suivante : la boucle tourne sans arrêt, vérifie à chaque passage si assez de temps s'est écoulé depuis le dernier pas, fait un seul pas si c'est le cas et rend aussitôt la main. Dans le code ci-dessous, l'effet K2000 et la LED intégrée fonctionnent en même temps comme deux tâches indépendantes : pendant que le chenillard défile à la vitesse fixée par le potentiomètre, la LED de D13 clignote une fois par seconde à son propre rythme. Pour aller plus loin, consulte Arduino : millis() ou delay().

C++ (Arduino IDE)
1// millis() ile bekletmesiz karaşimşek + potansiyometre / Non-blocking Knight Rider with millis() + pot
2const int LEDS[] = {2, 3, 4, 5, 6, 7, 8, 9};
3const int LED_SAYISI = sizeof(LEDS) / sizeof(LEDS[0]);
4const int POT = A0;
5
6int konum = 0;                     // şu an yanan LED / the LED that is lit now
7int yon = 1;                       // +1 sağa, -1 sola / +1 right, -1 left
8unsigned long sonAdim = 0;         // son adımın zamanı / time of the last step
9unsigned long sonBlink = 0;        // dahili LED için / for the onboard LED
10
11void setup() {
12  for (int i = 0; i < LED_SAYISI; i++) pinMode(LEDS[i], OUTPUT);
13  pinMode(LED_BUILTIN, OUTPUT);    // Uno'da D13 / D13 on the Uno
14  digitalWrite(LEDS[konum], HIGH);
15}
16
17void loop() {
18  unsigned long simdi = millis();
19  unsigned long aralik = map(analogRead(POT), 0, 1023, 400, 20);   // adım süresi (ms) / step time (ms)
20
21  // Görev 1: karaşimşek / Task 1: Knight Rider
22  if (simdi - sonAdim >= aralik) {          // taşmaya karşı güvenli / overflow-safe
23    sonAdim = simdi;
24    digitalWrite(LEDS[konum], LOW);
25    konum += yon;
26    if (konum == LED_SAYISI - 1 || konum == 0) yon = -yon;   // uçta yön değiştir / reverse at the ends
27    digitalWrite(LEDS[konum], HIGH);
28  }
29
30  // Görev 2: dahili LED kendi temposunda yanıp söner / Task 2: the onboard LED blinks at its own pace
31  if (simdi - sonBlink >= 500) {
32    sonBlink = simdi;
33    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
34  }
35  // Buraya buton, sensör ya da seri port kodu eklenebilir / button, sensor or serial code can go here
36}

Deux détails comptent ici. D'abord, les variables de temps doivent être de type unsigned long ; avec un int, la valeur déborde sur l'Uno au bout d'environ 32,7 secondes et la temporisation se dérègle : l'effet s'arrête ou s'emballe. Ensuite, la comparaison se fait avec une soustraction de la forme simdi - sonAdim >= aralik (maintenant moins le dernier pas, comparé à l'intervalle) ; cette méthode reste correcte même quand millis() repasse à zéro, environ tous les 49,7 jours. Comme nous gardons la position et le sens de la lumière dans deux variables (konum et yon), il n'y a plus de boucles : à chaque pas, la position augmente ou diminue de un et, aux extrémités, le sens change de signe.

8 LED sur 3 broches avec le 74HC595

Huit LED occupent huit broches de l'Uno ; dès que tu veux ajouter un écran LCD, des capteurs et des boutons à ton projet, les broches commencent à manquer. Le registre à décalage 74HC595 pilote ses huit sorties avec seulement trois broches de l'Arduino (données, horloge et latch). L'état de chaque LED est un bit d'un octet : l'expression 1 << i met uniquement le bit i à 1, ce qui allume une seule LED. Les opérations sur les bits permettent aussi de créer facilement des motifs : (1 << i) | (0x80 >> i) produit deux lumières qui arrivent en même temps des deux extrémités vers le centre. En chaînant deux circuits, tu peux même faire un K2000 à 16 LED avec les trois mêmes broches ; le chaînage, le pilotage rapide en SPI et l'utilisation avec des afficheurs 7 segments sont expliqués pas à pas dans l'article Registre à décalage 74HC595.

Broche du 74HC595Branchement (Arduino Uno)
DS (14)D11
SH_CP (11)D13
ST_CP (12)D10
OE (13)GND (sorties toujours actives)
MR (10)5V (remise à zéro désactivée)
VCC (16) / GND (8)5V / GND, avec un condensateur de 100 nF à côté
Q0 (15), Q1–Q7 (1–7)Chacune vers l'anode d'une LED à travers 470 Ω
Patte du milieu du potentiomètreA0
C++ (Arduino IDE)
1// 74HC595 ile 3 pinden 8 LED: karaşimşek ve ortada buluşma / 8 LEDs from 3 pins with a 74HC595: Knight Rider and meet-in-the-middle
2const int DATA_PIN = 11;    // DS (14)
3const int CLOCK_PIN = 13;   // SH_CP (11)
4const int LATCH_PIN = 10;   // ST_CP (12)
5const int POT = A0;
6
7void yaz595(byte desen) {
8  digitalWrite(LATCH_PIN, LOW);
9  shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, desen);   // 8 biti gönder / send the 8 bits
10  digitalWrite(LATCH_PIN, HIGH);                    // çıkışlara aktar / copy to the outputs
11}
12
13void setup() {
14  pinMode(DATA_PIN, OUTPUT);
15  pinMode(CLOCK_PIN, OUTPUT);
16  pinMode(LATCH_PIN, OUTPUT);
17  yaz595(0);                                        // açılışta hepsi sönük / all off at startup
18}
19
20void loop() {
21  int bekle = map(analogRead(POT), 0, 1023, 400, 20);
22
23  for (int i = 0; i < 7; i++) { yaz595(1 << i); delay(bekle); }   // Q0 -> Q7
24  for (int i = 7; i > 0; i--) { yaz595(1 << i); delay(bekle); }   // Q7 -> Q0
25
26  for (int i = 0; i < 4; i++) {                     // uçlardan ortaya / from the ends to the middle
27    yaz595((1 << i) | (0x80 >> i));
28    delay(bekle);
29  }
30  for (int i = 3; i >= 0; i--) {                    // ortadan uçlara / from the middle to the ends
31    yaz595((1 << i) | (0x80 >> i));
32    delay(bekle);
33  }
34}

Sur les sorties du 74HC595, on recommande 470 Ω au lieu de 220 Ω : le courant total qui traverse les broches VCC et GND du circuit ne doit pas dépasser 70 mA. Avec 470 Ω, environ 6,4 mA circulent par LED et, même avec les huit LED allumées, le total reste à 51 mA. Dans l'effet K2000, seules une ou deux LED sont allumées à la fois, donc elles restent bien visibles.

K2000 avec traînée sur une seule broche avec des WS2812B

La version qui ressemble le plus au vrai scanner de KITT se fait avec des LED adressables WS2812B. Chaque WS2812B intègre son propre pilote ; quelle que soit la longueur du ruban, tu règles la couleur et la luminosité de chaque LED séparément avec un seul fil de données. Pour la traînée, on garde un tableau : à chaque pas, la luminosité de toutes les LED est divisée par trois et la LED de tête passe à 255. Les LED de derrière s'éteignent alors vite en passant par 255, 85, 28 et 9, ce qui laisse une traînée naturelle derrière la lumière. Divise par 2 au lieu de 3 et la traînée s'allonge ; par 5, elle raccourcit. Pour passer de 8 à 60 LED avec la même méthode, il suffit de changer la valeur de NUM_LEDS.

LED RVB adressable WS2812B
WS2812B : chaque LED contient son propre pilote ; elle se branche par DIN, 5V et GND, et DOUT va vers la LED suivante.
C++ (Arduino IDE)
1// WS2812B ile kuyruklu karaşimşek (tek veri pini) / Knight Rider with a fading tail on WS2812B (one data pin)
2#include <Adafruit_NeoPixel.h>
3
4const int DATA_PIN = 6;      // DIN, 330 Ω üzerinden / DIN through 330 Ω
5const int NUM_LEDS = 8;      // şerit ya da çubuktaki LED sayısı / LEDs on the strip or stick
6const int POT = A0;
7
8Adafruit_NeoPixel strip(NUM_LEDS, DATA_PIN, NEO_GRB + NEO_KHZ800);
9
10uint8_t seviye[NUM_LEDS];    // her LED'in kırmızı parlaklığı / red brightness of each LED
11int konum = 0;
12int yon = 1;
13
14void setup() {
15  strip.begin();
16  strip.setBrightness(80);   // 0–255; USB için düşük tut / keep it low on USB power
17  strip.show();              // hepsini söndür / all off
18}
19
20void loop() {
21  for (int i = 0; i < NUM_LEDS; i++) seviye[i] = seviye[i] / 3;   // kuyruk söner / the tail fades
22  seviye[konum] = 255;                                            // baştaki LED tam parlak / the head is full brightness
23
24  for (int i = 0; i < NUM_LEDS; i++) {
25    strip.setPixelColor(i, strip.Color(seviye[i], 0, 0));         // yalnız kırmızı / red only
26  }
27  strip.show();
28
29  konum += yon;
30  if (konum == NUM_LEDS - 1 || konum == 0) yon = -yon;            // uçta yön değiştir / reverse at the ends
31  delay(map(analogRead(POT), 0, 1023, 150, 20));
32}
Pour brancher des WS2812B, mets une résistance de 330 Ω en série sur la ligne de données et un condensateur de 1000 µF entre 5V et GND ; si tu utilises une alimentation externe, relie son GND à celui de l'Arduino. Chaque LED peut consommer environ 60 mA en blanc à pleine puissance ; une barrette de 8 LED fonctionne sur l'USB, mais à partir de 30 LED il faut une alimentation 5 V séparée. Pour l'installation de la bibliothèque, l'ordre des couleurs et le calcul de puissance, consulte l'article LED WS2812B NeoPixel.

Effet K2000 sur ESP32 : traînée en PWM sur chaque broche

Sur l'Uno, un K2000 avec traînée est difficile à faire avec des LED ordinaires, car le PWM n'existe que sur les broches 3, 5, 6, 9, 10 et 11, et notre tableau D2–D9 n'en contient que quatre. Sur l'ESP32, grâce au matériel LEDC, presque toutes les broches de sortie peuvent générer du PWM, et l'ESP32 classique dispose de 16 canaux PWM. Comme analogWrite() fonctionne directement dans le cœur Arduino actuel pour ESP32, tu peux appliquer la logique de traînée des WS2812B à des LED ordinaires. Les broches du tableau sont des GPIO sûres qui n'influencent pas le démarrage ; le potentiomètre est relié à la GPIO 34 sur le canal ADC1, qui mesure correctement même avec le Wi-Fi actif, et comme l'ADC de l'ESP32 est sur 12 bits, la valeur va de 0 à 4095. Les broches de l'ESP32 délivrent 3,3 V : avec 220 Ω, environ 6 mA traversent une LED rouge, et les LED paraissent un peu moins lumineuses que sur l'Uno. Pour préparer la carte, consulte Qu'est-ce que l'ESP32 ?.

C++ (Arduino IDE)
1// ESP32: her pinde PWM ile kuyruklu karaşimşek / ESP32: Knight Rider with a PWM tail on every pin
2const int LEDS[] = {18, 19, 21, 22, 23, 25, 26, 27};
3const int LED_SAYISI = sizeof(LEDS) / sizeof(LEDS[0]);
4const int POT = 34;                        // ADC1, yalnızca giriş / ADC1, input only
5
6int parlaklik[LED_SAYISI];                 // 0–255
7int konum = 0;
8int yon = 1;
9unsigned long sonAdim = 0;
10
11void setup() {
12  // analogWrite() pini PWM için kendisi hazırlar / analogWrite() sets the pin up for PWM itself
13}
14
15void loop() {
16  unsigned long aralik = map(analogRead(POT), 0, 4095, 400, 20);   // ESP32 ADC 12 bit: 0–4095
17  if (millis() - sonAdim >= aralik) {
18    sonAdim = millis();
19    for (int i = 0; i < LED_SAYISI; i++) parlaklik[i] /= 3;        // kuyruk söner / the tail fades
20    parlaklik[konum] = 255;
21    for (int i = 0; i < LED_SAYISI; i++) analogWrite(LEDS[i], parlaklik[i]);
22    konum += yon;
23    if (konum == LED_SAYISI - 1 || konum == 0) yon = -yon;
24  }
25}

Effet K2000 sur Raspberry Pi Pico avec MicroPython

Sur le Raspberry Pi Pico, tu écris le même effet en quelques lignes de MicroPython. Ranger les objets Pin dans une liste joue le même rôle que le tableau sur Arduino. time.ticks_ms() et time.ticks_diff() sont les équivalents MicroPython de millis() et de la soustraction qui résiste au débordement. Le potentiomètre est relié à GP26 (ADC0) ; read_u16() renvoie une valeur de 0 à 65535 que le code convertit en 400 à 20 ms. Il est recommandé que le courant total tiré de toutes les GPIO du Pico reste sous 50 mA ; c'est pourquoi nous avons choisi 330 Ω dans le tableau : environ 4 mA circulent par LED et, même avec les huit allumées, le total tourne autour de 32 mA. Le projet K2000 pour Pico de BlueGrays utilise 6 LED sur les broches GP9 à GP14 ; si tu as monté ce circuit, il suffit de remplacer la liste PINLER par [9, 10, 11, 12, 13, 14]. Pour l'installation et le téléversement avec Thonny, consulte Qu'est-ce que le Raspberry Pi Pico ?.

MicroPython
1# Raspberry Pi Pico: potansiyometreyle hız ayarlı karaşimşek / Pico: Knight Rider with pot speed control
2from machine import Pin, ADC
3import time
4
5PINLER = [8, 9, 10, 11, 12, 13, 14, 15]        # GP8–GP15
6leds = [Pin(p, Pin.OUT) for p in PINLER]
7pot = ADC(26)                                   # GP26 = ADC0
8
9def adim_suresi():
10    # read_u16: 0–65535 -> 400–20 ms
11    return 400 - pot.read_u16() * 380 // 65535
12
13konum, yon = 0, 1
14leds[konum].on()
15son = time.ticks_ms()
16
17while True:
18    if time.ticks_diff(time.ticks_ms(), son) >= adim_suresi():   # millis() benzeri / like millis()
19        son = time.ticks_ms()
20        leds[konum].off()
21        konum += yon
22        if konum == len(leds) - 1 or konum == 0:
23            yon = -yon                          # uçta yön değiştir / reverse at the ends
24        leds[konum].on()

Chaque GPIO du Pico peut aussi générer du PWM ; avec machine.PWM et une valeur duty_u16() pour chaque LED, tu peux transposer l'effet de traînée de l'ESP32 sur le Pico. Si tu veux utiliser des WS2812B, le module neopixel intégré à MicroPython pilote un ruban depuis une seule GPIO ; mais un WS2812B alimenté en 5 V ne lit pas toujours de façon fiable le signal de données 3,3 V du Pico, donc si les couleurs se dérèglent, ajoute un convertisseur de niveau entre les deux.

Idées de projets avec l'effet K2000

  • Vumètre : décide combien de LED de la barre s'allument selon le niveau sonore mesuré avec le capteur de son KY-038.
  • Barre de LED pour radar de recul : allume davantage de LED à mesure que la distance mesurée par le HC-SR04 diminue, et fais-les toutes clignoter quand l'obstacle est tout proche.
  • Jeu « attrape la lumière » : pendant que la lumière fait des allers-retours rapides, essaie d'appuyer sur un bouton pile au moment où la LED du centre s'allume ; à chaque réussite, raccourcis le temps par pas.
  • Déco de nuit automatique : que l'effet démarre tout seul quand une photorésistance (LDR) détecte la tombée de la nuit.
  • Feu arrière pour voiture miniature ou vélo : fais un K2000 rouge avec traînée sur une barrette WS2812B, et allume toutes les LED à fond quand on appuie sur le bouton de frein.
  • Indicateur de niveau : affiche la position d'un potentiomètre ou la tension d'une batterie sous forme de barre qui se remplit.
  • Affichages plus grands : applique la même logique à une matrice de LED MAX7219 ou à un cube de LED.

Erreurs fréquentes et solutions

SymptômeCauseSolution
Les LED brillent très faiblementpinMode(OUTPUT) oublié ; digitalWrite active seulement la résistance de pull-up interneMets toutes les broches en OUTPUT avec une boucle dans setup()
Une LED ne s'allume jamaisLED montée à l'envers, ou résistance ou fil décalé d'une rangéePatte longue vers la résistance et la broche, patte courte au GND ; teste la LED seule avec le 5V et une résistance
Les LED des extrémités restent allumées deux fois plus longtempsLes deux boucles incluent les LED des extrémitésUtilise i < LED_SAYISI − 1 dans la boucle aller et i > 0 dans la boucle retour
Une broche au hasard scintille ou le programme se comporte bizarrementDépassement du tableau : i <= LED_SAYISIChange la condition en i < LED_SAYISI ; l'élément LEDS[8] n'existe pas
Le code ne se téléverse pas, ou les LED clignotent pendant le téléversementDes LED sont branchées sur D0 et D1Fais commencer le tableau à D2
Le potentiomètre ne change pas la vitesseC'est une patte extérieure qui est reliée à A0 au lieu de celle du milieu, ou la valeur n'est lue qu'une fois hors de la boucleRelie la patte du milieu à A0 ; appelle analogRead à chaque pas
L'effet se dérègle au bout d'environ 32 secondesLa valeur de millis() est stockée dans une variable intDéclare les variables de temps en unsigned long
Les WS2812B ne s'allument pas ou affichent des couleurs aléatoiresPas de GND commun, pas de résistance sur les données, ou ruban branché du mauvais côté (DOUT)Relie les GND, ajoute 330 Ω, branche-toi côté DIN, là où partent les flèches
Avant de monter le circuit, tu peux tester le code dans Tinkercad avec 8 LED et un potentiomètre. Si quelque chose ne va pas dans le vrai circuit, téléverse un court programme qui met toutes les broches à HIGH pendant quelques secondes pour tester les LED une par une ; tu verras tout de suite laquelle ne s'allume pas.

L'effet K2000 a l'air simple, mais il contient des idées de base que tu utiliseras ensuite dans tous tes projets : tableaux, boucles, lecture analogique, map(), temporisation non bloquante, opérations sur les bits et LED adressables. Pour la suite, jette un œil au projet feu tricolore Arduino ou à la liste d'idées de projets Arduino. Dans l'application BlueGrays, tu trouveras le chenillard, l'effet K2000 et leurs versions à vitesse réglable, les effets d'empilement et K2000 avec WS2812B, ainsi que les projets chenillard sur ESP32 et K2000 sur Pico, chacun avec un schéma pas à pas et un code prêt à essayer sur ta propre carte.

Questions fréquentes

Combien de LED peut-on piloter avec un Arduino Uno ?

L'Uno possède 20 broches utilisables comme sorties numériques, D0 à D13 et A0 à A5 ; si tu laisses D0 et D1 libres pour la liaison série, tu peux piloter directement 18 LED. Donne à chaque LED sa propre résistance et garde le courant total sous 200 mA ; si les 18 doivent être allumées en même temps, choisis 330 Ω ou plus. Pour davantage de LED, on utilise un registre à décalage 74HC595 ou un ruban WS2812B, qui pilote des centaines de LED avec une seule broche.

Quelle résistance pour un chenillard à LED ?

Sur un Arduino Uno en 5 V, 220 Ω convient aux LED rouges et donne environ 13,6 mA par LED ; 330 Ω fonctionne aussi, mais les LED sont un peu moins lumineuses. Sur l'ESP32 en 3,3 V, on recommande 220 Ω, et 330 Ω sur le Pico. Dans les effets où une seule LED est allumée, une résistance commune unique fonctionne aussi, mais la luminosité baisse dès que plusieurs LED s'allument ; une résistance par LED reste donc le bon choix.

Peut-on faire un chenillard K2000 sans Arduino ?

Oui, la méthode classique utilise un NE555 et un compteur CD4017. Le 555 produit les impulsions d'horloge et le 4017 met ses 10 sorties à HIGH l'une après l'autre, ce qui donne à lui seul un chenillard simple. Pour l'aller-retour, on combine les sorties avec des diodes : les 10 sorties sont reliées à 6 LED dans l'ordre 1-2-3-4-5-6-5-4-3-2, et la vitesse se règle avec un potentiomètre sur le 555.

Quelle différence entre un chenillard simple et l'effet K2000 ?

Dans un chenillard simple, la lumière avance dans un seul sens et repart du début après la dernière LED ; avec 8 LED, un cycle compte 8 pas. Dans l'effet K2000, la lumière fait demi-tour au bout et oscille entre les deux extrémités ; avec 8 LED, un cycle compte 14 pas. Côté code, la différence est faible : pour le K2000, tu ajoutes une seconde boucle qui compte à rebours.

Pourquoi utiliser millis() plutôt que delay() pour un chenillard ?

Pendant que delay() s'exécute, l'Arduino ne peut rien faire d'autre ; il rate les appuis sur les boutons et ne lit pas les capteurs. Avec millis(), chaque passage dans la boucle ne fait un pas que lorsque le temps est écoulé, et d'autres tâches tournent le reste du temps. Ainsi, pendant que le chenillard défile, les boutons, le potentiomètre ou les commandes série réagissent immédiatement.

Comment ajouter une traînée lumineuse à l'effet K2000 ?

Pour la traînée, il faut baisser progressivement la luminosité des LED qui suivent la tête, ce qui demande du PWM. Sur l'Uno, le PWM n'existe que sur les broches 3, 5, 6, 9, 10 et 11 : tu peux donc faire un K2000 à 6 LED avec traînée sur ces broches. Le plus simple reste un ruban WS2812B, où chaque LED se règle séparément, ou un ESP32 ou un Pico, qui ont du PWM sur toutes leurs broches.

Voir tous les projets
Chenillard K2000 à LED
#6Intermédiaire

Chenillard K2000 à LED

Le fameux balayage lumineux : un point de lumière glisse d'un bout à l'autre de six LED, puis revient. L'Arduino allume chaque LED un dixième de seconde avant de passer à la suivante, fait demi-tour à

4.8(106)
202
Chenillard à LED
#5Intermédiaire

Chenillard à LED

Des lumières qui s'allument l'une après l'autre, comme si elles couraient. L'Arduino allume six LED une par une ; chacune brille un court instant puis s'éteint, et la lumière parcourt la rangée du déb

4.6(85)
207
Chenillard K2000 à vitesse réglable
#8Intermédiaire

Chenillard K2000 à vitesse réglable

Une lumière court d'un bout à l'autre de six LED, fait demi-tour et repart. En tournant le bouton du potentiomètre, tu changes aussitôt la vitesse de sa course : bouton d'un côté, la lumière file pres

4.5(60)
120
Chenillard à LED à vitesse réglable
#7Intermédiaire

Chenillard à LED à vitesse réglable

Six LED s'allument l'une après l'autre et la lumière semble courir d'un bout à l'autre. Quand tu tournes le bouton du potentiomètre, la vitesse de cette course change aussitôt : dans un sens la lumièr

4.6(72)
146
Chenillard K2000 avec WS2812B
#73Intermédiaire
Premium

Chenillard K2000 avec WS2812B

Un point de lumière rouge glisse d'un bout à l'autre d'un ruban LED intelligent, puis revient, dans un va-et-vient qui ne s'arrête jamais. À chaque pas, l'Arduino n'allume qu'une seule LED, attend un

4.9(73)
94
Chenillard WS2812B (remplissage)
#72Intermédiaire
Premium

Chenillard WS2812B (remplissage)

Un ruban lumineux qui se remplit et se vide comme un verre d'eau. L'Arduino allume une à une dix LED de couleur en orange et les laisse allumées ; une fois le ruban plein, il les éteint une à une dans

4.7(50)
65
LED Chenillard ESP32 (Knight Rider)
#108Débutant

LED Chenillard ESP32 (Knight Rider)

6 LED se déplaçant séquentiellement de gauche à droite et de droite à gauche (style Knight Rider). Exemple de base de l'utilisation d'une boucle for et d'un tableau. Enseigne la logique du changement de direction.

4.5(19)
32
Raspberry Pi Pico Knight Rider LED Scanner (6 LED Aller-Retour)
#154Débutant

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.

0.0(0)
13