Advertisement
XirallicBolts

Milan - Remote Start - With LCD Display

Apr 22nd, 2017
257
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 17.09 KB | None | 0 0
  1. /*
  2. XirallicBolts
  3. 4/22/2017
  4. Remote Start program with passenger door method
  5. Bugfix: Chunk of code accidentally deleted
  6. Bugfix: Repeated brake timer resets
  7. */
  8.  
  9. #include <Wire.h>                                                               // Load the temperature sensor's library
  10. #include <LiquidCrystal_I2C.h>                                                  // Load the LCD's library
  11. LiquidCrystal_I2C lcd(0x3f, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);                  // Configure how to communicate with the LCD
  12.  
  13. #define BRAKES        A0                                                        // #define creates a single reference point for a
  14. #define TEMPERATURE   A1                                                        // value that may change in the future.   For example,
  15. #define FORCE0DEG     2                                                         // anywhere in the code we have "HORN", the compiler
  16. #define FORCE40DEG    3                                                         // will automatically replace it with '11', the pin the
  17. #define HORNLED       4                                                         // horn is connected to.
  18. #define BRAKELED      5                                                         // This means if you need to move the horn to pin 12,
  19. #define PASSENGERLED  6                                                         // you just need to change this one line and every
  20. #define PASSENGERDOOR 7                                                         // instance further along in the code will be changed.
  21. #define DRIVERHEAT    8                                                        
  22. #define PASSENGERHEAT 9
  23. #define DEFROST       10
  24. #define HORN          11
  25.  
  26.  
  27. void setup()
  28. {
  29.      //
  30.      // Stage 1: Initial Setup.  Set some variables and pin settings.
  31.      //
  32.      
  33.      Serial.begin(9600);                                                        // Begin communication with the LCD at 9600 baud
  34.      lcd.begin(20,4);                                                           // Initialize the LCD, set to 20 characters wide, 4 lines tall
  35.  
  36.      pinMode(BRAKES, INPUT);                                                    // For each pin, set whether it's an input or output.
  37.      pinMode(TEMPERATURE, INPUT);                                               // Some pins use an internal pullup resistor to stabilize the
  38.      pinMode(FORCE0DEG, INPUT_PULLUP);                                          // signal. (INPUT_PULLUP)
  39.      pinMode(FORCE40DEG, INPUT_PULLUP);
  40.      pinMode(HORNLED, OUTPUT);
  41.      pinMode(BRAKELED, OUTPUT);
  42.      pinMode(PASSENGERLED, OUTPUT);
  43.      pinMode(PASSENGERDOOR, INPUT);
  44.      pinMode(DRIVERHEAT, OUTPUT);
  45.      pinMode(PASSENGERHEAT, OUTPUT);
  46.      pinMode(DEFROST, OUTPUT);
  47.      pinMode(HORN, INPUT);
  48.      
  49.      digitalWrite(DRIVERHEAT, HIGH);                                            // The relay outputs need to be shut off right away.
  50.      digitalWrite(PASSENGERHEAT, HIGH);                                         // Their behavior is opposite what you would expect,
  51.      digitalWrite(DEFROST, HIGH);                                               // where LOW is on and HIGH is off.
  52.  
  53.      int HornTriggered = 0;                                                     // Create variables we will be using later.
  54.      int DoorDetected = 0;                                                      // int:  Integers (whole numbers)
  55.      int BrakeDetected = 0;                                                     // float: Floating Point (numbers with decimals)
  56.      int OldFloor = 10;
  57.      int ProgressXOffset = 4;
  58.      int Force0Deg = digitalRead(FORCE0DEG);                                    // Set 'Force0Deg' based on the status of pin FORCE0DEG.
  59.      int Force40Deg = digitalRead(FORCE40DEG);                                  // If the switch is ON, the value is 0. Otherwise, it's 1.
  60.      float WarmupDuration = 15000;
  61.      float AmbientTemp = (((analogRead(TEMPERATURE)*.48828125)*1.8)+32);        // Read the analog temperature sensor and convert to Farenheit
  62.      
  63.      if(Force0Deg == 0){  AmbientTemp = 0;  }                                   // If the 'Force Temperature' switch is used, overwrite the
  64.      if(Force40Deg == 0){ AmbientTemp = 40; }                                   // 'AmbientTemp' with 0°F or 40°F as needed.
  65.      
  66.      lcd.setCursor(0,0);                                                        // Move the LCD's cursor to the top left corner
  67.      lcd.print(" Watching for Horn     [            ]   --------------------"); // Print the text to the LCD screen.
  68.  
  69.  
  70.      //
  71.      // Stage 2: Watch the horn for ~10 seconds to see if it chirps.
  72.      //          Horn chirp indicates the car was remote started.
  73.      //
  74.  
  75.  
  76.      
  77.      for(int t=0; t<599; t++)                                                   // for(initial_condition;  loop_while_true; do_each_loop)
  78.      {                                                                          //  initial_condition: Create 't', set to 0
  79.                                                                                 //  loop_while_true: t<599.  When 't' is 600, the loop ends
  80.                                                                                 //  do_each_loop: t++. Adds 1 to 't'
  81.                                                                                 // This creates a loop that will repeat 600 times.
  82.                                                                                
  83.           if(digitalRead(HORN) == LOW)                                          // If the HORN pin goes LOW (Horn chirps, voltage drops
  84.           {                                                                     // to 0v), set the HornTriggered variable to 1 and print
  85.                HornTriggered = 1;                                               // 'Chirp Detected' to the LCD.  Then turn on the Horn
  86.                lcd.setCursor(3,4);                                              // LED by setting its output pin to HIGH.
  87.                lcd.print("Chirp Detected");
  88.                digitalWrite(HORNLED, HIGH);
  89.           }
  90.          
  91.           if(t % 50 == 0)                                                       // To create the progress bar, the modulo (%) divides
  92.           {                                                                     // 't' by 50. If the remainder is 0, 't' is currently a
  93.                lcd.setCursor(ProgressXOffset,2);                                // multiple of 50.
  94.                lcd.print(char(255));                                            // Print special character 255 (solid box) to the LCD
  95.                ProgressXOffset++;                                               // Move the progress bar X offset to the next position
  96.           }
  97.           delay(10);                                                            // Wait 10 milliseconds before continuing.
  98.      }
  99.  
  100.  
  101.      //
  102.      // Stage 3: Continue if the horn chirped, end the program if it didn't.
  103.      //
  104.  
  105.       if(HornTriggered == 0)
  106.       {
  107.           delay(500);
  108.           lcd.clear();
  109.           lcd.print("   PROGRAM HALTED      No Horn Signal   --------------------");
  110.       }
  111.  
  112.  
  113.       if(HornTriggered == 1)
  114.       {
  115.           //
  116.           // Stage 4: Wait ~13 seconds to allow the car to wake up.
  117.           //
  118.          
  119.           lcd.clear();
  120.           delay(50);
  121.           lcd.print("Climate Control Boot    [          ]    --------------------Ambient Temp: ");
  122.           lcd.print(AmbientTemp);
  123.           lcd.setCursor(18,3);
  124.           lcd.print(char(223));                                                 // Print a degree (°) symbol
  125.           lcd.print("F");
  126.           if(AmbientTemp > 150)                                                 // A bad temperature sensor will give an unusually
  127.           {                                                                     // high reading. Anything above 150°F will display
  128.                lcd.setCursor(0,3);                                              // a 'Fault' message.
  129.                lcd.print("[!]TEMP SENSOR FAULT");
  130.           }
  131.          
  132.           lcd.setCursor(5,2);
  133.           for(int t=0; t<10; t++)                                               // Another for() loop, ten cycles with a 1¼ second
  134.           {                                                                     // delay for each loop. Print a block character
  135.                lcd.print(char(255));                                            // each loop.  Quick and easy 12½-second delay
  136.                delay(1250);                                                     // with a progress bar.
  137.           }
  138.           delay(75);
  139.  
  140.           //
  141.           // Stage 5: Momentarily activate the Driver and Passenger Heat relays (simulate button presses),
  142.           //          then continuously hold the Defrost relay. Setting a pin to LOW turns the relay ON,
  143.           //          while setting a pin to HIGH will shut the relay off.
  144.           //
  145.          
  146.           lcd.setCursor(0,0);
  147.           lcd.print("                                                            ");
  148.           lcd.setCursor(0,0);
  149.           lcd.print("Driver Relay ON");
  150.           digitalWrite(DRIVERHEAT, LOW);
  151.           delay(150);
  152.           lcd.setCursor(0,0);
  153.           lcd.print("Driver Relay OFF");
  154.           digitalWrite(DRIVERHEAT, HIGH);
  155.           delay(350);
  156.           lcd.setCursor(0,1);
  157.           lcd.print("Passenger Relay ON");
  158.           digitalWrite(PASSENGERHEAT, LOW);
  159.           delay(150);
  160.           lcd.setCursor(0,1);
  161.           lcd.print("Passenger Relay OFF");
  162.           digitalWrite(PASSENGERHEAT, HIGH);
  163.           delay(350);
  164.           lcd.setCursor(0,2);
  165.           lcd.print("Defrost Relay ON");
  166.           digitalWrite(DEFROST, LOW);
  167.           delay(1000);
  168.  
  169.           //
  170.           // Stage 6: Set the length of the warmup period based on ambient temperature.
  171.           //          Colder temperatures mean longer runtimes ranging from 1 minute to
  172.           //          15 minutes (coldest).  
  173.           //          '||' means OR, while '&&' means AND.
  174.           //
  175.  
  176.           if(AmbientTemp <= 32 || AmbientTemp >= 150){    WarmupDuration = 15000;  }
  177.           if(AmbientTemp > 32  && AmbientTemp < 60)  {    WarmupDuration = 8000;   }
  178.           if(AmbientTemp >= 60 && AmbientTemp < 150) {    WarmupDuration = 1000;   }
  179.  
  180.  
  181.           //
  182.           // Stage 7: Monitor the brakes and passenger door during warmup.
  183.           //          The BRAKE pin is an analog signal, ranging from 0 to 1023.
  184.           //          If it exceeds 800, the brake pedal is being pressed.
  185.           //
  186.           //          The PASSENGERDOOR is a digital signal. If the door is opened,
  187.           //          the pin will go HIGH.
  188.  
  189.  
  190.           lcd.clear();
  191.           lcd.print("Watching for Brakes     [          ]    --------------------");
  192.  
  193.           ProgressXOffset = 5;
  194.           for(int TimeRemaining = WarmupDuration; TimeRemaining>0; TimeRemaining--)
  195.           {
  196.  
  197.                //
  198.                // Stage 7a: Create the Minutes:Seconds countdown timer.
  199.                //           'floor' will remove all decimals without rounding.
  200.                //           Since a TimeRemaining of 7,000 is 7 minutes, we can
  201.                //           divide TimeRemaining by 1000 to get our Minutes.
  202.                //           To get Seconds, remove the Minutes (in milliseconds)
  203.                //           and multiply by .06 to convert to seconds.
  204.                //
  205.                //           For example, take a TimeRemaining of 4495.
  206.                //           Minutes: 4395/1000 is 4.395, 'floor' converts this to 4.
  207.                //           Seconds: 4395-(4*1000) is 435.  435*.06 is 26.1 seconds.
  208.                //
  209.                
  210.                int Minutes = floor((TimeRemaining/1000));
  211.                int Seconds = ((TimeRemaining-(Minutes*1000))*.06);
  212.                lcd.setCursor(8,3);
  213.                lcd.print(Minutes);
  214.                lcd.print(":");
  215.                if(Seconds < 10){ lcd.print("0"); }          // If Seconds is less than 10, print a leading 0 to prevent
  216.                lcd.print(Seconds);                          // 2 minutes, 8 seconds from being displayed as "2:8"
  217.                lcd.print(" ");
  218.  
  219.                //
  220.                // Stage 7b: Create the progress bar. Since we have a variable time length, the
  221.                //           math is trickier.  We find the percentage remaining by dividing
  222.                //           TimeRemaining and WarmupDuration.  '57%' is expressed as '.5700'.
  223.                //           Multiply the percentage by 10 so it becomes 5.7, then floor() it to 5
  224.                //           Each loop, compare what the current 'floor' is to the previous loop.
  225.                //           When the percentage becomes 49%, the floor value will be 4.
  226.                //           Each time the NewFloor doesn't match OldFloor, add a progress bar chunk,
  227.                //           move the cursor (ProgressXOffset) forward one space, and set OldFloor to
  228.                //           match the new NewFloor.
  229.                //
  230.  
  231.                int NewFloor = floor((TimeRemaining/WarmupDuration)*10);
  232.                if(OldFloor != NewFloor)
  233.                {
  234.                     lcd.setCursor(ProgressXOffset,2);
  235.                     lcd.print(char(255));
  236.                     ProgressXOffset++;
  237.                     OldFloor = NewFloor;
  238.                }
  239.  
  240.                //
  241.                // Stage 7c: If the BRAKE pin goes above 800, the brakes are being pressed.
  242.                //           Turn on the Brake LED and turn off the Defrost relay.
  243.                //           If the passenger door was already opened, immediately exit the loop.
  244.                //           If the passenger door wasn't opened, reset the timer to 1 minute
  245.                //           to give the passenger time to get in.
  246.                //           BrakeDetected is used to prevent the timer from constantly resetting
  247.                //           from frequent brake presses (parking lots, reversing, etc)
  248.                //
  249.  
  250.                if(analogRead(BRAKES) >= 800 && BrakeDetected == 0)
  251.                {
  252.                     digitalWrite(BRAKELED, HIGH);
  253.                     digitalWrite(DEFROST, HIGH);
  254.                     lcd.setCursor(3,3);
  255.                     lcd.print("Brake Detected!");
  256.                     delay(2000);
  257.                     TimeRemaining = 1000;
  258.                     WarmupDuration = 1000;
  259.                     ProgressXOffset = 5;
  260.                     BrakeDetected = 1;
  261.                     lcd.print("  Passenger Delay       [          ]    --------------------");
  262.                }
  263.  
  264.                //
  265.                // Stage 7d: If the passenger door is opened, set DoorDetected to 1,
  266.                //           turn on the Passenger LED, and print a message to the LCD.
  267.  
  268.  
  269.                if(digitalRead(PASSENGERDOOR) == HIGH)
  270.                {
  271.                     digitalWrite(PASSENGERLED, HIGH);
  272.                     DoorDetected = 1;
  273.                     lcd.setCursor(0,3);
  274.                     lcd.print("Passenger Detected!");
  275.                     delay(1000);
  276.                }
  277.                delay(50);
  278.           }
  279.  
  280.           //
  281.           // Stage 8: If the door was opened, assume there is a passenger and do nothing.
  282.           //          If the door was NOT opened, turn off the passenger heated seat.
  283.           //          The 'switch' command is similar to using several 'if' statements.
  284.           //          Everything within 'case 0' occurs if DoorDetected is 0.
  285.           //          Likewise, 'case 1' is if DoorDetected is 1.
  286.           //          'default' is if DoorDetected is neither 0 nor 1, which should never happen.
  287.  
  288.  
  289.           lcd.clear();
  290.           switch(DoorDetected)
  291.           {
  292.                case 0:
  293.                     lcd.setCursor(0,0);
  294.                     lcd.print(" No Passenger Found");
  295.                     delay(1000);
  296.                     lcd.setCursor(0,1);
  297.                     lcd.print("Passenger Relay ON ");
  298.                     digitalWrite(PASSENGERHEAT, LOW);
  299.                     delay(150);
  300.                     lcd.setCursor(0,1);
  301.                     lcd.print("Passenger Relay OFF");
  302.                     digitalWrite(PASSENGERHEAT, HIGH);
  303.                     delay(350);
  304.                     lcd.setCursor(0,1);
  305.                     lcd.print("Passenger Relay ON ");
  306.                     digitalWrite(PASSENGERHEAT, LOW);
  307.                     delay(150);
  308.                     lcd.setCursor(0,1);
  309.                     lcd.print("Passenger Relay OFF");
  310.                     digitalWrite(PASSENGERHEAT, HIGH);
  311.                     delay(5000);
  312.                     lcd.clear();
  313.                     lcd.print("                          Complete!            Program");
  314.                     break;
  315.                    
  316.                case 1:
  317.                     lcd.print("                          Complete!            Program");
  318.                     break;
  319.                    
  320.                default:
  321.                     lcd.print("You should never see this message.");
  322.                     break;
  323.           }
  324.      }
  325. }
  326.  
  327.  
  328. void loop(){
  329.      // Do nothing. Entire program is run-once.
  330.      delay(20000);
  331. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement