Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
bharath.sBertin Senald GDeepak Shanmugam
Published © LGPL

MAQ-10 (An Intellectual Maritime Boundary Monitor)

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

AdvancedWork in progress20 hours4,473
MAQ-10 (An Intellectual Maritime Boundary Monitor)

Things used in this project

Hardware components

Creator Ci20
Creator Ci20
×1
Raspberry Pi 2 Model B
Raspberry Pi 2 Model B
×1
GY-521 MPU-6050 3 Axis Gyroscope + Accelerometer Module For Arduino
×1
Arduino Micro
Arduino Micro
×1
TURNIGY 2204-14T 19g Outrunner
×1
Turnigy Multistar 20 Amp
×1
1 LiPo 3s 3700 mAh battery
×1
QuadCopter frame
×1
4 channels RC Remote + Receiver
×1
SparkFun Logic Level Converter - Bi-Directional
SparkFun Logic Level Converter - Bi-Directional
×1

Software apps and online services

OpenCV
OpenCV

Hand tools and fabrication machines

Toolsmart PCB Hand Push Drill
Soldering iron (generic)
Soldering iron (generic)
Hot glue gun (generic)
Hot glue gun (generic)

Story

Read more

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

Code

arduino_code_spi_rpi-2

C/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

PILOT (files for Quad copter)

Credits

bharath.s

bharath.s

2 projects • 10 followers
Bertin Senald G

Bertin Senald G

1 project • 3 followers
Deepak Shanmugam

Deepak Shanmugam

1 project • 4 followers

Comments