Pages: [1] 2 3 4   Go Down
Author Topic: Car Keypad  (Read 9671 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Full Member
***
Karma: 0
Posts: 112
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey everyone.  After having it sit around unfinished for a few months, I finally finished my car door keypad code.  The keypad is a five button keypad from a ford explorer, interfaced with my arduino and ready to be embedded into my Dodge.  The software is 100% finished and now I'm letting the hardware run on 12v for a while in my house before I take the plunge and cut the hole in my door.

Basically, you type in the combo and it unlocks your doors. (closes an optical relay)  If you press the last two together, it locks your doors.  The backlight lights when you press a button, and goes out 4 seconds later.  The entered code is sliding, so if the code was 12345, you could press 5512345 and get in.  I thought about not having it this way, but I'd rather not have to wait if I mispress.  I mean, no one is really going to try and brute force it, so I'm not worried.  The entered code is cleared after the same timeout as the backlight.

This is my first real project, so it may be kind of hard to read.

Code:
// Car Keypad
// Version 0.20 beta
//
// Michael Casson Rogers (michael.casson@yahoo.com)
// March 10th, 2009
//
// Takes input from keys, compares last 5 pressed keys to the pre-programmed code.
// If last 5 pressed keys are the same as the code, unlock door.
// If last two buttons are pressed simultaneously, lock door.
//
// Input keys are assigned values starting with 0 for the first, 1 for the second, etc.
//
// Time out (reset input keys) after programmable time (default 4 seconds).
//
// For this program I borrowed heavily from Simple Simon 2.0 by Gian Pablo Villamil
// http://itp.nyu.edu/~gpv206/2006/09/simple_simon_v2.html
//


// Define the pins the lock and unlock relays are connected to.
#define UnlockPin 18
#define LockPin 19

#define BackLight 17 // Define backlight pin.

#define DebounceTime 20 // debounce time in milliseconds
#define TimeOutTime 4000 // timeout in milliseconds

// Define the pin assignments for the input switches
#define ButtonStartPin 2
#define ButtonEndPin 6

// Set how many buttons
int ButtonValues = ButtonEndPin - ButtonStartPin ;

int codeLength = 5; // Set code length
int CodeArray[5] = {1, 2, 4, 1, 0}; // Enter desired combination code here, must match codeLength
int InputArray[5] = {9, 9, 9, 9, 9}; // Starts InputArray with all 9's

// Remember when last press was for timeout function.
// Also, set lastPress as having just timed out so that the backlight doesn't light for the first few
// seconds on initialization because lastPress and millis are both zero.
unsigned long lastPress = millis() - (TimeOutTime + 1);

// Define inputScore (used to compare InputArray to CodeArray)
int inputScore = 0 ;
// Define rightAnswer (set to true when code is validated)
int rightAnswer = false ;

// counter for debouncing routine
unsigned long SwitchDownTime ;

void setup () {
//Serial.begin(9600);           // set up Serial library at 9600 bps, used for debugging.
pinMode(LockPin, OUTPUT);
pinMode(UnlockPin, OUTPUT);
pinMode(BackLight, OUTPUT);

for (int i = ButtonStartPin; i <= ButtonEndPin; i++) {
pinMode(i, INPUT);
}

}

// Main loop - should be easy to follow
void loop () {
getAnswer () ;
timeOut () ;
checkAnswer () ;
if (rightAnswer) {
Success();
}
}

// Get the user's button presses and store it in InputArray
void getAnswer () {

for (int i = 0; i < codeLength; i++) {
  for (int j = 0; j <= ButtonValues; j++) { // poll the switches
    if (digitalRead(ButtonStartPin+j)) {  // If current polled button is down
      SwitchDownTime = millis() ; // Record time it went down (for debounce)
      digitalWrite(BackLight, HIGH); // Light backlight while pressed
      lastPress = millis() ; // Needed here to light as soon as button is pressed
      while (digitalRead(ButtonStartPin+j)) { // While a button is pressed
        if (digitalRead(ButtonEndPin - 1) && digitalRead(ButtonEndPin)) { // If the last two are pressed together
          digitalWrite(LockPin, HIGH); //
        } else {
          digitalWrite(LockPin, LOW);
        }
      }

      if (millis() - SwitchDownTime > DebounceTime) { // If button was down longer than debounce
        InputArray[0] = InputArray[1];
        InputArray[1] = InputArray[2];
        InputArray[2] = InputArray[3];
        InputArray[3] = InputArray[4];
        InputArray[4] = j;
        lastPress = millis() ; //Needed here also, in case button is held down for more than timeout value
      } // end if
    } // end if
  } // end for
} // end for
} // end GetAnswer

// Compare CodeArray with InputArray
void checkAnswer () {

// Print current InputArray
//for (int i = 0; i < codeLength; i++) {
//  Serial.print(InputArray[i]);
//}
//  Serial.println(" ");
// End print current InputArray
    
inputScore = 0;
for (int i = 0; i < codeLength; i++) {
if (CodeArray[i] == InputArray[i]) {
inputScore = inputScore + 1;
}
}
if (inputScore == codeLength) {rightAnswer = true;}

}

void Success () {
digitalWrite(UnlockPin, HIGH);
delay(100);
digitalWrite(UnlockPin, LOW);
clearArray () ;
rightAnswer = false;
}

void timeOut () {
if (millis() - lastPress > TimeOutTime) {
  clearArray() ;
  digitalWrite(BackLight, LOW);
  lastPress = millis() - (TimeOutTime + 1); //lastPress follows millis() just outside of timeout, to prevent problems with millis rollover lighting backlight after 50 days
}  else {
  digitalWrite(BackLight, HIGH);
}
}

void clearArray () {
  InputArray[4] = 9;
  InputArray[3] = 9;
  InputArray[2] = 9;
  InputArray[1] = 9;
  InputArray[0] = 9;
}
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 112
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Photos:


Quick Keypad for writing software


Running in the house.


I really should have etched a board for this.


Schematic, quick and dirty.


The actual keypad it's wired to.

I had some shots of the board before I soldered the nano on it, so you could see the rest of the circuit, but I can't seem to find them.

The screw posts were mainly for testing, I wanted to solder my connections in permanently (connected to car with waterproof plugs) but I'm not sure if I'll bother to remove them when I install.  Anyone think they'll loosen and let go with time?

--

Also, as to not drain my car battery, I wanted to make it as low powered as possible.  I removed the power LED, but not sure how else to lower power.  It has to be available all the time, so the powered down modes of the chip wouldn't seem applicable.  It's pretty low power now, so I suppose I shouldn't worry about it.
Logged

0
Offline Offline
Edison Member
*
Karma: 8
Posts: 1411
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Good stuff!
A suggestion, if I may, for the version 2: make it remote controlled, with an IR receiver inside the car. No car thief uses a TV remote control.


Logged

Rio de janeiro
Offline Offline
Full Member
***
Karma: 0
Posts: 104
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Will you leave the option to open using the key?
Logged

Atascadero, CA
Offline Offline
Sr. Member
****
Karma: 2
Posts: 468
Arduino addict
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Pretty slick!  Here's another suggestion: make it honk the horn if the entered code is incorrect three times within a certain period.  That should help deter tampering.
Logged

What about elevensies? Luncheon? Afternoon tea? Dinner? Supper?

New Zealand
Offline Offline
God Member
*****
Karma: 0
Posts: 999
Arduino pebbles
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
It has to be available all the time, so the powered down modes of the chip wouldn't seem applicable.
You want to look at using one of the external or pin change interrupts to wake the processor in sleep mode. That would work in your situation AFAICT.

--Phil.
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 112
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
A suggestion, if I may, for the version 2: make it remote controlled, with an IR receiver inside the car. No car thief uses a TV remote control.
I've considered that, or RFID, but really my problem is always running out to my car and forgetting my key.  This way I don't need anything (remote, tag, key, fob) on me to get in.

Quote
Will you leave the option to open using the key?
Of course!  I didn't remove any functionality from my car.  To lock and unlock my car, all i had to do was close two wires already in the door together with either a 1k ohm resisitor (lock) or a 330 ohm resistor (unlock).  I wired those with tiny solid state relays on the board.  They are actually under the nano.

Quote
Here's another suggestion: make it honk the horn if the entered code is incorrect three times within a certain period.  That should help deter tampering.
I'm not really worried about anyone brute forcing the password.  I could make the code longer if I was worried.  I'd rather not have the car make noise.  Just my personal preference.

Quote
You want to look at using one of the external or pin change interrupts to wake the processor in sleep mode.
I've glanced over them before, but I didn't get a real solid grip on it.  Maybe I'll revisit it in the next few days.
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 112
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

As far as the sleep mode, it looks like I'd have to change the status of one of two pins to wake it.  Even if I made that pin one of my key's pins, it would only wake on that one key press.  I'd have to use it as my first number, and it would be obvious since the backlight wouldn't work until that one was pressed.

I can't think of how I would tie all five keys to change the state of the one pin without wreaking havok on my code entry.
Logged

Austin, TX
Offline Offline
Full Member
***
Karma: 2
Posts: 182
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
  about pin change interrupts. You would have to read the datasheet for the Atmel to get an idea of how to use the PCints.  But they do exactly what you want: when ANY of a set of pins changes, an interrupt can be generated.  It's easier when they are all on the same port, but it can be done.

As for power saving.  I don't know a lot about sleep mode, but there are several bits that turn off pieces of the chip that aren't used.  like analog input, secondary timer, UART, TWI etc.  Again it's in the datasheet. It saves some power when running, but sleep mode is probably going to save more.

HTH,
Logged

Chris J. Kiick
Robot builder and all around geek.

Rio de janeiro
Offline Offline
Full Member
***
Karma: 0
Posts: 104
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Connect a second wire from all keys to a interrupt pin. Probably, to avoid trying to awake the uC every time you press a key, you'll need a "state variable" telling you if the uC is awake or sleeping. I think it works...
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 112
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks chiick, I'll have to do some reading.

Lima, wouldn't that tie all of my buttons together?  Then pressing one presses all?

I wonder how much my car actually pulls when it's off.  I'll have to go measure sometime soon.  If it dwarfs what the nano is using now, I won't worry about it.  I'm really ready to be done testing and eager to install.
Logged

Atascadero, CA
Offline Offline
Sr. Member
****
Karma: 2
Posts: 468
Arduino addict
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
wouldn't that tie all of my buttons together?  Then pressing one presses all?
Actually that will work if you isolate the buttons with diodes on the lines going to the interrupt pin.
Logged

What about elevensies? Luncheon? Afternoon tea? Dinner? Supper?

0
Offline Offline
Full Member
***
Karma: 0
Posts: 112
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It looks like the only real considerable power savings comes from power-down.  To come out of power-down I would need to bring either pin 2 or 3 LOW.

The problem is, those pins are already held LOW all the time in my circuit.  (HIGH when button pressed) Perhaps for version 2.

If a typical car battery is about 45 amp hours, and I'm pulling 20mA or so, does that mean it would have to run for 1125 hours (almost 47 days) to half-discharge the battery?
« Last Edit: March 12, 2009, 08:30:27 am by neonpolaris » Logged

Atascadero, CA
Offline Offline
Sr. Member
****
Karma: 2
Posts: 468
Arduino addict
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
If a typical car battery is about 45 amp hours, and I'm pulling 20mA or so, does that mean it would have to run for 1125 hours (almost 47 days) to half-discharge the battery?
Yup.  Unless something shorts out, you won't drain the car battery with the Arduino.
Logged

What about elevensies? Luncheon? Afternoon tea? Dinner? Supper?

0
Offline Offline
Full Member
***
Karma: 0
Posts: 112
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Just as an update, I've decided to go with a different keypad. You see, the one pictured above has a solid membrane across the front. The first few buttons had a nice tactile response to being pressed, that is, you could 'feel it' when you pressed the button. But the last two, although they did work, didn't feel like you were doing anything. Since I'm ridiculously picky (and worried about longevity) I found another keypad. I found this one on a 2008 Escape: (Although it's on heaps of other models/years)


http://www.flickr.com/photos/43268066@N00/3421420250/

It has a nice feel, is good enough for Ford to use on their vehicles now, and still has the backlight. Unfortunately, it is not wired the same internally, so my old board is useless. I rewrote my program to handle the new keypad properly, but I still needed a new board. Instead of making another monstrocity like that first board, I learned enough Eagle to design a PCB and I've already sent it off to be profesionally fabbed. So now I'm waiting on this to come in the mail (a couple more weeks to go):


http://www.flickr.com/photos/43268066@N00/3421437586/

Note: That 1K resistor on the right side, above the 330, is incorrectly labelled. It should be 100. This board should fit just perfect into a radioshack 1x2x3in project box, and already have holes drilled to line up with the internal mounts in it.

I have the weather-proof external connectors, all my headers, resistors, internal connectors, and optical relays also. This board is more modular than the other one with quick disconnects for all external connections, and I'll be able to easily remove the Arduino Nano for reprogramming. I think I'll stick it in the door with some servo tape, and see how it holds up.

I'll post more when I get the pieces in!
Logged

Pages: [1] 2 3 4   Go Up
Jump to: