Hackd Project: “Really Remote Starter”

Note: this is a repost of my original article, dates and other data can refer to stuff in the past or things might be outdated. I’ll try to do my best on updating it but I may leave something by mistake or keep the narrative intact from when I originally wrote the article.

From my post in my former company blog

It’s HACKD season again at MeetMe! For those of you that are not familiar with the concept, hackathons are events that some companies, schools, and other organizations put together where people work on the projects they want, like new technologies, inventions, ideas, etc., that they usually don’t have time to spend on. I’ve had a project on the back burner for a while that I wanted to work on but, because lack of experience and knowledge (a.k.a self-confidence) and time, I never went forward with it.

MeetMe offers HACKD every couple of months and during one of the recent events, I decided to finally work on this project, which I call “Really Remote Starter”.

The problem

About 3 years ago, (update from the original post. It’s been 6 years now!) I used to live in Northwest Mexico, near Arizona, US. Since then I moved to the US East Coast. So I basically moved from here:
desierto
…to here:
nieve
I found out that in this weather I needed to sit in my car for a while until it gets warm. Sitting in the car does not provide an ideal comfort level. Even if you turn the heat on, it’s useless for those first few minutes.

By the end of the first winter season, I desperately wanted a remote starter for my car. I thought, “it would be nice to start my car just from the warmth of my home or office and then just go to my car into a warm interior and go”. Then, when I got a remote starter for my car, I quickly realized that it wasn’t always going to be that useful.

At work, the parking lot is located at the back of the business center, and it fills pretty quickly. It can take you a good 5 to 10 minutes to walk to your car. Also, in other cases like parking at malls, movie theaters, etc. makes the Remote Starter less useful. Why? Remote starters and car alarms have RF remotes, which are very limited in terms of reach.

In my other car, in Mexico, I have a high end car alarm with a two-way RF remote that promises a one mile reach. Well it has a one mile reach in a place like this:
parking_lot_empty
If you start adding cars, walls, and other barriers, the reach decreases dramatically. So, I came up with the idea to make my remote starter to start from wherever, without a distance restriction.

The idea

I wanted to start my car from wherever with my cellphone, sending the car some kind of signal. I wasn’t sure exactly how to achieve this, so I did some research and looked at a bunch of Youtube videos and written tutorials. It seemed that I wasn’t the first one to try this. It seemed that everyone wanted to use Bluetooth.

It makes sense. Your cell phone has Bluetooth and you can use an Arduino or a raspberry pi with a Bluetooth module and voilá. But that wasn’t enough for me because that doesn’t solve my problem. Although Bluetooth could have a longer reach than RF, it still has that distance restriction. I wanted something that doesn’t care how far are you from your car. Then the WIFI idea came to me. “What if I put a WIFI module in the Arduino or the raspberry pi?” Nope, that is not going to work either. It should have WIFI coverage everywhere and there’s no WIFI coverage everywhere; you also have to deal with password-protected networks and stuff like that.

Same happens with 3G or 4G there’s no 100% 3G/4G coverage everywhere, and it will turn this to a very expensive solution since 3G/4G mobile plans are expensive. But, what if I send an SMS to my starter?

Let’s think about it: cellular signal coverage is pretty much 100% (only remote places are deficient) and SMS can be received pretty much everywhere. Also, very basic, cheap plans can give you this advantage. Got it!

The solution

Then HACKD weekend was approaching. I researched a little bit about which board to use, there’s a bunch of options out there, not just the Arduino and the raspberry pi, but settled on the Arduino basically because it was the right price and the complexity level required.

How to

After deciding what to use and how to use it, I got everything I thought I would need.

BOM

Voltage regulator. Arduino documentation says that it works with 5V to 20V, but it can become unstable under 7V and you can burn it over 12V. Common car voltage is 12V so I needed this to convert down the voltage to turn on the Arduino. However, after 2 or 3 days @ 5V, it became unstable. I switched since then to a 9V Voltage Regulator and that solved the problem.
Well that’s pretty much everything I needed. Now the process.

Process

Installing a remote starter to a modern car isn’t an easy task. There are now transponders in the keys that you have to know how to bypass, you need to know different signals for several different instruments of the car, and you also need some security restrictions, like make it so the car shuts off some time after being started without a key (you could forget it was started, for example) or make it so the car can’t be driven without a key. (A thief could take advantage of the remote starter to just jump in and drive.) Because all of that logic was already implemented on the remote starter my car already had and the hackathon was a 3-day event, I decided just to hang my stuff off the installation already there.

