Monday, April 19, 2010

Got a keypad and an LCD

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. 


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;
}

Wednesday, March 10, 2010

Driving Mrs. Ademco



The siren on my current security system is made by Ademco.


It needs a half an amp at 12 volts to sound 106 decibels.  This is a problem since the output on the Arduino is around 5 volts max. Since I decided to use as much of my current system as I can I need to figure out how to drive the siren with what I have.  Fortunately my current system also has a 12 Volt sealed lead acid rechargeable battery for backup.


To get these three things working together I am going to need something called a driver.  A driver is basically a switch except the switch is flipped by a small positive input current.  Drivers are used a lot for doing the same thing with motors.

My driver is actually a pretty simple circuit.  The Arduino is connected to the base of a transistor (TIP31) through a resistor (10K). The Vcc of the 12 V battery goes to the siren. The siren goes to the collector of the transistor.  The emitter of the transistor is connected to the ground of the battery and the ground on the Arduino.



The only difference between driving a motor and a siren is that I don't think that I need to worry about feedback with a siren.  With a motor, when you turn the circuit off, you sometimes get a jolt of feedback from the motor.  Simple motor drivers just bridge between the collector and emitter with a diode to give the jolt somewhere to drain to.  I haven't seen any feed back from my circuit so hopefully this isn't going to be a problem.  I probably could do it anyway, it is just a diode, but what I have works.

Another thing that I need is a charger for the battery.  The charger on my current system is built into the board of the system so I can't use it and I don't know much about building a charger so I will probably just buy one.  The place where I am getting all of my sensors, www.homesecuritystore.com, has them starting at 14 bucks and going to 130. This is a little confusing because they seem to be similar systems.  Why the difference in prices?  I am not going to worry about that until I buy the sensors.

It seems that I can also use the battery to run my Arduino when the power goes south.  I was a little worried about it being too much for the regulator on the Arduino but a guy name Mike Cook at www.thebox.myzen.co.uk did the calculations and they look right, so I am going to trust him.  This seems to be working out pretty good.

Now I need to get rid of the code to make the siren sound in my current Arduino code and replace it with a simple cause the output to go high.

Next thing to think about is a keypad and display.

Monday, March 1, 2010

Mux

So having a security system that has only 6 analog inputs is kind of a bummer.  Of course the Arduino has 15 digital inputs along with the 6 analog but the way that I wanted to do the sensors was analog.

There are a couple of things that I could do to get more inputs.

One would be to upgrade to the Arduino Mega which has 16 analog and 54 digital.  This is better than my 6 and 16 and I probably could use the digital inputs for some of the sensors.  The Mega also has a lot more memory which would be cool but really don't need it (yet).  The big problem with this solution is that the Mega is about 60 bucks.

Since I already have a Arduino I am a little hesitant to go buy another even if it is bigger and better.  Fortunately you can make a few IOs into a bunch more IOs using a multiplexer ( mux for short ).  Look at the wikipedia link to see what a mux really is but basically it allows me to scrunch a bunch of input down to one or a few.  The circuit is more complicated than just reading a value on a wire but not too much so.

I went out looking for a mux.  There aren't a lot of places you can get these ICs on the web but I was able to find them for under a couple of bucks before shipping.  Add to that shipping and then I also need a board or shield to put it on with the pin connectors and I am up to at least 15 bucks.  It seemed like a big pain.

Then I came upon the Mux Shield from Mayhew Labs.  20 bucks for a shield that turns 4 digital and 3 analog IOs into 48.  It is designed to work with the Arduino and the only assembly is soldering a few headers on.

About 4 days later I got it in the mail.  The Mayhew Labs site has some example code on their site but it is so simple to use that I just took a line or two from their stuff and ripped out something a little more compact to test the board with.  Very cool, very easy.  Now I have gone from having to worry about "how I am going to access all of the sensors that I am planning" to "what can I do with all of these IOs".  I think that I will have to play with some other home automation after I finish the security system.

The code below reads inputs 16 and 17.  These are the 0th and 1st IOs on M1 which is the middle multiplexer.  Plug a couple potentiometers into these headers.  One row of headers is ground, one is Vcc and the bottom is the one that will be read.

