So I got my keypad and LCD in the mail. I ended up buying them from Jameco. The keypad was about $15 and the LCD was only $10. When you start adding up all of the $10 here and $15 there this project is starting to add up. I will have to list the total bill when I am done.
One of the costs that I didn't think that I would have was buying another arduino. I think that I am going to do just that though. After playing around with my new stuff I started to think about where I was going to stick this keypad and how I was going to enclose it. When I figured out where the thing was going I started to think about how I was going to run wire to it and that of course led to how much wire. 17 wires going from the arduino to the components for the keypad. That is a little bit more then the cat-5 that I was planning. There is also the problem of if the arduino would be able to drive enough power through 35 feet of wire to make the things work. I didn't really test this but I am positive that it was going to be a problem. Of course I still have the problem of the 2 arduinos communicating through 35 feet of wire but I know that people are doing that out there so I am not too worried about it.
There are other benefits to running the keypad on its own arduino. The biggest is that I don't really have to worry as much about how much code is in the program. Splitting the user interface code up from the actual security system monitoring code will probably half the code on each.
Another benefit is that I will get to play with making 2 arduinos communicate. I am thinking that if you are reading this blog you realize that it is more about the process then about the end product. I am going to assume for now that I will just use a serial connection between the 2. If I run into problems when I actually get a second arduino I will note the changes here.
So here is the setup. Fritzing ( the program I use to model my electronics ) didn't have the LCD and keypad components and I didn't want to take the time to make them. I know... shame on me. You are going to have to make due with a text description of how to put this together. What you will have when you are done is a keypad that you can use as a starter for any project that needs a keypad interface.
First of all let me apologize for the picture below. It looks a lot more complicated than it is because I didn't have a long breadboard. I ended up using my short one and the one on my protoshield. The thing attached to the LCD is not another arduino but only the protoshield, and I am only using the breadboard on it.
The keypad is the 4x4 keypad that I bought from Jameco. It has 9 pins on the back and is set up like a grid. The first four are the rows and the second are the columns. The 9th pin is for the electrostatic discharge shield which I am not connecting to anything. (Should I be?) Pin 1 is toward the 1 button. The first 4 pins are connected to the digital IO 12 through 9 on the arduino. The next 4 pins go through 10K resistors to a ground and also to the analog inputs 0 through 3 on the arduino. This is basically a big complicated pull down switch. The program causes a digital IO to go high then checks all of the analog inputs. If one of them is high then that means that one of the buttons on the row is pressed. Which analog input is high tells us what column it is and we can map the row and column to a particular key. The resistors just guarantee that if the button isn't pressed the analog input will be low when we check it.
For the piezo speaker the ground goes to the ground and the positive goes to digital pin 8 on the arduino.
The LCD I also got from Jameco. It is a 20 character, 4 row display. Also needed is a cheapo little potentiometer. I am using one that I have had for a few decades. I think that I got it with a intro to electronics kit back in the 80s. Still works great! I am using the LiquidCrystal library in the sketch code and the components are set up ALMOST exactly the same as the tutorial on arcuino.cc. The difference being that I am using pins 6 and 7 instead of 11 and 12. I am going to refer you to the tutorial for the setup for the LCD because I am lazy. It is at http://www.arduino.cc/en/Tutorial/LiquidCrystal. LCDs are super easy to use with the arduino and LiquidCrystal library.
First of all let me apologize for the picture below. It looks a lot more complicated than it is because I didn't have a long breadboard. I ended up using my short one and the one on my protoshield. The thing attached to the LCD is not another arduino but only the protoshield, and I am only using the breadboard on it.
The keypad is the 4x4 keypad that I bought from Jameco. It has 9 pins on the back and is set up like a grid. The first four are the rows and the second are the columns. The 9th pin is for the electrostatic discharge shield which I am not connecting to anything. (Should I be?) Pin 1 is toward the 1 button. The first 4 pins are connected to the digital IO 12 through 9 on the arduino. The next 4 pins go through 10K resistors to a ground and also to the analog inputs 0 through 3 on the arduino. This is basically a big complicated pull down switch. The program causes a digital IO to go high then checks all of the analog inputs. If one of them is high then that means that one of the buttons on the row is pressed. Which analog input is high tells us what column it is and we can map the row and column to a particular key. The resistors just guarantee that if the button isn't pressed the analog input will be low when we check it.
For the piezo speaker the ground goes to the ground and the positive goes to digital pin 8 on the arduino.
The LCD I also got from Jameco. It is a 20 character, 4 row display. Also needed is a cheapo little potentiometer. I am using one that I have had for a few decades. I think that I got it with a intro to electronics kit back in the 80s. Still works great! I am using the LiquidCrystal library in the sketch code and the components are set up ALMOST exactly the same as the tutorial on arcuino.cc. The difference being that I am using pins 6 and 7 instead of 11 and 12. I am going to refer you to the tutorial for the setup for the LCD because I am lazy. It is at http://www.arduino.cc/en/Tutorial/LiquidCrystal. LCDs are super easy to use with the arduino and LiquidCrystal library.
The code below is what runs everything and it is pretty much self documenting :). If you don't get the last joke you are probably not a programmer or manager of said programmers. Just install it an you get to hear the beep and see the key pressed. After you have played with it for a while search for the "now do something" and start there to implement your user interface. For instance I am going to use the 2nd key as a start command button so I might do something like:
if ( strcmp( newVal, "2ND") == 0 ) state = "StartCmd";
else if ( strcmp( state, "StartCmd" ) == 0 && strcmp( newVal, "1" ) == 0 ) turnOnAlarm();
That little bit of code would run the turnOnAlarm function when the user pressed 2nd then 1.
I will post the completed UI code when I get the rest of the stuff put together and figured out but this is the perfect starting point for any keypad device so I thought that I would throw this out now.
Another thing to note is that my piezo is a generic one and most out there are exactly like it but if the beep you hear is irritating then play with the tone variable until you like it. You could even change the program to add a function to change the tone when you press the up or down buttons. I probably will. Changing the value and then updating is a pain!
/*
* arduino keypad/lcd start
*
* author: Stacy Brothers
* http://stacysarduino.blogspot.com
*/
// include the library code:
#include <LiquidCrystal.h>
// debug stuff
boolean debug = true;
// communication stuff
const int MAX_CMD_LEN = 128;
char cmd[MAX_CMD_LEN];
boolean connected = false;
long pingWait = 0; // this is the counter to send the ping
const long pingSend = 50000L; // when to send the ping
long pingCount = 0; // how many times this has received a ping.
long pongCount = 0; // how many times this has received a pong.
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7,6,5,4,3,2);
// keypad stuff
int kppins[] = {12,11,10,9,0,1,2,3};
int keyWait = 0;
int keyDelay = 100; // If the last time this key was pressed < this then ignore
char* key[]={"1","2","3","UP",
"4","5","6","DOWN",
"7","8","9","2ND",
"CLEAR","0","HELP","ENTER"};
// noise maker stuff
int tone = 195;
// led stuff
int ledPin = 13;
void setup() {
// setup communications stuff
Serial.begin(9600);
// keypad pins
pinMode(kppins[0], OUTPUT);
pinMode(kppins[1], OUTPUT);
pinMode(kppins[2], OUTPUT);
pinMode(kppins[3], OUTPUT);
// set up the LCD
lcd.begin(20, 4); // 20 columns and 4 rows
// beeper
pinMode(8, OUTPUT);
}
void loop() {
if ( Serial.available() != 0 ) {
// something is on the line so read it
readln(cmd);
if ( debug && strcmp(cmd,"") != 0 ) {
Serial.print("Arduino got *");
Serial.print(cmd);
Serial.println("*");
}
}
if (strcmp(cmd,"") == 0 && pingWait > pingSend) {
// haven't sent or received any thing for a while so do a ping to see if anything is (still) there.
Serial.println("ping");
pingWait = 0;
} else if (strcmp(cmd, "pong") == 0) {
// received a pong response so something is connected
connected = true;
pingWait = 0;
pongCount++;
} else if (strcmp(cmd, "ping") == 0) {
// something wants to know if the arduino is still here. I must be connected. send a pong back.
Serial.println("pong");
connected = true;
pingWait = 0;
pingCount++;
}
cmd[0]= NULL; // what ever the command was reset it
// see if the keyboard has been pressed
int newVal = checkKeypad();
if ( newVal > -1 && keyWait > keyDelay ) {
keyBeep();
// now do something
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("Key pressed:");
lcd.print(key[newVal]);
keyWait = 0;
}
pingWait++;
keyWait ++;
}
void readln( char buffer[] ) {
char c;
int i = 0;
int quiet = 0;
while( true ) {
if ( Serial.available() ) {
quiet = 0;
c = Serial.read();
if ( c == 13 ) { // carriage return
Serial.read(); // line feed
break;
}
buffer[i++] = c;
if ( i == (MAX_CMD_LEN-1) ) break;
} else {
if ( quiet > 10000 ) break;
quiet ++;
}
delay(10); // short delay
}
buffer[i] = NULL;
}
void keyBeep() {
// beep and flash
digitalWrite(ledPin, HIGH);
for (long i = 0; i < 80000L; i += tone * 2.5) {
digitalWrite(8, HIGH);
delayMicroseconds(tone);
digitalWrite(8, LOW);
delayMicroseconds(tone);
}
digitalWrite(ledPin, LOW);
}
int checkKeypad() {
int rtn = -1;
for ( int i = 0; i < 4; i++ ) {
digitalWrite(kppins[i],HIGH);
for (int j = 0; j < 4; j ++) {
int pushed = map( analogRead(j), 0, 1024, 0, 2 );
if ( pushed == 1 ) {
rtn = (i<<2) + j;
}
}
digitalWrite(kppins[i],LOW);
}
return rtn;
}