Giampiero Baggiani
Published © CC BY

Iono access control

A cheap solution to keep them away from your secret room.

IntermediateFull instructions provided9,298
Iono access control

Things used in this project

Hardware components

Iono Uno
Sfera Labs Iono Uno
Both UNO or Ethernet version are OK
×1
HID RK40 Keypad Reader 6130
Can be substituted with any Wiegand keypad
×1
Arduino UNO
Arduino UNO
Included in Iono
×1
Arduino Ethernet
Included in Iono
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Schematics

Wiring

Code

Iono Wiegand keypad door lock controller

Arduino
Sketch for making Iono a controller for an electronic door lock and a Wiegand keypad.
/*
 * Iono Wiegand keypad door lock controller
 * Author: Giampiero Baggiani
 * http://www.sferalabs.cc
 * 
 * To be used with Iono (PCB v1.2).
 * http://www.sferalabs.cc/iono
 * 
 * This sketch makes Iono a controller for an electronic door lock and a Wiegand keypad.
 * It reads the digits sent by the keypad using the Wiegand protocol, matches them with the 
 * saved PIN code and unlocks the door if correct.
 * It also signals whether the access has been granted or denied activating a relay for a 
 * beeper and an LED (or whatever you attach to Iono's relays).
 * Finally it provides for a procedure to modify the saved PIN without reprogramming Iono.
 * 
 * 
 * The sketch will decode the Wiegand data sent from a keypad that uses 4 bits for a single digit.
 * The used keypad, other than the digits 0-9, should have a key to be used as terminator.
 * In this case the key '#' is used, which is sent from the keypad as number 11.
 * 
 * The Wiegand interface has two data lines, DATA0 and DATA1. These lines are normall held
 * high. When a 0 is sent, DATA0 drops to 0V for a few microsec. When a 1 is sent, DATA1 drops
 * to 0V for a few microsec. There is usually a few millisec delay between the pulses.
 *
 * Your keypad should have at least 4 connections (some have more). Connect the red wire to C+
 * the black wire to GND, the green wire (DATA0) to DI5 and the white wire (DATA1) to DI6.
 * 
 * Then you should connect your door lock to the realy set as the DOOR_RELAY constant. This relay
 * will be closed when the correct PIN is entered and then open again after OPEN_TIME milliseconds. 
 * 
 * Optionally you can use LED_RELAY and BEEP_RELAY to signal the access being denied or granted.
 * This sketch activates the LED while the door is unlocked and plays 1 beep when unlocking the door
 * and 3 beeps when a wrong PIN is entered.
 * 
 * To set the correct PIN connect the digital input set as the PROGRAMMING_INPUT constant to C+ and
 * enter the new PIN code on the keypad terminated by #. After saving the new PIN the beeper will
 * be activated for 2 seconds after which you should disconnect the PROGRAMMING_INPUT.
 * The PIN is saved in Arduino's EEPROM, therefore it will be restored even after a power off. 
 * 
 * This sketch is based on:
 * HID RFID Reader Wiegand Interface for Arduino Uno
 * Written by Daniel Smith, 2012.01.30
 * www.pagemac.com
 * 
 */

#include <EEPROM.h>
#include <Iono.h>

#define DOOR_RELAY          DO4
#define LED_RELAY           DO1
#define BEEP_RELAY          DO2
#define PROGRAMMING_INPUT   DI1
#define OPEN_TIME 4000

#define WIEGAND_WAIT_TIME 3000
#define MAX_BITS 32                
#define MAX_PIN_DIGITS 10

byte correctPin[MAX_PIN_DIGITS];
byte pinLen = MAX_PIN_DIGITS;

byte databits[MAX_BITS];
byte bitCount = 0;
byte pin[MAX_PIN_DIGITS];
byte pinCount = 0;

boolean flagDone = false;
unsigned int wiegand_counter;

// interrupt that happens when INTO goes low
void ISR_INT0() {
  addBit(0);
}

// interrupt that happens when INT1 goes low
void ISR_INT1() {
  addBit(1);
}

void addBit(unsigned char b) {
  if (bitCount < MAX_BITS) {
    databits[bitCount] = b;
    bitCount++;
    flagDone = false;
    wiegand_counter = WIEGAND_WAIT_TIME;
  }
}

void setup() {
  pinMode(2, INPUT);     // DATA0 (INT0)
  pinMode(3, INPUT);     // DATA1 (INT1)
  
  // Serial.begin(9600);
  // Serial.println("Ready");
  
  attachInterrupt(0, ISR_INT0, FALLING);  
  attachInterrupt(1, ISR_INT1, FALLING);
  
  wiegand_counter = WIEGAND_WAIT_TIME;

  loadPin();
}

void loadPin() {
  pinLen = EEPROM.read(0);
  if (pinLen < MAX_PIN_DIGITS) {
    for (int a = 1; a <= pinLen; a++) {
      correctPin[a - 1] = EEPROM.read(a);
      // Serial.println(correctPin[a - 1]);
    }
  }
}

void savePin() {
  EEPROM.write(0, pinLen);
  for (int a = 1; a <= pinLen; a++) {
    EEPROM.write(a, correctPin[a - 1]);
  }
}

void loop() {
  if (!flagDone) {
    if (--wiegand_counter == 0) {
      flagDone = true;
    }
    
  } else if (bitCount > 0) {
    long data = 0;
    for (int i = 0; i < bitCount; i++) {
      data <<= 1;
      data |= databits[i];
    }

    // Serial.print("Read ");
    // Serial.print(bitCount);
    // Serial.print(" bits: ");
    // Serial.println(data);
    
    if (bitCount == 4) { // keypad digit
      if (data == 11) { // key '#'
        if (Iono.read(PROGRAMMING_INPUT) == 0) {
          if (checkPin()) {
            openDoor();
          } else {
            signalErro();
          }
        } else { // programming
          pinLen = pinCount;
          savePin();
          Iono.write(BEEP_RELAY, 1);
          delay(2000);
          Iono.write(BEEP_RELAY, 0);
        }
        pinCount = 0;
        
      } else {
        if (pinCount < MAX_PIN_DIGITS) {
          if (Iono.read(PROGRAMMING_INPUT) == 0) {
            pin[pinCount++] = data;
          } else { // programming
            correctPin[pinCount++] = data;
          }
        }
      }
    }

    bitCount = 0;
    
  } else {
    delay(20);
  }
}

boolean checkPin() {
  if (pinCount != pinLen) {
    return false;
  }

  for (int i = 0; i < pinLen; i++) {
    if (pin[i] != correctPin[i]) {
      return false;
    }
  }

  return true;
}

void openDoor() {
  // Serial.println("OPEN");
  Iono.write(DOOR_RELAY, 1);
  Iono.write(LED_RELAY, 1);
  Iono.write(BEEP_RELAY, 1);
  delay(1000);
  Iono.write(BEEP_RELAY, 0);
  delay(OPEN_TIME);
  Iono.write(LED_RELAY, 0);
  Iono.write(DOOR_RELAY, 0);
}

void signalErro() {
  // Serial.println("ERROR");
  Iono.write(BEEP_RELAY, 1);
  delay(500);
  Iono.write(BEEP_RELAY, 0);
  delay(500);
  Iono.write(BEEP_RELAY, 1);
  delay(500);
  Iono.write(BEEP_RELAY, 0);
  delay(500);
  Iono.write(BEEP_RELAY, 1);
  delay(700);
  Iono.write(BEEP_RELAY, 0);
}

Credits

Giampiero Baggiani
4 projects • 18 followers
Contact
Thanks to Daniel Smith.

Comments

Please log in or sign up to comment.