skizziks_53

Reddit arduino door sensor alarm 1.0

Aug 12th, 2019
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.28 KB | None | 0 0
  1. /*
  2.   August 12, 2019
  3.   Reddit example - door sensor with RGB LED
  4.  
  5.   Board - not specified
  6.   hardware - NO button, some type of RGB LED arrangement (not specified, may be 3 separate single LEDs or one 4-wire common cathode LED)
  7.  
  8.  
  9.  
  10.  
  11.  
  12.   Some of these criticisms may seem like overkill for a small Arduino program.
  13.   When you move to writing larger and larger programs, the main factor in how easy you can continue is how well you have organized the code already written.
  14.  
  15.   --Don't use cryptic meaningless variable names. The name of the variable should explain clearly what it is used for.
  16.  
  17.   --Split the program up into separate functions. This allows you to place temporary Serial.print() statements into the separate functions,
  18.     to allow you to easily visualize when they are being called, as well as using more Serial.print statements to show any values that they are using.
  19.  
  20.   --Don't use cryptic function names even_if_it_means_writing_out_really_long_function_names_like_this(). The function should only do ONE thing, and the name of the function should explain clearly what it does.
  21.     If you need to go and look at what it does more than a couple times, then you either didn't name the function well, or you have too many things being done inside it.
  22.  
  23.   There is no performance penalty for using long variable and function names (they aren't used in the compiled code anyway) and there is very little memory penalty for splitting a bunch of statements into separate functions.
  24.  
  25.   Some people try to use short obtuse variable and function names, believing that they are saving time by not typing as much.
  26.   As the program gets larger--to 10K - 20K - 50K+ lines, those short names will kill your productivity,,,, until you go back and rename them properly.
  27.   The whole thing is much easier to work with if you just name them properly from the beginning.
  28. */
  29.  
  30. //int DoorSensor = A0;
  31. //int buzz = 9;
  32.  
  33. //int LT = 3; //blue
  34. //int LTR = 5; //red
  35. //int LTG = 6; //green
  36.  
  37. /*
  38.    Below--the variables are renamed with understandable names.
  39.    Always name your variables "what they are", in easily readable form.
  40.    Name I/O pins ending in '_pin' so you know that is an I/O pin. Use the _pin ending ONLY for pin ID variables.
  41.    Ideally you shouldn't ever need to look back at a variable declaration to understand what that variable is for.
  42. */
  43. int doorSensor_pin = A0;
  44. int doorSensor_pin_value = 0; // Notice how the variable to hold the pin VALUE ends in the word VALUE and not "pin"...
  45. int buzzer_pin = 9;
  46.  
  47. int rgb_led__blue_pin = 3;
  48. int rgb_led__red_pin = 5;
  49. int rgb_led__green_pin = 6;
  50.  
  51.  
  52.  
  53. // added variables----------------------
  54. const int door_sensor_mode__enabled = 1;
  55. const int door_sensor_mode__disabled = 2;
  56. int door_sensor_mode = 1; // A state indicator for the button. 1 means that the button can be checked, 2 means that the button is waiting through its delay.
  57. int door_sensor_delay_time = 200; // This is the milliseconds time interval for de-bouncing the button at.
  58. unsigned long door_sensor__begin_time = 0;
  59. unsigned long door_sensor__current_time = 0;
  60.  
  61.  
  62. int alarm_mode = 0; // The alarm has multiple phases it needs to pass through. I didn't bother with naming each of them.
  63. bool alarm_waiting = false; // This variable is for indicating if the alarm is waiting during a delay or not.
  64. const int alarm__short_delay = 75;
  65. const int alarm__long_delay = 1000;
  66. int alarm_time = 0; // This will be used to hold one of the above two values.
  67. unsigned long alarm__begin_time = 0;
  68. unsigned long alarm__ending_time = 0;
  69.  
  70.  
  71.  
  72. void setup() {
  73.   Serial.begin(9600); // ----------------------------------------- moved to beginning of setup() function.
  74.   pinMode(rgb_led__blue_pin, OUTPUT);
  75.   pinMode(rgb_led__red_pin, OUTPUT);
  76.   pinMode(rgb_led__green_pin, OUTPUT);
  77.   pinMode(doorSensor_pin, INPUT);
  78.   pinMode(buzzer_pin, OUTPUT);
  79.   //Serial.begin(9600);
  80.   Serial.println("Exiting setup()");
  81.   /*
  82.      In my experience it is good to declare the Serial object first, and put a last line that prints "Exiting setup()".
  83.      The reason is because errors in the setup() function can cause it to crash, but the processor just skips the remaining lines inside setup() and continues on to the main loop.
  84.      When you get this kind of error you will search fruitlessly in the main program to find what is not working.
  85.  
  86.      If you have the final line of setup() printing a Serial "exit" message, then you know that the whole setup() function completed normally.
  87.      If you don't see the "Exiting setup()" message, then that means that -something- wrong happened inside setup().
  88.   */
  89. }
  90.  
  91.  
  92. void loop() {
  93.  
  94.   if (door_sensor_mode == door_sensor_mode__enabled) {
  95.     /*
  96.        Break your program up into functions, and name the function what it does.
  97.        Generally you want a single function to do a single 'thing' or make a single decision.
  98.        Write all of the functions first, and then go back through and write what goes into them.
  99.        If you have named the functions well, you should be able to understand what needs to go into each of them!
  100.     */
  101.     check_door_sensor_for_press();
  102.   }
  103.   else { // if door_sensor_mode == door_sensor_mode__disabled
  104.     check_to_re_enable_door_sensor();
  105.   }
  106.  
  107.   if (alarm_waiting == true) {
  108.     check_alarm_timer();
  109.   }
  110.   else {
  111.     check_alarm_mode();
  112.   }
  113.  
  114.  
  115.   /*
  116.      Original code is below...........
  117.  
  118.     DoorSensor = analogRead(A0); // ------------------------------ this worked but looks odd.
  119.     // ----------------------------------------------------------- You declared DoorSensor as A0 (the pin number) but then after the setup() function, you used DoorSensor as a normal variable to hold the value of A0.
  120.  
  121.     if (DoorSensor < 50) {
  122.       analogWrite(LTG, 255);
  123.     }
  124.     else {
  125.       analogWrite(LTG, 0);
  126.     }
  127.     // ----------------------------------- Since the else() condition of both of them are from the same value (the sensor reading) the two separate if() statements above and below could be combined into an if-else statement.
  128.     // ----------------------------------- Placing them in two separate if() statements implies that both conditions could be true at the same time, which they can't.
  129.     if (DoorSensor > 600) {
  130.       analogWrite(LT, 255);
  131.       delay(75);
  132.       analogWrite(LT, 0);
  133.       analogWrite(LTR, 255);
  134.       delay(75);
  135.       analogWrite(LTR, 0);
  136.       analogWrite(buzz, 51);
  137.       delay(1000);
  138.       analogWrite(buzz, 0);
  139.     }
  140.     else {
  141.       analogWrite(LT, 0);
  142.       analogWrite(LTR, 0);
  143.       analogWrite(buzz, 0);
  144.     }
  145.   */
  146.  
  147.   //Serial.println(DoorSensor);
  148.   /*
  149.      Putting a Serial.print line into the main loop is not usually a good thing to do, since it will print out a LOT, and also since it will slow the main loop down.
  150.      It is okay to do this for testing or troubleshooting, but it's usually not helpful to leave it there permanetly.
  151.   */
  152. }
  153.  
  154.  
  155.  
  156.  
  157. void check_door_sensor_for_press() {
  158.   doorSensor_pin_value = analogRead(doorSensor_pin);
  159.   if (doorSensor_pin_value < 50) {
  160.     start_low_value_alarm();
  161.     // alternate disable_button() call location,,,,,,,,,,,,,,,,,,,,
  162.   }
  163.   else if (doorSensor_pin_value > 600) {
  164.     start_high_value_alarm();
  165.     // alternate disable_button() call location,,,,,,,,,,,,,,,,,,,,
  166.   }
  167.   else {
  168.     // We don't really need a condition here to "turn off" the alarm, since that is handled elsewhere.
  169.   }
  170.   disable_door_sensor(); // The way that this sketch is written, the door_sensor is only enabled once every 200 milliseconds.
  171.   // ----------------- This leaves all the other time free for the processor to do other things.
  172.   // ----------------- If you used it in the two "alternate locations" above, then the door_sensor would only be disabled after it was pressed... -and it would get checked thousands of times a second, as long as it wasn't pressed.
  173.   /*
  174.     With some Arduino programs you can check the button inputs on every pass through the loop and it doesn't matter, since the program is simple enough that it doesn't interfere with anything else.
  175.     The only question is if it's really necessary or helpful.
  176.  
  177.     If you are writing a more-complicated program, then you don't want to check the buttons on every pass through the main loop since there usually is no advantage to checking the intput buttons thousands of times a second.
  178.     For a normal device, you really only need to check input buttons 5 to 10 times a second.
  179.     For an Arduino game you might want to check the buttons maybe 20 times a second, but more than that isn't generally useful.
  180.   */
  181. }
  182.  
  183. void disable_door_sensor() {
  184.   door_sensor_mode == door_sensor_mode__disabled; // This changes the door_sensor from being active to being in debounce/delay mode.
  185.   door_sensor__begin_time = millis(); // This records the time that the door_sensor was initially pressed.
  186. }
  187.  
  188. void check_to_re_enable_door_sensor() {
  189.   // This function re-enables the door_sensor after the time value of door_sensor_delay_time has passed.
  190.   door_sensor__current_time = millis();
  191.   if (door_sensor__current_time >= door_sensor__begin_time) {
  192.     if (door_sensor__current_time >= (door_sensor__begin_time + door_sensor_delay_time)) {
  193.       door_sensor_mode = door_sensor_mode__enabled;
  194.     }
  195.   }
  196.   else {
  197.     door_sensor__begin_time = millis(); // millis() rollover condition
  198.   }
  199. }
  200.  
  201. void start_low_value_alarm() {
  202.   alarm_mode = 1; // The low-button-value alarm response is #1, and has no second stage.
  203. }
  204.  
  205. void start_high_value_alarm() {
  206.   alarm_mode = 2; // The high-button-value alarm response has multiple stages that begin with #2.
  207. }
  208.  
  209. void check_alarm_mode() {
  210.   // This function moves the alarm through its different stages.
  211.  
  212.   if (alarm_mode == 1) {
  213.     analogWrite(rgb_led__red_pin, 0);
  214.     analogWrite(rgb_led__green_pin, 255);
  215.     analogWrite(rgb_led__blue_pin, 0);
  216.     alarm_mode = 0;
  217.     /*
  218.        Note that the original sketch did not have any definite separate condition to turn off the green LED.
  219.        The if() statement that turned on the green LED was placed before the if() statement that operated the red and blue LEDs, and the final phase of the red & blue alarm set all three LED values back to zero.
  220.  
  221.        It appears as though the green LED was supposed to remain on all the time that the door was not opened (when doorSensor_pin_value < 50)
  222.        but the code had separate if() statements for turning on the green LED and also for turning on the other LEDs, implying that both states could occur at the same time?
  223.  
  224.        As a precaution to leaving the green LED on all the time, I put all three statements for the LEDs any time that any one of the LEDs was changed.
  225.     */
  226.   }
  227.  
  228.   if (alarm_mode > 1) {
  229.  
  230.     switch (alarm_mode) {
  231.  
  232.       case 2:
  233.         analogWrite(rgb_led__red_pin, 0);
  234.         analogWrite(rgb_led__green_pin, 0);
  235.         analogWrite(rgb_led__blue_pin, 255);
  236.         alarm_mode = 3;
  237.         set_alarm_to_short_delay();
  238.         break;
  239.  
  240.       case 3:
  241.         analogWrite(rgb_led__red_pin, 255);
  242.         analogWrite(rgb_led__green_pin, 0);
  243.         analogWrite(rgb_led__blue_pin, 0);
  244.         alarm_mode = 4;
  245.         set_alarm_to_short_delay();
  246.         break;
  247.  
  248.       case 4:
  249.         analogWrite(rgb_led__red_pin, 0);
  250.         analogWrite(rgb_led__green_pin, 0);
  251.         analogWrite(rgb_led__blue_pin, 0);
  252.         analogWrite(buzzer_pin, 51);
  253.         alarm_mode = 5;
  254.         set_alarm_to_long_delay();
  255.         break;
  256.  
  257.       case 5:
  258.         analogWrite(buzzer_pin, 0);
  259.         alarm_mode = 0;
  260.         break;
  261.     }
  262.   }
  263. }
  264.  
  265.  
  266. void set_alarm_to_short_delay() {
  267.   // All this function does is set the alarm timer to a short delay and sets the starting time.
  268.   alarm_time = alarm__short_delay;
  269.   alarm_waiting = true;
  270.   alarm__begin_time = millis();
  271. }
  272.  
  273. void set_alarm_to_long_delay() {
  274.   // All this function does is set the alarm timer to a long delay and sets the starting time.
  275.   alarm_time = alarm__long_delay;
  276.   alarm_waiting = true;
  277.   alarm__begin_time = millis();
  278. }
  279.  
  280. void check_alarm_timer() {
  281.   // This function re-enables the alarm after the time value of alarm_time has passed.
  282.   alarm__ending_time = millis();
  283.   if (alarm__ending_time >= alarm__begin_time) {
  284.     if (alarm__ending_time >= (alarm__begin_time + alarm_time)) {
  285.       alarm_waiting = false;
  286.     }
  287.   }
  288.   else {
  289.     alarm__begin_time = millis(); // millis() rollover condition
  290.   }
  291. }
  292.  
  293.  
  294. // --------- end ----------
Add Comment
Please, Sign In to add comment