Introduction: ELab Hackerspace GSM Access Control System

About: eLab Hackerspace
In this Instructable we'll show you hot to make a GSM Access Control System for your hackerspace/garage/house/bedroom/dormroom/laboratory just like the one we built for eLab Hackerspace. We only used some scavenged parts but they can be replaced with similar parts with minor changes.

Here's a video showing it working:



This system allows you to control who can access the space where it is used by keeping a list of authorised members phone numbers and also keeps an online log of entrances on Google Spreadsheets, so that you can check it out whenever you want and from wherever you are :)
It also allows you to choose which music should be played when a certain member enters the space! :)

Our main idea was to make a system that would allow anyone to open the hackerspace door using any cell phone just by ringing a phone number :)

For this instructable you will need the following parts:
- Siemens C55 cell phone / GSM modem / other cell phone with support for AT commands
- Data cable for cell phone or GSM modem
- Old computer / Raspberry Pi / BeagleBone Black / other single board computer
- PIC16F88 microcontroller / Arduino / other microcontroller
- ATX power supply / other 12V/5V power supply
- cables
- connectors
- DC geared motor
- screws
- MDF board / Acrylic Board
- Solder
- Hot Glue
- Discrete electronic components (resistors, capacitors, LEDs.... )
- Audio speakers

And the following tools:
- Side cutters
- Pliers
- Screwdriver
- Soldering Iron
- Hot Glue gun

This instructable has 7 main steps:
1 - Door opening mechanism
2 - Preparing the parts to be assembled
3 - Siemens C55 working as a GSM modem
4 - RS232, TTL and LVTTL serial communications board
5 - PIC16F88 board
6 - PIC16F88 programming
7 - Python application to send data to Google spreadsheets

This instructable has all the necessary information to make a similar system. However, if you are interested in more details and seeing better quality pictures check the original post on: http://www.thebitbangtheory.com/2013/11/elab-hackerspace-gsm-access-control-system/

Step 1: Door Opening Mechanism

The door of eLab Hackerspace is an aluminium door with an emergency exit lever. We weren't allowed to drill or modify the door in any way, so we tried to find a way of using the lever to open the door. We engineered a way of using a geared DC motor to pull it to open the door and also found a way of attaching the motor to the door without any drilling or glueing. We attached the motor to a piece of metal and then used the silicone frame of the aluminium door to hold it in place. It turned out to be surprisingly easy to put the motor in place. To pull the lever, we placed an off-centered pin in a gear that was attached to the motor's axle and then used a small piece of a pulley taken from an old printer to attach the off-centered pin to the lever. It's basically the same type of mechanism used in car pistons. In case your door does not have an opening lever, you can use any other mechanism to open it either using an electronic lock,  or by using a gear motor to open the door in any other way. You just have to be creative :)

We also added a switch that would be triggered by the rotating gear when the lever was in the "open" position. After the mechanics of the system were done, we designed a simple board with a PIC16F88 microcontroller (more details about the board on step 5) based on the PIC16F88 prototyping board that we had previously designed for us to use at the hackerspace. We also did some simple programming of the PIC16F88 just to test the door opening mechanism: when a button was clicked, it would turn on the motor until the "open" switch was activated, then wait three seconds, and then turn on the motor again until the "open" switch stopped being activated, which meant that the lever was in the "closed" position. However, we ran into our first problem: the motor was so noisy that it was generating voltage spikes in the pin that was supposed to read the switch. We tried putting the noise filtering capacitors in the motor's pins, tried using a more stable power supply, but we weren't being able to filter it using hardware. After some time trying to fix the problem using hardware, we remembered a simple and clever way that worked like a charm: implement a software mechanism that would ignore isolated voltage spikes. We simply implemented a counter and defined a counting threshold: the PIC16F88 would count every time that the pin read a logic 1 but would only consider that button as being activated when the threshold value was reached, The counter would increase its value with the voltage spikes, but when the switch was actually activated, the counting value would increase extremely fast, reaching the threshold value. Having the opening/closing mechanism ready, it was time to start  assembling all the control system and work on the GSM part of the system.

Step 2: Preparing the Parts to Be Assembled

