Indrukwekkende Lichtsequenties Maken met Arduino en Shift Register
Onderdelen en Benodigdheden
| Arduino UNO | × | 1 |
| Breadboard (generiek) | × | 2 |
| Draadjes (generiek) | × | 55 |
| 74HC595 Shift Register | × | 1 |
| Drukknoppen | × | 4 |
| Draaipotentiometer (generiek) | × | 1 |
| LED (generiek) | × | 8 |
| Weerstand 221 ohm | × | 9 |
| Weerstand 10k ohm | × | 4 |
Benodigde Tools en Machines
- Handen
Apps en Online Services
- Arduino IDE
Over dit Project
Ik heb plezier beleefd met lichten en arrays en dacht dat ik het shift register en het LCD-scherm kon gebruiken om een programma te maken waarmee je lichtanimaties kunt wijzigen en weergeven zonder telkens in de code te hoeven duiken om handmatig een animatie te maken.
Er zijn 4 knoppen, van links naar rechts genummerd 1 tot 4. Ze laten je door het menu navigeren en variabelen wijzigen. Knop 1 verhoogt waarden en zet een licht op HIGH. Knop 2 verlaagt waarden en zet een licht op LOW. Knop 3 verplaatst de cursor achterwaarts tijdens het maken van een frame, en knop 4 fungeert als 'terug'-knop.
Het programma kan de animatiesnelheid en het aantal loops aanpassen. Ik zal misschien een versie uitbrengen die meerdere animaties ondersteunt.
Je kunt frames wijzigen door ARR_SIZE bovenaan in de code aan te passen.
Veel plezier!
Code
Light Sequencer C/C++
Upload deze code en run het. Als de wiring correct is, zou het zonder problemen moeten werken!
#include <LiquidCrystal.h>
#define ARR_SIZE 16 // PAS DIT AAN naar elk aantal frames
#define LIGHTS 8 // Besturing van de spelknoppen
const int btn1 = 7, btn2 = 8, btn3 = 9, btn4 = 10;
// Variabelen voor het lezen van de drukknopstatus
int bs1 = 0, bs2 = 0, bs3 = 0, bs4 = 0;
// Pin aangesloten op ST_CP van 74HC595
const int latchPin = 11;
// Pin aangesloten op SH_CP van 74HC595
const int clockPin = 13;
// Pin aangesloten op DS van 74HC595
const int dataPin = 12;
// Holders voor informatie die je doorgeeft
byte data;
// Gebruikt om 1 of 0 te lezen
bool ArrOne[ARR_SIZE][LIGHTS] = {false}; // animatie
// Vertaald voor het register als bytes
byte lightArrOne[ARR_SIZE] = {0xFF};
// Variabelen die de animatie beïnvloeden
int animSpeed = 50; // ms tussen elke frame
int loopCount = 5; // aantal keren dat het draait
// LCD-pinnen
const int rs = 15, en = 14, d4 = 3, d5 = 4, d6 = 5, d7 = 6;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
void setup() {
// Stel elke knop in
pinMode(btn1, INPUT_PULLUP);
pinMode(btn2, INPUT_PULLUP);
pinMode(btn3, INPUT_PULLUP);
pinMode(btn4, INPUT_PULLUP);
// Stel LCD-aantal kolommen en rijen in
lcd.begin(16, 2);
// Stel register latch-pin in
pinMode(latchPin, OUTPUT);
PrintMenu();
}
void loop() {
bs1 = digitalRead(btn1);
bs2 = digitalRead(btn2);
bs3 = digitalRead(btn3);
bs4 = digitalRead(btn4);
// Speel de animatie af
if(bs1 == HIGH) {
bs1 = LOW; // voorkomt dubbele invoer
delay(150);
Play();
}
// Wijzig de animatie
else if(bs2 == HIGH) {
bs2 = LOW;
delay(150);
Create(ArrOne);
}
// Wijzig de snelheid
else if(bs3 == HIGH) {
bs3 = LOW;
delay(150);
SetSpeed();
}
// Wijzig het aantal loops
else if(bs4 == HIGH) {
bs4 = LOW;
delay(150);
SetLoop();
}
PrintMenu();
delay(150);
}
// Functie om info voor het hoofdmenu af te drukken
void PrintMenu() {
ClearScreen();
lcd.print("1-Play 3-Speed");
lcd.setCursor(0, 1);
lcd.print("2-Create 4-Loops");
}
// Functie om info voor het maken van een frame af te drukken
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]);
}
// Functie om info voor instellen snelheid af te drukken
void PrintSetSpeed() {
ClearScreen();
lcd.print("Set Speed(ms)");
lcd.setCursor(0, 1);
lcd.print(animSpeed);
}
// Functie om info voor wijzigen aantal animatieloops af te drukken
void PrintSetLoop() {
ClearScreen();
lcd.print("Set Loop Count");
lcd.setCursor(0, 1);
lcd.print(loopCount);
}
// Functie om de animatie af te spelen met gegeven parameters
void Play() {
for(int count = 0; count < loopCount; count++) {
for(int i = 0; i < ARR_SIZE; ++i) {
data = lightArrOne[i];
digitalWrite(latchPin, 0);
shiftOut(dataPin, clockPin, data);
digitalWrite(latchPin, 1);
delay(animSpeed);
}
}
data = 0;
for(int i = 0; i < ARR_SIZE; ++i) {
digitalWrite(latchPin, 0);
shiftOut(dataPin, clockPin, data);
digitalWrite(latchPin, 1);
}
}
// Menu voor het maken van een frame
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);
// Zorg dat b binnen grenzen blijft
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);
}
}
// Functie om de array om te zetten naar een byte voor het register
void IntToHexToByte(bool Arr[][LIGHTS]) {
for(int row = 0; row < ARR_SIZE; row++) {
lightArrOne[row] = BoolArrayToByte(Arr, row);
}
}
// Helper functie om binair om te zetten naar een byte
byte BoolArrayToByte(bool Arr[][LIGHTS], int row) {
byte result = 0;
for(int i = 0; i < LIGHTS; i++) {
if(Arr[row][i]) result = result | (1 << i);
}
return result;
}
// Menu om de animatiesnelheid in te stellen
void SetSpeed() {
bool leaving = false;
while(!leaving) {
PrintSetSpeed();
bs1 = digitalRead(btn1);
bs2 = digitalRead(btn2);
bs3 = digitalRead(btn3);
bs4 = digitalRead(btn4);
// Verhoog snelheid (lagere ms = sneller)
if(bs1 == HIGH) {
delay(10);
animSpeed++;
}
// Verlaag snelheid (hogere ms = langzamer)
if(bs2 == HIGH) {
delay(10);
if(animSpeed > 1) animSpeed--;
}
// Bevestig en ga terug
if(bs4 == HIGH) {
delay(150);
leaving = true;
}
delay(30);
}
}
// Functie om het aantal keren dat de animatie loopt te wijzigen
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);
}
}
// Functie om de bits daadwerkelijk in het register te shiften
void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {
int i = 0;
int pinState;
pinMode(myClockPin, OUTPUT);
pinMode(myDataPin, OUTPUT);
digitalWrite(myDataPin, 0);
digitalWrite(myClockPin, 0);
for (i = 7; i >= 0; i--) {
digitalWrite(myClockPin, 0);
if (myDataOut & (1 << i)) pinState = 1;
else pinState = 0;
digitalWrite(myDataPin, pinState);
digitalWrite(myClockPin, 1);
digitalWrite(myDataPin, 0);
}
digitalWrite(myClockPin, 0);
}
// Functie om het LCD leeg te maken door spaties te printen
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);
}
Schema's
Volg de lijntjes zorgvuldig. Vanwege beperkingen in de lengte van weerstanden in het programma en voor de leesbaarheid kon ik het niet zo compact maken als in mijn echte opstelling. Na het bouwen daag ik je uit om manieren te vinden om het op te schonen.

Productieproces
- TinyML Taaldetector met Edge Impulse op Arduino Nano 33 BLE Sense
- Bouw een real-time gyroscoop-spel met Arduino Nano & MPU-6050 sensor
- Arduino Digitale Dobbelsteen: Bouw Je Eigen LCD-willekeurige Getalgenerator
- Bouw Je Eigen 37-LED Roulette-spel met Arduino Nano
- ATtiny85 Mini Arcade: Snake – Bouw een Handheld OLED Game Console
- Draagbare Afstandsdetector – Arduino Nano DIY Kit met HC-SR04, 18650 Accu en 3D-geprinte Behuizing
- Een audio-reactieve bureaulamp bouwen met Arduino Nano
- Autonome Gezichtsvolgende Robot Auto met Arduino Nano & OpenCV
- Koper Elektrolyseren Project: Bouw een Slim Systeem met Arduino UNO
- NeoPixel Matrix Pong op Arduino Nano: Bouw je eigen neon Pong-spel
- Arduino MKR1000 WiFi Pick-to-Light Systeem – Project 2