Outils pour utilisateurs

Outils du site


wiki:god:not_today:home

Not Today

remplir probleme rencontré (fixation moteur + code)

I - Présentation de l’équipe

Les membres et leurs parcours

Nous sommes une équipe composée de 5 personnes de L3 Informatique :

  • Julien Gourraud (bac STI, DUT informatique)
  • William Lavoué (bac SSI spé SI)
  • Salmane Kechkar (bac S)
  • Yacine Boukhelif(bac S)
  • Emeric Goga (bac S, 1ère année en PEIP)
Pourquoi participer à cette compétition

Nous sommes très intéressés par cette compétition, car nous voulons mettre en places nos connaissances diverses en Informatique et Électronique, mais également pour le défi technique. La conception et la réalisation d’un drone sera une expérience valorisante tant sur le plan personnel que professionnel. De plus, elle nous permettra de nous confronter aux différents défis que représente le travail en équipe.

La répartition des tâches au sein de l’équipe

Nous avons réparti le travail de la manière suivante

  • William : Conception de la structure / Électronique
  • Julien : Électronique / Programmation
  • Yacine Boukhelif : Impression 3D
  • Salmane : Programmation / Modélisation mathématique
  • Emeric : Programmation / Mécanique

II - Type de drone

La structure

Nous avons choisi de réaliser un quadricoptère en X, car ce modèle représente un bon com-promis entre le prix de fabrication et la simplicité de conception ainsi que par la richesse de la documentation disponible. La structure (cf ci-dessous) sera réalisée à partir de plaques usinées et de tubes en fibres de carbone et les éléments d’assemblage imprimés en ABS. Nous avons choisi cette solution pour sa robustesse, sa légèreté et sa facilité de réalisation avec les moyens fournis par le PMCLab.

Plan 3D du drone

L’électronique et la mécanique du drone

Nous avons choisi des hélices de 10 pouces afin d’avoir un drone stable. Pour les faire tourner, nous avons décidés de prendre des moteurs tournant à une vitesse modérée. La position de l'ensemble sur les tubes sera variable.

Nous avons choisi de faire nous-mêmes la partie électronique du drone avec une carte bien connue : l’Arduino Due. Son avantage est sa simplicité d’utilisation, cette dernière est programmée grâce à son environnement de développement. Elle comporte de nombreuses Entrées/Sortie, ce qui permet de se connecter au mieux à nos différents composants.

Concernant la commande, nous avons opté pour une communication Radio, car c’est un mode de communication très robuste et simple d’utilisation. L'émetteur radio (une manette) comporte 6 canaux, quatre d’entre eux servent à la manœuvre du drone. Il nous en reste donc 2 pour d’autres applications telles qu’un changement de mode grâce au modification des PID.

Pour l’IMU, nous avons choisi une carte Adafruit qui comporte les 3 composants essentiels :

  • LSM303DLHC : accéléromètre 3 Axes / magnétomètre 3 Axes
  • L3GD20 : gyroscope 3 Axes
  • BMP180 : Baromètre

Les moteurs triphasé sont contrôlés à l’aide d’ESCs. Ces derniers sont alimentés par la batterie et contrôlés par la carte Arduino.

Ci-dessous, le montage électronique de notre drone.

III - Choix et prix des composants

Hélice (10 pouces) + Moteur (15 A max / 935KV) : 11.96*5 = 60 € http://www.hobbyking.com/hobbyking/store/__43884__MT2213_935KV_MultiStar_Motor_and_Propeller_Combo_10_4_5_CW_CCW.html

ESC(20 A) : 16*4 = 64 € http://hobbyking.com/hobbyking/store/__42549__Afro_HV_20A_MultiRotor_ESC_High_Voltage_3_8s.html

Carte de distribution : 4 € http://hobbyking.com/hobbyking/store/__27035__Hobby_King_Octocopter_Power_Distribution_Board.html

Carte Adruino Due : 36 € http://store.arduino.cc/index.php?main_page=product_info&cPath=11_12&products_id=243

Mannette + Recepteur RC (6 canaux / 2,4Ghz) : 44 $ = 35 € * 20% = 42 € http://www.hobbypartz.com/exrc62tr.html

IMU (10 degrés de liberté) : 29$ = 24 € * 20% = 28.8 € http://www.adafruit.com/product/1604

