Timer mit Zahlenvergleich

Hallo,

da das mein erster Beitrag ist möchte ich mich kurz vorstellen. Meine Name ist Bastian und ich bin 23 Jahre alt und habe eine Ausbildung zum Elektroniker für Betriebstechnik abgeschlossen.

So nun zu meinem Problem. Ich spiele in meiner Freizeit Paintball und wollte, da mir die Standard Spielmodi mit der Zeit zu langweilig werden ein Timer mit Zahlenvergleich herstellen.

Der Sketch, den ich mir aus dem Internet kopiert habe, scheint aber fehlerhaft zu sein.
Ich habe diesen ein wenig angepasst aber es sind immer noch Fehler enthalten, wo ich nicht weiß woran diese liegen.

Fehler die mir aufgefallen sind:
-Beim eingeben des Codes fürs starten des Timers, wird das Display falsch dargestellt
-Beim runterlaufen des Timers kommt es zwischendurch zu einem Ausfall der Darstellung auf dem LCD, der Timer läuft aber im Hintergrund (nicht sichtbar für den Moment) weiter
-Nachdem der zweite Code zum stoppen des Timers eingegeben wurde, fällt ebenfalls das Display aus und es wird auf nichts mehr reagiert
-Beim erreichen der Null fällt das Display ebenfalls aus und erst nach mehreren Sekunden erscheint der Schriftzug, anschließend reagiert der Controller nicht mehr
Kann mir einer dabei helfen?

Wenn einer ein bisschen Zeit hat könnte er sich die Schaltung aufbauen, dann wird deutlicher was ich mit den Fehlern meine.

Hier der Sketch:

#include <LiquidCrystal.h>;
#include <Keypad.h>;
#include <EEPROM.h>;
#include <EEPROMAnything.h>;