My plan then was that I would send an SMS from my cell to the Arduino (received via the GPRS Module). Then the Arduino would send a signal thru a cable to the remote starter via its remote control. All of this would be located in a hidden place inside the car. Here’s the diagram.
diagram
So I took out the remote from it’s case and connected one cable on each pole of each button.
remote1
remote2
remote3
Then I connected one switch relay to each button on the switches I had on the COM and N.O. pins
relay_diagram
Then, all three switches connected to all three buttons of the remote need to connect one of their left pins to the negative of the Arduino and each of the left pins on each of the three switches have to be connected to the three 5v pins that we are going to use to send the signals to it. So at the end all connected looked like this:
all_connected1
all_connected2
This module has to be connected to a continuous power source from the car; each car is different so anyone else trying has to figure that out. I added a voltage regulator because the reasons I already stated above.

Software

The language Arduino uses is a subset of C++. Arduino has an IDE that we can use, downloadable from here. I used it for this project and it helps and works fine. Then we also need a Serial Terminal Software to communicate with the Arduino and the Geeetech SIMCOM SIM900 Quad-band GSM GPRS Shield, to send and receive SMS messages. On the Shield documentation located here, they offer some different options for different platforms, I downloaded CoolTerm for my Mac OSX from here and it worked perfectly. There’s some setup you need to do in it to communicate with the Arduino and the Shield. Ah! You also need a SIM Card with a plan installed on the Geeetech Shield.

Terminal Pre-setup

  1. Connect to the computer USB port and turn on Arduino (with the Geeetech Shield mounted).
  2. Go to CoolTerm and click options.
  3. Pick port, usually usbmodemfd something, if doesn’t appear click Re-Scan Serial Ports at the bottom.
  4. Pick 19200 Baud Rate.
  5. Ready to send and receive commands and read them.
There’s a second “language” or set of commands to learn here, and those are the ones that are used to actually send and receive the SMS messages. There’s a whole bunch of commands, not only for SMS, there’s commands to make a call, to receive it, to store, delete, refresh SMS, and all SIM card activities, even internet browsing. That reference can be located here.

Arduino Code

// Setup to talk to the Serial Terminal when connected to the computer
#include <SoftwareSerial.h>
SoftwareSerial GPRS(7, 8);
unsigned char buffer[256]; 
int count=0;      


// Iniciating communication with the Serial Terminal and the PINS that are going to send the pulses to the remote
void setup()
{
 GPRS.begin(19200);                  
 Serial.begin(19200);            
 pinMode(2, OUTPUT);
 pinMode(3, OUTPUT);
 pinMode(4, OUTPUT);
}


void loop()
{
 delay(10000);
 if (GPRS.available())  // If there's data in the SIM Card
 {
  delay(5000);
  readPrint();
  clearBufferArray();

  delay(1000);
  GPRS.println("AT+CMGR=1");  //Get the message received
  delay(2000);

  readPrint();

// After getting the content of the message we look for the text
  String str1 = (const char*)buffer;
  int index = str1.lastIndexOf("\"");
  String text = str1.substring(index+1, str1.length()-1);
  String str2 = "Turn On";
  String str3 = "Open";
  String str4 = "Close";
  if (text.indexOf(str2) != -1)  //If text was Turn On
  {
     Serial.write("\nStart\n");  //Send text "Start" to the Serial Terminal
//Then do the double pulse to the PIN 2
     for (int x=0; x<2;x++)
     {
     digitalWrite(2, HIGH);
     delay(800);
     digitalWrite(2, LOW);    
     delay(1500);
     } 
  }
  else
  {
    if (text.indexOf(str3) != -1)  //If text was Open
  {
     Serial.write("\nOpen\n");   //Send text "Open" to the Serial Terminal
//Then do the double pulse to the PIN 3
     for (int x=0; x<2;x++)
     {
     digitalWrite(3, HIGH);
     delay(600);
     digitalWrite(3, LOW);    
     delay(600);
     } 
  }
  else
  {
  if (text.indexOf(str4) != -1)   //If text was Open
  {
     Serial.write("\nClose\n");   //Send text "Close" to the Serial Terminal
//Then do the double pulse to the PIN 4
     for (int x=0; x<2;x++)
     {
     digitalWrite(4, HIGH);
     delay(600);
     digitalWrite(4, LOW);    
     delay(600);
     } 
  }
  else
  Serial.write("\nnot found\n");  // If none was found print "not found" to the Serial Terminal
 }
}

  clearBufferArray();

  delay(1000);
  GPRS.println("AT+CMGD=1,4");  //Delete all messages in the SIM Card
  delay(1000);

    readPrint();
    clearBufferArray();
 }
}

