Keyless Entry System

I'm working on a project using an Arduino Duemelinove and Ethernet shield. Upon visiting a certain page on the local network and successfully loggin into a pre-made user account, the server will send a request to the Arduino. Upon receiving this request, the Arduino will activate a Relay, which in turn activates a set of Electric Door Strikes, enabling keyless entry into the building for a limited (10 seconds) time.

The Ethernet communication is working flawlessly, as well as the activation of the strikes. The current issue is, after a short running time and/or heavy 'spam' of the device, the Arduino will restart, locking the doors for a very short time instead of the expected amount of time. The problem seems to be one of two - either the TCP/IP buffer is overflowing (Although this seems like it won't be the case, as there are still problems even after 'spamming the device' has stopped and typical use resumes. It is more likely to be an overheating issue - the Arduino runs very hot and is probably restarting itself. Additionally, this restart only happens when the strikes are active and pulling current.

However, I do not see where the Arduino is overheating. The circuit is quite simple: The Arduino is powered by an external 12v Power Supply (A typical wall adapter), and is plugged into the network via the Ethernet Shield and a CAT5 cable. A single Digital Output pin is used to control the Relay. The relay also requires a GND and +5v and these are supplied off of the respective pins on the Arduino. The relay also has two output pins, one taking the 12v source rail and one that outputs that voltage when activated. The 12v source rail is taken off of the Vin pin from the Arduino, therefore bypassing the microcontroller and power supply circuit and should not be damaging/overheating the device, correct?

If the issue really is that I'm using the Vin pin to power the relay, what are my options? I'd like to not have to splice some wires but it could be done if that would solve the overheating problem. Additionally, if there is anything else that may be of issue, please let me know.

The relay used in the circuit is this one: http://www.robotshop.com/dfrobot-single-relay.html

And the Strikes are the 1006 and 5200 Series Strikes by HES.

Thank you!

The problem seems to be one of two

There could be other issues. Posting your code would be a big help.

It is more likely to be an overheating issue - the Arduino runs very hot and is probably restarting itself.

The Arduino should not be hot. Is it the chip itself that gets hot? Or, is it the voltage regulator that gets hot?

The Arduino is powered by an external 12v Power Supply (A typical wall adapter),

A 7.5 V adapter would require that the voltage regulator dissipate less energy as heat.

If the issue really is that I'm using the Vin pin to power the relay, what are my options?

How are you doing this? I would expect the relay to be between a digital pin and ground, for energizing the relay when you set the pin HIGH.

Since the lockup occurs when the relay is active, I'd look at noise as a possible issue.

The problem seems to be one of two

There could be other issues. Posting your code would be a big help.

Code is posted below. I believe it is more of a hardware issue but, of course, people make mistakes myself included :) My apologies for the double post. I am unable to include the code in this post (Too many characters) and I cannot attach it.

It is more likely to be an overheating issue - the Arduino runs very hot and is probably restarting itself.

The Arduino should not be hot. Is it the chip itself that gets hot? Or, is it the voltage regulator that gets hot?

The regulator is definitely the hottest spot. I believe that the rest of the chip is getting hot because the regulator is so hot, but the entire device is quite warm.

The Arduino is powered by an external 12v Power Supply (A typical wall adapter),

A 7.5 V adapter would require that the voltage regulator dissipate less energy as heat.

I considered a lower voltage adapter, however the Electric Strikes require either a 12v or 24v source. I figured I should go with the lowest, applicable source and selected 12v. For more explanation, I am using a Smartpak3 device between the relay and the Strikes. This device helps maintain the lifetime of the Strike as well as protect it against possible spikes, and helps manage power usage. The Smartpak3 has two settings - 12v and 24v. I suppose I could dabble with lower voltages, but the desired effect is not guaranteed at that point.

If the issue really is that I'm using the Vin pin to power the relay, what are my options?

How are you doing this? I would expect the relay to be between a digital pin and ground, for energizing the relay when you set the pin HIGH.

The relay has 7 pins. These are separated into two categories - Control and Output (For lack of better terms) Control has 3 pins: +5v, CTRL, GND. The +5v and GND are plugged in accordingly, and the Active-Low CTRL pin is connected directly into a Digital Output pin on the Arduino. Output has 4 pins: INVCC, INGND, OUTVCC, OUTGND. The input VCC and GND are hooked up to Vin on the Arduino and Ground, respectively. Vin is the 12v output from the wall adapter, if I am not mistaken. The output VCC and GND are connected to the Electric Strikes via the Smartpak3 devices mentioned above. The doors unlock correctly, the problem is the restarting of the microcontroller, which turns off the Relay and therefore locks the doors again.