LiquidCrystal lcd(7,8,10,11,12,13);
const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS]={
{‘1’,‘2’,‘3’,‘A’},
{‘4’,‘5’,‘6’,‘B’},
{‘7’,‘8’,‘9’,‘C’},
{’*’,‘0’,’#’,‘D’},
};
byte rowPins[ROWS] = {2,19,18,17}; //connect to the row pinouts of the
byte colPins[COLS] = {16,15,14,5}; //connect to the column pinouts of the keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

//Define all the bomb states
#define READY 0
#define ARMED 1
#define DISARMED 2
#define DETONATED 3

int second=30, minute=5, hour=0; // declare time variables
int bombState=0; //0 = Ready, 1 = Armed, 2 = Disarmed, 3 = detonated
int configMenuFlag = 0; //prevents configMenu from launching after a key is pressed
int speakerPin = 3;//pin that the piezo buzzer is connected to.
int interval=0;
//variables for buzzer chirp function
static unsigned long currentMillis = 0;
long previousTime = 0;//holds previous time in ms
long previousDelay = 0;//holds previous time in ms since buzzer was active

int stop = 0;//function kill flag
long code = 0;//keeps a running tally of the digits entered into the keypad
int count = 0;//number of correct digits

char ArmCode = “7355608”;//code to arm the bomb
char disarmCode = “1761820”;//code to disarm the bomb
char adminCode = “6306608”;//code to change timer

//configuration
//structure for storing the arm code, disarm code, admin code, and time in the eeprom memory
struct config_t
{
long arm;
long disarm;
long admin;
int c_hour;
int c_minute;
int c_second;
} configuration;

void setup()
{

pinMode(speakerPin, OUTPUT);//sets the output pin for the piezo buzzer

// readConfig();//read in the arm, disarm, admin codes and timer

//saveConfig();
//display the default timer when prop boots up

lcd.begin(16, 2);
lcd.setCursor(4, 0);
lcd.write(“U.S ARMY”);
lcd.setCursor(1, 1);
lcd.write(“BOMB RESEARCH”);
delay(3000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(hour, DEC); // the hour, sent to the screen in decimal format
lcd.write(":"); // a colon between the hour and the minute
lcd.print(minute, DEC); // the minute, sent to the screen in decimal format
lcd.write(":"); // a colon between the minute and the second
lcd.print(second, DEC); // the second, sent to the screen in decimal format
delay(1000);
lcd.clear();
}

void loop(){

switch (bombState) {

/***********************************************************
*Ready state prepares bomb, waits for arm code to be input *

************************************************************/
case READY:
while (count < (sizeof(ArmCode) - 1)) {//loop until the full and correct arm code is entered

lcd.setCursor(0,0);
lcd.write(“Enter Arm Code”);

lcd.setCursor(0, 1);
lcd.write(“Code”); //prompt for arm code
lcd.write(": ");

char key;

do{
key = keypad.getKey();
}
while(key == NO_KEY);

code = (code * 10) + (key - 48); //stores the current correct digits for display later

if(key == ‘#’ && configMenuFlag == 0) {//check if user wants to enter menu
//key = ‘\0’;
configMenu();// enter menu
count = 0;
code = 0;
lcd.clear();

}

else if(key == ArmCode[count]) {//if the key matches the code
//
key = ‘\0’;
count++;
configMenuFlag = 1;//once the code is started, the menu cannot be entered
}

else { //if the key does not match the code, reset
count = 0;
code = 0;
configMenuFlag = 1;//once the code is started, the menu cannot be entered
lcd.clear();
}

selectLineOne();
lcd.write(“Code”); //prompt for arm code
lcd.write(": ");
lcd.print(code);//display correct digits that have been entered

}//end while

lcd.clear();
bombState = ARMED;//when the correct code has been entered, move to armed state
count = 0;
code = 0;

break;

/***********************************************************
*Armed *

************************************************************/
case ARMED:

selectLineOne();
lcd.write(“Code”); //prompt for disarm code
lcd.write(": ");

char key;
do{
key = keypad.getKey();
countdown();//displays countdown while simultaneously checking for disarm code

if (second == 0 && minute == 0 && hour == 0) {
code = 0;
lcd.clear();
bombState = DETONATED; //clear LCD and set bomb state to “detonated” when timer runs out
break;
}
//if the correct code is entered, move to disarmed state
else if(count == (sizeof(disarmCode) - 1)){
code = 0;
lcd.clear();
bombState = DISARMED;
}

}//end do
while(key == ‘\0’ && bombState == ARMED);

code = (code * 10) + (key - 48); //store correct digits for display later

//if the key entered matches the disarm code, increase count.
if(key == disarmCode[count]) {
count++;
}

else {
count = 0;
code = 0;
lcd.clear();
}

selectLineOne();
lcd.write(“Code”); //prompt for arm code
lcd.write(": ");
lcd.write(code);//display the current correct digits

break;

/*******************************************************
*Detonated. activate buzzer for 8 beeps, then 1 long.
*Print bomb detonated message to LCD.
********************************************************/
case DETONATED:
lcd.clear();

digitalWrite(speakerPin, HIGH);//turn on buzzer
delay(5000);//wait 5 seconds
digitalWrite(speakerPin, LOW);//turn off buzzer

selectLineOne();
lcd.write(">Bomb Detonated<"); //loop message informing user of bomb detonation.

do{
stop = 1;
}
while(stop == 1);//endless loop stops program

/**************************************************************
*DISARMED. Counter stopped, displays “bomb disarmed”
*
**************************************************************/
case DISARMED:

selectLineOne();
lcd.write(“Bomb Disarmed”); //bomb has been disarmed, inform user.

do{
int stop = 1;
}
while(stop == 1);//endless loop stops program

}//end case statements
}

/***********************************************************

  • Main countdown timer *
  • countdown() *
    ************************************************************/
    void countdown(){

static unsigned long lastTick = 0; // set up a local variable to hold the last time we decremented one second

// (static variables are initialized once and keep their values between function calls)

// decrement one second every 1000 milliseconds
if (second > 0) {
if (millis() - lastTick >= 1000) {
lastTick = millis();
second–;
}
}

// decrement one minute every 60 seconds
if (minute > 0) {
if (second <= 0) {
minute–;
second = 60; // reset seconds to 60

}
}

// decrement one hour every 60 minutes
if (hour > 0) {
if (minute <= 0) {
hour–;
minute = 60; // reset minutes to 60
}//closes if
}//closes if

beepSecondaryBuzzer();

//the code below beeps the siren once every minute.

currentMillis = millis();
if (currentMillis - previousTime > interval)
{
previousTime = currentMillis;
previousDelay = currentMillis;

digitalWrite(speakerPin, HIGH);//turn on buzzer
}

if (currentMillis - previousDelay > 100) {//100ms chirp duration
digitalWrite(speakerPin, LOW);//turn off buzzer
}

selectLineTwo();

lcd.print(“ARMED: “);
lcd.print(hour, DEC); // the hour, sent to the screen in decimal format
lcd.print(”:”); // a colon between the hour and the minute
lcd.print(minute, DEC); // the minute, sent to the screen in decimal format
lcd.print(":"); // a colon between the minute and the second
lcd.print(second, DEC); // the second, sent to the screen in decimal format
lcd.print(" ");
} //close countdown();

/*********************************************************************

  • Serial LCD disagnostic and general use tools *
  • selectLineOne(); | selectLineTwo(); | goTo(); | lcd.clear(); *
  • backlightOn(); | backlightOff(); | serCommand(); *
    **********************************************************************/
    void selectLineOne(){ //puts the cursor at line 0 char 0.
    lcd.write(0xFE); //command flag
    lcd.write(128); //position
    }
    void selectLineTwo(){ //puts the cursor at line 0 char 0.
    lcd.write(0xFE); //command flag
    lcd.write(192); //position
    }
    void goTo(int position) { //position = line 1: 0-15, line 2: 16-31, 31+ defaults back to 0
    if (position<16){ lcd.write(0xFE); //command flag
    lcd.write((position+128)); //position
    }else if (position<32){Serial.write(0xFE); //command flag
    lcd.write((position+48+128)); //position
    } else { goTo(0); }
    }

void clearLCD(){
lcd.write(0xFE); //command flag
lcd.write(0x01); //clear command.
}
void backlightOn(){ //turns on the backlight
lcd.write(0x7C); //command flag for backlight stuff
lcd.write(157); //light level.
}
void backlightOff(){ //turns off the backlight
lcd.write(0x7C); //command flag for backlight stuff
lcd.write(128); //light level for off.
}
void serCommand(){ //a general function to call the command flag for issuing all other commands
lcd.write(0xFE);
}

/***********************************************************

  • admin code, arm code, disarm code, and timer editing *
  • function. *
  • configMenu(); *
    ************************************************************/
    void configMenu(){
    int exitMenu = 0;
    int back = 0; //prevent user from exiting without typing in full code
    char menuPage; //prompt for Menu page

lcd.clear();
selectLineOne();
lcd.write(“Menu”);//inform the user that they are entered the menu
delay(2000);
lcd.clear();

code = 0;
count = 0;
while (count < (sizeof(adminCode) - 1)) {
selectLineTwo();
lcd.write(“Enter AdminCode”);

selectLineOne();
lcd.write(“Code”); //prompt for admin code
lcd.write(": ");

char adminKey;
do{
adminKey = keypad.getKey(); //loop and wait for keypress
}
while(adminKey == ‘\0’);

code = (code * 10) + (adminKey - 48);//store correct digits for later use

if(adminKey == ‘#’) {
return;//return to the arm code state
count = 0;
code = 0;
lcd.clear();
}

//if the correct key is pressed
else if(adminKey == adminCode[count]) {
count++;
}

else {
count = 0;
code = 0;
lcd.clear();//if the key is incorrect, reset
}

selectLineOne();
lcd.write(“Code”); //prompt for admin code
lcd.write(": ");
lcd.write(code);//display correct digits

}//end while

lcd.clear();
do { //display menu
selectLineOne();
lcd.write(“1.Admin 2.Time”);
selectLineTwo();
lcd.write(“3.Arm 4.Disarm”);

do{
menuPage = keypad.getKey();
} //keep reading if anything but 1 - 4 is entered
while(menuPage == ‘\0’ || menuPage == ‘*’ || menuPage == ‘0’ || menuPage > 52);

switch(menuPage) {

case ‘1’: // Edit admin code

lcd.clear();
selectLineTwo();
lcd.write("# To Exit");
delay(2000);
lcd.clear();

selectLineTwo();
lcd.write(“AdminCode”);

selectLineOne();
lcd.write(“Code”); //prompt for admin code
lcd.write(": ");

count = 0;
code = 0;//
while(count < (sizeof(adminCode) - 1)) {
char adminCodeKey;
do{
adminCodeKey = keypad.getKey();//wait for a keypress
}
while(adminCodeKey == ‘\0’);

code = (code * 10) + (adminCodeKey - 48); //store correct digits for later use

if(adminCodeKey == ‘#’ && back == 0) {
count = sizeof(adminCode);
code = 0;
exitMenu = 1;//bail out if # is pressed
lcd.clear();
}

else {
//if key matches code
adminCode[count] = adminCodeKey;
count++;
back = 1;
}

selectLineOne();
lcd.write(“Code”); //prompt for arm code
lcd.write(": ");
lcd.write(code);
}//end admincode while
lcd.clear();

selectLineOne();
lcd.write(code);
selectLineTwo();
lcd.write("* to exit");//display new code and give user time to see it
char key1;
do{
key1 = keypad.getKey();
}
while(key1 == ‘\0’ || key1 != ‘*’);//keep looping until user presses *

break;

case ‘2’: //Timer

lcd.clear();
selectLineTwo();
lcd.write("# To Exit");
delay(2000);
lcd.clear();

char timeInt;
selectLineOne();
lcd.write(“Enter Hours”);
do{
timeInt = keypad.getKey();
}
while(timeInt == ‘\0’ || timeInt < ‘0’ || timeInt > ‘6’);

hour = (timeInt - ‘0’) * 10;//get first digit and convert to int
do{
timeInt = keypad.getKey();
}
while(timeInt == ‘\0’);
hour = (timeInt - ‘0’) + hour;//get second digit.
lcd.clear();
timeInt = ‘L’;

lcd.write(“Enter Minutes”);
do{
timeInt = keypad.getKey();
}
while(timeInt == ‘\0’ || timeInt < ‘0’ || timeInt > ‘6’);
while (timeInt < ‘0’ || timeInt > ‘6’){
timeInt = keypad.getKey();
}
minute = (timeInt - ‘0’) * 10;//get first digit and convert to int
do{
timeInt = keypad.getKey();
}
while(timeInt == ‘\0’);
minute = (timeInt - ‘0’) + minute;//get second digit.
lcd.clear();
timeInt = ‘L’;

lcd.write(“Enter Seconds”);
do{
timeInt = keypad.getKey();
}
while(timeInt == ‘\0’ || timeInt < ‘0’ || timeInt > ‘6’);
while (timeInt < ‘0’ || timeInt > ‘6’){
timeInt = keypad.getKey();
}
second = (timeInt - ‘0’) * 10;//get first digit and convert to int
do{
timeInt = keypad.getKey();
}
while(timeInt == ‘\0’);
second = (timeInt - ‘0’) + second;//get second digit.
lcd.clear();
timeInt = ‘L’;

lcd.clear();

selectLineOne();
lcd.print(hour, DEC); // the hour, sent to the screen in decimal format
lcd.print(":"); // a colon between the hour and the minute
lcd.print(minute, DEC); // the minute, sent to the screen in decimal format
lcd.print(":"); // a colon between the minute and the second
lcd.println(second, DEC); // the second, sent to the screen in decimal format

selectLineTwo();
lcd.print("* to exit");
char key2;
do{
key2 = keypad.getKey();
}
while(key2 == ‘\0’ || key2!= ‘*’);//display new code and give user time to see it

break;

case ‘3’: //Arm code
lcd.clear();
selectLineTwo();
lcd.print("# To Exit");
delay(2000);
lcd.clear();

selectLineTwo();
lcd.print(“ArmCode”);

selectLineOne();
lcd.print(“Code”); //prompt for admin code
lcd.print(": ");

count = 0;
code = 0;
back = 0;

while(count < (sizeof(ArmCode) - 1)) {
char armCodeKey;
do{
armCodeKey = keypad.getKey();
}
while(armCodeKey == ‘\0’);

code = (code * 10) + (armCodeKey - 48);//store correct digits for later use

if(armCodeKey == ‘#’ && back == 0) {
count = sizeof(ArmCode);
code = 0;
exitMenu = 1;
lcd.clear();//bail out if exit key is pressed
}

else {
//if key matches code
ArmCode[count] = armCodeKey;
count++;
back = 1;
}

selectLineOne();
lcd.write(“Code”); //prompt for arm code
lcd.write(": ");
lcd.write(code);
}//end armcode while
lcd.clear();

selectLineOne();
lcd.write(code);
selectLineTwo();
lcd.write("* to exit");
char key3;
do{
key3 = keypad.getKey(); //display new code and give user time to see it
}
while(key3 == ‘\0’ || key3!= ‘*’);

break;

case ‘4’: //disarm
lcd.clear();
selectLineTwo();
lcd.write("# To Exit");
delay(2000);
lcd.clear();

selectLineTwo();
lcd.write(“disarmCode”);

selectLineOne();
lcd.write(“Code”); //prompt for admin code
lcd.write(": ");

count = 0;
code = 0;
back = 0;

while(count < (sizeof(disarmCode) - 1)) {
char disarmCodeKey;
do{
disarmCodeKey = keypad.getKey();
}
while(disarmCodeKey == ‘\0’);

code = (code * 10) + (disarmCodeKey - 48);

if(disarmCodeKey == ‘#’ && back == 0) {
count = sizeof(disarmCode);
code = 0;
exitMenu = 1;
lcd.clear();
}

else {

disarmCode[count] = disarmCodeKey;
count++;
back = 1;
}

selectLineOne();
lcd.write(“Code”); //prompt for arm code
lcd.write(": ");
lcd.write(code);
}//end disarmcode while
lcd.clear();

selectLineOne();
lcd.write(code);
selectLineTwo();
lcd.write("* to exit");
char key4;
do{
key4 = keypad.getKey();//display new code and give user time to see it
}
while(key4 == ‘\0’ || key4 != ‘*’);

break;

case ‘#’://exit case
exitMenu = 1;//exit menu if # is pressed
break;

case ‘L’://exit case no admin code
exitMenu = 1;
break;

}//end switch

}while(exitMenu == 0); //end menu while loop

configMenuFlag = 1;//set flag so menu cannot be opened later

saveConfig();//write new configuration into memory

}//end configMenu

/***********************************************************

  • saves the admin code, arm code, disarm code, and timer *
  • into EEPROM memory where they will survive a power down *
  • saveConfig(); *
    ************************************************************/

void saveConfig() {

configuration.arm = atol(ArmCode);
configuration.disarm = atol(disarmCode);
configuration.admin = atol(adminCode);
configuration.c_hour = hour;
configuration.c_minute = minute;
configuration.c_second = second;

// EEPROM_writeAnything(0, configuration);

}

/***********************************************************

  • Reads the admin code, arm code, disarm code, and timer *
  • from EEPROM memory and into local variables *
  • readConfig(); *
    ************************************************************/

void readConfig() {

//EEPROM_readAnything(0, configuration);

ltoa(configuration.arm, ArmCode, 10);
ltoa(configuration.disarm,disarmCode,10);
ltoa(configuration.admin,adminCode,10);
hour = configuration.c_hour;
minute = configuration.c_minute;
second = configuration.c_second;
}

/***********************************************************

  • chirps a buzzer at 3 different intervals > 30 seconds *
  • < 30 seconds, and < 10 seconds *
  • beepSecondaryBuzzer() *
    ************************************************************/

void beepSecondaryBuzzer() {

int timeLeft = 0;//default, seconds > 30

if(hour == 0 && minute == 0 && second <= 30 && second > 10){
timeLeft = 1; //if less than 30 seconds but more than 10 seconds left
}

else if (hour == 0 && minute == 0 && second <= 10 && second > 0){
timeLeft = 2; //if less than 10 seconds left
}

switch(timeLeft){

case 0:
currentMillis = millis();
if (currentMillis - previousTime > 60000)//1 minute interval
{
previousTime = currentMillis;
previousDelay = currentMillis;

digitalWrite(speakerPin, HIGH);//turn on buzzer
}

if (currentMillis - previousDelay > 100) {//100ms chirp duration
digitalWrite(speakerPin, LOW);//turn off buzzer
}
break;

case 1:

currentMillis = millis();
if (currentMillis - previousTime > 2000)// 2 second interval
{
previousTime = currentMillis;
previousDelay = currentMillis;

digitalWrite(speakerPin, HIGH);//turn on buzzer
}

if (currentMillis - previousDelay > 100) {//100ms chirp duration
digitalWrite(speakerPin, LOW);//turn off buzzer
}

break;

case 2:

currentMillis = millis();
if (currentMillis - previousTime > 500)// 1/2 second interval
{
previousTime = currentMillis;
previousDelay = currentMillis;

digitalWrite(speakerPin, HIGH);//turn on buzzer
}

if (currentMillis - previousDelay > 100) {//100ms chirp duration
digitalWrite(speakerPin, LOW);//turn off buzzer
}

break;

}//end case statement

}//end beepSecondaryBuzzer();

Ich danke euch schon einmal im Voraus.

Gruß
Bastian