In order to keep everything organized we mounted all the parts in an MDF Board on the wall next to the door. We previously painted the MDF board black and screwed it to the wall. To make it look better, we also painted the ATX power supply black with spray paint.

Step 3: Siemens C55 Working As a GSM Modem

In case you didn't know, some old cell phones such as the ones from Siemens, Nokia and Samsung are really good for electronics projects. Some of them can be used as GSM modems, having a simple serial connection and a communication protocol based on AT Commands. The amount of supported commands may vary, depending on the model of the phone and on the manufacturer. The Siemens C55 turns out to be one of the best phones for electronics projects since its GSM modem supports a wide list of AT commands.

The first thing we needed was a SIM card. Luckily we had a SIM card from Vodafone that was given to a member of eLab Hackerspace in some promotion. The card had a prepaid plan with no mandatory payments. The only obligation to keep the number active is to make a phone call every 6 months. The card also came with a bonus of 5€, which should last forever making only a 1 second phone call twice a year :) The second thing I needed was a serial data cable for the Siemens C55, which we didn't had :\ We tried to find a cheap cable on ebay but we were out of luck. However, we had two Siemens chargers with the correct connector but only with the VCC and GND pins. We had no option but to hack one of the connectors to add the Tx and Rx pins and it worked just fine! :) Once we had the connector ready, we searched online to find which was the default baud rate for the Siemens C55 and found some websites saying that it was 9600bps, and others saying 38400bps. After searching for the baud rates, we connected the Tx and Rx pins to the Rx and Tx wires of a USB to Serial LVTTL cable and used putty to establish a serial connection with the phone. We decided to try with 9600 first. Once the connection was open, we typed "AT" and saw the letters being echoed to the putty terminal, which was a sign that the phone's GSM modem was replying and using a 9600 bps baud rate :) After clicking "Enter" the phone replied "OK" which, once more, was a good sign that the GSM modem was replying to the AT commands. Then we used the command "AT+CPIN=xxxx" , where <xxxx> is the pin of the SIM card, followed by "Enter" and once again the modem replied with "OK". :)

When someone makes a phone call to the phone number of the card inserted in the GSM modem of the phone, it usually only replies with "RING" every time you hear the calling tone. In order to activate the identification of the calling numbers, we had to send one more command: "AT+CLIP=1". After issuing this command and making a new phone call, the phone finally replied with:
<pre> RING

+CLIP: "911234567",161,,,,0
</pre>

We finally had the confirmation that the phone could provide all the data that we needed to continue the development of the access control system. :)

By the way, if you try to send AT commands to a phone, it may happen that it won't echo the characters that you send it. Some phones come with the echo disabled. It may happen that you type "AT" followed by "Enter" and only receive the response "OK". To activate the echo, you can send the command "ATE1". To deactivate it, you can send the command "ATE0". If you wish to know more about AT commands for the Siemens C55, see this document.

Step 4: RS232, TTL and LVTTL Serial Communications Board

The next step was to establish a serial connection between the PIC16F88 board, the Siemens C55 Cell Phone and an old computer via RS232 connection. Once again we faced some problems: the PIC16F88 was supplied with 5V and was working with TTL levels, the Siemens C55 phone required LVTTL levels and was not tolerant to TTL (it would turn itself off), and we still had to establish a connection with the computer using RS232 levels. Moreover, we had do create a UART communication with one Master (the PIC16F88 board) and two slaves (the Siemens C55 and the computer) which is something that requires a little trick to work. This trick consists in placing a diode in the Tx line of every Slave device, with the Cathode facing the device. Why is this necessary? Well, according to the UART specifications, when a device is in the inactive state (idle), its Tx pin must be high. When communication occurs, it is the Slave's responsibility to pull the Tx line down to sink the Master Rx channel's current. Using the diodes, when in idle state, every Slave is able to keep his own Tx high irrespective of what the master's Rx channel is at. A single Slave can transmit by pulling his Tx line down without affecting the Tx on other slaves. Having the Master/Slave trick done, it was time to do some level conversion. To convert the 5V TTL signal from the Tx pin of the PIC16F88 to an LVTTL level, a voltage divider using two resistors was used. To convert the 3.3V LVTTL signal from the Siemens C55 Tx pin to 5V TTL, an MCP6002 Op Amp was used as a comparator, pulling the voltage level to 5V every time the Tx signal from the cell phone passed the 2.5V threshold value, defined by a voltage divider built with two resistors. The conversion between TTL and RS232 levels was a lot simpler and was done by using a single MAX232 chip. Below you can see the PCB and the schematics where you can identify all the parts that have just been described.

