Project in progress
MAQ-10 (An Intellectual Maritime Boundary Monitor)

MAQ-10 (An Intellectual Maritime Boundary Monitor) © LGPL

MAQ-10 Reduces Maritime Disputes, prevents illegal entries and helps in risk free border surveillance of a country.

  • 2,654 views
  • 0 comments
  • 11 respects

Components and supplies

Necessary tools and machines

Toolsmart PCB Hand Push Drill
09507 01
Soldering iron (generic)
Hy gluegun
Hot glue gun (generic)

Apps and online services

About this project

Problem Statement and Problems Faced:

We know that many countries has its own disputes with their neighboring countries regarding maritime security.

Generally people cross the maritime border with or without their knowledge for a purpose which gives rise to illegal entries. Incidents like firing at fishing boats by the Navy ,violating immigration law by crossing the borders, arresting people due to boundary crossing etc.. has led to great deal of suffering among the fisherfolk and other sea vehicles of both countries.

Technical working of MAD-10:

To overcome the above motioned problems, we are building a Quad-copter named MAQ-10(Micro Aerial Quadcopter-10) which is controlled by a Raspberry pi-2 (I used an Rpi since i do not have two creator ci20 boards.... an alternative). The RPI will hold the PID, but a micorcontroller is used to interface the RC receiver and the ESCs. The Rpi aks the microcontroller for RC commands and sends motor speed values through I2C. An Arduino Micro has been chosen as microcontroller, for its compact size and sufficient abilites for the job.

Host (The Raspberry PI):

  • PID controller
  • Web interface to access the Camera (work in progress but i have uploaded the source code and other related files which i have been working for the interface till now :-)
  • Communication with the MPU6050 through I2C.
  • Communication to Arduino Micro through SPI

PRINCIPLE

Wiring

  • MPU6050 -> RPI : -VDD -> 3.3V -GND -> GND -SDA -> SDA -SCL -> SCL -VIO -> 3.3V
  • Arduino -> RPI : -VCC -> 5V from external Regulator -GND -> GND -MISO -> Logic Level converter ->MISO -MOSI -> Logic Level converter ->MOSI -SCK -> Logic Level converter ->SCK

ESCs and RC Receiver on Arduino:

  • Using PinChange interrupts
  • Check in the Arduino code.

I have also uploaded the files for ServoBlaster that I use to control the ESCs and the MPU6050 Digital motion processing and for the Timing and the code structure separately.

Client (Creator Ci20):

At receiving end we use Creator Ci20 board, since it has very a powerful processor with other cool and attractive features and also inexpensive when compared to computers we are using it as an alternative for PC's. Using Open CV installed on the Ci20, we can detect marine vehicles using object detection algorithms from the live video feed received from the Quad , fly it closer and take snap shots of the intruder's vehicle and make use of speakers to alert them

Receiver end object detection based on openCV and zeromq framework:

Requirements

  • Opencv (python) as cv (opencv) and cv2 (numpy)
  • Zeromq (python)
  • Gevent (light weight switch)
  • Knowledge about img process
  • Profile, logging each stage mem and cpu time

Server

  • capture img
  • send img to clinet
  • wait for next command from client
  • update status by new command

Client

  • receive img
  • run all detection
  • build up a new command, based on detection results

Detections

  • face detect
  • circle detect
  • line detect
  • find attribute obj

Running It

  • python poll_camera.py (using cv to capture/show img via remote protocol)
  • python poll_camera2.py (using cv2 to capture/show img ...)
  • python poll_thread_run2.py (using cv2 to run all thread detection based on CPU num)
  • python poll_series_run2.py (using cv2 to run all series detection ...)

Overall Roadmap;

1) build the MAQ-10 (Mechanical) body.... beginers follow this instructables http://www.instructables.com/id/Basic-Quads-Systems-My-Easy-Quad-Build/

2) Refer the Principle and perform the wiring as per the given details and build the qudcopter

3) Install the required softwares and packages in both the Rpi and Ci20

