Buat Urutan Lampu Menakjubkan dengan Arduino Shift Register
Komponen dan Perlengkapan
Berikut adalah daftar komponen yang diperlukan untuk membangun urutan lampu menakjubkan ini:
| Arduino UNO | 1 |
| Breadboard (umum) | 2 |
| Kabel jumper (umum) | 55 |
| 74HC595 Shift Register | 1 |
| Tombol push | 4 |
| Potensiometer rotary (umum) | 1 |
| LED (umum) | 8 |
| Resistor 221 ohm | 9 |
| Resistor 10k ohm | 4 |
Alat dan Mesin yang Diperlukan
Tangan (untuk pemasangan dan merangkaikan rangkaian).
Aplikasi dan Layanan Online
Arduino IDE — digunakan untuk menulis dan mengunggah kode ke papan Arduino.
Tentang Proyek Ini
Saya senang bereksperimen dengan lampu dan array, sehingga saya memutuskan untuk menggunakan shift register dan layar LCD guna membuat program yang memungkinkan Anda memodifikasi serta menampilkan animasi lampu tanpa harus masuk ke dalam kode dan membuat animasi secara manual setiap kali.
Ada 4 tombol, dari kiri ke kanan berurutan 1 hingga 4. Tombol-tombol ini memungkinkan Anda menavigasi menu dan mengubah variabel. Tombol 1 digunakan untuk menaikkan nilai dan mengubah status lampu menjadi HIGH. Tombol 2 digunakan untuk menurunkan nilai dan mengubah status lampu menjadi LOW. Tombol 3 dapat menggerakkan kursor ke belakang saat membuat frame, dan tombol 4 berfungsi sebagai tombol 'kembali'.
Program dapat mengubah kecepatan animasi dan jumlah perulangan. Saya mungkin akan merilis versi lain yang mendukung banyak animasi.
Anda dapat mengubah frame dengan mengubah ARR_SIZE di bagian atas kode.
Selamat mencoba!
Kode
Salin kode di bawah ini dan jalankan. Jika pemasangan kabel benar, seharusnya tidak akan ada masalah!
#include <LiquidCrystal.h>
#define ARR_SIZE 16 // Ganti dengan jumlah frame yang diinginkan
#define LIGHTS 8 // Mengontrol input tombol
const int btn1 = 7, btn2 = 8, btn3 = 9, btn4 = 10;
int bs1 = 0, bs2 = 0, bs3 = 0, bs4 = 0;
const int latchPin = 11; // Terhubung ke ST_CP 74HC595
const int clockPin = 13; // Terhubung ke SH_CP 74HC595
const int dataPin = 12; // Terhubung ke DS 74HC595
byte data;
bool ArrOne[ARR_SIZE][LIGHTS] = {false};
byte lightArrOne[ARR_SIZE] = {0xFF};
int animSpeed = 50; // ms antar frame
int loopCount = 5; // jumlah perulangan
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) {
bs1 = LOW;
delay(150);
Play();
} else if (bs2 == HIGH) {
bs2 = LOW;
delay(150);
Create(ArrOne);
} else if (bs3 == HIGH) {
bs3 = LOW;
delay(150);
SetSpeed();
} else if (bs4 == HIGH) {
bs4 = LOW;
delay(150);
SetLoop();
}
PrintMenu();
delay(150);
}
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);
}
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);
}
}
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);
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);
}
}
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 = result | (1 << i);
}
return result;
}
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);
}
}
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 (animSpeed > 1) loopCount--;
}
if (bs4 == HIGH) {
delay(150);
leaving = true;
}
delay(30);
}
}
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);
}
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);
}
Skematik
Ikuti garis-garis dengan hati-hati. Karena keterbatasan panjang resistor dalam program dan untuk keperluan keterbacaan, saya tidak dapat merapikannya sama seperti dalam pembuatan sebenarnya. Setelah membangun, saya menantang Anda untuk menemukan cara membersihkannya.