Project showcase
X-SEER - The New Smart Mobilizer

X-SEER - The New Smart Mobilizer © GPL3+

X-SEER is a device that enhances vehicles security system, especially motorcycles that have measly protection.

  • 197 views
  • 2 comments
  • 2 respects

Components and supplies

Abx00014 featured xjsqphgdlv
Arduino MKR Fox 1200
The brain and also a messenger for our project.
×1
11028 01
SparkFun Triple Axis Accelerometer and Gyro Breakout - MPU-6050
Motion Processing Unit for added safety. Prevents bike from getting lifted/tilted.
×1
3000 mAh 20A 18650 Li-Ion Battery
As backup power supply to the Arduino MKR Fox 1200 in case of motorcycle battery removal.
×2
18650 Battery Holder (2X)
To hold 18650 Battery Holder
×1
Adjustable Buck Step Down Voltage Regulator Power Module
One unit for Charging the Li-Ion Battery and another to power Arduino MKR Fox 1200 from Li-Ion Battery.
×2
61pby065esl  sx679  tnr8syww5d
HC-05 Bluetooth Module
Buy HC-05 and not HC-06 as HC-05 can be both transmitter and receiver.
×1
09264 1
RGB Diffused Common Cathode
You can use a modular one too as long as it is rated at 3.3V.
×1
5V 4-Channel Relay Module
To toggle Ignition, Power and 2 Alarms
×1

Necessary tools and machines

Plastic / Metal Casing (Water-Sealed for Added Durability)

Apps and online services

Sigfox logo rgb j7ilnvhq6o
Sigfox
Arduino Hybrid Application (HTML, CSS & JavaScript)

About this project

As time has evolved, transportation has become a key factor in many lives. From luxury to a basic need, owning a vehicle comes with great responsibility, considering the amount of money and effort poured into obtaining and maintaining such a vehicle. With such great importance placed on said vehicles it should come as no surprise that security is a very important aspect all owners will think about, especially with crimes such as thievery being so common. While cars have achieved a better security system, motorcycles are left with rather measly protection, the double-sided pin tumbler lock key and magnetic key, both of which are easily crack able.

A double-sided pin tumbler lock key is an outdated method of protection which can be easily misplaced or duplicated by any locksmith while the magnetic lock can be broken by a thief with simple tools. Using custom locks and chains mean nothing as a thief also can just load those motorcycles onto a larger vehicle and cart the entire thing away to a more secure location so that they can cut open any locks without attracting any attention. Some motorcycles have built-in alarm systems that trigger on suspicious activities happening to the bike, but this alarm is limited to loudness of said alarm and can be easily bypassed by removing the battery of the motorcycle.

Our X-Seer is innovated to be the best at what it does in the Anti-Theft Industry. We took the previously used double-sided pin tumbler lock with magnetic key and added a Bluetooth Transceiver as immobilizer. X-Seer requires 6 different security tokens to be exchanged before power can be turned on and all of them will be verified within 500 milliseconds. Apart from the first two physical security tokens and the link key token, the other three tokens will be using a 128-bit encryption, which means it will take an addition of 2384 combinations to break the encryption key on each cycle, and will be unique per cycle (motorcycle on or off).In case of any suspicious movements by the Motion Processing Unit, Lost Mode will be activated in which the alarm goes off and the ignition will be disabled. A Geo-Location Tracking from Arduino MKR FOX 1200 will be sent to the user via an Android Application (using REST API) that warns the user until he/she turns the power of the motorcycle on and off. In case of battery removal, Lost Mode will get activated with the Arduino MKR FOX's backup rechargeable battery that can continuously track the location one week from the battery removal. The motorcycle can then be retrieved with the aid of a police officer for security purposes. The Android Application also allows the recovery of lost keys, a feature that will be useful in many situations. By using an RGB LED, X-Seer can notify the user of the engine temperature condition. This is to provide optimal warm-up after firing up the engine and delays before shutting down the engine to prolong the engine health. During engine shut down process, a safety turn-off function will be running that will be triggered on any gear engagement that brings the engine to a halt for safety purposes.