4) Use the files uploaded here on those boards. if required, modify it according to your needs :-)

5) Fly the Quad using the remote and the live images will be received on the Ci20 board and processed using open CV

lnstalling Open CV:

Please Visit https://mipsci20.wordpress.com/ for step by step instructions to install open CV on Ci20.

Please Visit http://www.pyimagesearch.com/2015/02/23/install-opencv-and-python-on-your-raspberry-pi-2-and-b/ for step by step instructions to install open CV on RPI-2

How to fly the drone:

Please Visit http://uavcoach.com/how-to-fly-a-quadcopter-guide/ for the ultimate guide.....very useful :-)

Future Work:

The cameras installed should be used for navigation of the drone (Autopilot) hence we can approach the vehicles before crossing the border and alert them, simultaneously snapshots of the scene are captured and sent to the coastal guards, but right now using the camera feed from MAQ-10 we are manually controlling it.

Docking stations are being built certain spots for charging MAQ-10 and dock to dock patrolling can be performed at regular intervals and various stabilization algorithms are used for accurate flight and for night time surveillance

Instead of using the web camera to get the live feed, we could make use of (SWIR) Short Wave Infrared Night Vision Camera Systems in which images are not in color, This makes objects easily recognizeable but its expensive and heavier.

Conclusion:

  • Maritime Disputes of a country can be reduced
  • illegal entries are prevented
  • sea vehicles are warned when they are closing the border
  • We can scan wider area, zoom in target and also efficient during night
  • risk free surveillance

Thank you for your attention to this Project.

Code

arduino_code_spi_rpi-2C/C++
This sketch is for
- Get RC from Rx receiver
- transmit to Rpi pilot
- Receive ESC and Servos input from Rpi Pilot

Also include the pinchangeint library
#include <PinChangeInt.h>
#include <SPI.h>
#include <Servo.h>

//LED pin for checking
#define LED_PIN 13

//For ease of programming
#define THR 0
#define YAW 1
#define PITCH 2
#define ROLL 3

// Assign your channel in pins
#define THROTTLE_IN_PIN 8
#define YAW_IN_PIN 11
#define PITCH_IN_PIN 10
#define ROLL_IN_PIN 9

// shared variables are updated by the ISR and read by loop.
// In loop we immediatley take local copies so that the ISR can keep ownership of the
// shared ones. To access these in loop
// we first turn interrupts off with noInterrupts
// we take a copy to use in loop and the turn interrupts back on
// as quickly as possible, this ensures that we are always able to receive new signals
volatile uint16_t unThrottleInShared;
volatile uint16_t unYawInShared;
volatile uint16_t unPitchInShared;
volatile uint16_t unRollInShared;

// These are used to record the rising edge of a pulse in the calcInput functions
// They do not need to be volatile as they are only used in the ISR. If we wanted
// to refer to these in loop and the ISR then they would need to be declared volatile
uint32_t ulThrottleStart;
uint32_t ulYawStart;
uint32_t ulPitchStart;
uint32_t ulRollStart;


//servo variables
//Number of servos
#define SERVO_NUM 4
#define RC_MIN 1000
// Assign your channel out pins
#define FL_MOTOR_OUT_PIN 4
#define FR_MOTOR_OUT_PIN 5
#define BL_MOTOR_OUT_PIN 6
#define BR_MOTOR_OUT_PIN 7

//define Servo variables
Servo MOTOR[SERVO_NUM];

//define SPI data
volatile union int_byt{
  uint8_t u8[2];
  uint16_t u16;
} rc_data[4], esc_data[4];

volatile byte rx_buf[SERVO_NUM*2+1];
uint8_t pos=0;
uint8_t checksum=0;

bool start=false;
volatile bool update_servo=false;

