Introduction: SMS Controlled Gate/Garage Remote

About: Electrical Engineer by trade, tinkerer by heart.

Introduction

A dead-simple method of controlling a wireless gate/garage transmitter via GSM, utilising the MediaTek LinkIt One. The main drive behind creating a GSM controller for me was to make it easy-to-use for the non-tech-savvy. I could have just as easily done it via WiFi with something like the ESP8266, but then users would have to go to a webpage on their phones which, for the real Luddites, is just too much. Sending an SMS to a pre-defined number is far easier, even your granddad can do it.

If you are familiar with electronics, then I'm sure I have already explained enough for you to just do it. Yahoo! If you are just starting out, then this project is for you. I will try and give you an understanding of how one works through the process. It is perhaps a good first step in (ultra-basic) reverse engineering in order to interface with existing devices.

Pros:

  • Dead Simple Circuit
  • Password Controlled
  • Battery Powered (or mains power)
  • Luddite Appropriate
  • Less expensive that most other GSM solutions (GSM shields for Arduino etc. are pricey)

Cons:

  • Requires a SIM card
  • More Expensive than a WiFi solution (if you have to buy a LinkIt Board)
  • Cost of an SMS to open the gate (negligible, depending on you cell contract)

Parts You Will Need

  • LinkIt One
  • SIM card
  • NPN Transistor
  • 2.2kOhm resistor
  • Bits of wire

Optional Parts

  • Connectors
  • Cellphone Charger (for power)

Tools You Will Need

  • Soldering Iron
  • Wire Clippers
  • Screw Driver
  • Multi-meter

Step 1: Analyse the Gate/Garage Remote

What does the micro-controller see when we press a button?

The first step in a project like this is figuring out exactly how the micro-controller inside the remote registers a button press.

The micro-controller is a digital device, which means that it must detect a button press by a voltage that goes high from low or goes low from high.