X-Seer would be the top notch product in the entire Anti-Theft Industry in terms of motorcycle safety. Even though X-Seer is made especially for motorcycles, it will also be compatible with any vehicle in automotive industry. According to The Economic Journal, car theft is reduced by an estimated 40% with the usage of engine immobilizers. With X-Seer, we hope to reduce theft rate to near zero.

Keywords: X-Seer, Arduino MKR FOX 1200, Bluetooth Transceiver, Motion Processing Unit, Rechargeable Battery, RGB LED, Android Application.

Related Article: Jan C. van Ours, Ben Vollaard. The Engine Immobiliser: A Non-starter for Car Thieves. The Economic Journal, Volume 126, Issue 593 (2016). Link: http://onlinelibrary.wiley.com/doi/10.1111/ecoj.12196/abstract

Code

SigFox_Coding.inoArduino
Go to this link: http://www.arduinolibraries.info/libraries/arduino-sig-fox-for-mkr-fox1200. Download Arduino MKR Fox 1200 Version 1.0.2 Library and install it in your Arduino IDE (Sketch>Include Library>Add .ZIP Library,,,). Go to Sketch>Include Library>Manage Libraries and add RTCZero Library and Arduino Low Power Library. Restart Arduino IDE and go to Tools>Board>Boards Manager and search for "Arduino SAMD Boards (32-bits ARM Cortex-M0+) by Arduino and install the latest version. Select Arduino MkrFox1200 as your board (Tools>Board>Arduino MkrFox1200). Select the Port that your Arduino MKR Fox 1200 is connected to. Copy this code and paste in Arduino IDE. Upload it to your Arduino MKR Fox 1200 Board...
/*

X-Seer Revision 1.3 (Released On: September 2017)

This coding uses libraries as follows:

I2Cdev Library: https://github.com/jrowberg/i2cdevlib
RTCZero.h Library : Arduino Library Manager
Arduino Low Power Library: Arduino Library Manager
128-bit AES Encryption Library: https://github.com/DavyLandman/AESLib
MPU6050 Motion Processing Unit Library: https://playground.arduino.cc/Main/MPU-6050
Arduino MKR Fox 1200 Library: http://www.arduinolibraries.info/libraries/arduino-sig-fox-for-mkr-fox1200

Coding by Selvandiran Marimuthu from MV Project Clan: https://www.hackster.io/selvandiran

*/

#include <SigFox.h>
#include <ArduinoLowPower.h>
#include <RTCZero.h>

volatile bool alarmOccurred = false;

const int triggersigfox = 0;

void setup()
{
  if (!SigFox.begin())
  {
    reboot();
  }

  SigFox.debug();

  SigFox.end();

  pinMode(triggersigfox, INPUT_PULLUP);
  LowPower.attachInterruptWakeup(triggersigfox, alarmEvent, FALLING);
}

void loop()
{
  // Sleep until an event is recognized
  LowPower.sleep();

  // if we get here it means that an event was received

  if (alarmOccurred == false) {
    return;
  }

  SigFox.begin();

  delay(100);

  String to_be_sent = "ALERT!";

  SigFox.beginPacket();
  SigFox.print(to_be_sent);
  int ret = SigFox.endPacket();

  delay(100);

  SigFox.end();

  alarmOccurred = false;
}

void alarmEvent()
{
  alarmOccurred = true;
}

void reboot()
{
  NVIC_SystemReset();
  while (1);
}
Arduino_Coding.inoArduino
Select Arduino Uno as Board. Select the port that your Arduino Uno is connected to. Upload and you are done.
/*

X-Seer Revision 1.3 (Released On: September 2017)

This coding uses libraries as follows:

I2Cdev Library: https://github.com/jrowberg/i2cdevlib
128-bit AES Encryption Library: https://github.com/DavyLandman/AESLib
MPU6050 Motion Processing Unit Library: https://playground.arduino.cc/Main/MPU-6050
Arduino MKR Fox 1200 Library: http://www.arduinolibraries.info/libraries/arduino-sig-fox-for-mkr-fox1200

Coding by Selvandiran Marimuthu from MV Project Clan: https://www.hackster.io/selvandiran

*/