//setup function
void setup()
{
  Serial.begin(9600); //for debugging...

  pinMode(LED_PIN, OUTPUT);

  /*
    PWM measurement settings
  */

  // using the PinChangeInt library, attach the interrupts
  // used to read the channels
  PCintPort::attachInterrupt(THROTTLE_IN_PIN, calcThrottle,CHANGE);
  PCintPort::attachInterrupt(YAW_IN_PIN, calcYaw,CHANGE);
  PCintPort::attachInterrupt(PITCH_IN_PIN, calcPitch,CHANGE);
  PCintPort::attachInterrupt(ROLL_IN_PIN, calcRoll,CHANGE);

  // attach servo objects, these will generate the correct
  // pulses for driving Electronic speed controllers, servos or other devices
  // designed to interface directly with RC Receivers
  MOTOR[0].attach(FL_MOTOR_OUT_PIN);
  MOTOR[1].attach(FR_MOTOR_OUT_PIN);
  MOTOR[2].attach(BL_MOTOR_OUT_PIN);
  MOTOR[3].attach(BR_MOTOR_OUT_PIN);

  //Set servo values to min
  for (int i=0;i<SERVO_NUM;i++)
    {
      MOTOR[i].writeMicroseconds(RC_MIN);
    }

  /*
    SPI settings
  */

  // Declare MISO as output : have to send on
  //master in, *slave out*
  pinMode(MISO, OUTPUT);

  // turn on SPI in slave mode
  SPCR |= _BV(SPE);

  // now turn on interrupts
  SPI.attachInterrupt();


}

void loop()
{
  //Constantly update rc_data
  rc_data[THR].u16 = unThrottleInShared;
  rc_data[YAW].u16 = unYawInShared;
  rc_data[PITCH].u16 = unPitchInShared;
  rc_data[ROLL].u16 = unRollInShared;

  if (unThrottleInShared < 1000 &
      unYawInShared      < 1200 &
      unPitchInShared    < 1200 &
      unRollInShared     > 1200 ) {

    uint32_t t_old = millis();
    while (millis()-t_old < 500 ){
      //wait to be sure that sticks are still in position
    }

    // if so change current status
    if (unThrottleInShared < 1000 &
	unYawInShared      < 1200 &
	unPitchInShared    < 1200 &
	unRollInShared     > 1200 ) {

      start = !start;
      //change LED status
      digitalWrite(13, start);
    }
  }

  //Update servo (ESC) if necessary and started
  if (update_servo & start){
    uint8_t ipos=0;
    byte checksum2=0;
    for (int i=0;i<SERVO_NUM;i++)
      {
	//process buffer values
	for (int ibyte = 0;ibyte<2;ibyte++){
	  esc_data[i].u8[ibyte] = rx_buf[ipos];
	  checksum2+=rx_buf[ipos];
	  ipos++;
	}
      }

    if (rx_buf[ipos] == checksum2) {
      //write ESC output
      for (int i=0;i<SERVO_NUM;i++)
	MOTOR[i].writeMicroseconds(esc_data[i].u16);
    }

    update_servo = false;

  } else if (!start) {
    for (int i=0;i<SERVO_NUM;i++)
      {
	MOTOR[i].writeMicroseconds(RC_MIN);
      }
  }

}