void setup() { 
  pinMode(5, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(2, OUTPUT); 
  
  Serial.begin(9600);
}

void loop() { 
  int val = getSensorValue(16);
  Serial.print( "16:" );
  Serial.println( val );
  val = getSensorValue(17);
  Serial.print( "17:" );
  Serial.println( val );
  delay(200);
}

int getSensorValue( int sensor ) { 
  int muxId = sensor >> 4;
  int inputId = sensor % 16;
  
  digitalWrite(5, (inputId&15)>>3); 
  digitalWrite(4, (inputId&7)>>2);  
  digitalWrite(3, (inputId&3)>>1);  
  digitalWrite(2, (inputId&1));
  
  return analogRead(muxId);
}


I don't know if this is the best code but it works great.  I will post the security system code change for the new shield next post along with the change with for the real siren. 

I had to think about how to plug the sensors into the mux shield in a more secure way.  If I just plug the wires into the header like I would when I am prototyping they will probably fall out.  I probably should have ordered the mux shield without the headers on and soldered in male headers instead of the female headers. I will have to find out if he sells them that way.  Then I found some 4 pin female connectors to put on the ends of my sensor wires.  That will probably stay pretty secure.  UPDATE:  The mux shield without headers is what I was thinking it was.  If I were starting this from the beginning I might have just bought it and then soldered on the male headers.  Maybe Mark will offer a "Production Version" of his mux shield already assembled like this.

Pics of the mux shield on the Arduino, breakaway male headers and headers in the shield with a connector plugged in to input 17 or the input 1 on M1.

Sunday, January 31, 2010

The Simple Alarm

A simple alarm system is pretty easy.  Most alarm systems are just checking to see if the current going through a wire stops or changes in some way to say that the sensor has been tripped. 

You might ask why we would want the current to continually be going through the sensor instead of just kicking it high when the sensor is tripped.  That would certainly use less power and might be less work for the circuits.  This might be a good thing if your alarm is powered by a battery.  The problem with this is that to disable a sensor all you would need to do is clip a wire running to the sensor and it would never be tripped.  However if you are checking for the current to go low from your sensor then clipping a wire would trigger it off. 

Ok, if you knew that the system was looking for the low current, then instead of clipping the wire you could just bridge the wires.  Then if the sensor is tripped the current would still be going through the bridge and the monitor wouldn't know it was tripped.  There is a way to deal with this problem also.  Instead of just looking for a wire to go low we could look for the current going through the wire to change.

One way to do this is to have three wires and a couple of different sized resistors at the sensor. Two of the wires are the positive and ground, the last wire would be attached between the two resistors where you would measure. When the sensor is tripped the positive or ground is disconnected from the circuit and the value at the third wire changes to either very high or very low.  Your monitor would measure a difference and decide that the sensor has tripped.  If some one tries to cut or bridge the wires then the resistance in the circuit will still change and the monitor would signal a tripped sensor.  Of course there are still ways you could defeat a sensor like this but it would take time measuring current in all of the wires and building something that would measure exactly the same.  You would also have to be careful to not do anything that would cause a change in the wires while you were measuing or the monitor would think that it was tripped.  Part of what you are measuring is the difference in the resistors.  The resistors in the sensor wouldn't have to be different but for the different sensors you would probably want to switch them up just to make things more difficult to defeat.    

There is an issues that you need to deal with in a circuit like this.  It is that resistance in a circuit can change over time.  If a connection becomes oxidized or the sensor wears then the value that is measured at the third wire could change.  If you have hard coded the value you are going to start seeing false alarms.  In our system the values will be measured at start up or when the alarm is set.  Since you have different resistance in each of the different sensors you also have to deal with storing more than one value.

Below is the circuit that I have built to test my basic alarm system along with a parts list.  Instead of using 2 resistors I used a potentiometer.  You could probably also use one of these in your actual sensor too.  The pot is basically the circuit from above only the resistance can be varied very easily which was nice for testing the initialization stuff.  There are two of these sensors with the pots set at different resistance.  I haven't actually tested the sensors in my current alarm system to see if they work this way but I am pretty sure that the motion sensor does and if not I will deal with it when I get there.  The button is to turn the alarm off on the hardware side.  And of course every alarm has to be loud and obnoxious so I added a peizo buzzer and a routine in the sketch that will make noise.  I will replace this with a system to kick off the siren that is now a part of my current alarm. 


Fritzing Bill of Materials:

J1 Piezo Speaker
R1 10kΩ Resistor
R3 Basic Potentiometer
R4 Basic Potentiometer
S1 Pushbutton

This is what the system might look like if you want to build it with your ardurino and a small bread board.


Then what it looks like on the proto shield on top of my Arduino.
 

By the way, the program that I used to generate the schematic and the component view is an open-source app called fritzing and its available at http://www.fritzing.org/.  It is very cool and very useful.

By the way also, the proto shield came with my Arduino projects pack but the url on the board that tells how to assemble it is http://www.ladyada.net/make/pshield.  It came unassembled and I had to solder it together.  I love soldering ( is that weird or what ).  The shield is also very cool and very useful.

The biggest thing this time is the sketch code. 

/*
 * arduino alarm controler code
 *
 * author: Stacy Brothers
 * http://stacysarduino.blogspot.com
 */

const int MAX_CMD_LEN = 128;
char cmd[MAX_CMD_LEN];

int buttonState = 0;
int alarmPin = 9;
int sensorVal = 0;

const int ALARM_OFF = 0;
const int ALARM_ON = 1;
int alarmState = ALARM_ON;
boolean alarmTriggered = false;
int allowedError = 5;

int zonePins[] = {0,2};
int zoneVal[] = {0,0};
boolean zoneTripped[] = {false,false};
const int ZONE_OFF = 0;
const int ZONE_ON = 1;
int zoneStatus[] = {ZONE_ON, ZONE_ON};
int zoneCount = 2;

boolean connected = false;

void setup() {
  Serial.begin(9600);

  // triggers on doors etc.
  for ( int i = 0; i < zoneCount; i++ ) { 
    pinMode(zonePins[i], INPUT);
  }

  pinMode(13, OUTPUT);  // alarm flasher
  pinMode(alarmPin, OUTPUT); // alarm sounder
  
  pinMode(7, INPUT);  // reset alarm
  
  setupSensors();

}

long pingWait = 0; // this is the counter to send the ping
const long pingSend = 500000L; // when to send the ping

void loop() {
  if ( Serial.available() != 0 ) { 
      readln(cmd);
  }

  if (strcmp(cmd,"") == 0 && pingWait == pingSend) { 
    Serial.println("ping");
    pingWait = 0;
  } else if (strcmp(cmd, "pong") == 0) { 
    connected = true;
    pingWait = 0;
  } else if (strcmp(cmd, "ping") == 0) {
    Serial.println("pong");
    connected = true;
    pingWait = 0;
  } else if (strcmp(cmd, "reset alarm") == 0) { 
    Serial.println("alarm reset");
    alarmTriggered = false;
    digitalWrite( 13, LOW );
  } else if (strcmp(cmd, "alarm off") == 0) { 
    alarmState = ALARM_OFF;
    Serial.println("alarm turned off");
  } else if (strcmp(cmd, "alarm on") == 0) { 
    alarmState = ALARM_ON;
    Serial.println("alarm turned on");
  }
  cmd[0]= NULL;  // what ever the command was reset it
  pingWait++;
  
  // loop through the zones and make sure they are not triggered
  for ( int i = 0; i < zoneCount; i++ ) {
    if ( !zoneTripped[i] && zoneStatus[i] == ZONE_ON && alarmState == ALARM_ON ) { 
      sensorVal = analogRead(zonePins[i]);
      if ( sensorVal > zoneVal[i] + allowedError || sensorVal < zoneVal[i] - allowedError ) { 
        Serial.print("tripped zone: ");
        Serial.println(i);
        alarmTriggered = true;
        zoneTripped[i] = true;
      }
    }
  }
  
  // reset the alarm
  buttonState = digitalRead(7);
  if ( buttonState == LOW && alarmTriggered == true ) { 
    //if ( connected ) Serial.println("alarm reset");
    Serial.println("alarm reset");
    alarmTriggered = false;
    digitalWrite( 13, LOW );
    for ( int i = 0; i < zoneCount; i++ ) zoneTripped[i] = false;
  }
  
  if ( alarmTriggered && alarmState == ALARM_ON ) { 
    soundAlarm();
  }
  
}

// setup the base values for the sensors
void setupSensors() { 
  for ( int i = 0; i < zoneCount; i++ ) {
    int test1 = analogRead(zonePins[i]);
    delay(500);
    int test2 = analogRead(zonePins[i]);
    delay(500);
    int test3 = analogRead(zonePins[i]);
    delay(500);
    zoneVal[i] = ( test1 + test2 + test3 ) / 3; 
  }
}

int tone = 1915;  // c note...
boolean flasher = false;

void soundAlarm() {
  for (long i = 0; i < 200000L; i += tone * 2) {
    digitalWrite(alarmPin, HIGH);
    delayMicroseconds(tone);
    digitalWrite(alarmPin, LOW);
    delayMicroseconds(tone);
  }
  
  if ( tone == 1915 ) tone = 1700;   // d note...
  else tone = 1915;
  
  if ( flasher ) { 
    digitalWrite( 13, LOW );
    flasher = false;
  } else { 
    digitalWrite( 13, HIGH );
    flasher = true;
  } 
  // pause between notes
  delay(150); 
}

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;     
}

So this might look like a lot but really it isn't.  The setup method contains a call to the function setupSensors.  This is what I was talking about before.  This function takes a couple of readings on the pots and averages them.  It loops through all of the pots and stores a check value for each.  I had to do the average thing because I found that sometimes the pots are at a point where they will bounce by one.  So far it has only been by one but when I read the sensors in the loop I give or take 5.  I can change this later if I find that I don't need 5 or if I need more. So far it looks like I need only one or two.

There is the bit for making the noise on the piezo.  It will all go when I figure out how to hook up the real siren.  The problem with the real siren is that the thing is built to use 12V and 500 mA.  That is a way more than the arduino will push so I am going to use the rechargeable 12V on my current alarm to drive it and a big ole transistor to switch it on with input from the arduino. It might also be nice if I could figure out how to step the 12V down to use it for the arduino power. 

There is a bit of code in there that I will be using to turn zones on and off and to only deal with sensors that are in specific states so that I don't have to deal with events multiple times.

I had to play with the communication between the arduino and the java application quite a bit.  I want the arduino to be able to continue even if the java app isn't there so I have a flag to tell the arduino to deal with is if it is not.  Both applications need to deal with timeouts in their readln routines.  I have made these timeouts pretty short because we don't want to miss a sensor being tripped and if the program misses a command it will be back again soon enough to check again anyway.  I made it so that the sketch would notify the java app that there was an sensor tripped when the alarm was on.  The java app can reset the alarm and turn off the alarm all together.  That is it. 

