Ci-dessous, les différences entre deux révisions de la page.
Prochaine révision | Révision précédente | ||
wiki:god:not_today:home [2015/01/19 18:29] karang créée |
wiki:god:not_today:home [2016/09/11 11:14] (Version actuelle) |
||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
- | === Not Today === | + | ==== 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, | ||
+ | |||
+ | == 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' | ||
+ | |||
+ | 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, | ||
+ | |||
+ | 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' | ||
+ | |||
+ | 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:// | ||
+ | |||
+ | ESC(20 A) : 16*4 = 64 € | ||
+ | http:// | ||
+ | |||
+ | Carte de distribution : 4 € | ||
+ | http:// | ||
+ | |||
+ | Carte Adruino Due : 36 € | ||
+ | http:// | ||
+ | |||
+ | Mannette + Recepteur RC (6 canaux / 2,4Ghz) : 44 $ = 35 € * 20% = 42 € | ||
+ | http:// | ||
+ | |||
+ | IMU (10 degrés de liberté) : 29$ = 24 € * 20% = 28.8 € | ||
+ | http:// | ||
+ | |||
+ | Batterie (Lipo 5200mAh / 3S / 11.1V) : 22.18€ *2 = 44.36€ | ||
+ | http:// | ||
+ | |||
+ | Moniteur de batterie (Alarme en cas de batterie faible): 1.59€ | ||
+ | http:// | ||
+ | |||
+ | Chargeur de batterie : 18.39€ | ||
+ | http:// | ||
+ | |||
+ | Ubec (Alimentation de Arduino : 11.1V vers 9V): 4.70 € | ||
+ | http:// | ||
+ | |||
+ | Filtrage des vibrations : 2 € | ||
+ | http:// | ||
+ | |||
+ | Plaque de fibre de verre (1,5mm / 1000*500mm) : 34,90 € | ||
+ | http:// | ||
+ | |||
+ | Tube Carbone (300*16*14mm) : 4*2.81 = 11.24€ | ||
+ | http:// | ||
+ | |||
+ | Velcro | ||
+ | http:// | ||
+ | |||
+ | 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' | ||
+ | |||
+ | <file c notToday.ino> | ||
+ | |||
+ | #include " | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | #include < | ||
+ | |||
+ | #include < | ||
+ | |||
+ | / | ||
+ | / | ||
+ | / | ||
+ | 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; | ||
+ | |||
+ | // | ||
+ | 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; | ||
+ | |||
+ | |||
+ | |||
+ | / | ||
+ | / | ||
+ | / | ||
+ | |||
+ | /* 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; | ||
+ | |||
+ | // | ||
+ | PID pidPitch(& | ||
+ | PID pidRoll(& | ||
+ | PID pidYaw(& | ||
+ | |||
+ | int pitchMin = -30; | ||
+ | int pitchMax = 30; | ||
+ | |||
+ | int rollMin = -30; | ||
+ | int rollMax = 30; | ||
+ | |||
+ | int yawMin = -180; | ||
+ | int yawMax = 180; | ||
+ | |||
+ | |||
+ | |||
+ | / | ||
+ | / | ||
+ | / | ||
+ | |||
+ | //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; | ||
+ | |||
+ | |||
+ | / | ||
+ | / | ||
+ | / | ||
+ | |||
+ | void setup() | ||
+ | { | ||
+ | Serial.begin(115200); | ||
+ | initSensors(); | ||
+ | initInterrupt(); | ||
+ | initPID(); | ||
+ | initMotors(); | ||
+ | |||
+ | } | ||
+ | |||
+ | void loop() | ||
+ | { | ||
+ | getSensor(); | ||
+ | getRadio();// | ||
+ | calcSpeed();// | ||
+ | updateMotors();// | ||
+ | |||
+ | /// TEST_affichagePitch(); | ||
+ | // TEST_affichageCanaux(); | ||
+ | TEST_affichageMoteur(); | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | / | ||
+ | / | ||
+ | / | ||
+ | void isr1() | ||
+ | { | ||
+ | // | ||
+ | last_interrupt_time1 = micros(); | ||
+ | |||
+ | //Si high | ||
+ | if (digitalRead(pinCh1) == HIGH) | ||
+ | { | ||
+ | timer_start1 = micros(); | ||
+ | } | ||
+ | //Si low | ||
+ | else | ||
+ | { | ||
+ | //timer déclenché? | ||
+ | if (timer_start1 > 0) | ||
+ | { | ||
+ | // | ||
+ | pulse_time1 = ((volatile int)micros() - timer_start1); | ||
+ | // | ||
+ | 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, | ||
+ | attachInterrupt(pinCh2, | ||
+ | attachInterrupt(pinCh3, | ||
+ | attachInterrupt(pinCh4, | ||
+ | attachInterrupt(pinCh5, | ||
+ | } | ||
+ | |||
+ | void getRadio() { | ||
+ | ch1 = map(pulse_time1, | ||
+ | ch2 = map(pulse_time2, | ||
+ | ch3 = map(pulse_time3, | ||
+ | ch4 = map(pulse_time4, | ||
+ | ch5 = map(pulse_time5, | ||
+ | } | ||
+ | |||
+ | void TEST_affichageCanaux() { | ||
+ | Serial.print(" | ||
+ | Serial.print(pulse_time1); | ||
+ | Serial.print(" | ||
+ | Serial.print(ch1); | ||
+ | Serial.print(" | ||
+ | Serial.print(pulse_time2); | ||
+ | Serial.print(" | ||
+ | Serial.print(ch2); | ||
+ | Serial.print(" | ||
+ | Serial.print(pulse_time3); | ||
+ | Serial.print(" | ||
+ | Serial.print(ch3); | ||
+ | Serial.print(" | ||
+ | Serial.print(pulse_time4); | ||
+ | Serial.print(" | ||
+ | Serial.println(ch4); | ||
+ | } | ||
+ | |||
+ | |||
+ | / | ||
+ | / | ||
+ | / | ||
+ | /* Code fourni par AdaFruit */ | ||
+ | void initSensors() { | ||
+ | if (!accel.begin()) { | ||
+ | Serial.println(F(" | ||
+ | while (1); | ||
+ | } | ||
+ | if (!mag.begin()) { | ||
+ | Serial.println(" | ||
+ | while (1); | ||
+ | } | ||
+ | if (!bmp.begin()) { | ||
+ | Serial.println(" | ||
+ | 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(& | ||
+ | if (dof.accelGetOrientation(& | ||
+ | |||
+ | rollIN = map(orientation.roll, | ||
+ | pitchIN = map(orientation.pitch, | ||
+ | } | ||
+ | /* Calculate the heading using the magnetometer */ | ||
+ | mag.getEvent(& | ||
+ | if (dof.magGetOrientation(SENSOR_AXIS_Z, | ||
+ | |||
+ | yawIN = map(orientation.heading, | ||
+ | } | ||
+ | /* Calculate the altitude using the barometric pressure sensor */ | ||
+ | bmp.getEvent(& | ||
+ | if (bmp_event.pressure) { | ||
+ | /* Get ambient temperature in C */ | ||
+ | float temperature; | ||
+ | bmp.getTemperature(& | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | void TEST_affichagePitch() { | ||
+ | Serial.print(" | ||
+ | Serial.print(yawIN); | ||
+ | Serial.print(" | ||
+ | Serial.print(pitchKp); | ||
+ | Serial.print(" | ||
+ | Serial.print(pitchKi); | ||
+ | Serial.print(" | ||
+ | Serial.print(pitchKd); | ||
+ | Serial.print(" | ||
+ | Serial.print(ch2); | ||
+ | Serial.print(" | ||
+ | Serial.print(pitchIN); | ||
+ | Serial.print(" | ||
+ | Serial.println(pitchOUT); | ||
+ | } | ||
+ | |||
+ | void TEST_affichageRoll() { | ||
+ | Serial.print(" | ||
+ | Serial.print(rollIN); | ||
+ | Serial.print(" | ||
+ | Serial.println(rollOUT); | ||
+ | } | ||
+ | |||
+ | void TEST_affichageYaw() { | ||
+ | Serial.print(" | ||
+ | Serial.print(yawIN); | ||
+ | Serial.print(" | ||
+ | Serial.println(yawOUT); | ||
+ | } | ||
+ | / | ||
+ | / | ||
+ | / | ||
+ | void initPID() { | ||
+ | pidPitch.SetMode(AUTOMATIC); | ||
+ | pidPitch.SetOutputLimits(-20, | ||
+ | pidRoll.SetMode(AUTOMATIC); | ||
+ | pidRoll.SetOutputLimits(-20, | ||
+ | pidYaw.SetMode(AUTOMATIC); | ||
+ | pidYaw.SetOutputLimits(-180, | ||
+ | } | ||
+ | |||
+ | |||
+ | void calcSpeed() { | ||
+ | noInterrupts(); | ||
+ | pidPitch.Compute(); | ||
+ | pidRoll.Compute(); | ||
+ | pidYaw.Compute(); | ||
+ | interrupts(); | ||
+ | |||
+ | | ||
+ | speedM3 = map(constrain(ch3 - pitchOUT, 0, 100), 0, 100, motorSpeedMin, | ||
+ | | ||
+ | speedM4 = map(constrain(ch3 - rollOUT, 0, 100), 0, 100, motorSpeedMin, | ||
+ | |||
+ | //>>> | ||
+ | } | ||
+ | |||
+ | |||
+ | void TEST_affichageMoteur() { | ||
+ | Serial.print(" | ||
+ | Serial.print(speedM1); | ||
+ | Serial.print(" | ||
+ | Serial.print(speedM2); | ||
+ | Serial.print(" | ||
+ | Serial.print(speedM3); | ||
+ | Serial.print(" | ||
+ | Serial.println(speedM4); | ||
+ | } | ||
+ | / | ||
+ | / | ||
+ | / | ||
+ | |||
+ | // | ||
+ | void initMotors() { | ||
+ | Serial.println(" | ||
+ | |||
+ | 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(" | ||
+ | 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:// | ||
+ | |||
+ | |||
+ | === 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 : | ||
+ | - Faire voler le drone avec la manette en sauvegardant le chemin pris grâce aux coordonnées GPS | ||
+ | - 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 | ||
+ |