The board was designed in Kicad. You can download the PCB files by clicking here.

Step 5: PIC16F88 Board

This board is supposed to by powered with 12V and contains a 5V linear regulator do power the PIC microcontroller. It also contains a channel N MOSFET acting as a switch controlled by the MCU to turn the motor on and off. Besides that, it also contains all the necessary connectors for power, motor, motor switch and UART communications. The board was designed in Eagle and you can download the Eagle project files here. The firmware for the PIC16F88 is discussed and can be downloaded in the next section. In the pictures you can see the schematic and PCB of the board.

Step 6: PIC16F88 Programming

All the code was written in C using Piklab and compiled with SDCC (see here how to setup a microcontroller development environment with Piklab and SDCC). You should be able to compile it with other compilers with some minor modifications. You can also use the .hex file included in case you don't want to change anything. When developing the code we decided that the member's phone numbers would be stored in the PIC's EEPROM. This way, if the Internet connection failed for some reason, the door would still open for an authorized member, although the entrance would not be registered in the entrance log. The PIC16F88 has 256 bytes of EEPROM. Taking into account that all the cell phone numbers in our country have 9 digits and the first one is always a 9, we had to store 8 digits for every phone number, which allows us to store 32 phone numbers in the PIC's EEPROM. It may seem that 32 is a small number but eLab Hackerspace is also a small Hackerspace and has only a few members. If the day comes when we get more than 32 members, we'll be happy to replace the PIC with another one or even replace most of the Access Control System with a Raspberry Pi or something else :P Having the data storage defined, it was time to create an AT command protocol that would allow us to add, delete and view phone numbers stored in the internal EEPROM. Every command starts with "ELAB+".Here's a list of commands that were implemented:
- ELAB+P=<PASSWORD> - Insert admin password to enter admin mode. The <PASSWORD> field is to be replace with the real password, hard coded in the PIC's firmware. In case the password is accepted, the PIC emits a "AUTH OK" response. Otherwise, it replies with "NO AUTH".
- ELAB+A#XX=<NUMBER> - Add a number to position XX (from 01 to 32) where the <NUMBER> field must be replaced with the 9-digit phone number. This command only works after the admin mode has been activated. Otherwise you'll receive a message saying "NO AUTH". If the command is accepted you should be replied with an "OK". In case the command is not correctly entered the PIC will reply with "ERROR";
- ELAB+D#XX - Delete the number located in position XX (from 01 to 32). This command only works after the admin mode has been activated. Otherwise you'll receive a message saying "NO AUTH". If the command is accepted you should be replied with an "OK". In case the command is not correctly entered the PIC will reply with "ERROR";
- ELAB+V - View the full list of numbers stored in the internal EEPROM. This command only works after the admin mode has been activated. Otherwise you'll receive a message saying "NO AUTH". If the command is accepted you should be replied with an "OK". In case the command is not correctly entered the PIC will reply with "ERROR".

The default password is located in the password.txt file contained in the "PIC16F88 Control Board Firmware.zip" file. You can change it in the source code and recompile it if you want to change it.

To use the AT command interface, the system administrator just has to open the serial connection (9600bps baud rate) with the PIC microcontroller and send the commands above to perform add, delete and view operations. When all operations are made, the Reset button on the PIC board should be pressed to reactivate the security lock in the PIC microcontroller. A lot of improvement can still be done in the code, such as adding a command to reactivate the security lock or adding a command to open the door, among other possibilities.

Whenever the PIC receives a CLIP message from the cell phone, it checks if the received number exists in its internal EEPROM. In case it exists, it sends a "A:<9_DIGIT_NUMBER>" to the computer. In case the number does not exist, it sends a "R:<9_DIGIT_NUMBER>" to the computer.

