Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- XirallicBolts
- 4/22/2017
- Remote Start program with passenger door method
- Bugfix: Chunk of code accidentally deleted
- Bugfix: Repeated brake timer resets
- */
- #include <Wire.h> // Load the temperature sensor's library
- #include <LiquidCrystal_I2C.h> // Load the LCD's library
- LiquidCrystal_I2C lcd(0x3f, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Configure how to communicate with the LCD
- #define BRAKES A0 // #define creates a single reference point for a
- #define TEMPERATURE A1 // value that may change in the future. For example,
- #define FORCE0DEG 2 // anywhere in the code we have "HORN", the compiler
- #define FORCE40DEG 3 // will automatically replace it with '11', the pin the
- #define HORNLED 4 // horn is connected to.
- #define BRAKELED 5 // This means if you need to move the horn to pin 12,
- #define PASSENGERLED 6 // you just need to change this one line and every
- #define PASSENGERDOOR 7 // instance further along in the code will be changed.
- #define DRIVERHEAT 8
- #define PASSENGERHEAT 9
- #define DEFROST 10
- #define HORN 11
- void setup()
- {
- //
- // Stage 1: Initial Setup. Set some variables and pin settings.
- //
- Serial.begin(9600); // Begin communication with the LCD at 9600 baud
- lcd.begin(20,4); // Initialize the LCD, set to 20 characters wide, 4 lines tall
- pinMode(BRAKES, INPUT); // For each pin, set whether it's an input or output.
- pinMode(TEMPERATURE, INPUT); // Some pins use an internal pullup resistor to stabilize the
- pinMode(FORCE0DEG, INPUT_PULLUP); // signal. (INPUT_PULLUP)
- pinMode(FORCE40DEG, INPUT_PULLUP);
- pinMode(HORNLED, OUTPUT);
- pinMode(BRAKELED, OUTPUT);
- pinMode(PASSENGERLED, OUTPUT);
- pinMode(PASSENGERDOOR, INPUT);
- pinMode(DRIVERHEAT, OUTPUT);
- pinMode(PASSENGERHEAT, OUTPUT);
- pinMode(DEFROST, OUTPUT);
- pinMode(HORN, INPUT);
- digitalWrite(DRIVERHEAT, HIGH); // The relay outputs need to be shut off right away.
- digitalWrite(PASSENGERHEAT, HIGH); // Their behavior is opposite what you would expect,
- digitalWrite(DEFROST, HIGH); // where LOW is on and HIGH is off.
- int HornTriggered = 0; // Create variables we will be using later.
- int DoorDetected = 0; // int: Integers (whole numbers)
- int BrakeDetected = 0; // float: Floating Point (numbers with decimals)
- int OldFloor = 10;
- int ProgressXOffset = 4;
- int Force0Deg = digitalRead(FORCE0DEG); // Set 'Force0Deg' based on the status of pin FORCE0DEG.
- int Force40Deg = digitalRead(FORCE40DEG); // If the switch is ON, the value is 0. Otherwise, it's 1.
- float WarmupDuration = 15000;
- float AmbientTemp = (((analogRead(TEMPERATURE)*.48828125)*1.8)+32); // Read the analog temperature sensor and convert to Farenheit
- if(Force0Deg == 0){ AmbientTemp = 0; } // If the 'Force Temperature' switch is used, overwrite the
- if(Force40Deg == 0){ AmbientTemp = 40; } // 'AmbientTemp' with 0°F or 40°F as needed.
- lcd.setCursor(0,0); // Move the LCD's cursor to the top left corner
- lcd.print(" Watching for Horn [ ] --------------------"); // Print the text to the LCD screen.
- //
- // Stage 2: Watch the horn for ~10 seconds to see if it chirps.
- // Horn chirp indicates the car was remote started.
- //
- for(int t=0; t<599; t++) // for(initial_condition; loop_while_true; do_each_loop)
- { // initial_condition: Create 't', set to 0
- // loop_while_true: t<599. When 't' is 600, the loop ends
- // do_each_loop: t++. Adds 1 to 't'
- // This creates a loop that will repeat 600 times.
- if(digitalRead(HORN) == LOW) // If the HORN pin goes LOW (Horn chirps, voltage drops
- { // to 0v), set the HornTriggered variable to 1 and print
- HornTriggered = 1; // 'Chirp Detected' to the LCD. Then turn on the Horn
- lcd.setCursor(3,4); // LED by setting its output pin to HIGH.
- lcd.print("Chirp Detected");
- digitalWrite(HORNLED, HIGH);
- }
- if(t % 50 == 0) // To create the progress bar, the modulo (%) divides
- { // 't' by 50. If the remainder is 0, 't' is currently a
- lcd.setCursor(ProgressXOffset,2); // multiple of 50.
- lcd.print(char(255)); // Print special character 255 (solid box) to the LCD
- ProgressXOffset++; // Move the progress bar X offset to the next position
- }
- delay(10); // Wait 10 milliseconds before continuing.
- }
- //
- // Stage 3: Continue if the horn chirped, end the program if it didn't.
- //
- if(HornTriggered == 0)
- {
- delay(500);
- lcd.clear();
- lcd.print(" PROGRAM HALTED No Horn Signal --------------------");
- }
- if(HornTriggered == 1)
- {
- //
- // Stage 4: Wait ~13 seconds to allow the car to wake up.
- //
- lcd.clear();
- delay(50);
- lcd.print("Climate Control Boot [ ] --------------------Ambient Temp: ");
- lcd.print(AmbientTemp);
- lcd.setCursor(18,3);
- lcd.print(char(223)); // Print a degree (°) symbol
- lcd.print("F");
- if(AmbientTemp > 150) // A bad temperature sensor will give an unusually
- { // high reading. Anything above 150°F will display
- lcd.setCursor(0,3); // a 'Fault' message.
- lcd.print("[!]TEMP SENSOR FAULT");
- }
- lcd.setCursor(5,2);
- for(int t=0; t<10; t++) // Another for() loop, ten cycles with a 1¼ second
- { // delay for each loop. Print a block character
- lcd.print(char(255)); // each loop. Quick and easy 12½-second delay
- delay(1250); // with a progress bar.
- }
- delay(75);
- //
- // Stage 5: Momentarily activate the Driver and Passenger Heat relays (simulate button presses),
- // then continuously hold the Defrost relay. Setting a pin to LOW turns the relay ON,
- // while setting a pin to HIGH will shut the relay off.
- //
- lcd.setCursor(0,0);
- lcd.print(" ");
- lcd.setCursor(0,0);
- lcd.print("Driver Relay ON");
- digitalWrite(DRIVERHEAT, LOW);
- delay(150);
- lcd.setCursor(0,0);
- lcd.print("Driver Relay OFF");
- digitalWrite(DRIVERHEAT, HIGH);
- delay(350);
- lcd.setCursor(0,1);
- lcd.print("Passenger Relay ON");
- digitalWrite(PASSENGERHEAT, LOW);
- delay(150);
- lcd.setCursor(0,1);
- lcd.print("Passenger Relay OFF");
- digitalWrite(PASSENGERHEAT, HIGH);
- delay(350);
- lcd.setCursor(0,2);
- lcd.print("Defrost Relay ON");
- digitalWrite(DEFROST, LOW);
- delay(1000);
- //
- // Stage 6: Set the length of the warmup period based on ambient temperature.
- // Colder temperatures mean longer runtimes ranging from 1 minute to
- // 15 minutes (coldest).
- // '||' means OR, while '&&' means AND.
- //
- if(AmbientTemp <= 32 || AmbientTemp >= 150){ WarmupDuration = 15000; }
- if(AmbientTemp > 32 && AmbientTemp < 60) { WarmupDuration = 8000; }
- if(AmbientTemp >= 60 && AmbientTemp < 150) { WarmupDuration = 1000; }
- //
- // Stage 7: Monitor the brakes and passenger door during warmup.
- // The BRAKE pin is an analog signal, ranging from 0 to 1023.
- // If it exceeds 800, the brake pedal is being pressed.
- //
- // The PASSENGERDOOR is a digital signal. If the door is opened,
- // the pin will go HIGH.
- lcd.clear();
- lcd.print("Watching for Brakes [ ] --------------------");
- ProgressXOffset = 5;
- for(int TimeRemaining = WarmupDuration; TimeRemaining>0; TimeRemaining--)
- {
- //
- // Stage 7a: Create the Minutes:Seconds countdown timer.
- // 'floor' will remove all decimals without rounding.
- // Since a TimeRemaining of 7,000 is 7 minutes, we can
- // divide TimeRemaining by 1000 to get our Minutes.
- // To get Seconds, remove the Minutes (in milliseconds)
- // and multiply by .06 to convert to seconds.
- //
- // For example, take a TimeRemaining of 4495.
- // Minutes: 4395/1000 is 4.395, 'floor' converts this to 4.
- // Seconds: 4395-(4*1000) is 435. 435*.06 is 26.1 seconds.
- //
- int Minutes = floor((TimeRemaining/1000));
- int Seconds = ((TimeRemaining-(Minutes*1000))*.06);
- lcd.setCursor(8,3);
- lcd.print(Minutes);
- lcd.print(":");
- if(Seconds < 10){ lcd.print("0"); } // If Seconds is less than 10, print a leading 0 to prevent
- lcd.print(Seconds); // 2 minutes, 8 seconds from being displayed as "2:8"
- lcd.print(" ");
- //
- // Stage 7b: Create the progress bar. Since we have a variable time length, the
- // math is trickier. We find the percentage remaining by dividing
- // TimeRemaining and WarmupDuration. '57%' is expressed as '.5700'.
- // Multiply the percentage by 10 so it becomes 5.7, then floor() it to 5
- // Each loop, compare what the current 'floor' is to the previous loop.
- // When the percentage becomes 49%, the floor value will be 4.
- // Each time the NewFloor doesn't match OldFloor, add a progress bar chunk,
- // move the cursor (ProgressXOffset) forward one space, and set OldFloor to
- // match the new NewFloor.
- //
- int NewFloor = floor((TimeRemaining/WarmupDuration)*10);
- if(OldFloor != NewFloor)
- {
- lcd.setCursor(ProgressXOffset,2);
- lcd.print(char(255));
- ProgressXOffset++;
- OldFloor = NewFloor;
- }
- //
- // Stage 7c: If the BRAKE pin goes above 800, the brakes are being pressed.
- // Turn on the Brake LED and turn off the Defrost relay.
- // If the passenger door was already opened, immediately exit the loop.
- // If the passenger door wasn't opened, reset the timer to 1 minute
- // to give the passenger time to get in.
- // BrakeDetected is used to prevent the timer from constantly resetting
- // from frequent brake presses (parking lots, reversing, etc)
- //
- if(analogRead(BRAKES) >= 800 && BrakeDetected == 0)
- {
- digitalWrite(BRAKELED, HIGH);
- digitalWrite(DEFROST, HIGH);
- lcd.setCursor(3,3);
- lcd.print("Brake Detected!");
- delay(2000);
- TimeRemaining = 1000;
- WarmupDuration = 1000;
- ProgressXOffset = 5;
- BrakeDetected = 1;
- lcd.print(" Passenger Delay [ ] --------------------");
- }
- //
- // Stage 7d: If the passenger door is opened, set DoorDetected to 1,
- // turn on the Passenger LED, and print a message to the LCD.
- if(digitalRead(PASSENGERDOOR) == HIGH)
- {
- digitalWrite(PASSENGERLED, HIGH);
- DoorDetected = 1;
- lcd.setCursor(0,3);
- lcd.print("Passenger Detected!");
- delay(1000);
- }
- delay(50);
- }
- //
- // Stage 8: If the door was opened, assume there is a passenger and do nothing.
- // If the door was NOT opened, turn off the passenger heated seat.
- // The 'switch' command is similar to using several 'if' statements.
- // Everything within 'case 0' occurs if DoorDetected is 0.
- // Likewise, 'case 1' is if DoorDetected is 1.
- // 'default' is if DoorDetected is neither 0 nor 1, which should never happen.
- lcd.clear();
- switch(DoorDetected)
- {
- case 0:
- lcd.setCursor(0,0);
- lcd.print(" No Passenger Found");
- delay(1000);
- lcd.setCursor(0,1);
- lcd.print("Passenger Relay ON ");
- digitalWrite(PASSENGERHEAT, LOW);
- delay(150);
- lcd.setCursor(0,1);
- lcd.print("Passenger Relay OFF");
- digitalWrite(PASSENGERHEAT, HIGH);
- delay(350);
- lcd.setCursor(0,1);
- lcd.print("Passenger Relay ON ");
- digitalWrite(PASSENGERHEAT, LOW);
- delay(150);
- lcd.setCursor(0,1);
- lcd.print("Passenger Relay OFF");
- digitalWrite(PASSENGERHEAT, HIGH);
- delay(5000);
- lcd.clear();
- lcd.print(" Complete! Program");
- break;
- case 1:
- lcd.print(" Complete! Program");
- break;
- default:
- lcd.print("You should never see this message.");
- break;
- }
- }
- }
- void loop(){
- // Do nothing. Entire program is run-once.
- delay(20000);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement