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.