Regarding the door opening mechanism, once a message is received with a valid number, the motor is activated until a switch located near the motor is activated T times (to ignore the voltage spikes caused by motor noise). Then it waits 3 seconds and activates the motor again until the switch is released.

You can download the firmware by clicking here.

Step 7: Python Application to Send Data to Google Spreadsheets

As referred, in order to create an online entrance Log and to create a public log of daily entrances, we used an old computer to send the data to a spreadsheet on Google Docs. Of course we would prefer using a Raspberry Pi for this purpose, but we couldn't find nor a Raspberry Pi in our trash boxes nor 40€ to buy one :P Moreover, for proof of concept an old computer works perfectly fine. The computer is running a lightweight Linux distro: Lubuntu 12.04. All the code to send data to the spreadsheet was developed in Python and we advise that at the moment the code is not pretty and not commented, since it was written quickly just to get the system working. In order to be able to send and receive data from a Google spreadsheets we first had to install the Google Data API. To install it, just go here, download the latest version, extract the files into a folder and then run the script setup.py inside the folder by entering the following command in the console:
<pre> ./setup.py install </pre>
Before beginning coding, we had to set up two Google Spreadsheet files: one to store the list of eLab members, with columns for their names, cell phone numbers and some other contact info; and another one to be the eLab Entrance Log, containing columns for the date, hours, phone number, name of member, and if the entry was accepted or rejected. The second spreadsheet file contains also two other spreadsheets, being one of them just to perform operations on data for visualization and the second one being used to be the daily entrance log, with the entries of the current day being fetched from the first spreadsheet. Here you can see and download sample spreadsheets:
 - Members - https://docs.google.com/spreadsheet/ccc?key=0Amc7BxnuFafkdDBXc0pOcDVBRUV2VUt1bHJJWE9ldWc&usp=sharing
 - Entrance Log - https://docs.google.com/spreadsheet/ccc?key=0Amc7BxnuFafkdG1kc0NyOWZZRHVkLXJNODJIRkFBc1E&usp=sharing
For serial port communications we also had to install pyserial using the following command:
<pre> sudo apt-get install python-serial </pre>
Once we had the system working we thought it would be fun if every member could have its own entrance music :) So, we installed pygame using the command
<pre>sudo apt-get instal python-pygame </pre>
and added a new column for the song filename in the eLab members spreadsheet and also added a few more lines of code to the Python application to play the song. Of course at the beginning we had to joke around and put some stupid music for some eLab members entrances :P As an example, now when one of us enters it plays the epic Pirates of the Caribbean theme, for other member it plays the Champions League theme, and so on...

We'll now describe what the Python source code does, in a general way. Whenever the Python application receives a "A:<9_DIGIT_NUMBER>" message from the PIC16F88, it fetches the data from the Google spreadsheet containing the eLab Hackerspace members information and checks which user has the received phone number. After checking which user has the received phone number, it plays the corresponding entrance music and it sends the entry information to the eLab Hackerspace entrance Log spreadsheet. In case it receives a "R:<9_DIGIT_NUMBER>", it sounds the alarm sound and sends the rejected entry information to the eLab Hackerspace entrance Log spreadsheet. Below you can see the code for the Python application. If you try to use it don't forget to change the email, password, spreadsheet key and title of the members list spreadsheet. The spreadsheet key can be found on the url of the spreadsheet after the string "key=".
<pre>
import time
import gdata.spreadsheet.service
import pygame
import serial

pygame.init()
pygame.mixer.init()

#YOUR GOOGLE ACCOUNT EMAIL
email = 'user@gmail.com'
#YOUR GOOGLE ACCOUNT PASSWORD
password = 'password'

#TEST DATA
auth = 'granted'
number = '913564168'
#END OF TEST DATA

#SERIAL PORT SETUP
ser = serial.Serial("/dev/ttyS0",9600)
#END OF SERIAL PORT SETUP

var = 'X'
action = 'X'
phonenumber = 'X'

#START OF LOG ACCESS

# FIND THIS VALUE IN THE URL WITH 'key=XXX' AND COPY THE XXX BELOW
spreadsheet_key = 'XXX'
# ALL SPREADSHEETS HAVE WORKSHEETS. I THINK WORKSHEET #1 BY DEFAULT ALWAYS
# HAS A VALUE OF '0d6'
worksheet_id = 'od6'

