Předělání tlačítka aby používalo interupt
This commit is contained in:
+52
-94
@@ -4,12 +4,12 @@
|
||||
#include <Servo.h>
|
||||
|
||||
// piny
|
||||
constexpr byte ENCODER_CLK_PIN = 11; // pwm pin, ale nepoužívá se
|
||||
constexpr byte ENCODER_CLK_PIN = 11;
|
||||
constexpr byte ENCODER_DT_PIN = 12;
|
||||
constexpr byte BUTTON_PIN = 13;
|
||||
constexpr byte RGB_RED_PIN = 3; // pwm
|
||||
constexpr byte RGB_GREEN_PIN = 5; // pwm
|
||||
constexpr byte RGB_BLUE_PIN = 6; // pwm
|
||||
constexpr byte BUTTON_PIN = 2; // ZMĚNA: přesunuto na pin 2 (INT0) kvůli přerušení
|
||||
constexpr byte RGB_RED_PIN = 3;
|
||||
constexpr byte RGB_GREEN_PIN = 5;
|
||||
constexpr byte RGB_BLUE_PIN = 6;
|
||||
constexpr byte SERVO_PIN = 9;
|
||||
constexpr byte BUZZER_PIN = 8;
|
||||
|
||||
@@ -21,46 +21,48 @@ Servo servo;
|
||||
// LCD
|
||||
LiquidCrystal_I2C lcd(0x27, 16, 2);
|
||||
|
||||
// proměnné
|
||||
// příklad je zadávané heslo, stavy, apod.
|
||||
int password = 0; // 0-9999
|
||||
int password = 0;
|
||||
int passwordValue = 0;
|
||||
String savedPassword = "";
|
||||
|
||||
// stav zámku
|
||||
bool isOpen = false;
|
||||
|
||||
// enkodér
|
||||
int lastCLK = HIGH;
|
||||
|
||||
// blokace po špatných pokusech
|
||||
constexpr byte MAX_WRONG_ATTEMPTS = 3;
|
||||
constexpr unsigned long LOCKOUT_DURATION_MS = 30000UL;
|
||||
byte wrongAttempts = 0;
|
||||
bool lockedOut = false;
|
||||
unsigned long lockoutStart = 0;
|
||||
|
||||
// maska – po kolika ms nečinnosti se heslo maskuje
|
||||
constexpr unsigned long MASK_DELAY_MS = 2000;
|
||||
unsigned long lastEncoderMove = 0;
|
||||
bool masked = false;
|
||||
|
||||
// přeformátování kódu na 4 cifry
|
||||
// přerušení tlačítka
|
||||
volatile bool buttonPressed = false;
|
||||
constexpr unsigned long DEBOUNCE_MS = 50;
|
||||
unsigned long lastButtonTime = 0;
|
||||
|
||||
void onButtonPress() {
|
||||
if (const unsigned long now = millis(); now - lastButtonTime >= DEBOUNCE_MS) {
|
||||
lastButtonTime = now;
|
||||
buttonPressed = true;
|
||||
}
|
||||
}
|
||||
|
||||
String formatCode(const int value) {
|
||||
auto s = String(value);
|
||||
while (s.length() < 4) s = "0" + s;
|
||||
return s;
|
||||
}
|
||||
|
||||
// chování zámku
|
||||
void OpenLock() { servo.write(OPEN_POS); }
|
||||
void OpenLock() { servo.write(OPEN_POS); }
|
||||
void CloseLock() { servo.write(CLOSED_POS); }
|
||||
|
||||
// chování bzučáku
|
||||
void OpenSound() {
|
||||
const int melody[] = { 262, 330, 392, 523 }; // C4, E4, G4, C5
|
||||
const int melody[] = { 262, 330, 392, 523 };
|
||||
const int durations[] = { 150, 150, 150, 300 };
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
tone(BUZZER_PIN, melody[i], durations[i]);
|
||||
delay(durations[i] + 30);
|
||||
@@ -75,100 +77,73 @@ void CloseSound() {
|
||||
}
|
||||
|
||||
void ConfirmSound() {
|
||||
tone(BUZZER_PIN, 440, 100);
|
||||
delay(130);
|
||||
tone(BUZZER_PIN, 880, 200);
|
||||
delay(230);
|
||||
tone(BUZZER_PIN, 440, 100); delay(130);
|
||||
tone(BUZZER_PIN, 880, 200); delay(230);
|
||||
noTone(BUZZER_PIN);
|
||||
}
|
||||
|
||||
// chování RGB LED
|
||||
void OpenLED() {
|
||||
analogWrite(RGB_GREEN_PIN, 120);
|
||||
analogWrite(RGB_BLUE_PIN, 0);
|
||||
analogWrite(RGB_RED_PIN, 0);
|
||||
analogWrite(RGB_BLUE_PIN, 0);
|
||||
analogWrite(RGB_RED_PIN, 0);
|
||||
}
|
||||
|
||||
void CloseLED() {
|
||||
analogWrite(RGB_GREEN_PIN, 0);
|
||||
analogWrite(RGB_BLUE_PIN, 0);
|
||||
analogWrite(RGB_RED_PIN, 120);
|
||||
analogWrite(RGB_BLUE_PIN, 0);
|
||||
analogWrite(RGB_RED_PIN, 120);
|
||||
}
|
||||
|
||||
// když není uložené heslo, ukazuje se modrá
|
||||
void NeutralLED() {
|
||||
analogWrite(RGB_GREEN_PIN, 0);
|
||||
analogWrite(RGB_BLUE_PIN, 120);
|
||||
analogWrite(RGB_RED_PIN, 0);
|
||||
analogWrite(RGB_BLUE_PIN, 120);
|
||||
analogWrite(RGB_RED_PIN, 0);
|
||||
}
|
||||
|
||||
// blikání červené během blokace
|
||||
void BlockedLED() {
|
||||
// bliká každých 500 ms
|
||||
const bool blink = millis() / 500 % 2 == 0;
|
||||
analogWrite(RGB_RED_PIN, blink ? 120 : 0);
|
||||
analogWrite(RGB_GREEN_PIN, 0);
|
||||
analogWrite(RGB_BLUE_PIN, 0);
|
||||
}
|
||||
|
||||
void ButtonPressed() {
|
||||
if (savedPassword != "")
|
||||
{
|
||||
if (formatCode(password) == savedPassword) {
|
||||
OpenLock();
|
||||
OpenSound();
|
||||
OpenLED();
|
||||
password = 0;
|
||||
}
|
||||
else {
|
||||
CloseLock();
|
||||
CloseSound();
|
||||
CloseLED();
|
||||
password = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// zobrazení zadávací obrazovky
|
||||
void showEntryScreen(const bool showValue) {
|
||||
lcd.setCursor(0, 0);
|
||||
lcd.printstr("Zadejte heslo: ");
|
||||
lcd.setCursor(0, 1);
|
||||
if (showValue) {
|
||||
String code = formatCode(password);
|
||||
const String display = code[0] + String(" ") + code[1] + String(" ") + code[2] + String(" ") + code[3] + String(" ");
|
||||
String display = code[0] + String(" ") + code[1] + String(" ") + code[2] + String(" ") + code[3] + String(" ");
|
||||
lcd.printstr(display.c_str());
|
||||
} else {
|
||||
lcd.printstr("* * * * ");
|
||||
}
|
||||
}
|
||||
|
||||
// zobrazení setup obrazovky
|
||||
void showSetupScreen(const bool showValue) {
|
||||
lcd.setCursor(0, 0);
|
||||
lcd.printstr("Nastavte heslo: ");
|
||||
lcd.setCursor(0, 1);
|
||||
if (showValue) {
|
||||
String code = formatCode(passwordValue);
|
||||
const String display = code[0] + String(" ") + code[1] + String(" ") + code[2] + String(" ") + code[3] + String(" ");
|
||||
String display = code[0] + String(" ") + code[1] + String(" ") + code[2] + String(" ") + code[3] + String(" ");
|
||||
lcd.printstr(display.c_str());
|
||||
} else {
|
||||
lcd.printstr("* * * * ");
|
||||
}
|
||||
}
|
||||
|
||||
// setup fáze – blokující, dokud není heslo uloženo
|
||||
void runPasswordSetup() {
|
||||
NeutralLED();
|
||||
passwordValue = 0;
|
||||
masked = false;
|
||||
lastEncoderMove = millis();
|
||||
lastCLK = digitalRead(ENCODER_CLK_PIN);
|
||||
buttonPressed = false; // vyprázdnit případný příznak z doby před setupem
|
||||
|
||||
showSetupScreen(true);
|
||||
|
||||
while (savedPassword == "") {
|
||||
// čtení enkodéru
|
||||
const int currentCLK = digitalRead(ENCODER_CLK_PIN);
|
||||
if (currentCLK != lastCLK && currentCLK == LOW) {
|
||||
if (const int dt = digitalRead(ENCODER_DT_PIN); dt != currentCLK) {
|
||||
@@ -182,14 +157,15 @@ void runPasswordSetup() {
|
||||
}
|
||||
lastCLK = currentCLK;
|
||||
|
||||
// maskování po nečinnosti
|
||||
if (!masked && millis() - lastEncoderMove >= MASK_DELAY_MS) {
|
||||
masked = true;
|
||||
showSetupScreen(false);
|
||||
}
|
||||
|
||||
// potvrzení tlačítkem
|
||||
if (digitalRead(BUTTON_PIN) == HIGH) {
|
||||
// přerušení – konzumace příznaku místo přímého čtení pinu
|
||||
if (buttonPressed) {
|
||||
buttonPressed = false;
|
||||
|
||||
savedPassword = formatCode(passwordValue);
|
||||
ConfirmSound();
|
||||
|
||||
@@ -199,15 +175,10 @@ void runPasswordSetup() {
|
||||
lcd.printstr("* * * * ");
|
||||
delay(1500);
|
||||
|
||||
// přechod do normálního režimu
|
||||
lcd.setCursor(0, 0);
|
||||
lcd.printstr("Zadejte heslo: ");
|
||||
lcd.setCursor(0, 1);
|
||||
lcd.printstr(" ");
|
||||
|
||||
// debounce
|
||||
while (digitalRead(BUTTON_PIN) == HIGH) {}
|
||||
delay(50);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -224,41 +195,40 @@ void setup() {
|
||||
lcd.printstr("Program startuje");
|
||||
lcd.setCursor(0, 1);
|
||||
lcd.printstr("NastavujeSeMotor");
|
||||
|
||||
delay(100);
|
||||
|
||||
Serial.println("Nastavování motoru.");
|
||||
servo.attach(SERVO_PIN);
|
||||
servo.write(CLOSED_POS); // ve výchozím stavu je zamčeno
|
||||
servo.write(CLOSED_POS);
|
||||
Serial.println("Motor nastaven.");
|
||||
lcd.setCursor(0, 1);
|
||||
lcd.printstr("Motor nastaven. ");
|
||||
|
||||
delay(100);
|
||||
|
||||
lcd.setCursor(0, 1);
|
||||
lcd.printstr("NastavujiSePiny.");
|
||||
Serial.println("Nastavování pinů");
|
||||
|
||||
// Credit: formátování vymyšleno přes Claude Sonnet 4.6
|
||||
pinMode(BUTTON_PIN, INPUT_PULLDOWN); Serial.println("Piny: 1/8");
|
||||
pinMode(RGB_RED_PIN, OUTPUT); Serial.println("Piny: 2/8");
|
||||
pinMode(RGB_GREEN_PIN, OUTPUT); Serial.println("Piny: 3/8");
|
||||
pinMode(RGB_BLUE_PIN, OUTPUT); Serial.println("Piny: 4/8");
|
||||
pinMode(BUTTON_PIN, INPUT_PULLDOWN); Serial.println("Piny: 1/8");
|
||||
pinMode(RGB_RED_PIN, OUTPUT); Serial.println("Piny: 2/8");
|
||||
pinMode(RGB_GREEN_PIN, OUTPUT); Serial.println("Piny: 3/8");
|
||||
pinMode(RGB_BLUE_PIN, OUTPUT); Serial.println("Piny: 4/8");
|
||||
pinMode(ENCODER_CLK_PIN, INPUT); Serial.println("Piny: 5/8");
|
||||
pinMode(ENCODER_DT_PIN, INPUT); Serial.println("Piny: 6/8");
|
||||
pinMode(SERVO_PIN, OUTPUT); Serial.println("Piny: 7/8");
|
||||
pinMode(BUZZER_PIN, OUTPUT); Serial.println("Piny: 8/8");
|
||||
pinMode(ENCODER_DT_PIN, INPUT); Serial.println("Piny: 6/8");
|
||||
pinMode(SERVO_PIN, OUTPUT); Serial.println("Piny: 7/8");
|
||||
pinMode(BUZZER_PIN, OUTPUT); Serial.println("Piny: 8/8");
|
||||
Serial.println("Piny nastaveny.");
|
||||
lcd.setCursor(0, 1);
|
||||
lcd.printstr("Piny nastaveny. ");
|
||||
delay(1000);
|
||||
|
||||
// registrace přerušení – RISING: stisk při HIGH (INPUT_PULLDOWN)
|
||||
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), onButtonPress, RISING);
|
||||
|
||||
runPasswordSetup();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Serial Monitor – příkaz "unblock" zruší blokaci
|
||||
if (Serial.available()) {
|
||||
String cmd = Serial.readStringUntil('\n');
|
||||
cmd.trim();
|
||||
@@ -280,10 +250,8 @@ void loop() {
|
||||
}
|
||||
}
|
||||
|
||||
// blokace – čeká odpočítávání, neblokuje loop
|
||||
if (lockedOut) {
|
||||
if (const unsigned long elapsed = millis() - lockoutStart; elapsed >= LOCKOUT_DURATION_MS) {
|
||||
// konec blokace
|
||||
lockedOut = false;
|
||||
wrongAttempts = 0;
|
||||
Serial.println("Blokace skoncila.");
|
||||
@@ -293,7 +261,6 @@ void loop() {
|
||||
lastEncoderMove = millis();
|
||||
showEntryScreen(true);
|
||||
} else {
|
||||
// odpočítávání na LCD – aktualizuje jen každou sekundu
|
||||
static unsigned long lastCountdownUpdate = 0;
|
||||
if (millis() - lastCountdownUpdate >= 1000) {
|
||||
lastCountdownUpdate = millis();
|
||||
@@ -307,11 +274,10 @@ void loop() {
|
||||
}
|
||||
BlockedLED();
|
||||
}
|
||||
return; // zbytek loop se přeskočí
|
||||
buttonPressed = false; // zahazovat stisky během blokace
|
||||
return;
|
||||
}
|
||||
|
||||
// čtení enkodéru – jen pokud je zamčeno
|
||||
// (při odemčeném stavu enkodér nemá smysl)
|
||||
if (!isOpen) {
|
||||
const int currentCLK = digitalRead(ENCODER_CLK_PIN);
|
||||
if (currentCLK != lastCLK && currentCLK == LOW) {
|
||||
@@ -326,24 +292,20 @@ void loop() {
|
||||
}
|
||||
lastCLK = currentCLK;
|
||||
|
||||
// maskování po nečinnosti
|
||||
if (!masked && millis() - lastEncoderMove >= MASK_DELAY_MS) {
|
||||
masked = true;
|
||||
showEntryScreen(false);
|
||||
}
|
||||
}
|
||||
|
||||
// tlačítko
|
||||
if (digitalRead(BUTTON_PIN) == HIGH) {
|
||||
// debounce
|
||||
while (digitalRead(BUTTON_PIN) == HIGH) {}
|
||||
delay(50);
|
||||
// konzumace příznaku z přerušení
|
||||
if (buttonPressed) {
|
||||
buttonPressed = false;
|
||||
|
||||
if (!isOpen) {
|
||||
// pokus o odemčení
|
||||
if (formatCode(password) == savedPassword) {
|
||||
isOpen = true;
|
||||
wrongAttempts = 0; // reset po úspěšném odemčení
|
||||
wrongAttempts = 0;
|
||||
OpenLock();
|
||||
OpenLED();
|
||||
OpenSound();
|
||||
@@ -353,7 +315,6 @@ void loop() {
|
||||
lcd.setCursor(0, 1);
|
||||
lcd.printstr("Stiskni pro zamk");
|
||||
} else {
|
||||
// špatné heslo
|
||||
wrongAttempts++;
|
||||
Serial.print("Spatny pokus: ");
|
||||
Serial.print(wrongAttempts);
|
||||
@@ -363,7 +324,6 @@ void loop() {
|
||||
CloseSound();
|
||||
|
||||
if (wrongAttempts >= MAX_WRONG_ATTEMPTS) {
|
||||
// spustit blokaci
|
||||
lockedOut = true;
|
||||
lockoutStart = millis();
|
||||
Serial.println("Zamek zablokovan na 30 sekund. Pouzij 'unblock' pro zruseni.");
|
||||
@@ -382,14 +342,12 @@ void loop() {
|
||||
lcd.printstr(" ");
|
||||
delay(1500);
|
||||
|
||||
// návrat na zadávací obrazovku, hodnota zachována
|
||||
masked = false;
|
||||
lastEncoderMove = millis();
|
||||
showEntryScreen(true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// zamčení
|
||||
isOpen = false;
|
||||
CloseLock();
|
||||
CloseLED();
|
||||
|
||||
Reference in New Issue
Block a user