Batterie (Lipo 5200mAh / 3S / 11.1V) : 22.18€ *2 = 44.36€ http://www.hobbyking.com/hobbyking/store/__62884__MultiStar_High_Capacity_3S_5200mAh_Multi_Rotor_Lipo_Pack.html

Moniteur de batterie (Alarme en cas de batterie faible): 1.59€ http://hobbyking.com/hobbyking/store/__22749__On_Board_Lipoly_Low_Voltage_Alarm_2s_3s.html

Chargeur de batterie : 18.39€ http://www.hobbyking.com/hobbyking/store/__7028__Turnigy_Accucel_6_50W_6A_Balancer_Charger_w_Accessories.html

Ubec (Alimentation de Arduino : 11.1V vers 9V): 4.70 € http://hobbyking.com/hobbyking/store/__52862__X9_PRO_9V_3A_UBEC_2_5S_Lipoly_7_2_21v_.html

Filtrage des vibrations : 2 € http://www.hobbyking.com/hobbyking/store/__40612__Vibration_Damping_Ball_50gram_8_pcs_bag_.html

Plaque de fibre de verre (1,5mm / 1000*500mm) : 34,90 € http://www.masterplatex.de/epages/62236671.sf/de_DE/?ObjectPath=/Shops/62236671/Products/%22FR4%20schwarz%22/SubProducts/0%2C5-FR4-schw-M

Tube Carbone (300*16*14mm) : 4*2.81 = 11.24€ http://www.hobbyking.com/hobbyking/store/__13215__Carbon_Fiber_Round_Tube_330x16x14mm.html

Velcro : 2.22€ http://www.hobbyking.com/hobbyking/store/__9374__Polyester_Velcro_Peel_n_stick_adhesive_side_V_STRONG_1mtr_.html

Achat de visserie en petite quantité directement chez Bricorama ou LeroyMerlin : 30 € Total : 60 + 64 + 4 + 36 + 42 + 28.8 + 44.36 + 1.59 + 18.39 + 4.70 + 2 + 34.9 + 11.24 + 2.2 + 30 = 384 €

IV - Machines-outils

Nous avons utilisé la découpeuse laser pour usiner les 2 plaques de fibre de verre qui servent de “corps” pour le drone. L’imprimante 3D nous as servi pour réaliser nos éléments d’assemblage :

  • La fixation des bras sur le corps
  • La fixation des moteur sur les bras

V - L’informatique du drone

La programmation se fera sur la carte Arduino grâce à l'environnement de développement Ar-duino.

notToday.ino
#include "Wire.h"
#include <Adafruit_Sensor.h>
#include <Adafruit_LSM303_U.h>
#include <Adafruit_L3GD20_U.h>
#include <Adafruit_BMP085_U.h>
#include <Adafruit_10DOF.h>
 
#include <Servo.h>
 
#include <PID_v1.h>
 
/************************************************************************/
/**************************VARIABLE RADIO********************************/
/************************************************************************/
int vitesse = 0;
 
const int pinCh1 = A0;
const int pinCh2 = A1;
const int pinCh3 = A2;
const int pinCh4 = A3;
const int pinCh5 = A4;
 
//micros lors du HIGH
volatile unsigned long timer_start1;
volatile unsigned long timer_start2;
volatile unsigned long timer_start3;
volatile unsigned long timer_start4;
volatile unsigned long timer_start5;
 
//difference entre les périodes
volatile int pulse_time1;
volatile int pulse_time2;
volatile int pulse_time3;
volatile int pulse_time4;
volatile int pulse_time5;
 
//Pour mapper les commandes entre 0 et 100
const int minCh1 = 1190;
const int minCh2 = 1160;
const int minCh3 = 1137;
const int minCh4 = 1125;
const int minCh5 = 9999;
 
const int maxCh1 = 1930;
const int maxCh2 = 1810;
const int maxCh3 = 1790;
const int maxCh4 = 1890;
const int maxCh5 = 9999;
 
double ch1 = 0;
double ch2 = 0;
double ch3 = 0;
double ch4 = 0;
double ch5 = 0;
 
