Créez des séquences lumineuses époustouflantes avec un registre à décalage Arduino
Composants et fournitures
| Composant | Quantité |
|---|---|
| Arduino UNO | 1 |
| Plaque d'essai (breadboard) | 2 |
| Fils de liaison (jumper wires) | 55 |
| Registre à décalage 74HC595 | 1 |
| Boutons poussoirs | 4 |
| Potentiomètre rotatif | 1 |
| LED (génériques) | 8 |
| Résistance 221 Ω | 9 |
| Résistance 10 kΩ | 4 |
Outils nécessaires
- Vos mains
Applications et services en ligne
- Arduino IDE
À propos du projet
Je me suis amusé avec des lumières et des tableaux, et j'ai voulu exploiter le registre à décalage et l'écran LCD pour créer un programme permettant de modifier et d'afficher des animations lumineuses sans avoir à modifier le code à chaque fois.
Quatre boutons (numérotés 1 à 4 de gauche à droite) permettent de naviguer dans les menus et de modifier les variables :
- Bouton 1 : incrémenter les valeurs / mettre une LED à l'état HIGH
- Bouton 2 : décrémenter les valeurs / mettre une LED à l'état LOW
- Bouton 3 : reculer le curseur lors de la création d'une image
- Bouton 4 : bouton « Retour »
Le programme permet de régler la vitesse de l'animation et le nombre de boucles. Une future version pourrait gérer plusieurs animations. Vous pouvez changer le nombre d'images en modifiant la constante ARR_SIZE au début du code.
Code
Le sketch complet est fourni ci-dessous. Branchez le matériel selon le schéma, téléversez le code et profitez de votre séquenceur lumineux !
#include <LiquidCrystal.h>
#define ARR_SIZE 16 // Nombre d'images (frames) - MODIFIER selon besoin
#define LIGHTS 8 // Nombre de LEDs contrôlées
// Broches des boutons (entrées avec pull-up interne)
const int btn1 = 7, btn2 = 8, btn3 = 9, btn4 = 10;
int bs1 = 0, bs2 = 0, bs3 = 0, bs4 = 0;
// Broches du 74HC595
const int latchPin = 11; // ST_CP
const int clockPin = 13; // SH_CP
const int dataPin = 12; // DS
byte data; // Données à envoyer au registre
bool ArrOne[ARR_SIZE][LIGHTS] = {false}; // Tableau d'animation (booléens)
byte lightArrOne[ARR_SIZE] = {0xFF}; // Tableau traduit en octets
// Paramètres d'animation
int animSpeed = 50; // ms entre chaque image
int loopCount = 5; // Nombre de boucles
// Configuration LCD (RS, EN, D4, D5, D6, D7)
const int rs = 15, en = 14, d4 = 3, d5 = 4, d6 = 5, d7 = 6;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
void setup() {
pinMode(btn1, INPUT_PULLUP);
pinMode(btn2, INPUT_PULLUP);
pinMode(btn3, INPUT_PULLUP);
pinMode(btn4, INPUT_PULLUP);
lcd.begin(16, 2);
pinMode(latchPin, OUTPUT);
PrintMenu();
}
void loop() {
bs1 = digitalRead(btn1);
bs2 = digitalRead(btn2);
bs3 = digitalRead(btn3);
bs4 = digitalRead(btn4);
if (bs1 == HIGH) { // Jouer l'animation
bs1 = LOW; delay(150); Play();
} else if (bs2 == HIGH) { // Créer/modifier l'animation
bs2 = LOW; delay(150); Create(ArrOne);
} else if (bs3 == HIGH) { // Régler la vitesse
bs3 = LOW; delay(150); SetSpeed();
} else if (bs4 == HIGH) { // Régler le nombre de boucles
bs4 = LOW; delay(150); SetLoop();
}
PrintMenu();
delay(150);
}
// --- Fonctions d'affichage menu ---
void PrintMenu() {
ClearScreen();
lcd.print("1-Play 3-Speed");
lcd.setCursor(0, 1);
lcd.print("2-Create 4-Loops");
}
void PrintCreate(bool Arr[][LIGHTS], int frame, int _bit) {
ClearScreen();
lcd.print("Frame:"); lcd.print(frame + 1);
if (frame < 9) lcd.print(" ");
for (int j = 0; j < _bit; j++) lcd.print(" ");
lcd.print("v");
lcd.setCursor(0, 1);
lcd.print(" ");
for (int j = 0; j < 8; j++) lcd.print(Arr[frame][j]);
}
void PrintSetSpeed() {
ClearScreen();
lcd.print("Set Speed(ms)");
lcd.setCursor(0, 1);
lcd.print(animSpeed);
}
void PrintSetLoop() {
ClearScreen();
lcd.print("Set Loop Count");
lcd.setCursor(0, 1);
lcd.print(loopCount);
}
// --- Lecture de l'animation ---
void Play() {
for (int count = 0; count < loopCount; count++) {
for (int i = 0; i < ARR_SIZE; ++i) {
data = lightArrOne[i];
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, data);
digitalWrite(latchPin, HIGH);
delay(animSpeed);
}
}
// Éteindre toutes les LEDs à la fin
data = 0;
for (int i = 0; i < ARR_SIZE; ++i) {
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, data);
digitalWrite(latchPin, HIGH);
}
}
// --- Création d'une image ---
void Create(bool Arr[][LIGHTS]) {
for (int frame = 0; frame < ARR_SIZE; frame++) {
bool leaving = false;
int b = 0;
while (!leaving && b < LIGHTS) {
PrintCreate(Arr, frame, b);
// Gestion retour arrière sur frame précédente
if (b < 0 && frame > 0) { b = LIGHTS - 1; frame--; }
bs1 = digitalRead(btn1);
bs2 = digitalRead(btn2);
bs3 = digitalRead(btn3);
bs4 = digitalRead(btn4);
if (bs1 == HIGH) { delay(150); Arr[frame][b] = true; b++; }
else if (bs2 == HIGH) { delay(150); Arr[frame][b] = false; b++; }
else if (bs3 == HIGH) { delay(150); b--; }
else if (bs4 == HIGH) { delay(150); leaving = true; }
delay(10);
}
PrintCreate(Arr, frame, b);
IntToHexToByte(Arr);
delay(500);
}
}
// --- Conversion tableau booléen → octet pour le 74HC595 ---
void IntToHexToByte(bool Arr[][LIGHTS]) {
for (int row = 0; row < ARR_SIZE; row++) {
lightArrOne[row] = BoolArrayToByte(Arr, row);
}
}
byte BoolArrayToByte(bool Arr[][LIGHTS], int row) {
byte result = 0;
for (int i = 0; i < LIGHTS; i++) {
if (Arr[row][i]) result |= (1 << i);
}
return result;
}
// --- Réglage vitesse ---
void SetSpeed() {
bool leaving = false;
while (!leaving) {
PrintSetSpeed();
bs1 = digitalRead(btn1);
bs2 = digitalRead(btn2);
bs3 = digitalRead(btn3);
bs4 = digitalRead(btn4);
if (bs1 == HIGH) { delay(10); animSpeed++; }
if (bs2 == HIGH) { delay(10); if (animSpeed > 1) animSpeed--; }
if (bs4 == HIGH) { delay(150); leaving = true; }
delay(30);
}
}
// --- Réglage nombre de boucles ---
void SetLoop() {
bool leaving = false;
while (!leaving) {
PrintSetLoop();
bs1 = digitalRead(btn1);
bs2 = digitalRead(btn2);
bs3 = digitalRead(btn3);
bs4 = digitalRead(btn4);
if (bs1 == HIGH) { delay(10); loopCount++; }
if (bs2 == HIGH) { delay(10); if (loopCount > 1) loopCount--; }
if (bs4 == HIGH) { delay(150); leaving = true; }
delay(30);
}
}
// --- Fonction shiftOut personnalisée (MSB first) ---
void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {
pinMode(myClockPin, OUTPUT);
pinMode(myDataPin, OUTPUT);
digitalWrite(myDataPin, LOW);
digitalWrite(myClockPin, LOW);
for (int i = 7; i >= 0; i--) {
digitalWrite(myClockPin, LOW);
int pinState = (myDataOut & (1 << i)) ? HIGH : LOW;
digitalWrite(myDataPin, pinState);
digitalWrite(myClockPin, HIGH);
digitalWrite(myDataPin, LOW);
}
digitalWrite(myClockPin, LOW);
}
// --- Effacement LCD ---
void ClearScreen() {
lcd.setCursor(0, 0);
for (int col = 0; col < 16; col++) lcd.print(" ");
lcd.setCursor(0, 1);
for (int col = 0; col < 16; col++) lcd.print(" ");
lcd.setCursor(0, 0);
}
Schéma de câblage
Suivez attentivement les connexions. En raison des contraintes de représentation, le schéma peut paraître étalé ; une fois monté, vous pourrez optimiser le câblage.

Processus de fabrication
- Détecteur de langue TinyML avec Edge Impulse sur Arduino Nano 33 BLE Sense
- Construire un jeu gyroscopique temps réel avec Arduino Nano et capteur MPU-6050
- Dé numérique Arduino sur écran LCD 16x2 – Générateur aléatoire à bouton poussoir
- Créer votre propre jeu de roulette à 37 LED avec Arduino Nano
- ATtiny85 Mini Arcade : Snake – Construire une console de jeu portable OLED
- Détecteur de distance portable – Kit DIY Arduino Nano avec HC-SR04, alimentation 18650 et boîtier imprimé 3D
- Construire une lampe de bureau réactive à l'audio avec Arduino Nano
- Voiture robot autonome de suivi de visage avec Arduino Nano et OpenCV
- Projet de galvanoplastie au cuivre : Construisez un système intelligent avec Arduino UNO