#include <Arduino.h>
// 74HC595
const byte DATA_PIN = 8;
const byte CLOCK_PIN = 7;
const byte LATCH_PIN = 4;
// Кнопки
const byte BTN_INC = A1;
const byte BTN_MODE = A2;
const byte BTN_START = A3;
// АКТИВНЫЙ пьезо!
const byte BUZZER_PIN = 3;
// Сегменты (common anode)
const byte SEG_CA[10] = {
0xC0,0xF9,0xA4,0xB0,0x99,
0x92,0x82,0xF8,0x80,0x90
};
const byte DIGIT_SEL[4] = {0x01,0x02,0x04,0x08};
struct Button {
bool last = HIGH;
bool state = HIGH;
unsigned long t = 0;
};
Button b1,b2,b3;
const unsigned long DEB = 40;
const unsigned long TICK = 1000;
uint8_t minutes = 14;
uint8_t seconds = 59;
uint16_t remain = 0;
bool running = false;
bool done = false;
bool editMin = true;
unsigned long lastTick = 0;
unsigned long lastBlink = 0;
bool blink = true;
// --- ПИЩАЛКА (активная) ---
void beepShort() {
digitalWrite(BUZZER_PIN, HIGH);
delay(60);
digitalWrite(BUZZER_PIN, LOW);
}
// --- кнопка ---
bool press(Button &b, byte pin){
bool r = digitalRead(pin);
if(r != b.last){
b.t = millis();
b.last = r;
}
if(millis() - b.t > DEB){
if(r != b.state){
b.state = r;
if(r == LOW) return true;
}
}
return false;
}
// --- 595 ---
void send595(byte a, byte b){
digitalWrite(LATCH_PIN, LOW);
shiftOut(DATA_PIN,CLOCK_PIN,MSBFIRST,a);
shiftOut(DATA_PIN,CLOCK_PIN,MSBFIRST,b);
digitalWrite(LATCH_PIN, HIGH);
}
// --- отображение ---
void show(uint16_t val, bool blank=false){
byte d[4];
if(!blank){
d[3]=val%10; val/=10;
d[2]=val%10; val/=10;
d[1]=val%10; val/=10;
d[0]=val%10;
}
for(int i=0;i<4;i++){
if(blank){
send595(0xFF,0x00);
} else {
send595(SEG_CA[d[i]], DIGIT_SEL[i]);
}
delayMicroseconds(800);
}
}
uint16_t toSec(){
return minutes*60 + seconds;
}
// --- setup ---
void setup(){
pinMode(DATA_PIN,OUTPUT);
pinMode(CLOCK_PIN,OUTPUT);
pinMode(LATCH_PIN,OUTPUT);
pinMode(BTN_INC,INPUT_PULLUP);
pinMode(BTN_MODE,INPUT_PULLUP);
pinMode(BTN_START,INPUT_PULLUP);
pinMode(BUZZER_PIN,OUTPUT);
digitalWrite(BUZZER_PIN, LOW);
}
// --- loop ---
void loop(){
// --- КНОПКИ ---
if(press(b1,BTN_INC) && !running){
done = false;
if(editMin){
minutes = (minutes+1)%100;
} else {
seconds = (seconds+1)%60;
}
}
if(press(b2,BTN_MODE) && !running){
editMin = !editMin;
}
if(press(b3,BTN_START) && !running){
remain = toSec();
if(remain > 0){
running = true;
done = false;
lastTick = millis();
}
}
// --- ТАЙМЕР ---
if(running){
if(millis() - lastTick >= TICK){
lastTick += TICK;
// последние 10 секунд
if(remain <= 10 && remain > 0){
beepShort();
}
if(remain > 0) remain--;
if(remain == 0){
running = false;
done = true;
}
}
}
// --- КОНЕЦ ---
if(done){
if(millis() - lastBlink > 300){
lastBlink = millis();
blink = !blink;
// частое пищание
beepShort();
}
show(0, !blink);
return;
}
// --- ОТОБРАЖЕНИЕ ---
if(running){
show(remain);
} else {
show(toSec());
}
}