volatile int last_interrupt_time1;
volatile int last_interrupt_time2;
volatile int last_interrupt_time3;
volatile int last_interrupt_time4;
volatile int last_interrupt_time5;
 
 
 
/************************************************************************/
/**************************VARIABLES IMU*********************************/
/************************************************************************/
 
/* Assign a unique ID to the sensors */
Adafruit_10DOF dof = Adafruit_10DOF();
Adafruit_LSM303_Accel_Unified accel = Adafruit_LSM303_Accel_Unified(30301);
Adafruit_LSM303_Mag_Unified mag = Adafruit_LSM303_Mag_Unified(30302);
Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(18001);
 
/* Update this with the correct SLP for accurate altitude measurements */
float seaLevelPressure = SENSORS_PRESSURE_SEALEVELHPA;
 
double pitchKi = 0.5;
double pitchKp = 0;
double pitchKd = 1;
 
double rollKi = 2;
double rollKp = 5;
double rollKd = 1;
 
double yawKi = 2;
double yawKp = 5;
double yawKd = 1;
 
 
double pitchIN;
double rollIN;
double yawIN;
 
double pitchOUT;
double rollOUT;
double yawOUT;
 
//IN,OUT,SETPOINT
PID pidPitch(&pitchIN, &pitchOUT, &ch2, pitchKp, pitchKi, pitchKd, DIRECT);
PID pidRoll(&rollIN, &rollOUT, &ch1, rollKp, rollKi, rollKd, DIRECT);
PID pidYaw(&yawIN, &yawOUT, &ch4, yawKp, yawKi, yawKd, DIRECT);
 
int pitchMin = -30;
int pitchMax = 30;
 
int rollMin = -30;
int rollMax = 30;
 
int yawMin = -180;
int yawMax = 180;
 
 
 
/************************************************************************/
/**************************VARIABLES MOTORS******************************/
/************************************************************************/
 
//Objet servo pour controler les diff�rents moteurs
Servo motor1, motor2, motor3, motor4;
 
const int pinM1 = 9;
const int pinM2 = 10;
const int pinM3 = 11;
const int pinM4 = 6;
 
int speedM1 = 0;
int speedM2 = 0;
int speedM3 = 0;
int speedM4 = 0;
int speedM1M3 = 0;
int speedM2M4 = 0;
 
const int  motorSpeedMin = 0;
const int motorSpeedMax = 170;
 
 
/************************************************************************/
/***********************************MAIN*********************************/
/************************************************************************/
 
void setup()
{
  Serial.begin(115200);
  initSensors();
  initInterrupt();
  initPID();
  initMotors(); // 10 SECONDES
 
}
 
void loop()
{
  getSensor();
  getRadio();//map les cannaux de 0 � 100
  calcSpeed();//calcul en fontion des commandes et du PID la vitesse � appliquer aux moteurs
  updateMotors();//met � jour la vitesse des moteurs
 
  /// TEST_affichagePitch();
  // TEST_affichageCanaux();
  TEST_affichageMoteur();
 
}
 
 
/************************************************************************/
/****************************FONCTIONS RADIO*****************************/
/************************************************************************/
void isr1()
{
  //Enregistre la dernière interruption
  last_interrupt_time1 = micros();
 
  //Si high
  if (digitalRead(pinCh1) == HIGH)
  {
    timer_start1 = micros();
  }
  //Si low
  else
  {
    //timer déclenché?
    if (timer_start1 > 0)
    {
      //Enregristre le temps
      pulse_time1 = ((volatile int)micros() - timer_start1);
      //redémarre le timer
      timer_start1 = 0;
    }
  }
}
 
void isr2()
{
  last_interrupt_time2 = micros();
  if (digitalRead(pinCh2) == HIGH) {
    timer_start2 = micros();
  }
  else {
    if (timer_start2 > 0) {
      pulse_time2 = ((volatile int)micros() - timer_start2);
      timer_start2 = 0;
    }
  }
}
 
void isr3()
{
  last_interrupt_time3 = micros();
  if (digitalRead(pinCh3) == HIGH) {
    timer_start3 = micros();
  }
  else {
    if (timer_start3 > 0) {
      pulse_time3 = ((volatile int)micros() - timer_start3);
      timer_start3 = 0;
    }
  }
}
 