#include <I2Cdev.h>
#include <AESLib.h>
#include <MPU6050_6Axis_MotionApps20.h>
#include <SoftwareSerial.h>

// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation is used in I2Cdev.h
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
    #include "Wire.h"
#endif

MPU6050 mpu;

#define OUTPUT_READABLE_YAWPITCHROLL
#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)
bool blinkState = false;

// MPU control/status vars
bool dmpReady = false;  // set true if DMP init was successful
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer

// orientation/motion vars
Quaternion q;           // [w, x, y, z]         quaternion container
VectorInt16 aa;         // [x, y, z]            accel sensor measurements
VectorInt16 aaReal;     // [x, y, z]            gravity-free accel sensor measurements
VectorInt16 aaWorld;    // [x, y, z]            world-frame accel sensor measurements
VectorFloat gravity;    // [x, y, z]            gravity vector
float euler[3];         // [psi, theta, phi]    Euler angle container
float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector

int operate = 0;
int operateled = 12;

// packet structure for InvenSense teapot demo
uint8_t teapotPacket[14] = { '$', 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0x00, 0x00, '\r', '\n' };

volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high
void dmpDataReady() 
{
  mpuInterrupt = true;
}

SoftwareSerial BTserial(3, 4); // RX | TX

void(* resetFunc) (void) = 0;


const int ignitionrelay = 11;
const int powerrelay = 10;
const int alarmrelay = 9;
const int alarmrelaybackup = 8;
const int togglesigfox = 7;
 
