const int carRedPin = 2;
const int carYellowPin = 3;
const int carGreenPin = 4;
const int pedRedPin = 5;
const int pedGreenPin = 6;
const int buzzerPin = 7;
const int dataPin = 9;
const int clockPin = 8;
const int latchPin = 10;
const byte digitPatterns[13] = {
B00111111, // 0
B00000110, // 1
B01011011, // 2
B01001111, // 3
B01100110, // 4
B01101101, // 5
B01111101, // 6
B00000111, // 7
B01111111, // 8
B01101111, // 9
B00000000, // A
};
const unsigned long PED_SOLID_GREEN_TIME = 9000;
const unsigned long PED_BLINK_GREEN_TIME = 3000;
const unsigned long CAR_GREEN_TIME = 9000;
unsigned long phaseStartTime = 0;
unsigned long lastSecondUpdate = 0;
int currentCountdown = 12;
int currentPhase = 1;
bool isBlinkingPhase = false;
void setup() {
pinMode(carRedPin, OUTPUT);
pinMode(carYellowPin, OUTPUT);
pinMode(carGreenPin, OUTPUT);
pinMode(pedRedPin, OUTPUT);
pinMode(pedGreenPin, OUTPUT);
pinMode(buzzerPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(latchPin, OUTPUT);
updateLights();
displayNumber(currentCountdown);
phaseStartTime = millis();
}
void loop() {
unsigned long currentMillis = millis();
unsigned long phaseElapsed = currentMillis - phaseStartTime;
// Обновление счетчика каждую секунду
if (currentMillis - lastSecondUpdate >= 1000) {
lastSecondUpdate = currentMillis;
if (currentCountdown > 0) {
currentCountdown--;
}
}
// Управление фазами
switch(currentPhase) {
case 1: // Пешеходам зеленый (9 сек постоянно + 3 сек мигает)
if (phaseElapsed >= PED_SOLID_GREEN_TIME && !isBlinkingPhase) {
isBlinkingPhase = true;
}
if (phaseElapsed >= (PED_SOLID_GREEN_TIME + PED_BLINK_GREEN_TIME)) {
nextPhase();
}
break;
case 2: // Машинам зеленый (9 сек)
if (phaseElapsed >= CAR_GREEN_TIME) {
nextPhase();
}
break;
}
// Мигание зеленого для пешеходов в последние 3 секунды
if (isBlinkingPhase && currentPhase == 1) {
blinkPedGreen(currentMillis);
}
// Управление звуком
soundBuzzer(currentCountdown, currentMillis % 1000);
// Отображение таймера только для пешеходов
if (currentPhase == 1) {
displayNumber(currentCountdown);
} else {
clearDisplay();
}
}
void nextPhase() {
currentPhase = (currentPhase % 2) + 1; // Цикл между 1 и 2 фазами
phaseStartTime = millis();
isBlinkingPhase = false;
if (currentPhase == 1) {
currentCountdown = (PED_SOLID_GREEN_TIME + PED_BLINK_GREEN_TIME) / 1000; // 12 секунд
} else {
currentCountdown = CAR_GREEN_TIME / 1000; // 9 секунд
}
updateLights();
}
void updateLights() {
// Выключить все светодиоды
digitalWrite(carRedPin, LOW);
digitalWrite(carYellowPin, LOW);
digitalWrite(carGreenPin, LOW);
digitalWrite(pedRedPin, LOW);
digitalWrite(pedGreenPin, LOW);
switch(currentPhase) {
case 1: // Пешеходам зеленый/мигающий, машинам красный
digitalWrite(carRedPin, HIGH);
if (!isBlinkingPhase) {
digitalWrite(pedGreenPin, HIGH);
}
break;
case 2: // Пешеходам красный, машинам зеленый
digitalWrite(carGreenPin, HIGH);
digitalWrite(pedRedPin, HIGH);
break;
}
}
void blinkPedGreen(unsigned long currentMillis) {
static unsigned long lastBlinkTime = 0;
static bool ledState = HIGH;
if (currentMillis - lastBlinkTime >= 500) {
lastBlinkTime = currentMillis;
ledState = !ledState;
digitalWrite(pedGreenPin, ledState);
}
}
void displayNumber(int number) {
if (number < 0 || number > 99) {
clearDisplay();
return;
}
int tens = number / 10;
int ones = number % 10;
byte tensPattern = (tens > 0) ? digitPatterns[tens] : B00000000;
byte onesPattern = digitPatterns[ones];
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, onesPattern);
shiftOut(dataPin, clockPin, MSBFIRST, tensPattern);
digitalWrite(latchPin, HIGH);
}
void clearDisplay() {
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, B00000000);
shiftOut(dataPin, clockPin, MSBFIRST, B00000000);
digitalWrite(latchPin, HIGH);
}
void soundBuzzer(int countdown, unsigned long cycleTime) {
if (currentPhase == 1) { // Только для фазы пешеходного перехода
if (countdown <= 3) {
// Быстрое пищание в последние 3 секунды (3 сигнала в секунду)
int frequency = 1500 + (3 - countdown) * 300; // Частота растет: 1500→2400 Гц
if (cycleTime % 333 < 100) { // Каждые 333 мс (3 раза в секунду)
tone(buzzerPin, frequency, 80); // Короткий сигнал (80 мс)
} else {
noTone(buzzerPin);
}
}
else {
// Плавное увеличение частоты с каждой секундой
int frequency = 800 + (12 - countdown) * 100; // Частота растет: 800→1900 Гц
if (cycleTime < 150) { // Сигнал в начале каждой секунды (150 мс)
tone(buzzerPin, frequency, 120);
} else {
noTone(buzzerPin);
}
}
} else {
noTone(buzzerPin); // Выключаем звук в других фазах
}
}