Since the lockup occurs when the relay is active, I'd look at noise as a possible issue.

I'll look into this. However, I've had the relay run at times varying from 30 seconds straight to 1 second off-on-off-on and no problems. It seems to be a problem resulting from the Microcontroller itself.

/*
  Arduino Server
 Author: Devin Pentecost
 Date: July 5 2012
 Last Edited: July 5 2012
 
 Based off and borrowed from code by Randy Sarafan
 http://www.instructables.com/id/Arduino-Ethernet-Shield-Tutorial/?ALLSTEPS
 
 IP Address finding was made possible by the Arduino Forum Thread at:
 http://arduino.cc/forum/index.php/topic,54378.0.html
 More information can be found in the documentation.
 
 To use:
 http://%IP%/$%DURATION%
 %IP% is the Arduino's IP Address
 %DURATION% is the duration in ms
 
 Note: Arduino has integer limits of -32768 to +32767
 */

#include <SPI.h>
#include <Ethernet.h>

//#define DEBUG_SERIAL
#define DEBUG_PRINT_TIME
//#define DEBUG_PRINT_IP
//#define DEBUG_NO_OUTPUT

//Some globals. All preference changes should be available here
static const int MIN_TIME = 0;
static const int MAX_TIME = 10000;

//IP Address. Use comma instead of period!
#define IP_ADDRESS 192,168,1,250
byte gateway[] = { 
  192, 168, 1, 1 };
byte subnet[]  = { 
  255, 255, 255, 0 };

static const int R0_PIN = 8;
static const int R1_PIN = 9;
//////////////////////////////////////////////////////////////

//Prototypes
void activateBothRelays(void);
void activateRelay0(void);
void activateRelay1(void);
void deactivateBothRelays(void);
void deactivateRelay0(void);
void deactivateRelay1(void);
void checkUnlockRequest(void);

//Some vars
boolean incoming = 0;
unsigned long inputTime = 0;
boolean thisTime = 0;
byte requestIP[4];

//For keeping track of the unlock process. We have an array
//It contains whether or not it is running, set, as well as start/end times
unsigned long unlockRequest[4] = {
  0, 0, 0, 0};

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = { 
  0x00, 0xAA, 0xBB, 0xCC, 0xDA, 0x02 };
IPAddress ip(IP_ADDRESS);

// Initialize the Ethernet server library
// with the IP address and port you want to use 
// (port 80 is default for HTTP):
EthernetServer server(80);

void setup()
{ 
  //Setup pins
  pinMode(R0_PIN, OUTPUT);
  pinMode(R1_PIN, OUTPUT);
  digitalWrite(R0_PIN, HIGH);
  digitalWrite(R1_PIN, HIGH);

  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip, gateway, subnet);
  server.begin();

#ifdef DEBUG_SERIAL
  Serial.begin(9600);
#endif
}