void isr4()
{
  last_interrupt_time4 = micros();
  if (digitalRead(pinCh4) == HIGH) {
    timer_start4 = micros();
  }
  else {
    if (timer_start4 > 0) {
      pulse_time4 = ((volatile int)micros() - timer_start4);
      timer_start4 = 0;
    }
  }
}
 
void isr5()
{
  last_interrupt_time5 = micros();
  if (digitalRead(pinCh5) == HIGH) {
    timer_start5 = micros();
  }
  else {
    if (timer_start5 > 0) {
      pulse_time5 = ((volatile int)micros() - timer_start5);
      timer_start5 = 0;
    }
  }
}
 
void initInterrupt() {
  timer_start1 = 0;
  timer_start2 = 0;
  timer_start3 = 0;
  timer_start4 = 0;
  timer_start5 = 0;
  attachInterrupt(pinCh1, isr1, CHANGE);
  attachInterrupt(pinCh2, isr2, CHANGE);
  attachInterrupt(pinCh3, isr3, CHANGE);
  attachInterrupt(pinCh4, isr4, CHANGE);
  attachInterrupt(pinCh5, isr5, CHANGE);
}
 
void getRadio() {
  ch1 = map(pulse_time1, minCh1, maxCh1, rollMin, rollMax); //ROLL
  ch2 = map(pulse_time2, minCh2, maxCh2, pitchMin, pitchMax); //PITCH
  ch3 = map(pulse_time3, minCh3, maxCh3, 0, 100); //VITESSE
  ch4 = map(pulse_time4, minCh4, maxCh4, yawMin, yawMax); //YAW
  ch5 = map(pulse_time5, minCh5, maxCh5, 0, 100);
}
 
void TEST_affichageCanaux() {
  Serial.print("CH1 : ");
  Serial.print(pulse_time1);
  Serial.print("-->");
  Serial.print(ch1);
  Serial.print(" - CH2 : ");
  Serial.print(pulse_time2);
  Serial.print("-->");
  Serial.print(ch2);
  Serial.print(" - CH3 : ");
  Serial.print(pulse_time3);
  Serial.print("-->");
  Serial.print(ch3);
  Serial.print(" - CH4 : ");
  Serial.print(pulse_time4);
  Serial.print("-->");
  Serial.println(ch4);
}
 
 
/************************************************************************/
/***************************FONCTIONS IMU********************************/
/************************************************************************/
/* Code fourni par AdaFruit */
void initSensors() {
  if (!accel.begin()) {
    Serial.println(F("Ooops, no LSM303 detected ... Check your wiring!"));
    while (1);
  }
  if (!mag.begin()) {
    Serial.println("Ooops, no LSM303 detected ... Check your wiring!");
    while (1);
  }
  if (!bmp.begin()) {
    Serial.println("Ooops, no BMP180 detected ... Check your wiring!");
    while (1);
  }
}
 
void getSensor() {
  sensors_event_t accel_event;
  sensors_event_t mag_event;
  sensors_event_t bmp_event;
  sensors_vec_t orientation;
 
  /* Calculate pitch and roll from the raw accelerometer data */
  accel.getEvent(&accel_event);
  if (dof.accelGetOrientation(&accel_event, &orientation)) {
 
    rollIN = map(orientation.roll, -180, 180, -30, 30);
    pitchIN = map(orientation.pitch, -180, 180, -30, 30);
  }
  /* Calculate the heading using the magnetometer */
  mag.getEvent(&mag_event);
  if (dof.magGetOrientation(SENSOR_AXIS_Z, &mag_event, &orientation)) {
 
    yawIN = map(orientation.heading, -180, 180, -30, 30);
  }
  /* Calculate the altitude using the barometric pressure sensor */
  bmp.getEvent(&bmp_event);
  if (bmp_event.pressure) {
    /* Get ambient temperature in C */
    float temperature;
    bmp.getTemperature(&temperature);
    }
}
 
 
void TEST_affichagePitch() {
  Serial.print("Yaw:");
  Serial.print(yawIN);
  Serial.print(" - Kp:");
  Serial.print(pitchKp);
  Serial.print(" - Ki:");
  Serial.print(pitchKi);
  Serial.print(" - Kd:");
  Serial.print(pitchKd);
  Serial.print(" - CH2:");
  Serial.print(ch2);
  Serial.print(" - PitchIN:");
  Serial.print(pitchIN);
  Serial.print(" - PitchOUT:");
  Serial.println(pitchOUT);
}
 