Here is the code for the java app.

package com.stacybro.arduino;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;

/**
 * @author Stacy Brothers
 * http://stacysarduino.blogspot.com
 *
 */
public class ArduinoAlarmCtrl {
 
 static String CRLN = "" + (char)13 + (char)10;

 public static void main(String[] args) {
  InputStream input;
     OutputStream output;  
  CommPortIdentifier portId = null;
  SerialPort port = null;
  
  try {
   portId = CommPortIdentifier.getPortIdentifier("COM3");
   port = (SerialPort)portId.open("arduino", 4000);
         input = port.getInputStream();
         output = port.getOutputStream();
         port.setSerialPortParams(9600,
                 SerialPort.DATABITS_8,
                 SerialPort.STOPBITS_1,
                 SerialPort.PARITY_NONE);
         while ( true ) { 
          String inStr = readln(input);
          String outStr;
          System.out.println("From Arduino:|" + inStr + "|");
          if ( inStr.equals("ping" ) ) { 
           outStr = "pong" + CRLN;
           System.out.println("Sending:"+ outStr); output.write(outStr.getBytes());
          } else if ( inStr.startsWith("zone triggered:" ) ) {
           String zone = inStr.replace("zone triggered:", "");
           System.out.println("Alarm Triggered!  zone: " + zone + " (" + inStr + ")");
           // wait a while and then reset the alarm
           inStr = readln(input);System.out.println("From Arduino:|" + inStr + "|");
           if ( inStr.equals("alarm reset")) continue;
           outStr = "reset alarm" + CRLN;
           System.out.println("Sending:"+ outStr); output.write(outStr.getBytes());
          } 
         }
         
  } catch (Exception e) {
   e.printStackTrace();
  } finally { 
   port.close();
  }
 }
 
 static String readln(InputStream input) throws IOException { 
        String inStr = "";
        int quiet = 0;
        while ( true ) {
         if (input.available() > 0) {
          int inChar = input.read();
          if ( inChar == 13 ) { // carriage return 
           input.read();  // line feed
           break;
          }
          quiet = 0;
          inStr += (char)inChar;
         } else {
          if ( quiet > 5000 ) break;
          quiet ++;
            }
         try {
    Thread.sleep(10);
   } catch (InterruptedException e) {
    System.out.println("Interrupted");
   }
        }
  return inStr;
 }
}

The only really important thing is the readln routine in the java app.

