// Sistem Lampu Lalu Lintas Simpang Empat
// Dikembangkan oleh: Kelas XI-10 | Kelompok 5
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Konfigurasi LCD
LiquidCrystal_I2C lcd(0x27, A4, A5); // Alamat I2C 0x27, menggunakan pin A4 dan A5
// Definisi pin untuk setiap arah lalu lintas
const int NORTH[3] = {2, 3, 4}; // Urutan: Merah, Kuning, Hijau
const int EAST[3] = {5, 6, 7};
const int SOUTH[3] = {8, 9, 10};
const int WEST[3] = {11, 12, 13};
const int BUZZER = A0;
const int VISUALIZER = A1;
// Daftar frekuensi nada (dalam Hz) untuk efek suara
const int notes[] = {262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494, 523};
// Array nama arah dan warna untuk tampilan LCD
const char* directions[] = {"UTARA", "TIMUR", "SELATAN", "BARAT"};
const char* colors[] = {"MERAH", "KUNING", "HIJAU"};
void setup() {
// Inisialisasi pin-pin
for(int i = 2; i <= 13; i++) {
pinMode(i, OUTPUT);
}
pinMode(BUZZER, OUTPUT);
pinMode(VISUALIZER, OUTPUT);
// Inisialisasi LCD
lcd.init();
lcd.backlight();
// Memulai sekuens startup yang menarik
startupSequence();
}
void loop() {
// Siklus lampu lalu lintas untuk setiap arah
cycleTraffic(NORTH, 0, 0);
cycleTraffic(EAST, 2, 1);
cycleTraffic(SOUTH, 4, 2);
cycleTraffic(WEST, 6, 3);
}
void startupSequence() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Lampu Lalu Lintas");
lcd.setCursor(0, 1);
lcd.print("Sistem Aktif!");
// Pola 1: Efek strobo
for(int i = 0; i < 10; i++) {
allOn();
playNote(notes[random(13)], 50);
analogWrite(VISUALIZER, 255);
delay(50);
allOff();
analogWrite(VISUALIZER, 0);
delay(50);
}
// Pola 2: Efek gelombang
for(int k = 0; k < 3; k++) {
for(int i = 2; i <= 13; i++) {
for(int j = 2; j <= 13; j++) {
if(abs(i-j) <= 2) {
digitalWrite(j, HIGH);
playNote(notes[map(j, 2, 13, 0, 12)], 20);
} else {
digitalWrite(j, LOW);
}
}
analogWrite(VISUALIZER, map(i, 2, 13, 0, 255));
delay(50);
}
}
// Pola 3: Kejar-kejaran warna
for(int c = 0; c < 3; c++) {
for(int d = 0; d < 4; d++) {
int pin = 0;
switch(d) {
case 0: pin = NORTH[c]; break;
case 1: pin = EAST[c]; break;
case 2: pin = SOUTH[c]; break;
case 3: pin = WEST[c]; break;
}
digitalWrite(pin, HIGH);
playNote(notes[c*4 + d], 100);
analogWrite(VISUALIZER, map(d, 0, 3, 50, 255));
delay(100);
}
delay(200);
allOff();
}
// Pola 4: Lampu DJ acak
lcd.clear();
lcd.print("MODE DJ AKTIF!");
for(int i = 0; i < 20; i++) {
int randomPin = random(2, 14);
digitalWrite(randomPin, HIGH);
int randomNote = notes[random(13)];
playNote(randomNote, 50);
analogWrite(VISUALIZER, random(50, 255));
delay(50);
digitalWrite(randomPin, LOW);
}
// Sentuhan akhir startup
lcd.clear();
lcd.print("SISTEM SIAP!");
for(int i = 0; i < 3; i++) {
allOn();
playSiren(200, 1000, 100);
allOff();
delay(100);
}
victorySound();
allRed();
}
void cycleTraffic(const int* direction, int baseNote, int dirIndex) {
updateLCD(dirIndex, "KUNING");
playFancyTransition(baseNote, true);
fancyYellowTransition(direction);
updateLCD(dirIndex, "HIJAU");
digitalWrite(direction[0], LOW);
digitalWrite(direction[2], HIGH);
// Efek kedip ala DJ selama lampu hijau
for(int i = 0; i < 10; i++) {
analogWrite(VISUALIZER, map(sin(i * 0.6) * 128 + 128, 0, 255, 50, 255));
if(i % 2 == 0) {
playNote(notes[random(13)], 50);
}
delay(500);
}
updateLCD(dirIndex, "KUNING");
playFancyTransition(baseNote, false);
digitalWrite(direction[2], LOW);
fancyYellowTransition(direction);
updateLCD(dirIndex, "MERAH");
digitalWrite(direction[0], HIGH);
analogWrite(VISUALIZER, 0);
}
void updateLCD(int dirIndex, const char* color) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(directions[dirIndex]);
lcd.print(": ");
lcd.print(color);
// Menampilkan status arah lainnya
lcd.setCursor(0, 1);
int nextDir = (dirIndex + 1) % 4;
lcd.print(directions[nextDir]);
lcd.print(": MERAH");
}
void fancyYellowTransition(const int* direction) {
for(int i = 0; i < 5; i++) {
digitalWrite(direction[1], HIGH);
analogWrite(VISUALIZER, 255);
playNote(notes[random(13)], 100);
delay(150);
digitalWrite(direction[1], LOW);
analogWrite(VISUALIZER, 0);
delay(50);
}
}
void playSiren(int minFreq, int maxFreq, int step) {
for(int freq = minFreq; freq < maxFreq; freq += step) {
tone(BUZZER, freq);
analogWrite(VISUALIZER, map(freq, minFreq, maxFreq, 50, 255));
delay(5);
}
for(int freq = maxFreq; freq > minFreq; freq -= step) {
tone(BUZZER, freq);
analogWrite(VISUALIZER, map(freq, minFreq, maxFreq, 50, 255));
delay(5);
}
noTone(BUZZER);
analogWrite(VISUALIZER, 0);
}
void victorySound() {
int melody[] = {notes[0], notes[4], notes[7], notes[12]};
for(int i = 0; i < 4; i++) {
playNote(melody[i], 150);
analogWrite(VISUALIZER, map(i, 0, 3, 100, 255));
delay(100);
}
}
void playNote(int frequency, int duration) {
tone(BUZZER, frequency);
analogWrite(VISUALIZER, map(frequency, 262, 523, 50, 255));
delay(duration);
noTone(BUZZER);
}
void playFancyTransition(int baseNote, bool rising) {
if(rising) {
for(int i = 0; i < 8; i++) {
playNote(notes[(baseNote + i) % 13], 80);
analogWrite(VISUALIZER, map(i, 0, 7, 50, 255));
delay(50);
}
} else {
for(int i = 7; i >= 0; i--) {
playNote(notes[(baseNote + i) % 13], 80);
analogWrite(VISUALIZER, map(i, 0, 7, 50, 255));
delay(50);
}
}
}
void allOn() {
for(int i = 2; i <= 13; i++) {
digitalWrite(i, HIGH);
}
}
void allOff() {
for(int i = 2; i <= 13; i++) {
digitalWrite(i, LOW);
}
}
void allRed() {
digitalWrite(NORTH[0], HIGH);
digitalWrite(EAST[0], HIGH);
digitalWrite(SOUTH[0], HIGH);
digitalWrite(WEST[0], HIGH);
for(int i = 1; i <= 2; i++) {
digitalWrite(NORTH[i], LOW);
digitalWrite(EAST[i], LOW);
digitalWrite(SOUTH[i], LOW);
digitalWrite(WEST[i], LOW);
}
}