/*-----------------------
  SPI interrupt routine
------------------------*/
ISR (SPI_STC_vect)
{

  //grab a new command and process it
  byte cmd = SPDR;

  if (cmd == 'S') {
    //STOP do nothing : end of sending RC data
    pos=0;
    return;
  }

  if (cmd == 'P') {
    //process it !
    update_servo = true;
    pos=0;
    return;
  }

  if (cmd == 'C') {
    //push Cheksum into the register
    SPDR = checksum;
    checksum = 0;
    pos=0;
    return;
  }


  //push data into a byte buffer
  rx_buf[pos++] = cmd;

  // 10-11 -> send 2bytes channel 1 value
  // ...
  // 40-41 -> send 2bytes channel 4 value
  // ...
  // 60-61 -> send 2bytes channel 6 value
  switch (cmd){
  case 10:
    SPDR = rc_data[THR].u8[0];
    checksum += rc_data[THR].u8[0];
    break;

  case 11:
    SPDR = rc_data[THR].u8[1];
    checksum += rc_data[THR].u8[1];
    break;

  case 20:
    SPDR = rc_data[YAW].u8[0];
    checksum += rc_data[YAW].u8[0];
    break;

  case 21:
    SPDR = rc_data[YAW].u8[1];
    checksum += rc_data[YAW].u8[1];
    break;

  case 30:
    SPDR = rc_data[PITCH].u8[0];
    checksum += rc_data[PITCH].u8[0];
    break;

  case 31:
    SPDR = rc_data[PITCH].u8[1];
    checksum += rc_data[PITCH].u8[1];
    break;

  case 40:
    SPDR = rc_data[ROLL].u8[0];
    checksum += rc_data[ROLL].u8[0];
    break;

  case 41:
    SPDR = rc_data[ROLL].u8[1];
    checksum += rc_data[ROLL].u8[1];
    break;
 }

}

/*----------------------------------
  simple interrupt service routine
  for PWM measurements
*/
void calcThrottle()
{
  // if the pin is high, its a rising edge of the signal pulse, so lets record its value
  if(digitalRead(THROTTLE_IN_PIN) == HIGH)
    {
      ulThrottleStart = micros();
    }
  else
    {
      // else it must be a falling edge, so lets get the time and subtract the time of the rising edge
      // this gives use the time between the rising and falling edges i.e. the pulse duration.
      unThrottleInShared = (uint16_t)(micros() - ulThrottleStart);

    }
}

void calcYaw()
{
  if(digitalRead(YAW_IN_PIN) == HIGH)
    {
      ulYawStart = micros();
    }
  else
    {
      unYawInShared = (uint16_t)(micros() - ulYawStart);
    }
}

void calcPitch()
{
  if(digitalRead(PITCH_IN_PIN) == HIGH)
    {
      ulPitchStart = micros();
    }
  else
    {
      unPitchInShared = (uint16_t)(micros() - ulPitchStart);
    }
}

void calcRoll()
{
  if(digitalRead(ROLL_IN_PIN) == HIGH)
    {
      ulRollStart = micros();
    }
  else
    {
      unRollInShared = (uint16_t)(micros() - ulRollStart);
    }
}
The Main code.....C/C++
I have uploaded a zip file which contains the main.cpp along with all other necessary files & headers
#include <signal.h>
#include "main.h"

void stop_motors(int s){
  printf("Caught signal %d\n",s);

  uint8_t checksum=0;
  ArduSPI.writeByte('S');
  for (int iesc=0;iesc < 8; iesc++) {
    ArduSPI.writeByte((uint8_t) 0);
  }
  ArduSPI.writeByte(checksum);
  //sending end of transaction
  ArduSPI.writeByte('P');

  exit(0);
}

void Set_default_PID_config(){
  //manual initialization of PID constants
  yprRATE[YAW].set_Kpid(6.0, 0.0, 0.0);
  for (int i=1;i<3;i++){
    yprSTAB[i].set_Kpid(2.0, 0.001, 0.1);
    yprRATE[i].set_Kpid(2.0, 0.0, 0.0);
  }
}

void Blink_led(int N){
  // use gpio to blink an led on pin 0
  for(int i=0;i<N;i++){
  system("/usr/local/bin/gpio write 0 0");
  usleep(50000);
  system("/usr/local/bin/gpio write 0 1");
  usleep(50000);
  }
}

void Beep(int N){
  // use gpio to blink an led on pin 0
  for(int i=0;i<N;i++){
  system("sudo /home/pi/MAQ-10/BEEP/beep");
  usleep(160000);
  }
}

//-------------------------------------
//--------- Main-----------------------