void setup()
{

  pinMode(ignitionrelay, OUTPUT);
  pinMode(powerrelay, OUTPUT);
  pinMode(alarmrelay, OUTPUT);
  pinMode(alarmrelaybackup, OUTPUT);
  pinMode(togglesigfox, OUTPUT);

  digitalWrite(ignitionrelay, LOW);
  digitalWrite(powerrelay, LOW);
  digitalWrite(alarmrelay, LOW);
  digitalWrite(alarmrelaybackup, LOW);
  digitalWrite(togglesigfox, LOW);
  
  #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
  Wire.begin();
  TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
  #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
    Fastwire::setup(400, true);
  #endif

  Serial.begin(9600);
  while (!Serial);
  BTserial.begin(9600);
  Serial.println("Arduino with HC-05 is ready");
  Serial.println("BTserial started at 9600");

  delay(500);

  Serial.println(F("Initializing I2C devices..."));
  mpu.initialize();

  Serial.println(F("Testing device connections..."));
  Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));

  Serial.println(F("Initializing DMP..."));
  devStatus = mpu.dmpInitialize();

  // supply your own gyro offsets here, scaled for min sensitivity
  mpu.setXGyroOffset(220);
  mpu.setYGyroOffset(76);
  mpu.setZGyroOffset(-85);
  mpu.setZAccelOffset(1788); // 1688 factory default for my test chip

  if (devStatus == 0)
  {
    // turn on the DMP, now that it's ready
    Serial.println(F("Enabling DMP..."));
    mpu.setDMPEnabled(true);

    // enable Arduino interrupt detection
    Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
    attachInterrupt(0, dmpDataReady, RISING);
    mpuIntStatus = mpu.getIntStatus();

    // set our DMP Ready flag so the main loop() function knows it's okay to use it
    Serial.println(F("DMP ready! Waiting for first interrupt..."));
    dmpReady = true;

    // get expected DMP packet size for later comparison
    packetSize = mpu.dmpGetFIFOPacketSize();
  } 
  else 
  {
    // ERROR!
    // 1 = initial memory load failed
    // 2 = DMP configuration updates failed
    // (if it's going to break, usually the code will be 1)
    Serial.print(F("DMP Initialization failed (code "));
    Serial.print(devStatus);
    Serial.println(F(")"));
  }

  // configure LED for output
  pinMode(LED_PIN, OUTPUT);

  loop();

  uint8_t key[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
  char data[] = "0123456789012349"; //16 chars == 16 bytes
  aes128_enc_single(key, data);

  BTserial.write(data);
  
  while(BTserial.available())
  {
    while(1)
    {
      String inputString = "";
      char inChar = (char)BTserial.read();
      inputString += inChar;
      delay(10);
      if (inChar == '=')
      {
        if (inputString == "ZP4ZG5uD629F2jNbWe/o9dHkKEgZfpDFe02Go8+PT+4=")
        {
          break;
        }
        else
        {
          resetFunc();
        }
      }
      delay(50);
    }
  }

  uint8_t key2[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
  char data2[] = "0123466789012349"; //16 chars == 16 bytes
  aes128_enc_single(key, data2);

  BTserial.write(data);

  while(BTserial.available())
  {
    while(1)
    {
      String inputString = "";
      char inChar = (char)BTserial.read();
      inputString += inChar;
      delay(10);
      if (inChar == '=')
      {
        if (inputString == "ei5eqvgbLmLrWAsOxvFwzBy5OczBTErk/JPrEDBtpGs=")
        {
          break;
        }
        else
        {
          resetFunc();
        }
      }
      delay(50);
    }
  }
  digitalWrite(ignitionrelay, HIGH);
  digitalWrite(powerrelay, HIGH);

  while(BTserial);
  
}

void loop()
{
  int ypr0 = (ypr[0] * 180 / M_PI); // yaw
  int ypr1 = (ypr[1] * 180 / M_PI); // pitch
  int ypr2 = (ypr[2] * 180 / M_PI); // roll
    
  if (!dmpReady) return;

  // wait for MPU interrupt or extra packet(s) available
  while (!mpuInterrupt && fifoCount < packetSize)
  {
  }

  // reset interrupt flag and get INT_STATUS byte
  mpuInterrupt = false;
  mpuIntStatus = mpu.getIntStatus();

  // get current FIFO count
  fifoCount = mpu.getFIFOCount();

  // check for overflow (this should never happen unless our code is too inefficient)
  if ((mpuIntStatus & 0x10) || fifoCount == 1024)
  {
    // reset so we can continue cleanly
    mpu.resetFIFO();
    Serial.println(F("FIFO overflow!"));
    // otherwise, check for DMP data ready interrupt (this should happen frequently)
  }

  if (mpuIntStatus & 0x02)
  {
    // wait for correct available data length, should be a VERY short wait
    while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

    // read a packet from FIFO
    mpu.getFIFOBytes(fifoBuffer, packetSize);

    // track FIFO count here in case there is > 1 packet available
    // (this lets us immediately read more without waiting for an interrupt)
    fifoCount -= packetSize;

    #ifdef OUTPUT_READABLE_YAWPITCHROLL
        // display Euler angles in degrees
        mpu.dmpGetQuaternion(&q, fifoBuffer);
        mpu.dmpGetGravity(&gravity, &q);
        mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
    
        Serial.print("ypr\t");
        Serial.print(ypr0);
        Serial.print("\t");
        Serial.print(ypr1);
        Serial.print("\t");
        Serial.print(ypr2);
        Serial.println("\t");
    #endif

    // blink LED to indicate activity
    blinkState = !blinkState;
    digitalWrite(LED_PIN, blinkState);
  }

  if (ypr2 >= 10 || ypr2 <=-10 || ypr1 >= 10 || ypr1 <=-10)
  {
    digitalWrite(ignitionrelay, LOW);
    digitalWrite(powerrelay, LOW);
    digitalWrite(alarmrelay, HIGH);
    digitalWrite(alarmrelaybackup, HIGH);
    digitalWrite(togglesigfox, HIGH);
    resetFunc();
  }
  else
  {
    digitalWrite(togglesigfox, LOW);
    digitalWrite(alarmrelay, LOW);
    digitalWrite(alarmrelaybackup, LOW);
    resetFunc();
  }

  operate = 1 + 0;
  digitalWrite(operateled, HIGH);
}

Schematics

Circuit Diagram - X-Seer
Connect the components as shown in the image. Upload the code and you are done...
Circuit diagram ttpak42pdz

Comments

Add projectSign up / Login