const int LED_PIN = D13;
const int BUTTON_PIN = PC13;
const unsigned long INFINITE_DURATION = 0xFFFFFFFFUL;
const unsigned long DURATIONS[4] = {
2000UL,
1000UL,
10000UL,
INFINITE_DURATION
};
const unsigned int FREQUENCIES[4] = {6, 12, 2, 0};
int currentStage = 0;
int dir = 1;
bool finished = false;
unsigned long stageStart = 0;
unsigned long lastToggle = 0;
bool ledState = LOW;
// UART
char serialBuffer[8];
int serialIndex = 0;
unsigned int customFreqHz = 0;
// debounce
const unsigned long DEBOUNCE_MS = 40;
int lastRaw = HIGH;
int stableState = HIGH;
unsigned long lastBounce = 0;
const int PRESSED_LEVEL = LOW;
// =====================
void setup() {
pinMode(LED_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP);
digitalWrite(LED_PIN, LOW);
Serial.begin(115200);
delay(50);
lastRaw = digitalRead(BUTTON_PIN);
stableState = lastRaw;
lastBounce = millis();
stageStart = millis();
lastToggle = millis();
Serial.println("=== СТАРТ ===");
Serial.println("Введіть нову частоту блимання (1-1000 Гц) і натисніть Enter");
Serial.println("Щоб повернутися до автоматичного режиму, введіть 0");
}
// =====================
bool isFinalForDir(int stageIndex, int d) {
return (d == 1 && stageIndex == 3) || (d == -1 && stageIndex == 0);
}
// =====================
void loop() {
unsigned long now = millis();
// ==== debounce кнопки ====
int raw = digitalRead(BUTTON_PIN);
if (raw != lastRaw)
lastBounce = now;
lastRaw = raw;
if ((now - lastBounce) > DEBOUNCE_MS) {
if (raw != stableState) {
stableState = raw;
if (stableState == PRESSED_LEVEL) {
dir = -dir;
currentStage = (dir == 1) ? 0 : 3;
stageStart = now;
lastToggle = now;
ledState = LOW;
digitalWrite(LED_PIN, ledState);
finished = false;
Serial.print("Напрям змінено на: ");
Serial.println(dir == 1 ? "ПРЯМИЙ" : "РЕВЕРС");
}
}
}
// ==== UART ====
while (Serial.available()) {
char c = Serial.read();
if (c == '\n' || c == '\r') {
if (serialIndex > 0) {
serialBuffer[serialIndex] = 0;
int f = atoi(serialBuffer);
serialIndex = 0;
if (f == 0) {
customFreqHz = 0;
Serial.println("Повернення до автоматичного режиму перемикання stage");
} else if (f >= 1 && f <= 1000) {
customFreqHz = f;
Serial.print("Встановлено нову частоту блимання: ");
Serial.print(customFreqHz);
Serial.println(" Гц");
} else {
Serial.println("Невірне значення! Діапазон 1-1000 Гц або 0 для скидання");
}
}
} else if (serialIndex < sizeof(serialBuffer) - 1) {
serialBuffer[serialIndex++] = c;
}
}
// ==== фінальний стан ====
if (finished) {
digitalWrite(LED_PIN, HIGH);
delay(2);
return;
}
// ==== перехід між етапами ====
unsigned long rawDuration = DURATIONS[currentStage];
unsigned long durationForCheck =
(rawDuration == INFINITE_DURATION && !isFinalForDir(currentStage, dir))
? 1
: rawDuration;
if (durationForCheck != INFINITE_DURATION &&
now - stageStart >= durationForCheck) {
int next = currentStage + dir;
if (next < 0 || next > 3) {
finished = true;
digitalWrite(LED_PIN, HIGH);
Serial.println("Послідовність завершена (світлодіод постійно світиться)");
} else {
currentStage = next;
stageStart = now;
lastToggle = now;
ledState = LOW;
digitalWrite(LED_PIN, ledState);
Serial.print("Перехід до етапу: ");
Serial.println(currentStage);
}
}
// ==== частота ====
unsigned int freq;
if (customFreqHz > 0)
freq = customFreqHz;
else if (dir == 1)
freq = FREQUENCIES[currentStage];
else {
switch (currentStage) {
case 3: freq = 0; break;
case 2: freq = 2; break;
case 1: freq = 12; break;
case 0: freq = 6; break;
}
}
// ==== повідомлення ====
static unsigned int lastFreq = 0;
if (freq != lastFreq) {
Serial.print("Поточна частота блимання: ");
Serial.print(freq);
Serial.println(" Гц");
lastFreq = freq;
}
// ==== блимання ====
if (freq > 0) {
unsigned long half = 500 / freq;
if (now - lastToggle >= half) {
ledState = !ledState;
digitalWrite(LED_PIN, ledState);
lastToggle = now;
}
} else {
digitalWrite(LED_PIN, HIGH);
}
delay(2);
}