spr_client = gdata.spreadsheet.service.SpreadsheetsService()
spr_client.email = email
spr_client.password = password
spr_client.source = 'Example Spreadsheet Writing Application'
spr_client.ProgrammaticLogin()
#END OF LOG LINE

# NECESSARY DATA TO PLAY MEMBER SOUND

#Query Members list
gd_client = gdata.spreadsheet.service.SpreadsheetsService()
gd_client.email = email
gd_client.password = password
gd_client.source = spr_client.source
gd_client.ProgrammaticLogin()

while(1):
    var = ser.read()
    pnumber = 0
    if var == "A" or var == "R":
        if var == "A":
            auth = "granted"
        else:
            auth = "rejected"
        var = ser.read()
        if var == ":":
            pnumber = ser.read(9)
            number = str(pnumber)
            print auth
            print number
            q = gdata.spreadsheet.service.DocumentQuery()
            #Below relace with the name of the member list spreadsheet
            q['title'] = 'eLab Members'
            q['title-exact'] = 'true'
            feed = gd_client.GetSpreadsheetsFeed(query=q)
            spreadsheet_id = feed.entry[0].id.text.rsplit('/',1)[1]
            feed = gd_client.GetWorksheetsFeed(spreadsheet_id)
            worksheet_id = feed.entry[0].id.text.rsplit('/',1)[1]

            rows = gd_client.GetListFeed(spreadsheet_id, worksheet_id).entry

            telefone = ''
            som = ''
            nome = "Desconhecido"
            done = False
            for row in rows:
                if done == True:
                    done = False
                    break
            #   print " %s %s" % (row.custom['telefone'], row.custom['nome'].text)
                for key in row.custom:
                    if key == 'nome':
                        nome = row.custom[key].text
                        print nome
                    if key == 'som':
                        som = row.custom[key].text
                        print som
                    if key == 'telefone':
                        telefone = row.custom[key].text
                        print telefone
                if telefone == number or nome == "Desconhecido":
                    # Prepare the dictionary to write
                    dict = {}
                    dict['date'] = time.strftime('%d/%m/%Y')
                    dict['time'] = time.strftime('%H:%M:%S')
                    dict['number'] = number
                    dict['auth'] = auth
                    dict['nome'] = nome
                    print dict

                    entry = spr_client.InsertRow(dict, spreadsheet_key, worksheet_id)
                    if isinstance(entry, gdata.spreadsheet.SpreadsheetsList):
                        print "Insert row succeeded."
                    else:
                        print "Insert row failed."
                    if not isinstance(som, basestring):
                        break
                    pygame.mixer.music.load(som)
                    pygame.mixer.music.set_volume(1)
                    pygame.mixer.music.play()
                    print "Playing song!"
                    done = True
                    while True:
                        #for event in pygame.event:
                            while pygame.mixer.music.get_busy():
                                pygame.time.Clock().tick(10)
                            break 
                    print "End of song!"
            print
            
#END OF MEMBER SOUND
</pre>
To publish the daily Entrance log in a webpage you just have to open the spreadsheet on Google Drive, click on File -> Publish to Web  and then choose which sheet you want to publish and click the button to start publishing. Then, in the bottom of the popup window choose HTML to embed in a webpage and copy the HTML code and paste it in your webpage.

Step 8: GSM Access Control System Complete! :)

And we think that's everything you need to know to make a similar access control system for you hackerspace/garage/house/bedroom/etc. :) If you don't have the exact parts that we have, you can do it with similar parts and with minor modifications. In case we forgot to mention something you find necessary, just let us know in the comments section below! :) 

I hope you liked this project. Although it is working perfectly, there is still a lot of room for improvement either in software or hardware :)

In case you want to know more details about the system and see higher quality pictures check the original post here in one of this project's authors blog: http://www.thebitbangtheory.com/2013/11/elab-hackerspace-gsm-access-control-system/

For other projects of the same author check his blog: http://www.thebitbangtheory.com

For more projects made by eLab Hackerspace members check eLab Hackerspace's blog: http://elabualg.wordpress.com/