int main(int argc, char *argv[])
{
  printf("MAQ-10\n");
  printf("----------------------\n");
  printf("\n");

  system("rm quadpilot.log");


  //handling of CTRL+C input
  struct sigaction sigIntHandler;
  sigIntHandler.sa_handler = stop_motors;
  sigemptyset(&sigIntHandler.sa_mask);
  sigIntHandler.sa_flags = 0;
  sigaction(SIGINT, &sigIntHandler, NULL);

  //setting up IMU
  imu.set_com();
  imu.initialize();

  //setting up SPI
  ArduSPI.initialize();

  //Set PID config
  if (argc == 8) {
    printf("Setting PID constants\n");
    printf("Rate PID :\n");
    printf("    Kp = %f, Ki = %f, Kd = %f\n",
	   atof(argv[1]),atof(argv[2]),atof(argv[3]));
    printf("Rate PID :\n");
    printf("    Kp = %f, Ki = %f, Kd = %f\n",
	   atof(argv[4]),atof(argv[5]),atof(argv[6]));
      for (int i=1;i<3;i++){
	yprRATE[i].set_Kpid(atof(argv[1]),atof(argv[2]),atof(argv[3]));
	yprSTAB[i].set_Kpid(atof(argv[4]),atof(argv[5]),atof(argv[6]));
      }
    printf("Yaw Rate PID :\n");
    printf("    Kp = %f\n",atof(argv[7]));
    yprRATE[YAW].set_Kpid(atof(argv[7]), 0.0, 0.0);

  }else {
    printf("Setting default PID constants\n");
    Set_default_PID_config();
  }

  //Say I am ready
  Beep(3);
  Blink_led(10);

  //Starting Timer
  Timer.start();

  /* Sleeping everything is done via
     software interrupts  */
  while (true){

    usleep(20000);

  }//end

  return 0;
}


//
OpenCV_remote
this is an example about how to use remote object detection based on openCV and zeromq framework. > ##requirements - opencv(python) as cv(opencv) and cv2(numpy) - zeromq(python) - gevent(light weight switch) - knowledge about img process - profile, logging each stage mem and cpu time ##method - Server - capture img - send img to clinet - wait for next command from client - update status by new command - Client - receive img - run all detection - build up a new command based on detection results ##detections - face detect - circle detect - line detect - find attribute obj ##how to run it? - python poll_camera.py (using cv to capture/show img via remote protocol) - python poll_camera2.py (using cv2 to capture/show img ...) - python poll_thread_run2.py (using cv2 to run all thread detection based on CPU num) - python poll_series_run2.py (using cv2 to run all series detection ...)
Arduino code
- Get RC from Rx receiver - transmit to Rpi pilot - Receive ESC and Servos input from Rpi Pilot

Schematics

Host side(Quadcopter) Wiring
MPU6050 -> RPI : -VDD -> 3.3V -GND -> GND -SDA -> SDA -SCL -> SCL -VIO -> 3.3V

Arduino -> RPI : -VCC -> 5V from external Regulator -GND -> GND -MISO -> Logic Level converter ->MISO -MOSI -> Logic Level converter ->MOSI -SCK -> Logic Level converter ->SCK

ESCs and RC Receiver on Arduino: -Using PinChange interrupts -Check in the arduino code
Host%20side

Comments

Similar projects you might like

Omni-Directional People Tracking Friendly Robot

Project tutorial by Team Think Engineer

  • 3,987 views
  • 8 comments
  • 26 respects

Ball Tracking Robot

Project showcase by Rohan Juneja

  • 38,434 views
  • 34 comments
  • 86 respects

Smart Face Tracking Robot Car

Project tutorial by Sebastian Hernandez

  • 5,967 views
  • 5 comments
  • 36 respects

Android Guided Vehicle

Project in progress by bharath.s

  • 2,568 views
  • 0 comments
  • 7 respects

Terminator Vision System

Project showcase by Team SUAI/IHPCNT

  • 6,535 views
  • 0 comments
  • 24 respects

Personal Home Assistant

Project tutorial by 3 developers

  • 4,003 views
  • 0 comments
  • 26 respects
Add projectSign up / Login