The next things that I need to deal with is the real user interface on both the hardware side and the software side.

Saturday, January 9, 2010

Communication

Please note that I am making some assumptions. 

The first is that you have already made yourself familiar with your arduino by going through the getting started tutorials at http://arduino.cc/en/Guide/HomePage.  This would mean that you have already installed the arduino tools and have tested the USB communication between the arduino and your PC using the arduino tool.  BTW I am using version 17.

The next is that you are familiar with java.  If not then buy a book.  Or you could pay a university a crazy amount of money to teach you and then buy a book to teach yourself.  That is pretty much what I did.  Whatever.  I don't feel resentful about that at all.  Anyway...

I am using eclipse for the java side of the development and the arduino tool for the sketch code. Since you are familiar with java and you understand the arduino tool then that shouldn't be a problem.  I am also running everything under windows.

First thing that you need to do to start is install a communication library for your Java environment.  You can use the Sun libraries or you can use the rxtx communication libraries.  The Sun stuff is better documented and probably better supported but the arduino tool uses the rxtx and it seems to work well.  The arduino tool also comes with all of the required rxtx libraries and it turns out it is pretty easy to install so I went with the rxtx.  To use them I just copied the rxtxSerial.dll from the arduino directory into the bin directory of the jre that I am using (ex: c:/program files/java/jre6/bin).  I also included the RXTXcomm.jar file from the ardurino tools lib directory in my class path.  If everything is set up right, the first time that you run your java application you will see a message like the following:

     Stable Library
     =========================================
     Native lib Version = RXTX-2.1-7
     Java lib Version = RXTX-2.1-7

If you don't see that then you will probably see an error about the serial libraries not being found which may mean that you do not have your dll in the correct place.  Make sure that you are using the jre that you think you are ( in eclipse you would look under Window->Preferences->Java->Installed JREs and see which one is checked ).  If not then look at the rxtx link above or try using the sun api instead. 

So here is some code.  First is the sketch code the arduino will run.  Basically communicating via serial is built into the arduino.  It is how you program the thing.  This program starts the conversation.  It just sits there saying hello until somethng responds.  Then it responds based on what it receives.

const int MAX_CMD_LEN = 128;

char cmd[MAX_CMD_LEN];
int quiet = 0;

void setup() {
     Serial.begin(9600);
     // start conversation
     while (Serial.available() <= 0) {
          Serial.println("hello");
          delay(300);
     }
}

void loop() {
     readln(cmd);
     if (strcmp(cmd,"") == 0) {
          Serial.println("ping");
          delay(1000);
          readln(cmd);
          if ( strcmp(cmd,"pong") != 0 ) {
               // there was a problem so do something like flash a red led
               Serial.println("error!");
          }
     } else if (strcmp(cmd, "hello") == 0) {
          Serial.println("How are you?");
     } else if (strcmp(cmd, "How are you?") == 0) {
          Serial.println("I am working...");
          delay(3000);
          Serial.println("good bye.");
     } else if (strcmp(cmd, "ping") == 0) {
          Serial.println("pong");
     }
}

void readln( char buffer[] ) {
     char c;
     int i = 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);
     }
     buffer[i] = NULL;
}

Some things to note about the sketch code. I have set the max length of a string to be received at 128 characters. Should be enough but if it isn't then we will change it. All communication is ended by sending a CR/LF. The arduino does this automatically with println().  In the Java code below we do it by appending the (char)13 + (char)10 on to all of the strings that are going to be sent.  The readln has a timeout of sorts.  If things are quiet for a while it will ping the java app.  It should get a pong back and if it doesn't then something might have gone wrong.  The quiet on the line could be a normal situation. 


The Java class does almost exactly the same thing as the arduino sketch.  Super simple.  Listen on the port specified and respond.  Note the com port that my machine decided to use was COM3.  Yours might be different.  Look in your control panel device manager under USB controllers.
 
package com.stacybro.arduino;
 
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import gnu.io.CommPortIdentifier;

public class Communicate {
     static String CRLN = "" + (char)13 + (char)10;