//This function reads and puts together everything on the SIM Card and prints it to the Serial Port
void readPrint()
{
     while(GPRS.available())           
   {
     buffer[count++]=GPRS.read();    
     if(count == 256)break;
    }
   Serial.write(buffer,count);           
}


void clearBufferArray()              // function to clear buffer array
{

 for (int i=0; i<count;i++)
   { buffer[i]=NULL;}                  
  count = 0; 
}
That code can be also viewed here and is going to be running in a neverending loop in the arduino and basically waits for the SIM card to get an SMS. Once the SMS arrives, it sends a double pulse (needed by the remote buttons) to the desired remote button, depending of the content of the SMS received. After that it deletes all the messages to avoid filling up the SIM Card.

Well, after “uploading” that to our Arduino, we can manually send SMS messages to our installation and it should work. This is a little video when I was testing it:

This is with the car already connected to the module:

I have to thank for this part of the code to my friends and coworkers Bob Dauth and Diana Shkolnikov, who helped me a lot with C++ because I had no C++ coding experience at all. After that, it was mostly done, however, I wanted an app that with a tap of a button I could tell my car to start or to open and close the door locks. I asked my also friend and coworker David Breneisen to help me with that. He came up in less than half hour with a very simple app that does the work. Here’s a screenshot:
first_app_screenshot
Pretty much what it does is to send the SMS when you tap the button and that’s it. It also gets confirmation and shows a toast message when the SMS has been sent. Because its so many files you can find the code here. After putting that together, we finished our project.

I was able to use it all winter long and it was awesome! Now, for this most recent HACKD, I wanted to improve on it. I projected the following changes:
  1. Remove the phone number from the code in the app and put a settings page so the user can change the phone number of the car.
  2. Get better-looking buttons with icons instead of just text.
  3. Get reporting back from the car when the car has been started, closed, or opened after the SMS is received.
  4. Add an alert to be sent by the car when a door has been opened.
This last one representing the biggest challenge because I needed to hook up more stuff to the car. I wanted to get reporting back from the car when it has started or closed or opened because there were times where my cell plan has expired and the SMS weren’t going out, I didn’t noticed that the car wasn’t started, and I was going out in the cold just to find out that the car hasn’t been started. Or vice-versa, the SMS was sent, but the car didn’t get the order, because the plan on the Arduino’s chip was expired. For these new challenges I had to construct a new, more complex circuit represented in the following diagram:
new_diagram
I have to thank here to my friend from México, Carlos Pinto; he is an Electronics Engineer and helped me with coming up with this circuit. A little bit of description.
  1. The icons on the top left corner are switches on the doors, this switches send the signal to the car computer to let it know a door has been opened, you can see a light coming off on your dashboard when a door is open, these are the responsibles. We need to connect those sensors to the Arduino somehow to get the signal. There’s some considerations to make — these are negative signals, and we need diodes in order to avoid the signal to go between them.
  2. To the center (Doors Relay), it’s basically a signal converter. That relay basically takes the negative signal from any of the doors and sends a positive signal to a voltage regulator.
  3. The signal from the Doors Relay is converted to a 12V signal so that’s why we need a voltage regulator, to convert the 12V to a 5V signal that is going to be connected to an input pin on the Arduino (we convert it to 5V because that’s what the Arduino supports).
The rest of the circuit is pretty much the same as it was, just the connection from the car to power up the Arduino and the switches needed for sending the signals to the remote control of the starter. Then we need to update our code for the Arduino as follows:
// Setup to talk to the Serial Terminal when connected to the computer
#include <SoftwareSerial.h>
SoftwareSerial GPRS(7, 8);
unsigned char buffer[256];
int count = 0;

// Setting up inicial door state
int last_door_value = -1;
int current_door_value = -1;

int total_delay = 0;

// Iniciating communication with the Serial Terminal and the PINS that are going to send and receive the pulses to the remote
void setup()
{
  GPRS.begin(19200);
  Serial.begin(19200);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, INPUT);
}