My steps were as follows, yours will be similar, try and draw a simple diagram as you go along (my crude sketch is attached, with notes)

  1. Open the remote and measure the battery, it is more than likely a 12V
  2. Take a look at the switches, first determining which pins are connected to which (generally the 4-pin push-buttons have two pins connected to each other.
  3. Measure the potential (voltage) on both terminals of the push-button. One side will be high (12V in my case) and the other will be low (0V/Ground)
  4. One of these ends is likely to be connected directly to the battery (probably Ground, but it could be either). You can test this by taking the battery out of the remote and testing for continuity between the push-buttons pins and the battery holder terminals.
  5. The side that does not have direct continuity to a battery terminal is the one going to the micro-controller (via some level shifting if it is 12V at the button)

How do we emulate a button press?

In my case the 12V was obviously going to the micro, since the 0V was direct to the battery's negative terminal. The other way to determine this is to measure which side of the switch changes potential when it is pressed (you will have to hold the button down to see it if you are measuring with a multi-meter).

Since the microcontroller-input side of the switch goes from 12V to 0V when pressed, this meant that there was some sort of pull-up resistor arrangement.

I want to simulate a button press, so I put a NPN transistor in parallel with the switch. When the transistor is "off" (in other words, the voltage on the base is low and no current can flow), the collector will be at 12V, but when a voltage is applied to the base (and the transistor turns "on"), there will be almost* no voltage drop across the transistor collector-emitter (there will actually be about 0.6V drop, but that is low enough to register as a logic low).

Here is a nice intro to transistors as switches.

Step 2: Build the Circuit

There is almost nothing to this circuit. Take a look at my attached scribble diagram. There is no reason to build a circuit board, I simple wired everything directly to the transistor, being careful to insulate (with heat shrink tubing) all of the exposed legs.

Transistor

The base is connected to pin D12 of the LinkIt One via a 2.2kOhm resistor

The collector is connected to the +12V (when un-pressed) side of the push-button (i.e. the side the micro-controller is measuring)

The emitter is connected to Ground/0V on the LinkIt One as well as on the remote.

Choosing the Resistor

You can find out more about transistors as switches here if you are not familiar. I chose my resistor of 2.2k fairly arbitrarily in order to get a base-current of about 1.3mA, well within the LinkIt One's digital output pin limits.

Considering the LinkIt is a 3.5V logic device the current flowing through the digital pin is calculated as follows:

(base voltage - base emitter drop)/(base resistor) = (3.5-0.6)/2200 = 0.0013A

Connectors

I chose to add a connector to the remote, so that I could easily remove it an connect it to a different project in the future if I want to. It is important that the connector can only be connected in the correct polarity or you are likely to damage your remote.

Antennas

Make sure to attach the GSM antenna that is provided with the LinkIt One.

Power

Although I didn't use it for my project, you could use the LinkIt One's included battery to power the device (or just as backup). I decided that it wasn't necessary for my use case, so it was easier to just plug the board into an old android phone charger.

Step 3: Set Up the LinkIt One

Configure the Environment

If you have never use your LinkIt One for anything at all, then I recommend reading through this intro on setting up the environment: link

Onboard Switches

“ms/uart” set to the “uart” position. This allows the board to be programmed by the Arduino IDE.

“USB/BAT” set to the “USB” position for programming (or BAT if the battery is connected and charged)

“SPI/SD” set to the the “SPI” position.

Sim Card

Insert your sim card as shown in my photo. Make sure that there is no pin code required on it.

Step 4: Writing the Code

First of all, I read the MediaTek LinkIt One Developer's Guide, in particular, the section about receiving smses, as well as the API. I have attached the guide here in case that link stops working.

I have attached my full code here, which should just work. I specifically broke it into small functions that should be easy to understand, I will go through each of them here. Please read the inline comments too for extra info.

Initialise Global Variables

#include <LGSM.h>

//these variables are used for the LED
int ledGreenPin = 13; //I am using the onboard LED as an indicator
boolean ledGreenState = LOW;

//this is the pin that is connected to the transistor base (via a resistor)
int triggerPin = 12;

//these variables are for the sms
char smsContent[200];
int  smsLength = 0;
char smsSender[20];

//these variables are for the password
const int passwordLength = 20; //number of possible characters in password, remember the null terminator
const char password[passwordLength] = "mellon"; //this is the actual password

setup() function

The setup function is run once after the device starts up. The pin that controls the onboard led (D13) and the pin connected to the transistor's base (D12) are initialised as outputs and set to default values of 0 ('LOW').

The serial port is initialised at a baud rate of 9600, so that debugging information can be printed out.

The waitForSim() function is called once (described later)

void setup() {
  //this code runs once at setup
  pinMode(ledGreenPin, OUTPUT);   //initialise LED
  pinMode(triggerPin, OUTPUT);   //initialise PIN
  digitalWrite(ledGreenPin, ledGreenState); //turn LED off
  digitalWrite(triggerPin, LOW); //make sure trigger is off (assuming NPN transistor on a pullup input)
  Serial.begin(9600); //start the serial port
  waitForSim();   //wait for simcard to be active
}

waitForSim() function

The waitForSim() function simply sits in a loop, checking every half a second, defined by delay(500), whether the SIM card is ready. The green LED is turned on/off each check so that it flashes and then left on once the SIM is ready.

void waitForSim() {
  //this is just a function to wait until the SIM is ready

  Serial.print("waiting for sim");
  while (!LSMS.ready())
  {
    delay(500);
    ledGreenState = !ledGreenState; //blink the led
    digitalWrite(ledGreenPin, ledGreenState);
    Serial.print('.');
  }
  ledGreenState = HIGH; //turn led on once SIM is ready
  digitalWrite(ledGreenPin, ledGreenState);
  Serial.println("Sim Ready");
}

receiveSms() function

This function will check if there is a new SMS. If there is one, it is read in, one character at a time, and stored in the smsContent buffer. If there is no new SMS then the function returns false. This allows us to call it as often as we like in the main loop.

Once the SMS has been read it is removed with the flush() command.

boolean receiveSMS() {
  //this function will store a new sms in the buffers
  //or return false if there is no new sms
  int v;
  if (LSMS.available()) // Check if there is new SMS
  {
    Serial.println("There is new message.");
    LSMS.remoteNumber(smsSender, 20); // store sender in buffer

    smsLength = 0; //storing a new sms
    while (true)
    {
      v = LSMS.read();
      if (v < 0)
        break;
      smsContent[smsLength] = v;
      smsLength++;
    }
    smsContent[smsLength] = '\0';
    smsLength++;
    LSMS.flush(); // delete message
    return HIGH;
  }
  else {
    return LOW;
  }
}

displaySMS() function

This function just prints out the sender and content buffers to the serial port, which is handy for debugging.

void displaySMS() {
  Serial.print("Sender:");
  Serial.println(smsSender);
  Serial.print("Content:");
  Serial.println(smsContent);
  Serial.println();
}

validatePassword() function

This function is used to compare the content of the SMS with the password string. If the content matches the string, then the function returns 1 (HIGH), otherwise it returns 0 (LOW).

boolean validatePassword() {
  //this function will return true if the contents of the sms start with the defined password
  Serial.print("Comparing ");
  Serial.println(password);
  Serial.print("with ");
  Serial.println(smsContent );
  if (strcmp(password, smsContent) == 0) {
    Serial.println("Password Valid");
    return HIGH;
  }
  else {
    Serial.println("Password Invalid");
    return LOW;
  }
}

triggerRemote() function

Function This function simply sets the D12 pin (transistor base) high for a specified amount of time (1 second worked for me, you remote might prefer something different)

void triggerRemote() {
  //this function will "turn on" the transistor that emulates a button press
  Serial.println("Emulating button press");
  digitalWrite(triggerPin, HIGH);
  delay(1000);
  digitalWrite(triggerPin, LOW);
  Serial.println("Emulating button release");
}

loop() function

This function is the core of an Arduino program and just runs over and over again for all eternity. Since everything has already been broken down into functions it is completely self-explanatory.

void loop() {
  if (receiveSMS()) {
    displaySMS();
    if (validatePassword()) {
      triggerRemote();
    }
  }
  delay(1000);
}