Aller au contenu

Sylvainm Mahem

Nouveau
  • Compteur de contenus

    17
  • Inscription

  • Dernière visite

À propos de Sylvainm Mahem

  • Rang
    Pilote

Profile Information

  • Sexe
    Non Spécifié
  • Identité
    sylvain
  • Club
    dominelais

Visiteurs récents du profil

589 visualisations du profil
  1. Construction d'une radiocommande !

    Bonjour, j'ai écrit un nouveau paragraphe sur mon site pour expliquer une fonctionnalité qui peut vous intéresser: Système multidirectionnel (multiceiver) (voir: http://www.sylvainmahe.site/projectRadioControl.html). Le système de radiocommande 2.4GHz que je propose ici permet la communication multidirectionnelle entre la radiocommande et un ou plusieurs modèles, autorise le dialogue entre les modèles eux-mêmes (réseau d'émetteurs/récepteurs, ou multiceivers), et rend possible l'ajout de plusieurs émetteurs/récepteurs (tranceivers) embarqués dans un même véhicule (pour les gros modèles notamment). Tout projet est alors possible, sans même évoquer le modélisme piloté dont il est question ici: Ce principe d'émetteur/récepteur intégré donne également la possibilité à l'utilisateur d'effectuer des communications longues distances en basse puissance d'émission (inférieure à 100mW), ceci par transmission de données de la radiocommande vers des périphériques relais qui se chargent non pas de traiter l'information et de l'utiliser, mais plutôt de la relayer vers d'autres périphériques afin d'atteindre la portée radio vers le modèle. Il est envisageable d'imaginer un robot d'exploration de décombres hors de portée radio directe avec le poste de pilotage (à cause des bardages métalliques des bâtiments par exemple), mais étant à portée radio de plusieurs relais qui se chargent seulement de transmettre (relayer) les informations aux téléopérateurs. À noter que les paragraphes qui relatent de l'utilisation de ma radiocommande sur mon site font état d'une utilisation avec un seul modèle, car c'est mon application principale (l'aéromodélisme). Néanmoins tout ce qui est expliqué (utilisation des menus, fonctionnalités, etc...) fonctionne avec plusieurs modèles (suivant la logique que vous avez programmé dans leurs microcontrôleurs respectifs bien entendu). Dans les caractéristiques de la radiocommande j'ai donc rajouté: - Communication multidirectionnelle vers (sol/air air/sol) et entre (air/air) plusieurs modèles. - Communication vers périphériques relais pour applications longues distances basse puissance.
  2. Construction d'une radiocommande !

    J'ai rajouté à la radio/et aux modèles en paramètres par défaut l'inversion des voies, et les courbes (équivalent à l'exponentiel) sur les gaz, tangage, roulis, et lacet. Ce sont des paramètres utiles tellement communs à bon nombres de modèles... Ils sont bien évidement enregistrés comme tous les autres paramètres dans le modèle. J'ai modifié à ce propos ma fonction de courbe dans MODULE. J'ai également mieux expliqué certaines parties des fonctionnalités, et rajouté quelques paragraphes (voir notament: "Inversions des voies et courbes": http://www.sylvainmahe.site/projectRadioControl.html J'attends encore quelques pièces pour tester le tout (radio + quadri) sur le terrain (certaines pièces viennent d’Australie, et c'est pas évident de trouver l'équivalent ailleurs). Les KISS ESC 24A en mode 3D sont soudés
  3. Construction d'une radiocommande !

    Le quadri est maintenant en version pour le vol 3D, voir l'article que j'ai modifié avec les nouvelles caractéristiques de la bêbête: http://sylvainmahe.xyz/projectQuadcopter.html
  4. Construction d'une radiocommande !

    Bonjour J'ouvre ce sujet pour vous montrer la radiocommande que je fabrique, boîtier, électronique, et logiciel sont faits à partir de zéro (pas de bibliothèque arduino, ni de bibliothèque avr, ni de bibliothèque c++ en supplément du langage lui même, ..), par contre je ne créé pas les manches de la radio (je n'avais qu'une semaine pour faire les usinages). Le programme de cette radio fait 4036 lignes (et sera téléchargeable bientôt), le principe de ce programme est entièrement basé sur mon système que j'ai développé (MODULE), et est entièrement téléchargeable ici (logiciel + plans des cartes): http://sylvainmahe.xyz/ L'automate programmable est le MODULABLE M32, il est équipé de l'ATmega1284P. Le composant qui fait la communication 2.4GHz est le nRF24L01+, mon système de programmation comporte une classe dédiée à ce composant, voir ici: http://sylvainmahe.xyz/exampleNrf24l01p.html Les caractéristiques de la radiocommande: L'interface électromécanique entre l'homme et la machine: Le concept de cette radiocommande: Depuis les premiers temps ou je pilote des modèles radiocommandés dans des associations d'aéromodélisme jusqu'à aujourd'hui, je me suis souvent demandé et au vu de l'avancée précédente et actuelle en matière d'électronique embarquée: À ce propos je ne citerais que l'exemple d'un ami au terrain de modélisme sans le nommer, qui par mégarde se trompe assez régulièrement de mémoire de modèles (il vol avec beaucoup de choses). En conséquence cela lui arrive souvent d'écraser ses réglages, ou d'écraser son modèle tout simplement au sens physique du terme ! En fait, cette "lacune" des mémoires de modèles dans les radiocommandes modernes trouve historiquement ses racines dans la conception même des premiers radio-émetteurs/récepteurs. En effet, les premières radiocommandes se contentaient uniquement d'être émetteur d'information, et le modèle étant lui simplement un récepteur. Dans cette situation (unidirectionnelle), il est facile de comprendre que le modèle reste toujours muet. Plus tard, les concepteurs et divers industriels se sont décidés (au vue de la demande qui augmentait) à ajouter une communication du modèle vers la radiocommande, sur un circuit électronique bien distinct et avec une antenne radio supplémentaire sur le modèle et la radiocommande. C'est un retour air/sol qui a été appelé télémétrie (en rapport avec la télémétrie à l'époque des débuts de la conquête spatiale jusqu'à nos jours). Cette idée simple permet beaucoup de choses, notamment le fait que c'est le modèle qui envoi des paramètres et réglages personnalisés à la radiocommande, qui à l'origine dispose d'un menu des paramètres et réglages presque vide. La radiocommande se voit alors garnie de paramètres personnalisés relatifs au modèle qui est actuellement en communication avec elle. Elle dispose également de l'affichage de la tension de la batterie du modèle en temps réel, et d'une télémétrie personnalisée en fonction du modèle. Une fois cette notion comprise, tout est alors possible. Ma radiocommande dispose d'un maximum de 16 paramètres personnalisés par le modèle, ceci est largement suffisant parce que par définition même, ils sont spécifiques au modèle considéré. Si vous souhaitez en savoir plus et avoir d'autres explications pour mieux comprendre ce projet, je ne peux que vous conseiller de lire l'article que j'ai écrit sur mon blog qui est un peu plus documenté: http://sylvainmahe.xyz/projectRadioControl.html J'y explique par exemple "La copie des paramètres d'un modèle", ou bien encore "La vitesse de communication", ce qui peut vous intéresser ! N'hésitez pas si vous avez des questions module.zip
  5. Drone sauteur

    Bonjour
  6. Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

    Merci pour le commentaire ça fait plaisir C'est vrai que ce projet a été très long et difficile, je le partage avec le plus d'infos possibles pour que les gens intéressés puissent se lancer plus facilement dans le monde de l'électronique amateur
  7. Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

    Après quelques mois de recherches infructueuses en ce qui concerne le nom et le logo de mon projet cartes+bibliothèque, j'ai finalement réussi à en dessiner un qui me convient: Module pour modulable, mais aussi pour génération de signal modulé (pulse width modulation), d’où la forme du logo (onde carrée). GPL pour General Public Licence (https://fr.wikipedia.org/wiki/Licence_publique_g%C3%A9n%C3%A9rale_GNU). J'ai aussi travailler sur le site aujourd'hui pour que cela soit cohérent niveau formes et couleurs, mais il me faudra d'autres week-end pour finaliser ce site http://sylvainmahe.xyz/ Encore une fois n'hésitez pas pour les commentaires et si vous avez des questions pour le fonctionnement de la bibliothèque, et/ou idées que vous pouvez apporter
  8. Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

    Nouvelle vidéo avec un peu de voltige (soyez indulgents c'est pas facile de piloter avec les pouces gelés :p) https://www.youtube.com/watch?v=0M3INZuHvoc N'hésitez pas si vous avez des interrogations coté réalisation ou autre.
  9. Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

    Bonjour *DanRaZor, merci pour ton commentaire Tu as raison l'héritage des classes est une bonne idée vue comme ça, mais ce qu'il faut comprendre c'est que la classe Private existe uniquement parce que j'ai adopté la convention de ne faire aucun appel de fonction dans une même classe, et aussi par le fait qu'un calcul plus ou moins long dans une classe ou devant être automatisé, ou étant utilisé par plusieurs classes, se doit d'être écrit dans la classe Private pour être utilisé ou on en a besoin. L'avantage de ce système c'est que ma bibliothèque est entièrement démontable sans soucis mise à part qu'il y a la classe Private qui suit derrière, mais ça ne pose aucun problème. Après comme je le dit, libre au gens de tout reprogrammer, de créer votre propre bibliothèque, en c++ ou dans un autre language, etc... Pour le "gain" variable, il est variable en fonction du manche de gaz, la raison à ceci est que plus les hélices tournent vite, plus elles augmentent en rendement, et donc plus on doit soit diminuer les débattements, soit diminuer la sensibilité. Il s'avère que la courbe de rendement d'une hélice est quasiment linéaire sur toute sa plage de fonctionnement, donc au final j'ai juste créé une courbe linéaire paramétrable qui diminue la sensibilité en fonction du manche de gaz, et ça marche vraiment super bien Pour le verrouillage, pour le coup je ne sais pas si je vais arriver à vous expliquer ça, mais c'est carrément indépendant de la vitesse de la boucle de calcul, contrairement à ce qu'on peu penser. Pour faire un exemple simple, si on imagine une boucle de calcul faisant 1 tour en 1 seconde, si la vitesse angulaire du quad est constante et à bougé de 90° en 1 seconde, l'ordre à appliquer sur les moteurs on va dire sera de 100trs/min, par contre si la vitesse de la boucle de calcul est de 1 tour pour 2 secondes, le quad aura eu le temps de parcourir non pas 90° mais plutôt 180° d'angle et donc l'ordre à appliquer sur les moteurs sera de 200trs/min, le verrouillage sera en théorie le même, les sensibilités seront les mêmes, etc... En réalité le verrouillage du quad dépend surtout des débattements max disponibles pour les compensations effectuées par le gyro, à savoir que si on a des ESC qui on une plage gaz mini gaz maxi comme les kiss esc de 1050us à 1950us, il est bon d'appliquer en paramètres: const uint16_t SETUP_TRAVEL_PITCH = 300; const uint16_t SETUP_TRAVEL_ROLL = 300; const uint16_t SETUP_TRAVEL_YAW = 300; De sorte que 300us + 300us + 300us = 1950us - 1050us = 900us On peut très bien également voler avec: const uint16_t SETUP_TRAVEL_PITCH = 200; const uint16_t SETUP_TRAVEL_ROLL = 200; const uint16_t SETUP_TRAVEL_YAW = 500; Les "gains" ou sensibilités seront à rehausser sur le pitch et le roll, et le yaw sera plus verrouillé (ces débattements sont indépendant du taux de rotation désiré pour une action max sur le manche de pitch, roll, ou yaw, le "rate" en degrés par seconde), voir ici: const uint16_t SETUP_SPEED_PITCH = 300; const uint16_t SETUP_SPEED_ROLL = 300; const uint16_t SETUP_SPEED_YAW = 200; Ici je souhaite que mon quad vire sur le pitch à une vitesse de 300 degrés par secondes (ne pas confondre les paramètres TRAVEL avec les SPEED, unité us et °/s, ici c'est un hasard si ils ont les mêmes valeurs...). Pour les sécurités effectivement sa fait un moment que je me dit faut que je rajoute dans la boucle principale une sécurité en cas de perte de lecture des voies pwm du récepteur Bon malgré tout je ne vois pas pourquoi cela arriverais, ca voudrais dire que les fils se débranchent... Faut savoir que ma classe Cycle, celle qui fait du "pwm in" (duty cycle), est elle même sécurisé, c'est à dire que si elle n'arrive pas à lire le pwm d'une pin de l'atmega328p, il y a un délai au bout duquel elle fait un certain nombre de tentatives de lecture, puis si elles échouent toutes, elle laisse la main, pour retenter au prochain try.. Pour du pwm de 50Hz comme ceux souvent envoyé par les récepteur de modélisme standard, on peut pourquoi pas attendre le double de temps soit 20ms x 2 = 40ms, si au bout de 40ms ça n'arrive toujours pas à lire la largeur du pwm, la dernière valeur lue reste inchangée, jusqu'au prochain essai (soit la prochaine interruption, car j'utilise bien les interruptions du 328p pour avoir une boucle de calcul principale qui tourne le plus vite possible sans attendre quoi que ce soit.) Le temps d'attente maximal avant de laisser la main si la fonction n'arrive pas à chopper le duty cycle est défini ici: Cycle::start (100); J'ai mis 100ms, j'aurais pu mettre 40ms... Voila merci encore pour ton commentaire et n'hésitez pas si vous avez des questions
  10. Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

    Voila après une 30ène de vols de tests le code source final sans horizon artificiel (pour l'instant): Main.cpp #include "../library/Timer.h" #include "../library/Delay.h" #include "../library/Random.h" #include "../library/Math.h" #include "../library/Buzzer.h" #include "../library/Servo.h" #include "../library/Cycle.h" #include "../library/Gyroscope.h" using namespace std; int main() { uint8_t n = 0; Gyroscope mpu6050 = Gyroscope (0); Cycle channelThrottle = Cycle (1, false); uint16_t slowChannelThrottle = 0; uint16_t centerChannelThrottle = 0; Cycle channelPitch = Cycle (2, false); uint16_t centerChannelPitch = 0; Cycle channelRoll = Cycle (3, false); uint16_t centerChannelRoll = 0; Cycle channelYaw = Cycle (4, false); uint16_t centerChannelYaw = 0; Cycle channelHold = Cycle (5, false); uint16_t centerChannelHold = 0; Cycle channelOption = Cycle (6, false); uint16_t centerChannelOption = 0; Servo motor1 = Servo (7, 0, 0, 0); Servo motor2 = Servo (8, 0, 0, 0); Servo motor3 = Servo (9, 0, 0, 0); Servo motor4 = Servo (10, 0, 0, 0); Delay delaySoundStartCondition = Delay (1000, false); uint16_t mixThrottle = 0; int16_t mixThrustPitchGain = 0; int16_t mixThrustRollGain = 0; int16_t mixInertiaYawGain = 0; int16_t mixMinClearancePitch = 0; int16_t mixMaxClearancePitch = 0; int16_t mixMinClearanceRoll = 0; int16_t mixMaxClearanceRoll = 0; int16_t mixMinClearanceYaw = 0; int16_t mixMaxClearanceYaw = 0; const uint16_t SPEED_GYRO = 1000; int16_t speedPitch = 0; int16_t speedRoll = 0; int16_t speedYaw = 0; int16_t mixPitchOffsetGyro = 0; int16_t mixRollOffsetGyro = 0; int16_t mixYawOffsetGyro = 0; uint8_t thrustGainPitch = 0; uint8_t thrustGainRoll = 0; uint8_t inertiaGainYaw = 0; uint16_t gainMinRxGyro = 0; uint16_t gainMaxRxGyro = 0; uint16_t gainMinRyGyro = 0; uint16_t gainMaxRyGyro = 0; uint16_t gainMinRzGyro = 0; uint16_t gainMaxRzGyro = 0; int16_t mixMinRxGyro = 0; int16_t mixMaxRxGyro = 0; int16_t mixMinRyGyro = 0; int16_t mixMaxRyGyro = 0; int16_t mixMinRzGyro = 0; int16_t mixMaxRzGyro = 0; uint16_t mixMotor1 = 0; uint16_t mixMotor2 = 0; uint16_t mixMotor3 = 0; uint16_t mixMotor4 = 0; const uint16_t SETUP_MIN_CHANNEL_THROTTLE = 1000; const uint16_t SETUP_MAX_CHANNEL_THROTTLE = 2000; const uint16_t SETUP_MIN_CHANNEL_PITCH = 1000; const uint16_t SETUP_MAX_CHANNEL_PITCH = 2000; const uint16_t SETUP_MIN_CHANNEL_ROLL = 1000; const uint16_t SETUP_MAX_CHANNEL_ROLL = 2000; const uint16_t SETUP_MIN_CHANNEL_YAW = 1000; const uint16_t SETUP_MAX_CHANNEL_YAW = 2000; const uint16_t SETUP_MIN_CHANNEL_HOLD = 1000; const uint16_t SETUP_MAX_CHANNEL_HOLD = 2000; const uint16_t SETUP_MIN_CHANNEL_OPTION = 1500; const uint16_t SETUP_MAX_CHANNEL_OPTION = 2000; const int16_t SETUP_ZERO_PITCH = 38; const int16_t SETUP_ZERO_ROLL = -11; const int16_t SETUP_ZERO_YAW = -46; const uint16_t SETUP_FREQUENCY_ESC = 100; const uint16_t SETUP_HOLD_ESC = 950; const uint16_t SETUP_MIN_ESC = 1050; const uint16_t SETUP_MAX_ESC = 1950; const uint16_t SETUP_TRAVEL_PITCH = 300; const uint16_t SETUP_TRAVEL_ROLL = 300; const uint16_t SETUP_TRAVEL_YAW = 300; const uint16_t SETUP_SPEED_PITCH = 300; const uint16_t SETUP_SPEED_ROLL = 300; const uint16_t SETUP_SPEED_YAW = 200; const uint8_t SETUP_GAIN_PITCH = 87; const uint8_t SETUP_GAIN_ROLL = 83; const uint8_t SETUP_GAIN_YAW = 92; const uint8_t SETUP_THRUST_PROPELLER = 60; const uint8_t SETUP_INERTIA_PROPELLER = 100; Timer::pause (1000); slowChannelThrottle = round (double (SETUP_MIN_CHANNEL_THROTTLE) + ((double (SETUP_MAX_CHANNEL_THROTTLE) - double (SETUP_MIN_CHANNEL_THROTTLE)) / double (10))); centerChannelThrottle = round (double (SETUP_MAX_CHANNEL_THROTTLE) - ((double (SETUP_MAX_CHANNEL_THROTTLE) - double (SETUP_MIN_CHANNEL_THROTTLE)) / double (2))); centerChannelPitch = round (double (SETUP_MAX_CHANNEL_PITCH) - ((double (SETUP_MAX_CHANNEL_PITCH) - double (SETUP_MIN_CHANNEL_PITCH)) / double (2))); centerChannelRoll = round (double (SETUP_MAX_CHANNEL_ROLL) - ((double (SETUP_MAX_CHANNEL_ROLL) - double (SETUP_MIN_CHANNEL_ROLL)) / double (2))); centerChannelYaw = round (double (SETUP_MAX_CHANNEL_YAW) - ((double (SETUP_MAX_CHANNEL_YAW) - double (SETUP_MIN_CHANNEL_YAW)) / double (2))); centerChannelHold = round (double (SETUP_MAX_CHANNEL_HOLD) - ((double (SETUP_MAX_CHANNEL_HOLD) - double (SETUP_MIN_CHANNEL_HOLD)) / double (2))); centerChannelOption = round (double (SETUP_MAX_CHANNEL_OPTION) - ((double (SETUP_MAX_CHANNEL_OPTION) - double (SETUP_MIN_CHANNEL_OPTION)) / double (2))); Buzzer::pin (11); while (centerChannelThrottle == 0 || centerChannelPitch == 0 || centerChannelRoll == 0 || centerChannelYaw == 0 || centerChannelHold == 0 || centerChannelOption == 0) { delaySoundStartCondition.state(); if (delaySoundStartCondition.update == true) { Buzzer::play (200, 100); } } delaySoundStartCondition.reset(); Cycle::start (100); while (channelThrottle.us == 0 || channelPitch.us == 0 || channelRoll.us == 0 || channelYaw.us == 0 || channelHold.us == 0 || channelHold.us == 0) { channelThrottle.state(); channelPitch.state(); channelRoll.state(); channelYaw.state(); channelHold.state(); channelOption.state(); delaySoundStartCondition.state(); if (delaySoundStartCondition.update == true) { Buzzer::key (200, 100); Buzzer::key (0, 100); Buzzer::key (200, 100); Buzzer::playKey(); } } delaySoundStartCondition.reset(); while (channelThrottle.us > slowChannelThrottle || channelHold.us < centerChannelHold) { channelThrottle.state(); channelHold.state(); delaySoundStartCondition.state(); if (delaySoundStartCondition.update == true) { Buzzer::key (200, 100); Buzzer::key (0, 100); Buzzer::key (200, 100); Buzzer::key (0, 100); Buzzer::key (200, 100); Buzzer::playKey(); } } Random::seed (15); for (n = 0; n < 16; n++) { if (n != 0) { Buzzer::key (0, Random::integer (25, 75)); } Buzzer::key (Random::integer (70, 3000), Random::integer (25, 75)); } Buzzer::playKey(); speedPitch = Math::curve (0, SETUP_SPEED_PITCH, SPEED_GYRO, 0, 32767, 0); speedRoll = Math::curve (0, SETUP_SPEED_ROLL, SPEED_GYRO, 0, 32767, 0); speedYaw = Math::curve (0, SETUP_SPEED_YAW, SPEED_GYRO, 0, 32767, 0); thrustGainPitch = Math::curve (0, SETUP_THRUST_PROPELLER, 100, 0, SETUP_GAIN_PITCH, 0); gainMinRxGyro = Math::curve (0, thrustGainPitch, 100, 32767, 0, 0); gainMaxRxGyro = Math::curve (0, SETUP_GAIN_PITCH, 100, 32767, 0, 0); thrustGainRoll = Math::curve (0, SETUP_THRUST_PROPELLER, 100, 0, SETUP_GAIN_ROLL, 0); gainMinRyGyro = Math::curve (0, thrustGainRoll, 100, 32767, 0, 0); gainMaxRyGyro = Math::curve (0, SETUP_GAIN_ROLL, 100, 32767, 0, 0); inertiaGainYaw = Math::curve (0, SETUP_INERTIA_PROPELLER, 100, 0, SETUP_GAIN_YAW, 0); gainMinRzGyro = Math::curve (0, inertiaGainYaw, 100, 32767, 0, 0); gainMaxRzGyro = Math::curve (0, SETUP_GAIN_YAW, 100, 32767, 0, 0); mpu6050.setZero (SETUP_ZERO_PITCH, SETUP_ZERO_ROLL, SETUP_ZERO_YAW); motor1.hold (SETUP_HOLD_ESC); motor1.min (SETUP_MIN_ESC); motor1.max (SETUP_MAX_ESC); motor2.hold (SETUP_HOLD_ESC); motor2.min (SETUP_MIN_ESC); motor2.max (SETUP_MAX_ESC); motor3.hold (SETUP_HOLD_ESC); motor3.min (SETUP_MIN_ESC); motor3.max (SETUP_MAX_ESC); motor4.hold (SETUP_HOLD_ESC); motor4.min (SETUP_MIN_ESC); motor4.max (SETUP_MAX_ESC); motor1.moveHold(); motor2.moveHold(); motor3.moveHold(); motor4.moveHold(); Servo::start (SETUP_FREQUENCY_ESC); while (true) { mpu6050.state(); channelThrottle.state(); channelPitch.state(); channelRoll.state(); channelYaw.state(); channelHold.state(); channelOption.state(); if (channelHold.us > centerChannelHold) { motor1.moveHold(); motor2.moveHold(); motor3.moveHold(); motor4.moveHold(); } else { mixThrottle = Math::curve (SETUP_MIN_CHANNEL_THROTTLE, channelThrottle.us, SETUP_MAX_CHANNEL_THROTTLE, SETUP_MIN_ESC, SETUP_MAX_ESC, 0); mixMotor1 = mixThrottle; mixMotor2 = mixThrottle; mixMotor3 = mixThrottle; mixMotor4 = mixThrottle; mixMinClearancePitch = Math::curve (SETUP_MIN_CHANNEL_THROTTLE, channelThrottle.us, SETUP_MAX_CHANNEL_THROTTLE, 0, SETUP_TRAVEL_PITCH, 0); mixMaxClearancePitch = Math::curve (SETUP_MIN_CHANNEL_THROTTLE, channelThrottle.us, SETUP_MAX_CHANNEL_THROTTLE, SETUP_TRAVEL_PITCH, 0, 0); mixPitchOffsetGyro = Math::curve (SETUP_MIN_CHANNEL_PITCH, channelPitch.us, SETUP_MAX_CHANNEL_PITCH, -speedPitch, speedPitch, 0); mixThrustPitchGain = Math::curve (SETUP_MIN_CHANNEL_THROTTLE, channelThrottle.us, SETUP_MAX_CHANNEL_THROTTLE, gainMaxRxGyro, gainMinRxGyro, 0); mixMinRxGyro = Math::wurve (-mixThrustPitchGain, mpu6050.rx + mixPitchOffsetGyro, mixThrustPitchGain, -mixMaxClearancePitch, 0, mixMinClearancePitch, 0, 0); mixMaxRxGyro = Math::wurve (-mixThrustPitchGain, mpu6050.rx + mixPitchOffsetGyro, mixThrustPitchGain, -mixMinClearancePitch, 0, mixMaxClearancePitch, 0, 0); mixMotor1 -= mixMinRxGyro; mixMotor2 -= mixMinRxGyro; mixMotor3 += mixMaxRxGyro; mixMotor4 += mixMaxRxGyro; mixMinClearanceRoll = Math::curve (SETUP_MIN_CHANNEL_THROTTLE, channelThrottle.us, SETUP_MAX_CHANNEL_THROTTLE, 0, SETUP_TRAVEL_ROLL, 0); mixMaxClearanceRoll = Math::curve (SETUP_MIN_CHANNEL_THROTTLE, channelThrottle.us, SETUP_MAX_CHANNEL_THROTTLE, SETUP_TRAVEL_ROLL, 0, 0); mixRollOffsetGyro = Math::curve (SETUP_MIN_CHANNEL_ROLL, channelRoll.us, SETUP_MAX_CHANNEL_ROLL, -speedRoll, speedRoll, 0); mixThrustRollGain = Math::curve (SETUP_MIN_CHANNEL_THROTTLE, channelThrottle.us, SETUP_MAX_CHANNEL_THROTTLE, gainMaxRyGyro, gainMinRyGyro, 0); mixMinRyGyro = Math::wurve (-mixThrustRollGain, mpu6050.ry - mixRollOffsetGyro, mixThrustRollGain, -mixMaxClearanceRoll, 0, mixMinClearanceRoll, 0, 0); mixMaxRyGyro = Math::wurve (-mixThrustRollGain, mpu6050.ry - mixRollOffsetGyro, mixThrustRollGain, -mixMinClearanceRoll, 0, mixMaxClearanceRoll, 0, 0); mixMotor1 -= mixMinRyGyro; mixMotor2 += mixMaxRyGyro; mixMotor3 -= mixMinRyGyro; mixMotor4 += mixMaxRyGyro; mixMinClearanceYaw = Math::curve (SETUP_MIN_CHANNEL_THROTTLE, channelThrottle.us, SETUP_MAX_CHANNEL_THROTTLE, 0, SETUP_TRAVEL_YAW, 0); mixMaxClearanceYaw = Math::curve (SETUP_MIN_CHANNEL_THROTTLE, channelThrottle.us, SETUP_MAX_CHANNEL_THROTTLE, SETUP_TRAVEL_YAW, 0, 0); mixYawOffsetGyro = Math::curve (SETUP_MIN_CHANNEL_YAW, channelYaw.us, SETUP_MAX_CHANNEL_YAW, -speedYaw, speedYaw, 0); mixInertiaYawGain = Math::curve (SETUP_MIN_CHANNEL_THROTTLE, channelThrottle.us, SETUP_MAX_CHANNEL_THROTTLE, gainMaxRzGyro, gainMinRzGyro, 0); mixMinRzGyro = Math::wurve (-mixInertiaYawGain, mpu6050.rz + mixYawOffsetGyro, mixInertiaYawGain, -mixMaxClearanceYaw, 0, mixMinClearanceYaw, 0, 0); mixMaxRzGyro = Math::wurve (-mixInertiaYawGain, mpu6050.rz + mixYawOffsetGyro, mixInertiaYawGain, -mixMinClearanceYaw, 0, mixMaxClearanceYaw, 0, 0); mixMotor1 -= mixMinRzGyro; mixMotor2 += mixMaxRzGyro; mixMotor3 += mixMaxRzGyro; mixMotor4 -= mixMinRzGyro; motor1.pulse (mixMotor1); motor2.pulse (mixMotor2); motor3.pulse (mixMotor3); motor4.pulse (mixMotor4); } } return 0; } Pour quadricoptère avec: Moteur1 = avant gauche Moteur2 = avant droit Moteur3 = arrière gauche Moteur4 = arrière droit Les paramètres à adapter selon votre quad commencent par le préfixe SETUP. La gestion des moteurs prends en compte le rendement des hélices (paramètre THRUST), cette gestion est asymétrique de sorte que vous avez votre plein ralenti et plein gaz avec 100% des ordres pitch/roll/yaw disponible même manche de gaz (THROTTLE) en butée mini ou maxi. Le quad est très verrouillé sur ses axes, la voltige passe sans aucune difficulté, j'ai testé pleins de choses: plein gaz vers le bas, boucles carrés, etc... Il y a bien-sûr les trois sécurités d'avant démarrage que j'ai cité dans ce sujet. Ma config actuelle est: tiger motors mn2206 kiss esc 18A lipo 4s 2200mAh hélices hq 6x4.5" Le code est très robuste, vous pouvez-y aller sans problème :) N'hésitez pas si vous avez un soucis ou des questions.
  11. Bonjour Pour que vous compreniez le sujet et mon intervention, je fait un bref récapitulatif de ma modeste expérience de l'électronique: J'ai donc débuté l'électronique amateur il y a 1 an, au départ je ne savais pas à quoi servait un condensateur, je suis donc parti de zéro. J'ai été comme un peu tout les amateurs qui ne savent pas par ou commencer au départ, j'ai téléchargé Arduino, puis au bout d'une semaine j'ai voulu savoir ce qu'il y avait derrière digitalWrite, et 2 ou 3 fonctions que j'avais utilisé au courant de cette semaine découverte. J'ai été voir la source et j'ai compris qu'il suffisait d'appliquer mes connaissances en programmation C++, de lire les 650 pages du datasheet du 328P (voir ici: http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf), pour créer ma propre bibliothèque et me passer finalement d'Arduino. Voila en gros le résumé. Photos de quelques projets en électronique que j'ai réalisé durant l'année http://sylvainmahe.xyz/forum/ Ceci étant dit, la bibliothèque étant maintenant terminée, je la met à disposition des internautes dans le but qu'ils puissent créer tout comme moi des projets assez complexes très facilement Voici donc pour télécharger ma bibliothèque (qui n'a pas encore de nom): http://sylvainmahe.xyz/ (mon site dédié au projet est encore en construction) J'estime le temps de développement de cette bibliothèque à entre 3000 à 4000 heures durant l'année. Coté performances, ma bibliothèque est plus proche d'avr que d'arduino, par exemple, 1 million de pin toggling donne: AVR: 651ms ma bibliothèque: 753ms Arduino: 4550ms Le sujet ici présent: J'ai dernièrement construit un quadricoptère (chassis/carte pcb/électronique/programmation) en utilisant les fonctions de ma bibliothèque (voir lien ci-dessus), j'aimerais partager avec vous cette expérience car elle peut être intéressante pour ceux qui souhaitent se lancer dans le quadricoptère fait maison sans utiliser Arduino/Multiwii Le premier test moteur avec hélices: https://www.youtube.com/watch?v=rwDVVNhByQM Les premiers tests en vol hier: https://www.youtube.com/watch?v=lEjDbypSjDE La puissance peut paraître légère (c'est censé être un quadricoptère de voltige), mais pour les premiers tests j'ai réglé la course des gaz à 50% max pour plus de sécurité, ceci explique cela Demain j'essayerais avec 100% de gaz. Pour commencer, le code source sans ma bibliothèque (le main.cpp), fait seulement 326 lignes, donc sachez qu'un quadricoptère est en ordre de vol avec seulement 326 lignes dans le main avec ma bibliothèque qui tourne derrière, c'est très peu, ceci avec toutes les sécurités d'avant vol au branchement de la batterie lipo avec buzzer de signalement, à savoir: -vérification que votre radiocommande est bien calibrée -vérification de l'arrivée du pwm de toutes les voies du récepteur -vérification de l'inter coupure moteur activé et du manche de gaz inférieur à 10% Et également avec la musique au démarrage, ce qui n'est pas indispensable vous en conviendrez Voila la photo du quadricoptère: La photo de la carte électronique: Cette carte maison me sert à tous mes projets en électronique. Le plan de celle-ci se trouve en bas du sujet. La machine pour réaliser le châssis, si vous le réalisez en tube aluminium le mieux est d'avoir une fraiseuse sous la main: L'idée de ce topic est de comprendre qu'avec ma bibliothèque on peut en quelques lignes de programmation créer des choses plus ou moins complexes beaucoup plus facilement qu'Arduino et avec une plus grande vitesse d'execution et une quantité de mémoire moindre. Exemple/Tuto - Potar + Servo avec ma bibliothèque (sans Arduino): Vous devez déjà savoir programmer et linker une bibliothèque, avoir une petite idée de pourquoi se passer d'Arduino et qu'il faut AVR (l'architecture AVR de l'atmega328p), mais dans l'idéal, le processus est: -télécharger la bibliothèque, décompresser les fichiers -avoir une carte arduino uno ou équivalent -avoir un programmateur (vous pouvez utiliser l'usbasp avec mes batchs windows ou linux inclus dans l'archive de la bibliothèque pour compiler) -avoir avr c d'installé sur votre ordinateur -avoir un servo-moteur et un potentiomètre sous la main J'ai créé une vidéo qui vous montre très exactement la procédure: https://www.youtube.com/watch?v=l6W0OJiucN0 Je recopie mon exemple ici (main.cpp): #include "../library/Potentiometer.h" #include "../library/Servo.h" using namespace std; int main() { Servo myServo = Servo (1, 1100, 1900); Potentiometer myPotentiometer = Potentiometer (15); Servo::start (250); while (true) { myPotentiometer.state(); myServo.pulse (myPotentiometer.curve (0, 1023, 1100, 1900, 0)); } return 0; } En premier, remplacer "library" par le dossier dans l'archive qui contient la bibliothèque, encore une fois je ne suis pas encore sûr du nom que je vais lui donner. A la déclaration de l'objet Servo, le premier paramètre est le numéro de la pin sur la carte (voir ma carte 328P en bas de ce sujet pour connaître la distribution des pins sur votre carte Arduino UNO par rapport à la mienne). On indique également 1100, c'est le débattement min du servo, et 1900 le max, voyez le datasheet de votre servo-moteur pour connaître ces débattements, ou faites des tests. A la déclaration de l'objet Potentiometer, on indique juste le numéro de la pin, ici la 15 c'est à dire PC0. Ensuite on démarre le servo-moteur avec Servo::start et on indique en paramètre la fréquence du servo en Hz. Ici c'est un savox qui va jusqu'à 250Hz. Dans la boucle principale on récupère l'état du potentiomètre avec state, sa correspond à connaître la tension en valeur 10 bit sur la pin PC0. Ensuite on indique une position de palonnier de servo-moteur avec pulse, on lui injecte avec la fonction curve du potentiomètre la tension sous la forme d'une valeur de 10 bit (0 à 1023) interpolé de 1100 à 1900 (les débattements en us de notre servo-moteur) tout cela avec une courbe linéaire (le 0 à la fin). Ensuite compilation avec le compilateur AVR et upload dans l'Atmega 328P avec le programmateur de votre choix, moi j'utilise l'usbasp, voir ici: http://www.fischl.de/usbasp/ Et normalement ça fonctionne Photos pour comprendre la distribution des pins sur ma carte 328P faite maison en relation avec la distribution des pins de ma bibliothèque: Ma carte 328P et ma bibliothèque me servent à réaliser pleins de projets, cette carte n'est pas plus spécialisé dans le quadricoptère qu'autre chose, un exemple d'autre projet avec cette carte: Un jeu PONG: https://www.youtube.com/watch?v=x0699wl6ggg Voila ce sera tout pour aujourd'hui, n'hésitez pas si vous avez des interrogations ou des commentaires
  12. Oscillations axe tangage sur maquette alouette turbine

    Je suis précis, pour la précession gyroscopique, la pale passant à gauche du plateau cylique, sens giratoire horaire au rotor principal, avait sa biellette du pied de pale en prise +60 degrés sens horaire sur le plateau cyclique, du coup la précession gyroscopique de 90 degrés de décalage pour tout objet physique en rotation sur lui même, n'était pas respecté. La notice de la mécanique rotor tripale indiquait bien ceci, ce qui est logique, tout objet en rotation à une précession de 90 degrés. Sinon pour la version, comme indiqué au premier message, c'est un bavarian demon rigid v2.
  13. Oscillations axe tangage sur maquette alouette turbine

    Oui tout à fait, disons qu'on a essayé de se rapprocher au mieux mécaniquement, et finir au trim fait forcément travailler le gyro pas forcément au mieux. Sur mon raptor ou trex je ne trim jamais biensûr, mais la c'est la dérive en hl qui parait bizarre sur cet helicommand. On verra si on arrive à ne plus avoir de dérive du tout mais ça va se jouer au dixème de mm ou pas loin, en réglage mécanique.
  14. Oscillations axe tangage sur maquette alouette turbine

    Ah ok, donc on est pas seul pour l'anticouple On restera donc avec notre petit coup de trim à l'anticouple pour voler sans dériver. En tout cas merci pour vos conseils, mon ami est vraiment content que ça vol bien, surtout qu'il a passé beaucoup de temps dessus
  15. Oscillations axe tangage sur maquette alouette turbine

    Merci pour les conseils On a du nouveau, mon colègue à mis 90 degrés de précession mécaniquement (comme effectivement le dit la notice), et une meilleur fixation pour le boitier gyro helicommand (moins souple), du coup sa vol nickel, il n'y a plus aucun problème! La fixation de l'anticouple a également été revue. Il y a juste une dernière chose mais banale, l'anticouple dérive légèrement, je soupçonne un mode normal plutôt que conservateur de cap, pourtant en vent arrière il ne fait pas gyrouette, currieux... Impossible de voir la case "heading hold" cochée dans le logiciel helicommand. Enfin j'y est pas passé 3 heures sur helicommand comme ce n'est pas mon matos, mais le peu que j'ai inspecté ça le curseur "normal" "heading hold" n'a pas l'air de changer grand chose.

Copyright 2002-2017 par FRANCE-HELICO.COM

France-Helico est un site créé sans but commercial par des passionnés de l'hélicoptère.
×