void loop()
{
  //We want to see if there is anything we need to take into account for the 
  checkUnlockRequest();

  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    String time = "";

    //Request the IP and store it
    client.getIPAddress(&requestIP[0]);

    while (client.connected()) {

      if (client.available()) {
        char c = client.read();

#ifdef DEBUG_SERIAL
        Serial.print(c);
#endif

        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {

#ifndef DEBUG_NO_OUTPUT
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: application/json");
          client.println("Connnection: close");
          client.println();

          //Output JSON         
          client.print("{");
          client.print("\"timeRequested\":");
          client.print(inputTime);
          client.print(",\"requestIgnored\":");
          client.print(!thisTime);
          if(thisTime) thisTime = 0;

#ifdef DEBUG_PRINT_IP
          client.print(",\"requestIP\":\"");
          client.print(requestIP[0]);
          for(int i = 1; i < 4; ++i){
            client.print(".");
            client.print((int)requestIP[i]);
          }
          client.print("\"");
#endif

#ifdef DEBUG_PRINT_TIME
          client.print(",\"START.CURRENT.END\":\"");
          client.print(unlockRequest[2]);
          client.print(".");
          client.print(millis());
          client.print(".");
          client.print(unlockRequest[3]);
          client.print("\"");
#endif

          client.println("}");
#endif

          break;
        }

        //reads URL string from $ to first blank space
        if(incoming && c == ' '){ 
          incoming = 0;

          //Are we not already requesting?
          if(!unlockRequest[0]){
            //We are done with the number parsing. We can change it to an int!
            char charArray[time.length()+1];
            time.toCharArray(charArray, time.length()+1);
            inputTime = atoi(charArray);

            //Put it in range
            if(inputTime < MIN_TIME) inputTime = MIN_TIME;
            if(inputTime > MAX_TIME) inputTime = MAX_TIME;

#ifdef DEBUG_SERIAL
            Serial.print("\nInput Time: ");
            Serial.println(inputTime);
#endif

            //We want to tell ourselves we are requesting an open
            //Mark the current time and the requested time
            unlockRequest[0] = 1;
            unlockRequest[1] = 0;
            unlockRequest[2] = millis();
            unlockRequest[3] = unlockRequest[2] + inputTime;

            //Get this party started
            thisTime = 1;
            checkUnlockRequest();
          }
        }
        if(c == '

){
          incoming = 1;
        }

//Checks for the URL Duration
        if(incoming == 1){

if(c >= ‘0’ && c <= ‘9’){
            //Add to the time string
            time += c;
          }
        }

if (c == ‘\n’) {
          // you’re starting a new line
          currentLineIsBlank = true;
        }
        else if (c != ‘\r’) {
          // you’ve gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
  }
}

/*
  activateBothRelays
Author: Devin Pentecost
Activates both of the relays
*/
void activateBothRelays(void){
  //Enable both relays
  digitalWrite(R0_PIN, LOW);
  digitalWrite(R1_PIN, LOW);

#ifdef DEBUG_SERIAL
  Serial.println(“Both On”);
#endif
}

/*
  activateRelay0
Author: Devin Pentecost
Activates Relay 0 for a time, in ms
*/
void activateRelay0(int time){
  //Enable relay 0
  digitalWrite(R0_PIN, LOW);

#ifdef DEBUG_SERIAL
  Serial.println(“R0 On”);
#endif
}

/*
  activateRelay1
Author: Devin Pentecost
Activates Relay 0
*/
void activateRelay1(void){
  //Enable relay 1
  digitalWrite(R1_PIN, LOW);

#ifdef DEBUG_SERIAL
  Serial.println(“R1 On”);
#endif
}

/*
  deactivateBothRelays
Author: Devin Pentecost
Deactivates both of the relays
*/
void deactivateBothRelays(void){
  //Disable both relays 
#ifdef DEBUG_SERIAL
  Serial.println(“Both Off”);
#endif

digitalWrite(R0_PIN, HIGH);
  digitalWrite(R1_PIN, HIGH);
}

/*
  deactivateRelay0
Author: Devin Pentecost
Deactivates Relay 0 for a time, in ms
*/
void deactivateRelay0(void){
  //Disable R0
#ifdef DEBUG_SERIAL
  Serial.println(“R0 Off”);
#endif

digitalWrite(R0_PIN, HIGH);
}

/*
  deactivateRelay1
Author: Devin Pentecost
Deactivates Relay 0 for a time, in ms
*/
void deactivateRelay1(void){
  //Disable R1
#ifdef DEBUG_SERIAL
  Serial.println(“R1 Off”);
#endif

digitalWrite(R1_PIN, HIGH);
}

/*
checkUnlockRequest
Author: Devin Pentecost
Checks the unlock request and acts accordingly
*/
void checkUnlockRequest(void){
  //Is the unlock request active?
  if(unlockRequest[0]){
    //We are requesting an unlock.
    //Is it not already unlocked?
    if(!unlockRequest[1]){
      //Time to activate the request
      unlockRequest[1] = 1;

//For now, we activate both of them
      activateBothRelays();
    }
    else{
      //Check and see if we are actually done
      //Are we past the end of the request (Or somehow before the start?)
      if( (millis() < unlockRequest[2]) || (millis() > unlockRequest[3]) ){
        //Set ourselves as done with the request
        unlockRequest[0] = 0;
      }
    }
  }
  else{
    //We are not requesting an unlock.
    //Is it already unlocked?
    if(unlockRequest[1]){
      //Time to deactivate the request
      unlockRequest[1] = 0;

//For now, we deactivate both of them
      deactivateBothRelays();

//Clear away old data
      unlockRequest[2] = 0;
      unlockRequest[3] = 0;
    }
  }
  //Done
  return;
}

I suppose I could dabble with lower voltages, but the desired effect is not guaranteed at that point.

There's nothing that says that the Arduino and the locks have to be powered by the same power source, is there? For the time being, power the Arduino by it's own power supply (at 7.5 V) and see if that corrects your problem.

Thank you for the help.

I dug around and found an older Duemilanove 138 and replaced the current device. The older Arduino ran cooler than the other one, and by replacing it with this one the problem went away. I believe it is safe to say the problem was due to overheating as I do not have any problems no matter how hard I run the system.

My next step will be to follow PaulS's advice and put the Arduino and Relay on separate power sources. It makes the circuit slightly more complex, but will save the 5v Regulator some heat and make the system better.

Also, the Ethernet Shield has some problems with lockup -- check in the networking forum