skizziks_53

Reddit arduino alarm v2.0

May 2nd, 2019
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 39.78 KB | None | 0 0
  1. /*
  2.     Reddit arduino alarm (re-written) version 2.0
  3.     April 30, 2019
  4.  
  5.     This version is changed somewhat.
  6.  
  7.     1. This has serial.print() statements through it, to allow troubleshooting events. They can be disabled with the first variable declared.
  8.     2. All of the password-entry screens are the same in that the password is shown on the bottom line. The top three lines can be changed but the bottom line must be left empty.
  9.     3. This version does not leave the lasers on all the time. It only turns them on long enough to stabilize and then check the sensor.
  10.     4. This version checks the lasers on a time interval that does not use delay().
  11.     5. This version checks the keypad on a time interval that does not use delay().
  12.     6. There are a couple delay() commands used for splash screens but the times are short.
  13.    
  14. */
  15.  
  16.  
  17.  
  18. #include <LiquidCrystal.h> // includes the LiquidCrystal Library (standard Arduino library)
  19. #include <Keypad.h> // includes the Keypad Library (standard Arduino library)
  20.  
  21.  
  22. // Added variable:
  23. bool show_serial_messages = true; // This is a switch to enable or disable all the serial messages, for troubleshooting.
  24.  
  25.  
  26. // PIN NUMBERS
  27. int LaserEmitterWindow = 11;
  28. int LaserEmitterDoor = 13;
  29. //Assigning pin numbers to receivers
  30. int LaserDetectorWindow = 10;
  31. int LaserDetectorDoor = 12;
  32. //Assigning pin number to piezo buzzer
  33. int Buzzer = 46;
  34.  
  35.  
  36.  
  37. // Below are two variables that tell how the alarm is activated.
  38. // There is a current and past version, in order to react to transitions between different states.
  39. int alarm_main_mode__current_state = 0;
  40. int alarm_main_mode__previous_state = 0;
  41. const int alarm_main_mode__not_activated = 0;
  42. const int alarm_main_mode__activated = 1; // This means activated in either [stay] or [away] mode.
  43. const int alarm_main_mode__alarm_triggered = 2; // 2 = alarm has been triggered.
  44. const int alarm_main_mode__change_password = 3; // This mode is only accessible from the alarm_main_mode__not_activated mode.
  45.  
  46.  
  47. int alarm_activation_type = 1; // This value is used to indicate what mode the alarm is activated in.
  48. const int alarm_activation_type__stay_mode = 1;
  49. const int alarm_activation_type__away_mode = 2;
  50.  
  51.  
  52. // When the alarm is triggered, there are two different stages that may occur (a countdown and sounding the beeper).
  53. // So another state variable is needed for that.
  54. int alarm_trigger_status = 1;
  55. const int alarm_trigger_status__countdown_mode = 1;
  56. const int alarm_trigger_status__sounding_mode = 2;
  57.  
  58.  
  59. // Below are variables to use for the 30-second countdown timer.
  60. bool countdown_timer_in_use = false; // This is a flag telling if the countdown timer is in use.
  61. int countdown_limit = 30; // This is the time in seconds for the count down timer.
  62. int countdown_counter = 0; // This is used for counting the seconds as they elapse.
  63. unsigned long countdown_beginOneSecond_time = 0;
  64. unsigned long countdown_currentOneSecond_time = 0;
  65.  
  66.  
  67. // This program doesn't leave the lasers on all the time. It only turns them on to check the beam, then turns them off again.
  68. // Semiconductor lasers tend to "bounce" when turning on, due to the cheap power regulators they usually use.
  69. // For this reason you want to turn them on and then wait a bit, about .1 seconds.
  70. // So the laser_state flag has a stage for 'turning on'.
  71. int laser_state = 0; // This is a single digit that tells what state the two lasers are in. Both lasers will use this one variable.
  72. const int laser_state__off ;// 0 = turned off
  73. const int laser_state__turning_on ;// 1 = powering up delay. (These lasers take a bit of time to reach a stable level).
  74. const int laser_state__on ;// 2 = laser is turned on. Read the value of the laser sensor(s).
  75. const int laser_state__blocked ;// 3 = either laser has been blocked, triggering the alarm. This value is necessary because after being triggered, neither laser is checked until the alarm is reset.
  76.  
  77.  
  78. // Below is the variables that will be used for waiting after the lasers are turned on.
  79. int laser_power_up_delay = 100; // This is a time delay, stated in milliseconds.
  80. unsigned long laser_startup_previous_time = 0; // used for laser start timing.
  81. unsigned long laser_startup_current_time = 0;
  82.  
  83.  
  84. int laser_triggered_state = 1; // This tells which laser was triggered to set off the alarm.
  85. const int laser_triggered_state__window = 1;
  86. const int laser_triggered_state__door = 2;
  87. // The original code had a section to handle if both lasers were triggered at once.
  88. // Note: since there is no possible way to check both sensors literally at the same time, the laser_triggered_state only holds values indicating the first laser that was blocked.
  89.  
  90.  
  91. // Since we want the lasers to trigger the first time they detect interference and not turn off when the beam is simply un-blocked,
  92. // we need to track their past and current states separately.
  93. // Since a digitalRead() call is performed on the laser sensors and the value stored, 1 = not blocked and 0 = blocked.
  94. int laser_window_sensor_previous_state = 1;
  95. int laser_window_sensor_current_state = 1;
  96. int laser_door_sensor_previous_state = 1;
  97. int laser_door_sensor_current_state = 1;
  98. const int laser_sensor_blocked = 0;
  99. const int laser_sensor_not_blocked = 1;
  100.  
  101.  
  102. // Checking the keypad inputs on every pass through the main loop uses a lot of processor time where it isn't needed, so this program doesn't do that.
  103. bool keypad_enabled = true; // This is used to enable and disable the keypad, to provide stating the interval that it is to be polled at.
  104. int keypad_check_interval = 250; // A time stated in milliseconds, that the keypad will be checked for presses.
  105. // (Note that this is different than the de-bounce time, that the Keypad library does already)
  106. // This is the time interval that the keypad is checked for presses at.
  107. unsigned long keypad_previous_time = 0; // used for keypad timing.
  108. unsigned long keypad_current_time = 0;
  109.  
  110.  
  111. bool lasers_enabled = true;
  112. int laser_check_interval = 1000; // This is the time interval (stated in milliseconds) that the lasers will be checked at.
  113. unsigned long laser_check_previous_time = 0; // used for laser check timing.
  114. unsigned long laser_check_current_time = 0;
  115.  
  116.  
  117. int password_mode = 0; // This is a state flag for the password. zero = not entered, 1 = current password entered, 2 = entering new password.
  118. const int password_mode__not_entered = 0;
  119. const int password_mode__current_password_is_entered = 1;
  120. const int password_mode__entering_new_password = 2;
  121. //String password = "1234"; // Used in enterPassword function as the current password to disable alarm or change password
  122. // Arduinos don't handle Strings real well, from a memory standpoint.
  123. // And the Keypad.h library function getChar() returns characters anyway, so I changed the passwords to arrays of chars.
  124. char password[] = {'1', '2', '3', '4'};
  125. int passwordLength = 4; // To allow variable-length passwords with a char array, the length must be tracked (this value is an actual count of chars).
  126. char enteredPassword[4]; // This is what will hold the entered password.
  127. int enteredPasswordLength = 0; // This value is an actual count of chars.
  128. int maximumPasswordLength = 4; // Maximum password length (an actual count of chars).
  129. int current_password_display_position = 0; // This is used to progressively count the password chars as they are entered.
  130.  
  131.  
  132. const byte ROWS = 4; //four rows
  133. const byte COLS = 4; //four columns
  134. //define the symbols on the buttons of the keypads
  135. char keyMap[ROWS][COLS] = {
  136.   {'1', '2', '3', 'A'},
  137.   {'4', '5', '6', 'B'},
  138.   {'7', '8', '9', 'C'},
  139.   {'*', '0', '#', 'D'}
  140. };
  141. byte rowPins[ROWS] = {18, 19, 20, 21}; //Row pinouts of the keypad
  142. byte colPins[COLS] = {14, 15, 16, 17}; //Column pinouts of the keypad
  143. Keypad myKeypad = Keypad( makeKeymap(keyMap), rowPins, colPins, ROWS, COLS);
  144.  
  145. LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // Creates an LC object. Parameters: (rs, enable, d4, d5, d6, d7)
  146.  
  147.  
  148.  
  149.  
  150. void setup() {
  151.   Serial.begin (9600);
  152.  
  153.   unsigned int key_debounce = 50; // This is a time stated in milliseconds.
  154.   myKeypad.setDebounceTime(key_debounce); // The keypad library defaults to 1 millisecond debounce (which makes sense from a code library standpoint) but is not real helpful IRL.
  155.  
  156.   lcd.begin(20, 4); //defines dimensions of lcd (20 columns by 4 rows)
  157.  
  158.   //Defines lasers and buzzer as outputs and receivers as inputs
  159.   pinMode(LaserEmitterWindow, OUTPUT);
  160.   pinMode(LaserDetectorWindow, INPUT);
  161.   pinMode(LaserEmitterDoor, OUTPUT);
  162.   pinMode(LaserDetectorDoor, INPUT);
  163.   pinMode(Buzzer, OUTPUT);
  164.  
  165.   if (show_serial_messages == true) {
  166.     // If you are using serial messages anyway, it is good to show a message when exiting the setup() function.
  167.     // Errors can occur inside setup() causing it to crash and skip the rest of setup(), but the processor still proceeds on to run the rest of the code.
  168.     // This can cause program errors that are rather mystifying, because they occur in the main loop, but aren't caused by anything in the main loop.
  169.     // The message below will *usually* only show if setup() has been completed successfully.
  170.     Serial.println("Exiting setup()");
  171.   }
  172. }
  173.  
  174.  
  175. // It is not necessary to declare function prototypes in the Arduino IDE any more, if they are either on the main tab or on sub-tabs.
  176. // Note that all global variables must still be declared on the main tab.
  177.  
  178.  
  179. void loop() { //start of main loop
  180.  
  181.   // The lasers need to be checked in the main loop because the lasers change alarm_main_mode from [alarm activated] to [alarm triggered] when blocked.
  182.   check_laser_status();
  183.  
  184.   // The keypad needs to be checked in the main loop because it performs the alarm_main_mode changes of [alarm not activated] and [alarm activated].
  185.   check_keypad_status();
  186.  
  187.   // The countdown timer must be checked in the main loop because it is not part of the laser code or the keypad code.
  188.   check_countdown_timer();
  189.  
  190. } //end of main loop
  191.  
  192.  
  193.  
  194. // Note: I had this done in separate tabs in the arduino IDE but none of the code sites allow posting grouped files.
  195. // So for this I coped and pasted it all into one file, but it is much more convenient to work with in tabs.
  196. // The triple lines of asterisks below are dividers for each 'tab'.  
  197.  
  198.  
  199. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  200. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  201. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  202. // tab name = buzzer_functions
  203.  
  204. /*
  205.    This tab is just for the buzzer functions, even though there isn't a lot of them.
  206. */
  207.  
  208. void turn_buzzer_on() {
  209.   digitalWrite(Buzzer, HIGH);
  210. }
  211.  
  212. void turn_buzzer_off() {
  213.   digitalWrite(Buzzer, LOW);
  214. }
  215.  
  216. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  217. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  218. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  219. // tab name = countdown_timer
  220.  
  221. /*
  222.   This is just the function to operate the 30-second countdown timer in [away] mode.
  223.   (-this code is really a one-second timer that repeats 30 times-)
  224. */
  225.  
  226. // Below are variables to use for the 30-second countdown timer.
  227. // bool countdown_timer_in_use = false; // This is a flag telling if the countdown timer is in use.
  228. // int countdown_limit = 30; // This is the time in seconds for the count down timer.
  229. // int countdown_counter = 0; // This is used for counting the seconds as they elapse.
  230. // unsigned long countdown_beginOneSecond_time = 0;
  231. // unsigned long countdown_currentOneSecond_time = 0;
  232.  
  233. void reset_countdown_timer() {
  234.   // All this does is reset the starting seconds value, so the LCD can display it.
  235.   // This must be called before start_countdown_timer()
  236.   countdown_counter = countdown_limit;
  237. }
  238.  
  239. void start_countdown_timer() {
  240.   // This starts the countdown timer running.
  241.   countdown_timer_in_use = true;
  242.   countdown_beginOneSecond_time = millis();
  243. }
  244.  
  245. void check_countdown_timer() {
  246.   countdown_currentOneSecond_time = millis();
  247.   if (countdown_currentOneSecond_time >= countdown_beginOneSecond_time) {
  248.     if (countdown_currentOneSecond_time >= (countdown_beginOneSecond_time + 1000)) {
  249.       countdown_counter -= 1;
  250.       lcd_message_update_countdown_timer_value();
  251.       if (countdown_counter == 0) {
  252.         countdown_timer_in_use = false;
  253.         countdown_timer_expired();
  254.       }
  255.     }
  256.   }
  257.   else {
  258.     countdown_beginOneSecond_time = millis(); // millis() rollover condition
  259.   }
  260. }
  261.  
  262. void countdown_timer_expired() {
  263.   // This function is what gets called when the coutdown timer runs out.
  264.   alarm_trigger_status = alarm_trigger_status__sounding_mode;
  265.   turn_buzzer_on();
  266. }
  267.  
  268. void stop_countdown_timer() {
  269.   // The only thing needed to stop the timer is to change the value below.
  270.   countdown_timer_in_use = false;
  271. }
  272.  
  273. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  274. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  275. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  276. // tab name = keypad_functions
  277.  
  278. /*
  279.   This tab is only for functions relating to the keypad.
  280.  
  281.   References-----
  282.   ASCII value of zero is 48
  283.   ASCII value of 9 is 57
  284.   Therefore you can obtain the int value of a digit char by subtracting 48 from it.
  285.   A = 65
  286.   B = 66
  287.   C = 67
  288.   D = 68
  289.   # = 35
  290.   (asterisk) = 42
  291. */
  292.  
  293. void check_keypad_status() {
  294.  
  295.   // This function is just for detecting transitions between alarm_main_mode__ values.
  296.   // All of the if() statements here require that alarm_main_mode__previous_state and alarm_main_mode__current_state are different values.
  297.   // Toward the end of this function, alarm_main_mode__current_state is copied into alarm_main_mode__previous_state, so that these if() statements only execute once per transition.
  298.  
  299.   if (alarm_main_mode__previous_state == -1 && alarm_main_mode__current_state == alarm_main_mode__not_activated) {
  300.     // Meeting these conditions means the arduino has powered up, and so the welcome screen needs to be shown.
  301.     lcd_message_display_welcome_screen();
  302.   }
  303.  
  304.   if (alarm_main_mode__previous_state == alarm_main_mode__activated && alarm_main_mode__current_state == alarm_main_mode__not_activated) {
  305.     // transition from alarm=on to alarm=off.
  306.     lcd_message_display_welcome_screen();
  307.   }
  308.  
  309.   if (alarm_main_mode__previous_state == alarm_main_mode__not_activated && alarm_main_mode__current_state == alarm_main_mode__activated) {
  310.     if (alarm_activation_type == alarm_activation_type__stay_mode) {
  311.       lcd_message_alarm_activated_in_stay_mode();
  312.     }
  313.     if (alarm_activation_type == alarm_activation_type__away_mode) {
  314.       lcd_message_alarm_activated_in_away_mode();
  315.     }
  316.   }
  317.  
  318.   if (alarm_main_mode__previous_state == alarm_main_mode__activated && alarm_main_mode__current_state == alarm_main_mode__alarm_triggered) {
  319.     if (alarm_activation_type == alarm_activation_type__stay_mode) {
  320.       // [stay] activation: immediately sound the alarm and change the LCD to password input mode.
  321.       turn_buzzer_on();
  322.       //lcd_message_change_to_password_input_mode(); // ???????????????????????????????????????????????????????????????????????????????? needs to change for sensor type
  323.       lcd_message_display_trigger_and_prompt_for_password();
  324.       alarm_trigger_status = alarm_trigger_status__sounding_mode;
  325.       if (show_serial_messages == true) {
  326.         Serial.println("Alarm triggered in stay mode");
  327.       }
  328.     }
  329.     if (alarm_activation_type == alarm_activation_type__away_mode) {
  330.       // [away] mode: change the LCD and keypad mode and start the 30-second timer.
  331.       reset_countdown_timer();
  332.       lcd_message_change_to_long_countdown_mode();
  333.       alarm_trigger_status = alarm_trigger_status__countdown_mode;
  334.       start_countdown_timer();
  335.       if (show_serial_messages == true) {
  336.         Serial.println("Alarm triggered in away mode");
  337.       }
  338.     }
  339.   }
  340.  
  341.   if (alarm_main_mode__previous_state == alarm_main_mode__alarm_triggered && alarm_main_mode__current_state == alarm_main_mode__not_activated) {
  342.     // transition from alarm=triggered to alarm=off.
  343.     lcd_message_display_welcome_screen();
  344.   }
  345.  
  346.   if (alarm_main_mode__previous_state == alarm_main_mode__change_password && alarm_main_mode__current_state == alarm_main_mode__not_activated) {
  347.     // Meeting these conditions means that the mode is returning from changing the password.
  348.     lcd_message_display_welcome_screen();
  349.   }
  350.  
  351.   alarm_main_mode__previous_state = alarm_main_mode__current_state;
  352.  
  353.   if (keypad_enabled == true) {
  354.     check_keypad_for_presses(); // This checks the keypad for input.
  355.     start_keypad_delay_interval(); // This starts the delay timer to limit how much time is spend checking the keypad for input.
  356.   }
  357.   else {
  358.     check_keypad_delay_timer(); // This checks the timer that re-enables the keypad after the set time interval has passed.
  359.   }
  360. }
  361.  
  362.  
  363. void check_keypad_for_presses() {
  364.   // This checks the keypad for input.
  365.   // All of these conditions are steady-state conditions, not transitional conditions.
  366.   // At this point keypad_alarm_main_mode_previous_state equals the value of keypad_alarm_main_mode_current_state, so only one of them needs to be checked here.
  367.  
  368.   //int alarm_main_mode = 0; // This is a single digit that tells how the alarm is activated.
  369.   //const int alarm_main_mode__not_activated = 0;
  370.   //const int alarm_main_mode__activated = 1; // This means activated in either [stay] or [away] mode.
  371.   //const int alarm_main_mode__alarm_triggered = 2; // 2 = alarm has been triggered.
  372.   //const int alarm_main_mode__change_password = 3; // This mode is only accessible from the alarm_main_mode__not_activated mode.
  373.  
  374.   char buttonPress = myKeypad.getKey();
  375.   if (alarm_main_mode__current_state == alarm_main_mode__not_activated) {
  376.     // The allowable inputs at this state [lcd_message_display_welcome_screen()] are A, B and C.
  377.     if (keypad_char_is_A(buttonPress)) {
  378.       // A = activate away
  379.       alarm_main_mode__current_state = alarm_main_mode__activated;
  380.       alarm_activation_type = alarm_activation_type__away_mode;
  381.       if (show_serial_messages == true) {
  382.         Serial.println("Activate alarm in away mode");
  383.       }
  384.     }
  385.     if (keypad_char_is_B(buttonPress)) {
  386.       // B = activate stay
  387.       alarm_main_mode__current_state = alarm_main_mode__activated;
  388.       alarm_activation_type = alarm_activation_type__stay_mode;
  389.       if (show_serial_messages == true) {
  390.         Serial.println("Activate alarm in stay mode");
  391.       }
  392.     }
  393.     if (keypad_char_is_C(buttonPress)) {
  394.       // C = change password
  395.       alarm_main_mode__current_state = alarm_main_mode__change_password;
  396.       reset_enteredPassword_array();
  397.       lcd_message_change_password_enter_current_password();
  398.       if (show_serial_messages == true) {
  399.         Serial.println("Enter password change mode");
  400.       }
  401.     }
  402.   }
  403.   else if (alarm_main_mode__current_state == alarm_main_mode__activated) {
  404.     // This means the alarm is activated but not triggered.
  405.     // The only allowable input at this state is to enter the password to disable the alarm.
  406.     enter_password_to_disable_or_reset_alarm(buttonPress);
  407.   }
  408.   else if (alarm_main_mode__current_state == alarm_main_mode__alarm_triggered) {
  409.     // This means the alarm has been triggered.
  410.     // The only allowable input at this state is to enter the password to disable the alarm.
  411.     enter_password_to_disable_or_reset_alarm(buttonPress);
  412.   }
  413.   else if (alarm_main_mode__current_state == alarm_main_mode__change_password) {
  414.     // This means the password is being changed.
  415.     bool oldPasswordEntered = false;
  416.     bool newPasswordEntered = false;
  417.     if (password_mode == password_mode__not_entered) { // This means that the current password has not been entered.
  418.       if (enteredPasswordLength < (maximumPasswordLength - 1)) {
  419.         oldPasswordEntered = enter_password_character(buttonPress);
  420.         lcd_display_show_entered_password_character();
  421.         if (show_serial_messages == true) {
  422.           Serial.println("Entering current password");
  423.         }
  424.       }
  425.       if (oldPasswordEntered == true) {
  426.         // If they are done entering the current password, compare it.
  427.         compare_entered_password(); // This changes password_mode to 1 if the two passwords match.
  428.         if (password_mode == password_mode__not_entered) {
  429.           // You have failed
  430.           reset_enteredPassword_array();
  431.           lcd_message_change_password_current_entry_failed();
  432.         }
  433.         else if (password_mode = password_mode__current_password_is_entered) {
  434.           // Show the screen to enter the new password.
  435.           lcd_message_change_password_enter_new_password();
  436.         }
  437.       }
  438.     }
  439.     else if (password_mode == password_mode__current_password_is_entered) { // This means that the new password is being entered.
  440.  
  441.       if (enteredPasswordLength < (maximumPasswordLength - 1)) {
  442.         newPasswordEntered = enter_password_character(buttonPress);
  443.         lcd_display_show_entered_password_character();
  444.         if (show_serial_messages == true) {
  445.           Serial.println("Entering new password");
  446.         }
  447.       }
  448.       if (newPasswordEntered == true) {
  449.         // If they are done entering the new password, then copy it into the regular password array.
  450.         // (first show the two passwords in the serial messages however)
  451.         if (show_serial_messages == true) {
  452.           Serial.println("Changing password");
  453.           Serial.print("Old password = ");
  454.           char tempChar;
  455.           for (int x = 0; x < (passwordLength - 1); x++) {
  456.             tempChar = password[x];
  457.             Serial.print(tempChar);
  458.           }
  459.           Serial.print("New password = ");
  460.           for (int x = 0; x < (passwordLength - 1); x++) {
  461.             tempChar = enteredPassword[x];
  462.             Serial.print(tempChar);
  463.           }
  464.         }
  465.         change_old_password_to_new_password();
  466.         alarm_main_mode__current_state = alarm_main_mode__not_activated;
  467.       }
  468.     }
  469.   }
  470. }
  471.  
  472. void enter_password_to_disable_or_reset_alarm(char buttonPress) {
  473.   bool passwordEntered = false;
  474.   if (password_mode == password_mode__not_entered) { // This means that the current password has not been entered.
  475.     if (enteredPasswordLength < (maximumPasswordLength - 1)) {
  476.       passwordEntered = enter_password_character(buttonPress);
  477.       lcd_display_show_entered_password_character();
  478.       if (show_serial_messages == true) {
  479.         Serial.println("Entering current password to disable alarm");
  480.       }
  481.     }
  482.     if (passwordEntered == true) {
  483.       // If they are done entering the current password, compare it.
  484.       compare_entered_password(); // This changes password_mode to 1 if the two passwords match.
  485.       if (password_mode == password_mode__not_entered) {
  486.         // You have failed
  487.         reset_enteredPassword_array();
  488.         lcd_message_show_alarm_armed_enter_password_screen();
  489.       }
  490.       else if (password_mode = password_mode__current_password_is_entered) {
  491.         alarm_main_mode__current_state = alarm_main_mode__not_activated;
  492.         turn_buzzer_off();
  493.         lcd_message_display_welcome_screen();
  494.       }
  495.     }
  496.   }
  497. }
  498.  
  499. void start_keypad_delay_interval() {
  500.   // This starts the delay timer to limit how much time is spend checking the keypad for input.
  501.   keypad_enabled = false;
  502.   keypad_previous_time = millis();
  503. }
  504.  
  505.  
  506. void check_keypad_delay_timer() {
  507.   // This checks the timer that re-enables the keypad after the set time interval has passed.
  508.   keypad_current_time = millis();
  509.   if (keypad_current_time >= keypad_previous_time) {
  510.     if (keypad_current_time >= (keypad_previous_time + keypad_check_interval)) {
  511.       keypad_enabled = true;
  512.     }
  513.   }
  514.   else {
  515.     keypad_previous_time = millis(); // rollover condition
  516.   }
  517. }
  518.  
  519.  
  520. int get_keypad_digit_value(char buttonPress) {
  521.   // This function is for detirmining if a character returned from the keypad is a numeral or not.
  522.   // If the char is a digit, this returns the digit value.
  523.   // If the char is not a digit, this returns a value of -1.
  524.   int returnValue = -1;
  525.   // ASCII value of zero is 48
  526.   // ASCII value of 9 is 57
  527.   // Therefore you can obtain the int value of a digit char by subtracting 48 from it.
  528.   if (buttonPress > 47 && buttonPress < 58) {
  529.     // returnValue was initialized to -1 however, so only 47 is subtracted from it, so char[zero] results in [int] zero.
  530.     returnValue = buttonPress - 47;
  531.   }
  532.   return returnValue;
  533. }
  534.  
  535. bool keypad_char_is_A(char buttonValue) {
  536.   // This function answers true if the character is A.
  537.   bool answer = false;
  538.   if (buttonValue == 65) {
  539.     answer = true;
  540.   }
  541.   return answer;
  542. }
  543.  
  544. bool keypad_char_is_B(char buttonValue) {
  545.   // This function answers true if the character is B.
  546.   bool answer = false;
  547.   if (buttonValue == 66) {
  548.     answer = true;
  549.   }
  550.   return answer;
  551. }
  552.  
  553. bool keypad_char_is_C(char buttonValue) {
  554.   // This function answers true if the character is C.
  555.   bool answer = false;
  556.   if (buttonValue == 67) {
  557.     answer = true;
  558.   }
  559.   return answer;
  560. }
  561.  
  562. bool keypad_char_is_D(char buttonValue) {
  563.   // This function answers true if the character is D.
  564.   bool answer = false;
  565.   if (buttonValue == 68) {
  566.     answer = true;
  567.   }
  568.   return answer;
  569. }
  570.  
  571. bool keypad_char_is_poundSign(char buttonValue) {
  572.   // This function answers true if the character is #.
  573.   bool answer = false;
  574.   if (buttonValue == 35) {
  575.     answer = true;
  576.   }
  577.   return answer;
  578. }
  579.  
  580. bool keypad_char_is_asterisk(char buttonValue) {
  581.   // This function answers true if the character is *.
  582.   bool answer = false;
  583.   if (buttonValue == 42) {
  584.     answer = true;
  585.   }
  586.   return answer;
  587. }
  588.  
  589.  
  590.  
  591. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  592. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  593. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  594. // tab name = laser_functions
  595.  
  596. /*
  597.    This tab is only for functions related to the lasers themselves.
  598. */
  599.  
  600. void check_laser_status() {
  601.   if (alarm_main_mode__current_state == alarm_main_mode__activated) { // The lasers only get checked, if the alarm is activated and the alarm is not already triggered.
  602.     if (lasers_enabled == true) {
  603.       check_for_laser_interference(); // This function is the one that checks to see if either laser is blocked.
  604.       reset_laser_delay_timer(); // This function sets lasers_enabled to false and starts the interval timer.
  605.     }
  606.     else {
  607.       check_laser_delay_timer(); // This function checks the laser interval timer, and changes lasers_enabled back to true when enough time has passed.
  608.     }
  609.   }
  610. }
  611.  
  612.  
  613. void check_for_laser_interference() {
  614.   // This function is the one that checks to see if either laser is blocked.
  615.   switch (laser_state) {
  616.     case 0:
  617.       // Zero means laser_state__off
  618.       // You can't use variables for cases in a switch-case statement (even variables declared as const)
  619.       // #define might work but can cause other issues, so I didn't do that.
  620.       digitalWrite(LaserEmitterWindow, HIGH); // Turn the lasers on.
  621.       digitalWrite(LaserEmitterDoor, HIGH);
  622.       laser_startup_previous_time = millis(); // Set the "previous" time value.
  623.       laser_state = laser_state__turning_on; // Change to the next state.
  624.       break;
  625.     case 1:
  626.       // 1 means laser_state__turning_on
  627.       laser_startup_current_time = millis();
  628.       if (laser_startup_previous_time >= laser_startup_current_time) {
  629.         if (laser_startup_previous_time >= (laser_startup_current_time + laser_power_up_delay)) {
  630.           laser_state = laser_state__on; // After the laser start-up delay has passed, change to the next state.
  631.         }
  632.       }
  633.       else {
  634.         laser_startup_current_time = millis(); // millis() rollover condition.
  635.       }
  636.       break;
  637.     case 2:
  638.     // 2 means laser_state__on
  639.       laser_window_sensor_current_state = digitalRead(LaserDetectorWindow);
  640.       if (laser_window_sensor_current_state = 0) {
  641.         if (laser_window_sensor_previous_state = 1) {
  642.           laser_state = laser_state__blocked;
  643.           laser_triggered_state = laser_triggered_state__window;
  644.           alarm_main_mode__current_state = alarm_main_mode__alarm_triggered;
  645.           if (show_serial_messages == true) {
  646.             Serial.println("Window laser triggered.");
  647.           }
  648.         }
  649.       }
  650.       laser_window_sensor_previous_state = laser_window_sensor_current_state;
  651.  
  652.       laser_door_sensor_current_state = digitalRead(LaserDetectorDoor);
  653.       if (laser_door_sensor_current_state = 0) {
  654.         if (laser_door_sensor_previous_state = 1) {
  655.           laser_state = laser_state__blocked;
  656.           laser_triggered_state = laser_triggered_state__door;
  657.           alarm_main_mode__current_state = alarm_main_mode__alarm_triggered;
  658.           if (show_serial_messages == true) {
  659.             Serial.println("Door laser triggered.");
  660.           }
  661.         }
  662.       }
  663.       laser_door_sensor_previous_state = laser_door_sensor_current_state;
  664.  
  665.       // Turn both lasers off again:
  666.       digitalWrite(LaserEmitterWindow, LOW);
  667.       digitalWrite(LaserEmitterDoor, LOW);
  668.  
  669.       laser_state = laser_state__off; // Reset the laser state back to zero again.
  670.       reset_laser_delay_timer(); // Reset the laser check interval back again.
  671.       break;
  672.   }
  673. }
  674.  
  675.  
  676. void reset_laser_delay_timer() {
  677.   // This function sets lasers_enabled to false and starts the interval timer.
  678.   lasers_enabled = false;
  679.   laser_check_previous_time = millis();
  680. }
  681.  
  682.  
  683. void check_laser_delay_timer() {
  684.   // This function checks the laser interval timer, and changes lasers_enabled back to true when enough time has passed.
  685.   laser_check_current_time = millis();
  686.   if (laser_check_previous_time >= laser_check_current_time) {
  687.     if (laser_check_previous_time >= (laser_check_current_time + laser_check_interval)) {
  688.       lasers_enabled = true;
  689.     }
  690.   }
  691.   else {
  692.     laser_check_current_time = millis(); // millis() rollover condition.
  693.   }
  694. }
  695.  
  696.  
  697. void reset_lasers_after_triggering() {
  698.   laser_state = laser_state__off; // This should be set to zero already, but anyway.
  699.   laser_window_sensor_previous_state = laser_sensor_not_blocked;
  700.   laser_window_sensor_current_state = laser_sensor_not_blocked;
  701.   laser_door_sensor_previous_state = laser_sensor_not_blocked;
  702.   laser_door_sensor_current_state = laser_sensor_not_blocked;
  703. }
  704.  
  705.  
  706.  
  707.  
  708. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  709. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  710. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  711. // tab name = lcd_message_displays
  712.  
  713. /*
  714.    This tab contains basic functions to clear one or all lines of the LCD.
  715.    With these LCDs, the line doesn't get cleared unless you print spaces over the entire line.
  716. */
  717.  
  718. void lcd_clear_all_lines() {
  719.   lcd_clear_line1();
  720.   lcd_clear_line2();
  721.   lcd_clear_line3();
  722.   lcd_clear_line4();
  723. }
  724.  
  725. void lcd_clear_line1() {
  726.   lcd.setCursor(0, 0);
  727.   lcd.print("                    "); // This is printing twenty spaces.
  728. }
  729.  
  730. void lcd_clear_line2() {
  731.   lcd.setCursor(0, 1);
  732.   lcd.print("                    "); // This is printing twenty spaces.
  733. }
  734.  
  735. void lcd_clear_line3() {
  736.   lcd.setCursor(0, 2);
  737.   lcd.print("                    "); // This is printing twenty spaces.
  738. }
  739.  
  740. void lcd_clear_line4() {
  741.   lcd.setCursor(0, 3);
  742.   lcd.print("                    "); // This is printing twenty spaces.
  743. }
  744.  
  745. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  746. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  747. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  748. // tab name = lcd_message_displays
  749.  
  750. /*
  751.    This tab is just for the functions to show normal messages on the LCD.
  752. */
  753.  
  754. void lcd_message_change_to_long_countdown_mode() {
  755.   // This screen changes to the countdown mode and then starts the 30-second timer code.
  756.   lcd_clear_all_lines();
  757.   lcd.setCursor(0, 0);
  758.   lcd.print("Alarm engaged in:");
  759.   lcd.setCursor(0, 1);
  760.   lcd_message_update_countdown_timer_value();
  761.   lcd.setCursor(0, 2);
  762.   lcd.print("Type PW to disable");
  763.   lcd.setCursor(0, 3);
  764.   lcd.print(">");
  765. }
  766.  
  767. void lcd_message_update_countdown_timer_value() {
  768.   // This function only prints the countdown_counter value to the LCD.
  769.   lcd_clear_line2();
  770.   lcd.setCursor(9, 1);
  771.   lcd.print(countdown_counter);
  772. }
  773.  
  774. void lcd_message_alarm_activated_in_stay_mode() {
  775.   lcd_clear_all_lines();
  776.   lcd.setCursor(0, 0);
  777.   lcd.print("Alarm Activated!");
  778.   lcd.setCursor(0, 1);
  779.   lcd.print("Mode = [stay]");
  780.   delay(2000);
  781.   lcd_message_show_alarm_activated_final_message();
  782. }
  783.  
  784. void lcd_message_alarm_activated_in_away_mode() {
  785.   lcd_clear_all_lines();
  786.   lcd.setCursor(0, 0);
  787.   lcd.print("Alarm Activated!");
  788.   lcd.setCursor(0, 1);
  789.   lcd.print("Mode = [away]");
  790.   delay(2000);
  791.   lcd_message_show_alarm_activated_final_message();
  792. }
  793.  
  794. void lcd_message_show_alarm_activated_final_message() {
  795.   lcd_clear_all_lines();
  796.   lcd.setCursor(0, 1);
  797.   lcd.print(" *** ALARM *** ");
  798.   lcd.setCursor(0, 2);
  799.   lcd.print("Type PW to disable");
  800.   lcd.setCursor(0, 3);
  801.   lcd.print(">");
  802. }
  803.  
  804. void lcd_message_display_trigger_and_prompt_for_password() {
  805.   // This function displays a different screen depending on which laser was blocked.
  806.   lcd_clear_all_lines();
  807.   lcd.setCursor(0, 0);
  808.   if (laser_triggered_state == laser_triggered_state__window) {
  809.     lcd.print("Window - ALERT!");
  810.     lcd.setCursor(0, 1);
  811.     lcd.print("Door - Armed");
  812.   }
  813.   if (laser_triggered_state == laser_triggered_state__door) {
  814.     lcd.print("Window - Armed");
  815.     lcd.setCursor(0, 1);
  816.     lcd.print("Door - ALERT!");
  817.   }
  818.   lcd.setCursor(0, 2);
  819.   lcd.print("Type PW to disable");
  820.   lcd.setCursor(0, 3);
  821.   lcd.print(">");
  822. }
  823.  
  824. void lcd_message_show_transition_to_alarm_armed() {
  825.   // This shows a brief message for 2 seconds, before changing to lcd_message_show_alarm_armed_enter_password_screen()
  826.   lcd_clear_all_lines();
  827.   lcd.setCursor(0, 2);
  828.   lcd.print("Window - Armed");
  829.   lcd.setCursor(0, 3);
  830.   lcd.print("Front Door - Armed");
  831.   delay(2000);
  832.   lcd_message_show_alarm_armed_enter_password_screen();
  833. }
  834.  
  835. void lcd_message_show_alarm_armed_enter_password_screen() {
  836.   // This is the normal message to show to enter the password, when the alarm is armed but not yet triggered.
  837.   lcd_clear_all_lines();
  838.   lcd.setCursor(0, 1);
  839.   lcd.print("Type PW to disable");
  840.   lcd.setCursor(0, 3);
  841.   lcd.print(">");
  842. }
  843.  
  844. void lcd_message_change_password_enter_current_password() {
  845.   // This is the text that shows first, requiring the user to enter the current password correctly.
  846.   // This gets called only once, to change to this screen.
  847.   lcd_clear_all_lines();
  848.   lcd.setCursor(0, 1);
  849.   lcd.print("Current Password");
  850.   lcd.setCursor(0, 3);
  851.   lcd.print(">");
  852. }
  853.  
  854. void lcd_display_show_entered_password_character() {
  855.   // This function updates the currently-entered password as it is keyed in.
  856.   // This gets called every time a new character is entered.
  857.   // The password is always shown on the bottom line, for all the password-entry screens.
  858.   lcd_clear_line4();
  859.   lcd.setCursor(0, 3);
  860.   lcd.print(">");
  861.   char tempChar;
  862.   int tempValue = enteredPasswordLength - 1;
  863.   for (int x = 0; x < tempValue; x++) {
  864.     lcd.setCursor((1 + x), 1);
  865.     tempChar = enteredPassword[x];
  866.     lcd.print(tempChar);
  867.   }
  868. }
  869.  
  870. void lcd_message_change_password_current_entry_failed() {
  871.   // This message is shown if the entered password does not match.
  872.   lcd_clear_all_lines();
  873.   lcd.setCursor(0, 1);
  874.   lcd.print("Wrong! Try Again");
  875.   delay(2000);
  876.   reset_enteredPassword_array();
  877.   lcd_message_change_password_enter_current_password();
  878. }
  879.  
  880. void lcd_message_change_password_enter_new_password() {
  881.   // This is the text that shows second after the current password was entered correctly, allowing entering the new password.
  882.   // This gets called only once, to change to this screen.
  883.   lcd_clear_all_lines();
  884.   lcd.setCursor(0, 1);
  885.   lcd.print("Set New Password");
  886.   lcd.setCursor(0, 3);
  887.   lcd.print(">");
  888. }
  889.  
  890. void lcd_message_display_welcome_screen() {
  891.   lcd_clear_all_lines();
  892.   lcd.setCursor(0, 0);
  893.   lcd.print("***** Welcome *****");
  894.   lcd.setCursor(0, 1);
  895.   lcd.print("A - Activate Away");
  896.   lcd.setCursor(0, 2);
  897.   lcd.print("B - Activate Stay");
  898.   lcd.setCursor(0, 3);
  899.   lcd.print("C - Change Password");
  900. }
  901.  
  902. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  903. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  904. // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  905. // tab name = password_functions
  906.  
  907. /*
  908.    This tab is only for the password-handling functions.
  909.  
  910.    char password[] = {'1', '2', '3', '4'}; // Since the Keypad.h library function getChar() returns characters, it is easiest to just store the password as an array of chars.
  911.    char enteredPassword[4]; // This is what will hold the entered password.
  912.    int lcd_screen_password_start_position = 5; // This is to allow the password to print after the text already placed on the line. See lcd_message_add_entered_password_char(int cPosition, int oneDigit) for use.
  913.    int current_password_position = 0; // This is used to progressively count the password chars as they are entered.
  914.  
  915. */
  916.  
  917. void reset_enteredPassword_array() {
  918.   // This just resets password_mode and the temporary password array to all-zero char values.
  919.   password_mode = 0;
  920.   enteredPasswordLength = 0;
  921.   for (int x = 0; x < 4; x++) {
  922.     enteredPassword[x] = 0;
  923.   }
  924. }
  925.  
  926. void reset_password_array() {
  927.   // This just resets the regular password array to all-zero char values.
  928.   passwordLength = 0;
  929.   for (int x = 0; x < 4; x++) {
  930.     password[x] = 0;
  931.   }
  932. }
  933.  
  934. bool enter_password_character(char buttonValue) {
  935.   // This adds new characters into enteredPassword as they are entered.
  936.   // This function allows any buttons as password characters except the asterisk, since that is the end-of-password marker.
  937.   // The function returns false unless the added character is the asterisk.
  938.   if (keypad_char_is_asterisk(buttonValue) == false) {
  939.     if (enteredPasswordLength < (maximumPasswordLength - 1)) {
  940.       enteredPassword[enteredPasswordLength] = buttonValue;
  941.       enteredPasswordLength += 1;
  942.     }
  943.     return false;
  944.   }
  945.   else {
  946.     // The user has entered the asterisk, that indicates the end of the password.
  947.     return true;
  948.   }
  949.  
  950. }
  951.  
  952. void compare_entered_password() {
  953.   // This compares the entered password with the set one, and sets password_mode to 1 if they match.
  954.   bool matchingValues = true;
  955.   // First just compare the lengths to see if they match:
  956.   if (passwordLength != enteredPasswordLength) {
  957.     matchingValues = false;
  958.   }
  959.   // If the lengths of the two passwords were the same, then compare the chars in them:
  960.   if (matchingValues == true) { // The character comparison must be skipped if the password lengths are not the same.
  961.     for (int x = 0; x < (passwordLength - 1); x++) {
  962.       if (password[x] != enteredPassword[x]) {
  963.         matchingValues = false;
  964.       }
  965.     }
  966.   }
  967.   if (matchingValues == true ) {
  968.     password_mode = password_mode__current_password_is_entered;
  969.   }
  970. }
  971.  
  972. void change_old_password_to_new_password() {
  973.   // This changes the set password to the one entered.
  974.   reset_password_array();
  975.   for (int x = 0; x < (enteredPasswordLength - 1); x++) {
  976.     password[x] = enteredPassword[x]; // copy the chars
  977.   }
  978.   passwordLength = enteredPasswordLength; // copy the length
  979.   reset_enteredPassword_array();
  980. }
Add Comment
Please, Sign In to add comment