     public static void main(String[] args) {
          InputStream input;
          OutputStream output;
          CommPortIdentifier portId = null;
          SerialPort port = null;

          try {
               portId = CommPortIdentifier.getPortIdentifier("COM3");
               port = (SerialPort)portId.open("testing", 4000);
               input = port.getInputStream();
               output = port.getOutputStream();
               port.setSerialPortParams(9600,
                         SerialPort.DATABITS_8,
                         SerialPort.STOPBITS_1,
                         SerialPort.PARITY_NONE);
               while ( true ) {
                    String inStr = readln(input);
                    String outStr;
                    System.out.println("From Arduino:" + inStr );
                    if ( inStr.equals("hello")) {
                         outStr = "hello" + CRLN;
                         System.out.println("Sending:"+ outStr);
                         output.write(outStr.getBytes());
                    } else if ( inStr.equals("How are you?" ) ) {
                         outStr = "I am functional." + CRLN;
                         System.out.println("Sending:"+ outStr);
                         output.write(outStr.getBytes());
                         Thread.sleep(5000);
                         outStr = "How are you?" + CRLN;
                         System.out.println("Sending:"+ outStr);
                         output.write(outStr.getBytes());
                    } else if ( inStr.equals("ping" ) ) {
                         outStr = "pong" + CRLN;
                         System.out.println("Sending:"+ outStr);
                         output.write(outStr.getBytes());
                    } else {
                         outStr = "I am testing" + CRLN;
                         System.out.println("Sending:"+ outStr);
                         output.write(outStr.getBytes());
                    }
               }
          } catch (Exception e) {
               e.printStackTrace();
          } finally {
               port.close();
          }
     }

     static String readln(InputStream input) throws IOException {
          String inStr = "";
          while ( true ) {
               // should probably do something here to do a timeout
               if (input.available() > 0) {
                    int inChar = input.read();
                    if ( inChar == 13 ) { // carriage return
                         input.read(); // line feed
                         break;
                    }
                    inStr += (char)inChar;
               }
          }
          return inStr;
     }
}

Thanks to Silveira at http://silveiraneto.net/2009/03/01/arduino-and-java/.  It is what got me started.

Friday, January 8, 2010

The Project

One of my favorite magazines is a DIY magazine called Make.  Pretty much every issue since the magazine started has had a project including an Arduino.

The Arduino is "an open-source physical computing platform based on a simple microcontroller board".  The Arduino has been used as a component in about a bazillion projects.  Everything from robots to "scent dispensers", musical instruments to moisture sensors.  I read (not sure where) that a recent NASA satellite launch had 3 Arduino based sensor projects.

I wanted one.  But I had to have some justification to spend the cash.  It isn't that they are expensive, you can get one for as little as 35 bucks, 20 if you want to practice your soldering skills.  I am just one of those types of people that can't buy themselves a "toy" without feeling guilty.  I had to have some really useful project in order to feel good about spending the time and money.

The Project: Home Security System.  OK, we already have a security system, but it sucks.  I can't control it from my phone or the web and the keypad is ugly.  Was that enough justification?  Too late... already bought the arduino!

The Ardurino Projects Pack.  I decided to go all out, because I might need the extra components (yuk yuk), and went with the Arduino Projects Pack from the Maker Shed.  99 bucks.  Only 2 digits and not too much guilt, after all my wife can spend that on hair cuts for her and our daughter.  It seems to have lots of fun stuff in it like thermistors, tilt sensors, a couple dinky motors, photoresistors, and an NPN Transistor.  Well, the thermistors added an item to my feature list but I will have to think a bit in order to figure out how to use the rest.  Is a RC robot a necessary part of a security system?  Most important part is the Arduino Duemilanove.  Only 14 digital inputs ( 6 analog ) so I am going to have to use one of the protoboards for a couple of multiplexers to give me more inputs.  The ATmega328 microprocesser, 32K of flash memory to hold controller code.  Hopefully that will be enough to give me good control.  This model has a USB link built on which is probably the most important part.  Since I am a software developer "in my real life", there is also going to be a lot I want to do on the server that it is connected to. 

Planned Features:
  • Enough sensors for all of the windows and doors.
  • Motion sensor.
  • Connect to our Fire / CO2 alarm system.
  • Key pad & lcd, maybe touch screen interface. 
  • House temperature sensor ( got a thermistor, gotta use it! )
  • Web based interface.
  • Commands and notifications via text message/email.
I think that my first task will be to figure out how to do communication between Arduino and Java app.


A quick google for "arduino security system" tells me that I am not alone in thinking that this is a good project.  There should be lots of resources anyway.

Some links:
http://arduino.cc/en
http://blog.makezine.com/archive/arduino
http://hacknmod.com/hack/top-40-arduino-projects-of-the-web
http://www.arduinoprojects.com/
http://www.practicalarduino.com/projects