void TEST_affichageRoll() {
  Serial.print("RollIN : ");
  Serial.print(rollIN);
  Serial.print(" - RollOUT : ");
  Serial.println(rollOUT);
}
 
void TEST_affichageYaw() {
  Serial.print("YawIN : ");
  Serial.print(yawIN);
  Serial.print(" - YawOUT : ");
  Serial.println(yawOUT);
}
/************************************************************************/
/***************************FONCTION CALCUL*****************************/
/************************************************************************/
void initPID() {
  pidPitch.SetMode(AUTOMATIC);
  pidPitch.SetOutputLimits(-20, 20);
  pidRoll.SetMode(AUTOMATIC);
  pidRoll.SetOutputLimits(-20, 20);
  pidYaw.SetMode(AUTOMATIC);
  pidYaw.SetOutputLimits(-180, 180);
}
 
 
void calcSpeed() {
  noInterrupts();
  pidPitch.Compute();
  pidRoll.Compute();
  pidYaw.Compute();
  interrupts();
 
   speedM1 = map(constrain(ch3 + pitchOUT, 0, 100), 0, 100, motorSpeedMin, motorSpeedMax);
    speedM3 = map(constrain(ch3 - pitchOUT, 0, 100), 0, 100, motorSpeedMin, motorSpeedMax);
     speedM2 = map(constrain(ch3 + rollOUT, 0, 100), 0, 100, motorSpeedMin, motorSpeedMax);
    speedM4 = map(constrain(ch3 - rollOUT, 0, 100), 0, 100, motorSpeedMin, motorSpeedMax);
 
  //>>>Appliquer le YAW
}
 
 
void TEST_affichageMoteur() {
  Serial.print("M1 :");
  Serial.print(speedM1);
  Serial.print(" - M2:");
  Serial.print(speedM2);
  Serial.print(" - M3:");
  Serial.print(speedM3);
  Serial.print(" - M4:");
  Serial.println(speedM4);
}
/************************************************************************/
/***************************FONCTIONS MOTORS*****************************/
/************************************************************************/
 
//Initialisation des moteurs : 10 SECONDES
void initMotors() {
  Serial.println("InitMotors");
 
  motor1.attach(pinM1);
  motor2.attach(pinM2);
  motor3.attach(pinM3);
  motor4.attach(pinM4);
  motor1.write(170);
  motor2.write(170);
  motor3.write(170);
  motor4.write(170);
  Serial.println("Brancher ALIM!!");
  delay(5000);
  motor1.write(0);
  motor2.write(0);
  motor3.write(0);
  motor4.write(0);
  delay(5000);
}
 
//Mise a jour de la vitesse des moteur en fontion des variables globales
void updateMotors() {
  vitesse = map(ch3, 0, 100, 0, 160);
  motor1.write(vitesse);
  motor2.write(vitesse);
  motor3.write(vitesse);
  motor4.write(vitesse);
 
 
}

VI - Les réglages

Les réglages important sur un drone sont les PID (Proportionnel-Integral-Derivé). Pour effectuer ces différents réglages, nous avons suivi les astuces de ce site : http://fr3d.kazeo.com/reglages-et-astuces/reglages-et-astuces,r409844.html

VII - Les problèmes rencontré

Les fixations des moteurs

== Le code

VIII - Évolution possible du drone

Nous souhaitons faire évoluer notre drone s’il nous reste du temps (et de l’argent). Nous ajouterions un GPS et un Raspberry Pi au drone. Le but serait de :

  1. Faire voler le drone avec la manette en sauvegardant le chemin pris grâce aux coordonnées GPS
  2. Faire voler le drone sur le même passage

Le coût de cette amélioration serait d’environ 100€ : Carte GPS : 50 € Antenne GPS : 10 € Raspberry Pi : 40 €

IX - Sites de nos recherches

  • Wiki de Game of Drone 2013-2014
  • Adafruit
  • Site officiel Arduino
  • Instructable
  • HobbyKing
  • DiyDrones
wiki/god/not_today/home.txt · Dernière modification: 2016/09/11 13:14 (modification externe)