void loop()
{
  current_door_value = digitalRead(5);

  if (last_door_value == -1) {
    // This will initialize our "What was the last thing we read?" variable
    last_door_value = current_door_value;
  }

  delay(1000);

  total_delay += 1000;

// This will send the SMS letting me know that a Door has been opened or closed
  if (current_door_value != last_door_value) {
    if (current_door_value == 0) {
      GPRS.println("AT+CMGF=1");
      delay(100);
      GPRS.println("AT+CMGS = \"+12674671270\"");
      delay(100);
      GPRS.println("Door Closed");
      delay(500);
      GPRS.println((char)26);
      delay(500);
      GPRS.println();
      delay(500);
      readPrint();
      clearBufferArray();
      delay(3500);
    } else {
      GPRS.println("AT+CMGF=1");
      delay(100);
      GPRS.println("AT+CMGS = \"+12674671270\"");
      delay(100);
      GPRS.println("Door Opened");
      delay(500);
      GPRS.println((char)26);
      delay(500);
      GPRS.println();
      delay(500);
      readPrint();
      clearBufferArray();
      delay(3500);
    }
    last_door_value = current_door_value;
  }

// Next several lines are for receiving the SMS and sending the signal to the Arduino to Start the car, Close or Open the door locks
  if (total_delay > 5000 && GPRS.available())
  {
    total_delay = 0;
    delay(5000);
    readPrint();
    clearBufferArray();

    delay(1000);
    GPRS.println("AT+CMGR=1");
    delay(2000);

    readPrint();

    String str1 = (const char*)buffer;
    int index = str1.lastIndexOf("\"");
    String text = str1.substring(index + 1, str1.length() - 1);
    String str2 = "Start";
    String str3 = "Open";
    String str4 = "Close";
    if (text.indexOf(str2) != -1)
    {
      //     Serial.write("\nStart\n");
      for (int x = 0; x < 2; x++)
      {
        digitalWrite(2, HIGH);
        delay(800);
        digitalWrite(2, LOW);
        delay(1500);
      }
      GPRS.println("AT+CMGF=1");
      delay(100);
      GPRS.println("AT+CMGS = \"+12674671270\"");
      delay(100);
      GPRS.println("Started");
      delay(500);
      GPRS.println((char)26);
      delay(500);
      GPRS.println();
      delay(500);
      readPrint();
      clearBufferArray();
      delay(3500);

    }
    else
    {
      if (text.indexOf(str3) != -1)
      {
        //     Serial.write("\nOpen\n");
        for (int x = 0; x < 2; x++)
        {
          digitalWrite(3, HIGH);
          delay(600);
          digitalWrite(3, LOW);
          delay(600);
        }
        GPRS.println("AT+CMGF=1");
        delay(100);
        GPRS.println("AT+CMGS = \"+12674671270\"");
        delay(100);
        GPRS.println("Unlock Succesful");
        delay(500);
        GPRS.println((char)26);
        delay(500);
        GPRS.println();
        delay(500);
        readPrint();
        clearBufferArray();
        delay(3500);
      }
      else
      {
        if (text.indexOf(str4) != -1)
        {
          //     Serial.write("\nClose\n");
          for (int x = 0; x < 2; x++)
          {
            digitalWrite(4, HIGH);
            delay(600);
            digitalWrite(4, LOW);
            delay(600);
          }
          GPRS.println("AT+CMGF=1");
          delay(100);
          GPRS.println("AT+CMGS = \"+12674671270\"");
          delay(100);
          GPRS.println("Lock Succesful");
          delay(500);
          GPRS.println((char)26);
          delay(500);
          GPRS.println();
          delay(500);
          readPrint();
          clearBufferArray();
          delay(3500);
        }
        else
          Serial.write("\nnot found\n");  // If none was found print "not found" to the Serial Terminal
      }
    }

    clearBufferArray();

    delay(1000);


    GPRS.println("AT+CMGD=1,4");  //Delete all messages in the SIM Card
    delay(1000);

    readPrint();
    clearBufferArray();
  }
}

void readPrint()  // This function reads and puts together everything on the SIM Card and prints it to the Serial Port
{
  while (GPRS.available())
  {
    buffer[count++] = GPRS.read();
    if (count == 256)break;
  }
  Serial.write(buffer, count);
}


void clearBufferArray()              // function to clear buffer array
{

  for (int i = 0; i < count; i++)
  {
    buffer[i] = (unsigned char)0;
  }
  count = 0;
This code is also on my Github and I have to thank Drew Denardo also friend and coworker for helping me with this code and putting together the new version of the Android app that now looks like this:
new_screenshot1
new_screenshot2
The code for this version can be also viewed here. After presenting and wrapping up the new version of the remote starter in the HACKD event, I realized an issue on the way it is programmed now; it sends me an SMS when a door has been opened or closed, even when I open or close the door. Obviously I don’t need an SMS telling me a door has been opened/closed if I’m the one doing it. I need to add some kind of logic to tell it when it is me doing or not. But I guess that’s going to be for the next HACKD?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.