Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Modérateur : Dehas

Avatar du membre
sylvainmahe
Bicopter
Messages : 48
Enregistré le : jeu. 3 juil. 2014 18:21
Réputation : 4

Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Message non lu par sylvainmahe »

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- ... mplete.pdf" onclick="window.open(this.href);return false;), 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/" onclick="window.open(this.href);return false;


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/" onclick="window.open(this.href);return false;
(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:


Les premiers tests en vol hier:


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:
Image

La photo de la carte électronique:
Image
Image

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:
Image
Image

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:


Je recopie mon exemple ici (main.cpp):

Code : Tout sélectionner

#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/" onclick="window.open(this.href);return false;

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:
Image
Image


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:



Voila ce sera tout pour aujourd'hui, n'hésitez pas si vous avez des interrogations ou des commentaires :)
Modifié en dernier par sylvainmahe le sam. 19 sept. 2015 12:17, modifié 1 fois.


Avatar du membre
roudoudou
Pilote toutes catégories
Messages : 833
Enregistré le : dim. 11 mai 2014 18:19
Réputation : 0
Contact :

Re: Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Message non lu par roudoudou »

Hello,

Très beau travail. Bravo.

Est ce que ta lib est cross platform ? J'ai la flemme de me faire une VM pour tester :)


MT220mm - ZMR250 - Alien 560 - DART450 - DART 400 - Blade Nano QX FPV - F450 , ....
ma page fb sur les quads : https://www.facebook.com/lapatpatrouille
Avatar du membre
Dehas
Administrateur du site
Messages : 16171
Enregistré le : ven. 3 juin 2011 12:50
Réputation : 5
Localisation : Saint Dié des Vosges
Genre :
Contact :

Re: Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Message non lu par Dehas »

Ben ça c'est du home made, j'ai pas tout compris mais je suis.


Avatar du membre
BerTiN25
Pilote toutes catégories
Messages : 1070
Enregistré le : mar. 26 août 2014 23:27
Réputation : 0

Re: Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Message non lu par BerTiN25 »

Superbe travail ! Je suis une quenelle en code, mais quand je vois qu'il y a un an tu savais pas à quoi servait un condo, et aujourd'hui tu as juste réinventé une carte de contrôle, à partir d'un système 200% DIY et universel, que tu as développé toi-même.... Ben Chuis sur le cul !

Bravo à toi, et je vais suivre avec intérêt !


Further 210 - RMRC Dodo - Emax RS2205 2300kv- HQ 5x4x3 - LittleBee 20A - Sky+ - LemonCore pro - Xiaomi - 4S - 625 gr

Further 180 - Naze32 - Cobra 2204 2300kv- HQ 4x4x3 - LittleBee 20A - Sky+ - microminimosd- XSR - 4S - 500 gr
Avatar du membre
sylvainmahe
Bicopter
Messages : 48
Enregistré le : jeu. 3 juil. 2014 18:21
Réputation : 4

Re: Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Message non lu par sylvainmahe »

Bonjour les passionnés :)

Merci pour vos commentaires, sa me donne envie de continuer à bricoler et à développer des trucs !

Pour ta question *roudoudou, crossplateforme oui, c'est du code C/C++ standard qui fonctionne sur linux (mon os), windows, etc... par contre crossplateforme au sens est ce que ca marche sur un UC PIC, non. Disons que la bibliothèque est dédié à l'UC Atmega328p, mais via juste une petite adaptation de la distribution des pins on peut la faire marcher pour toute la gamme Atmel 8bits (elle fonctionne pour les architectures d'UC AVR Atmel 8bits), tu pourrais la faire fonctionner sur une Naze32 par exemple car l'UC de cette carte est un Atmega32u4 8bits.

*Dehas comme je le disais l'autre jour à un colègue, on est jamais dans le homemade à 100%, je n'ai pas fait les moteurs, les hélices, les esc, etc... mais je me suis fixé de ne pas les faire car je ne peux pas tout faire non plus, c'est trop de travail. J'avais regardé sur le net des exemples d'esc fait maison, c'est passionnant, mais ça demande sans doute plusieurs mois de conception et de tests...

En tout cas j'ai contacté le petit magasin la ou j'ai acheté les kiss esc 18A, il m'ont indiqué qu'ils n'étaient pas programmé avec Arduino, c'est à dire très certainement en AVR pure C/C++ comme moi. C'est ce que je voulais, un quad sans Arduino.

*BerTiN25 en effet tu as tout compris de mon projet et de l'idée que j'explique ;)

Depuis j'ai fait une 10ène de vols avec le quad, j'ai simplifié le programme de vol, il fait maintenant 276 lignes seulement.
J'ai pu faire pas mal de flips assez sympa à quelques mètres du sol, mon programme est vraiment robuste en vol, le quad est bien verrouillé sur ses axes.
Avec ce programme vous pilotez un quad comme un hélico FBL, mais je vais faire une autre version du programme avec via un inter la possibilité de basculer entre "mode accro" et "mode horizon artificiel", qui fait que vous piloterez aussi avec des angles d'inclinaison min max (pour débutants ou pour faire de la vidéo/photo).

Une fois ça fait je mettrais à votre disposition le code source, c'est un petit fichier simplement (main.cpp).
Normalement en quelques lignes en plus cet horizon artificiel est intégré au code, puisque ma bibliothèque via le gyro génère ce qu'il faut (un elevator et un roll calé sur l'horizon).


...Je n'avais jamais eu de drone/quad pour l'instant, donc j'étais vraiment content d'arriver à tenir un statio sans difficulté au 2ème décolage avec ma logique/mathématique qui tourne derrière, et au bout de 10vols ce quad était réglé nickel pour la voltige :) Ce projet de quadricoptère aurait pu ne pas exister car la finalité de ma bibliothèque c'est de faire n'importe quel type de robot... Si on veut on peut même faire n'importe quoi avec, de la domotique, ... Mais étant passionné de tout ce qui vol et pratiquant le modélisme je me suis dit, bon aller j'essaye de faire voler un truc.

En tout cas merci pour vos commentaires, je vous donnerais des nouvelles du projet quad bientôt ;)


Avatar du membre
bruno
Pilote toutes catégories
Messages : 1820
Enregistré le : mar. 15 avr. 2014 11:39
Réputation : 1
Localisation : Créteil (94)

Re: Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Message non lu par bruno »

Sylvain,

Si ça c'est pas le plaisir du Home Made je comprends plus rien.
Très très beau travail, bravo.

Une question:
Serait-il possible d'obtenir une carte 328P ?


Avatar du membre
sylvainmahe
Bicopter
Messages : 48
Enregistré le : jeu. 3 juil. 2014 18:21
Réputation : 4

Re: Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Message non lu par sylvainmahe »

Merci *bruno pour le commentaire, tu as raison je ne fait ça que par passion du bricolage et pour le partage avec les gens ;)

Je peux t'envoyer une carte 328P si tu veux mais ce ne sera pas avant 3 semaines je pense (j'habite à rennes et je suis en formation à dinan mais du coup j'ai moins de temps pour mes projets perso).

Si tu as un petit programmateur usb type usbasp et que tu es motivé y a pas de raison de ne pas se lancer sans arduino effectivement :)


Avatar du membre
bruno
Pilote toutes catégories
Messages : 1820
Enregistré le : mar. 15 avr. 2014 11:39
Réputation : 1
Localisation : Créteil (94)

Re: Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Message non lu par bruno »

En arduino j'ai des nano et uno et même du teensy pour hack du pmu du Naza M.
Tiens moi informe par MP lorsque tu pourra la faire.
Ton prix sera le miens car en fait je la trouve sympas ta carte.


Avatar du membre
sylvainmahe
Bicopter
Messages : 48
Enregistré le : jeu. 3 juil. 2014 18:21
Réputation : 4

Re: Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Message non lu par sylvainmahe »

Ok pas de soucis, je te dirais quand je pourrais faire ça :)

Concernant le prix je vais faire comme si c'est toi qui devait la faire à partir de zéro, c'est à dire prix de la plaque pcb + prix des composants, ce qui donne:
1x TO220 - TO-220 Small Aluminium Heatsink = 0.4€
http://www.futurlec.com/Heatsinks/TO220pr.shtml" onclick="window.open(this.href);return false;

1x CRYLF16M000 - 16.000MHz Low Profile Crystal = 0.3€
http://www.futurlec.com/Crystals/CRYLF16M000pr.shtml" onclick="window.open(this.href);return false;

1x Led 3mm - rouge diffusant - 8mcd = 0.1€
http://composants.e44.com/led/leds-econ ... D3RLN.html" onclick="window.open(this.href);return false;

1x Mc 8bit 1,8v 32kb flash 20mhz sdip28 = 5.3€
http://composants.e44.com/circuits-inte ... 8P-PU.html" onclick="window.open(this.href);return false;

1x Support ci tulipe 28 broches l=7.62mm = 0.65€
http://composants.e44.com/circuits-inte ... TU28E.html" onclick="window.open(this.href);return false;

1x Self axiale 10 uh 230ma 3.5x10mm = 0.4€
http://composants.e44.com/inductances/s ... FSA10.html" onclick="window.open(this.href);return false;

2x Cond. ceram. 5.08 mm 22pf (0.1€ * 2) = 0.2€
http://composants.e44.com/condensateurs ... 522PF.html" onclick="window.open(this.href);return false;

3x Condensateur tantale 0.10aµf / 35v pas 2.54mm (0.3€ * 3) = 0.9€
http://composants.e44.com/condensateurs ... 0.135.html" onclick="window.open(this.href);return false;

1x Condensateur chimique radial 0.1uf 63v 5x11mm 105°c = 0.15€
http://composants.e44.com/condensateurs ... 0.163.html" onclick="window.open(this.href);return false;

1x Condensateur chimique radial 0.22uf 63v 5x11mm 105°c = 0.15€
http://composants.e44.com/condensateurs ... .2263.html" onclick="window.open(this.href);return false;

1x Regulateur de tension 5v - 1a to220 = 0.5€
http://composants.e44.com/regulateurs/r ... -7805.html" onclick="window.open(this.href);return false;

1x Resistance carbone 1/4w 220 ohms tolerance 5% (lot de 10 pieces) (0.35€ / 10) = 0.035€
http://composants.e44.com/resistances/r ... 25220.html" onclick="window.open(this.href);return false;

1x Resistance carbone 1/4w 10 kohms tolerance 5% (lot de 10 pieces) (0.35€ / 10) = 0.035€
http://composants.e44.com/resistances/r ... 2510K.html" onclick="window.open(this.href);return false;

1x Barrette male double rangee - 34 broches = 0.4€
http://composants.e44.com/circuits-inte ... CC065.html" onclick="window.open(this.href);return false;

1x Barrette male simple rangee - 36 broches = 0.5€
http://composants.e44.com/circuits-inte ... CC077.html" onclick="window.open(this.href);return false;

1x PCB 40.64mm x 66.04mm = 2.8€

TOTAL = 12.82€ (sans port)
(j'appliquerais le taux de change pour les sites en $)

Pour la partie gyroscope de mon quadricoptère, j'ai dessiné une carte de distribution de la partie puissance + gyro mpu6050 + buzzer intégré, le soucis c'est que ce gyro c'est un boitier QFN cms, et comme je n'avais pas de flux de soudure cms à la finalisation du quadricoptère, et que j'avais un mpu6050 en version monté sur pcb, j'avais décidé de coller ce pcb à l'époxy sur mon pcb, disons que pour un 1er proto ça n'avait pas d'importance.

Je pense que la meilleure solution pour l'instant (parce que je n'ai pas trop le temps de souder des cartes), c'est d'acheter le mpu6050 soudé sur pcb, on le trouve sur internet à moins de 10$, alors que le composant seul coûte facilement 15$... :cote:


Si jamais tu souhaites fabriquer cette carte immédiatement, je te met à disposition mon plan en pièce jointe (j'utilise le logiciel kicad pour dessiner).
Dans ce .zip il y a un autre .zip, qui contient les fichiers "Gerber" pour la production (pistes, perçages, sérigraphie, etc...).


Comme tu le sous-entend tu peux très bien commencer à faire des tests avec une Arduino Uno ou équivalent, mais comme tu l'as sans doute constaté ma carte est plus ergonomique que les Arduino puisque elle dispose d'une ligne positive et négative de puissance, en plus d'avoir les pins toutes dans l'ordre et alignés, et de pouvoir tirer un peu plus d'1A dessus.

N'hésites pas en tout cas si tu souhaites d'autres fichiers ou infos.
A bientôt :)
Vous n’avez pas les permissions nécessaires pour voir les fichiers joints à ce message.
Modifié en dernier par sylvainmahe le sam. 26 sept. 2015 11:50, modifié 1 fois.


Avatar du membre
sylvainmahe
Bicopter
Messages : 48
Enregistré le : jeu. 3 juil. 2014 18:21
Réputation : 4

Re: Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Message non lu par sylvainmahe »

Mince j'ai oublié un truc sinon tu ne verras pas tout si tu ouvres mes fichiers kicad, c'est ma bibliothèque de composants pour kicad (en vue schéma et vue pcb) en pièce jointe, car dans les logiciels je n'aime pas utiliser les bibliothèques toutes faites, ça c'est mon coté bricoleur encore :) , je préfères les créer moi même.

A bientôt.
Vous n’avez pas les permissions nécessaires pour voir les fichiers joints à ce message.


Avatar du membre
bruno
Pilote toutes catégories
Messages : 1820
Enregistré le : mar. 15 avr. 2014 11:39
Réputation : 1
Localisation : Créteil (94)

Re: Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Message non lu par bruno »

Oui j'ai bien remarqué les piste de ta carte. Bien mieux qu'une uno ;)
Et merci pour le reste.
Fait moi signe via MP lorsque tu pourra faire la carte.


Avatar du membre
sylvainmahe
Bicopter
Messages : 48
Enregistré le : jeu. 3 juil. 2014 18:21
Réputation : 4

Re: Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Message non lu par sylvainmahe »

Ok, je ne sais pas si d'autres personnes seraient intéressé?

En gros il ne me reste plus qu'un PCB de la 328P qui doit aller pour un ami du club (il me l'avait demandé il y a 1 mois déjà), donc niveau frais de port ça risque d'être assez important car il ne me reste plus grand chose en composants, à moins que vous les preniez en charge, je dois être sûr de pouvoir rentabiliser un minimum car les composants et le pcb sont acheté sur des sites bien différents.
http://www.futurlec.com" onclick="window.open(this.href);return false;
http://composants.e44.com" onclick="window.open(this.href);return false;
http://www.pcbway.com/" onclick="window.open(this.href);return false;
et éventuellement http://www.atlantique-composants.fr/eGold/" onclick="window.open(this.href);return false; , c'est la que je trouve des barrettes de pins de 7mm au lieu de 6mm, c'est plus sécuritaire pour les objets volants car les prises de servo sont mieux bloquées... :cote:


Avatar du membre
sylvainmahe
Bicopter
Messages : 48
Enregistré le : jeu. 3 juil. 2014 18:21
Réputation : 4

Re: Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Message non lu par sylvainmahe »

Ok j'ai passé une commande pour les PCB (en envoi lent pour limiter les frais de port et la douane), normalement dans moins de 30 jours je recevrais ça, je pourrais les souder et vous les envoyer.
Je vous tiens au courant, il y a effectivement plusieurs personnes intéressé par la carte :)

A bientôt.


Avatar du membre
bruno
Pilote toutes catégories
Messages : 1820
Enregistré le : mar. 15 avr. 2014 11:39
Réputation : 1
Localisation : Créteil (94)

Re: Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Message non lu par bruno »

Merci.


Avatar du membre
sylvainmahe
Bicopter
Messages : 48
Enregistré le : jeu. 3 juil. 2014 18:21
Réputation : 4

Re: Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Message non lu par sylvainmahe »

Pas de soucis ;)

Bon du coup après plusieurs 10ènes de vol de tests/validation voila le code source final sans horizon artificiel (pour l'instant) du main.cpp pour faire voler un quadricoptère:
Main.cpp

Code : Tout sélectionner

#include "../framework/Timer.h"
#include "../framework/Delay.h"
#include "../framework/Random.h"
#include "../framework/Math.h"
#include "../framework/Buzzer.h"
#include "../framework/Servo.h"
#include "../framework/Cycle.h"
#include "../framework/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 = 250;
	const uint16_t SETUP_TRAVEL_ROLL = 250;
	const uint16_t SETUP_TRAVEL_YAW = 400;
	const uint16_t SETUP_SPEED_PITCH = 300;
	const uint16_t SETUP_SPEED_ROLL = 300;
	const uint16_t SETUP_SPEED_YAW = 300;
	const uint8_t SETUP_GAIN_PITCH = 90;
	const uint8_t SETUP_GAIN_ROLL = 85;
	const uint8_t SETUP_GAIN_YAW = 90;
	const uint8_t SETUP_THRUST_PROPELLER = 55;
	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 || channelOption.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.
Modifié en dernier par sylvainmahe le sam. 21 nov. 2015 15:57, modifié 1 fois.


Avatar du membre
Vincent81
Quadricopter
Messages : 196
Enregistré le : dim. 30 nov. 2014 12:31
Réputation : 0
Localisation : Puylaurens, Tarn, France
Contact :

Re: Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Message non lu par Vincent81 »

Ça m’intéresse aussi ton truc, je vais suivre ton post...
Ça me rappelleras ma jeunesse d'électronicien, depuis je suis passé depuis du côte obscure: l'informatique :)


Avatar du membre
bruno
Pilote toutes catégories
Messages : 1820
Enregistré le : mar. 15 avr. 2014 11:39
Réputation : 1
Localisation : Créteil (94)

Re: Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Message non lu par bruno »

Vincent81 a écrit :Ça m’intéresse aussi ton truc, je vais suivre ton post...
Ça me rappelleras ma jeunesse d'électronicien, depuis je suis passé depuis du côte obscure: l'informatique :)
;) copieur ;)


Avatar du membre
sylvainmahe
Bicopter
Messages : 48
Enregistré le : jeu. 3 juil. 2014 18:21
Réputation : 4

Re: Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Message non lu par sylvainmahe »

Bonjour à tous, je n'ai toujours pas reçu cette fameuse commande de PCB :|

Je vais voir si c'est pas resté à la douane.

Je suis désolé je suis pas mauvais concepteur mais je suis mauvais commercial :)


Avatar du membre
bruno
Pilote toutes catégories
Messages : 1820
Enregistré le : mar. 15 avr. 2014 11:39
Réputation : 1
Localisation : Créteil (94)

Re: Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Message non lu par bruno »

sylvainmahe a écrit :
Je suis désolé je suis pas mauvais concepteur mais je suis mauvais commercial :)
:mdr1:
Bonne année.


Avatar du membre
sylvainmahe
Bicopter
Messages : 48
Enregistré le : jeu. 3 juil. 2014 18:21
Réputation : 4

Re: Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Message non lu par sylvainmahe »

Nouvelle vidéo avec un peu de voltige ;)
(soyez indulgents c'est pas facile de piloter avec les pouces gelés :p)



Image
Image

N'hésitez pas si vous avez des interrogations coté réalisation ou autre.


Avatar du membre
sylvainmahe
Bicopter
Messages : 48
Enregistré le : jeu. 3 juil. 2014 18:21
Réputation : 4

Re: Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Message non lu par sylvainmahe »

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:

Image

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_p ... A9rale_GNU" onclick="window.open(this.href);return false;).

J'ai aussi travaillé 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/" onclick="window.open(this.href);return false;


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 :)


Avatar du membre
bauerman
Octocopter
Messages : 591
Enregistré le : mar. 21 mai 2013 21:28
Réputation : 0
Localisation : quimper/lorient

Re: Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Message non lu par bauerman »

un Grand Bravo, chapeau bas !!!


Service de découpe CNC et d'impression 3D pour les membres du forum
Avatar du membre
sylvainmahe
Bicopter
Messages : 48
Enregistré le : jeu. 3 juil. 2014 18:21
Réputation : 4

Re: Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Message non lu par sylvainmahe »

Merci *bauerman c'est sympa :)

Aillant quelques demandes supplémentaires pour des personnes intéressés, j'ai recommandé des PCB de la carte atmega328p, j'espère que ceux-ci vont arriver cette fois !


Avatar du membre
sylvainmahe
Bicopter
Messages : 48
Enregistré le : jeu. 3 juil. 2014 18:21
Réputation : 4

Re: Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Message non lu par sylvainmahe »

PCB reçus en envoi lent ;)
Donc commandés le 5, reçus aujourd'hui le 16, ça fait environ 10 jours de délais, c'est parfait pour de l'envoi lent sans se payer la douane.

*Bruno tu en veux toujours une du coup? Si c'est le cas je te communique mon adresse, tu envois l'argent en espèces, et je t'envoi le PCB à souder? (je te donne une liste de composants et tu les prend ou tu veux au prix que tu veux).


Avatar du membre
sylvainmahe
Bicopter
Messages : 48
Enregistré le : jeu. 3 juil. 2014 18:21
Réputation : 4

Re: Homemade Quadcopter/C++ Code sans ARDUINO/MULTIWII

Message non lu par sylvainmahe »

Mise à jour importante de ma bibliothèque pour l'ATmega328P: http://sylvainmahe.xyz/data/module.zip" onclick="window.open(this.href);return false;
Celle ci est maintenant indépendante au sens ou je n'utilise plus aucun include vers des fichiers avr, ou des fichiers couramment utilisés/admis en langage c/c++, à savoir:

Code : Tout sélectionner

#include <stdlib.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <math.h>
#include <string.h>
A noter que ces fichiers avaient eux aussi de multiples include...


Voila à quoi ressemble ma bibliothèque maintenant:

Code : Tout sélectionner

"../module/GpioRead.h"
"../module/GpioWrite.h"
"../module/AnalogRead.h"
"../module/InterruptRead.h"
"../module/PwmRead.h"
"../module/PwmWrite.h"
"../module/SoundWrite.h"

"../module/Timer.h"
"../module/Delay.h"

"../module/Math.h"
"../module/Iteration.h"
"../module/Average.h"
"../module/Random.h"

"../module/Max7219.h"
"../module/Mpu6050.h"

"../module/Network.h"

"../module/Memory.h"
"../module/Power.h"
"../module/Tool.h"
Vous avez à disposition 19 classes pour créer vos projets, et selon les composants que j'achète j'ajouterais des classes dédiées à ces composants. Normalement une classes Si4432 devrait bientôt voir le jour pour la communication sans fil.


Pour ceux intéressés par la programmation c/c++ pour l'ATmega328P, voici ma liste des déclaration de registre et vecteurs d'interruption pour l'ATmega328P (c'est dans l'ordre comme indiqué dans le datasheet):

Code : Tout sélectionner

#define _UDR0 (*(volatile unsigned char *)(0xc6))
#define _UBRR0H (*(volatile unsigned char *)(0xc5))
#define _UBRR0L (*(volatile unsigned char *)(0xc4))
#define _UBRR0HL (*(volatile unsigned int *)(0xc4))
#define _UCSR0C (*(volatile unsigned char *)(0xc2))
#define _UCSR0B (*(volatile unsigned char *)(0xc1))
#define _UCSR0A (*(volatile unsigned char *)(0xc0))
#define _TWAMR (*(volatile unsigned char *)(0xbd))
#define _TWCR (*(volatile unsigned char *)(0xbc))
#define _TWDR (*(volatile unsigned char *)(0xbb))
#define _TWAR (*(volatile unsigned char *)(0xba))
#define _TWSR (*(volatile unsigned char *)(0xb9))
#define _TWBR (*(volatile unsigned char *)(0xb8))
#define _ASSR (*(volatile unsigned char *)(0xb6))
#define _OCR2B (*(volatile unsigned char *)(0xb4))
#define _OCR2A (*(volatile unsigned char *)(0xb3))
#define _TCNT2 (*(volatile unsigned char *)(0xb2))
#define _TCCR2B (*(volatile unsigned char *)(0xb1))
#define _TCCR2A (*(volatile unsigned char *)(0xb0))
#define _OCR1BH (*(volatile unsigned char *)(0x8b))
#define _OCR1BL (*(volatile unsigned char *)(0x8a))
#define _OCR1BHL (*(volatile unsigned int *)(0x8a))
#define _OCR1AH (*(volatile unsigned char *)(0x89))
#define _OCR1AL (*(volatile unsigned char *)(0x88))
#define _OCR1AHL (*(volatile unsigned int *)(0x88))
#define _ICR1H (*(volatile unsigned char *)(0x87))
#define _ICR1L (*(volatile unsigned char *)(0x86))
#define _ICR1HL (*(volatile unsigned int *)(0x86))
#define _TCNT1H (*(volatile unsigned char *)(0x85))
#define _TCNT1L (*(volatile unsigned char *)(0x84))
#define _TCNT1HL (*(volatile unsigned int *)(0x84))
#define _TCCR1C (*(volatile unsigned char *)(0x82))
#define _TCCR1B (*(volatile unsigned char *)(0x81))
#define _TCCR1A (*(volatile unsigned char *)(0x80))
#define _DIDR1 (*(volatile unsigned char *)(0x7f))
#define _DIDR0 (*(volatile unsigned char *)(0x7e))
#define _ADMUX (*(volatile unsigned char *)(0x7c))
#define _ADCSRB (*(volatile unsigned char *)(0x7b))
#define _ADCSRA (*(volatile unsigned char *)(0x7a))
#define _ADCH (*(volatile unsigned char *)(0x79))
#define _ADCL (*(volatile unsigned char *)(0x78))
#define _ADCHL (*(volatile unsigned int *)(0x78))
#define _TIMSK2 (*(volatile unsigned char *)(0x70))
#define _TIMSK1 (*(volatile unsigned char *)(0x6f))
#define _TIMSK0 (*(volatile unsigned char *)(0x6e))
#define _PCMSK2 (*(volatile unsigned char *)(0x6d))
#define _PCMSK1 (*(volatile unsigned char *)(0x6c))
#define _PCMSK0 (*(volatile unsigned char *)(0x6b))
#define _EICRA (*(volatile unsigned char *)(0x69))
#define _PCICR (*(volatile unsigned char *)(0x68))
#define _OSCCAL (*(volatile unsigned char *)(0x66))
#define _PRR (*(volatile unsigned char *)(0x64))
#define _CLKPR (*(volatile unsigned char *)(0x61))
#define _WDTCSR (*(volatile unsigned char *)(0x60))
#define _SREG (*(volatile unsigned char *)(0x5f))
#define _SPH (*(volatile unsigned char *)(0x5e))
#define _SPL (*(volatile unsigned char *)(0x5d))
#define _SPHL (*(volatile unsigned int *)(0x5d))
#define _SPMCSR (*(volatile unsigned char *)(0x57))
#define _MCUCR (*(volatile unsigned char *)(0x55))
#define _MCUSR (*(volatile unsigned char *)(0x54))
#define _SMCR (*(volatile unsigned char *)(0x53))
#define _ACSR (*(volatile unsigned char *)(0x50))
#define _SPDR (*(volatile unsigned char *)(0x4e))
#define _SPSR (*(volatile unsigned char *)(0x4d))
#define _SPCR (*(volatile unsigned char *)(0x4c))
#define _GPIOR2 (*(volatile unsigned char *)(0x4b))
#define _GPIOR1 (*(volatile unsigned char *)(0x4a))
#define _OCR0B (*(volatile unsigned char *)(0x48))
#define _OCR0A (*(volatile unsigned char *)(0x47))
#define _TCNT0 (*(volatile unsigned char *)(0x46))
#define _TCCR0B (*(volatile unsigned char *)(0x45))
#define _TCCR0A (*(volatile unsigned char *)(0x44))
#define _GTCCR (*(volatile unsigned char *)(0x43))
#define _EEARH (*(volatile unsigned char *)(0x42))
#define _EEARL (*(volatile unsigned char *)(0x41))
#define _EEARHL (*(volatile unsigned int *)(0x41))
#define _EEDR (*(volatile unsigned char *)(0x40))
#define _EECR (*(volatile unsigned char *)(0x3f))
#define _GPIOR0 (*(volatile unsigned char *)(0x3e))
#define _EIMSK (*(volatile unsigned char *)(0x3d))
#define _EIFR (*(volatile unsigned char *)(0x3c))
#define _PCIFR (*(volatile unsigned char *)(0x3b))
#define _TIFR2 (*(volatile unsigned char *)(0x37))
#define _TIFR1 (*(volatile unsigned char *)(0x36))
#define _TIFR0 (*(volatile unsigned char *)(0x35))
#define _PORTD (*(volatile unsigned char *)(0x2b))
#define _DDRD (*(volatile unsigned char *)(0x2a))
#define _PIND (*(volatile unsigned char *)(0x29))
#define _PORTC (*(volatile unsigned char *)(0x28))
#define _DDRC (*(volatile unsigned char *)(0x27))
#define _PINC (*(volatile unsigned char *)(0x26))
#define _PORTB (*(volatile unsigned char *)(0x25))
#define _DDRB (*(volatile unsigned char *)(0x24))
#define _PINB (*(volatile unsigned char *)(0x23))

#define _RESET __vector_ ## 0
#define _INT0 __vector_ ## 1
#define _INT1 __vector_ ## 2
#define _PCINT0 __vector_ ## 3
#define _PCINT1 __vector_ ## 4
#define _PCINT2 __vector_ ## 5
#define _WDT __vector_ ## 6
#define _TIMER2_COMPA __vector_ ## 7
#define _TIMER2_COMPB __vector_ ## 8
#define _TIMER2_OVF __vector_ ## 9
#define _TIMER1_CAPT __vector_ ## 10
#define _TIMER1_COMPA __vector_ ## 11
#define _TIMER1_COMPB __vector_ ## 12
#define _TIMER1_OVF __vector_ ## 13
#define _TIMER0_COMPA __vector_ ## 14
#define _TIMER0_COMPB __vector_ ## 15
#define _TIMER0_OVF __vector_ ## 16
#define _SPI_STC __vector_ ## 17
#define _USART_RX __vector_ ## 18
#define _USART_UDRE __vector_ ## 19
#define _USART_TX __vector_ ## 20
#define _ADC __vector_ ## 21
#define _EE_READY __vector_ ## 22
#define _ANALOG_COMP __vector_ ## 23
#define _TWI __vector_ ## 24
#define _SPM_READY __vector_ ## 25

#define _INTERRUPT_JUMP(vector) extern "C" void vector() __attribute__ ((signal)); void vector()

Un petit rappel (et mise à jour du code) de ce qu'il faut pour faire voler un quadri-hélicoptère:

Code : Tout sélectionner

#include "../module/Timer.h"
#include "../module/Delay.h"
#include "../module/Random.h"
#include "../module/Math.h"
#include "../module/SoundWrite.h"
#include "../module/PwmWrite.h"
#include "../module/PwmRead.h"
#include "../module/Mpu6050.h"

int main()
{
	unsigned char n = 0;
	Mpu6050 gyroscope = Mpu6050 (0);
	PwmRead channelThrottle = PwmRead (1, false);
	unsigned int slowChannelThrottle = 0;
	unsigned int centerChannelThrottle = 0;
	PwmRead channelPitch = PwmRead (2, false);
	unsigned int centerChannelPitch = 0;
	PwmRead channelRoll = PwmRead (3, false);
	unsigned int centerChannelRoll = 0;
	PwmRead channelYaw = PwmRead (4, false);
	unsigned int centerChannelYaw = 0;
	PwmRead channelHold = PwmRead (5, false);
	unsigned int centerChannelHold = 0;
	PwmRead channelOption = PwmRead (6, false);
	unsigned int centerChannelOption = 0;
	PwmWrite motor1 = PwmWrite (8, 0, 0, 0);
	PwmWrite motor2 = PwmWrite (9, 0, 0, 0);
	PwmWrite motor3 = PwmWrite (10, 0, 0, 0);
	PwmWrite motor4 = PwmWrite (11, 0, 0, 0);
	Delay delaySoundStartCondition = Delay (1000, false);
	unsigned int mixThrottle = 0;
	signed int mixThrustPitchGain = 0;
	signed int mixThrustRollGain = 0;
	signed int mixInertiaYawGain = 0;
	signed int mixMinClearancePitch = 0;
	signed int mixMaxClearancePitch = 0;
	signed int mixMinClearanceRoll = 0;
	signed int mixMaxClearanceRoll = 0;
	signed int mixMinClearanceYaw = 0;
	signed int mixMaxClearanceYaw = 0;
	const unsigned int SPEED_GYRO = 1000;
	signed int speedPitch = 0;
	signed int speedRoll = 0;
	signed int speedYaw = 0;
	signed int mixPitchOffsetGyro = 0;
	signed int mixRollOffsetGyro = 0;
	signed int mixYawOffsetGyro = 0;
	unsigned char thrustGainPitch = 0;
	unsigned char thrustGainRoll = 0;
	unsigned char inertiaGainYaw = 0;
	unsigned int gainMinRxGyro = 0;
	unsigned int gainMaxRxGyro = 0;
	unsigned int gainMinRyGyro = 0;
	unsigned int gainMaxRyGyro = 0;
	unsigned int gainMinRzGyro = 0;
	unsigned int gainMaxRzGyro = 0;
	signed int mixMinRxGyro = 0;
	signed int mixMaxRxGyro = 0;
	signed int mixMinRyGyro = 0;
	signed int mixMaxRyGyro = 0;
	signed int mixMinRzGyro = 0;
	signed int mixMaxRzGyro = 0;
	unsigned int mixMotor1 = 0;
	unsigned int mixMotor2 = 0;
	unsigned int mixMotor3 = 0;
	unsigned int mixMotor4 = 0;
	const unsigned int SETUP_MIN_CHANNEL_THROTTLE = 1000;
	const unsigned int SETUP_MAX_CHANNEL_THROTTLE = 2000;
	const unsigned int SETUP_MIN_CHANNEL_PITCH = 1000;
	const unsigned int SETUP_MAX_CHANNEL_PITCH = 2000;
	const unsigned int SETUP_MIN_CHANNEL_ROLL = 1000;
	const unsigned int SETUP_MAX_CHANNEL_ROLL = 2000;
	const unsigned int SETUP_MIN_CHANNEL_YAW = 1000;
	const unsigned int SETUP_MAX_CHANNEL_YAW = 2000;
	const unsigned int SETUP_MIN_CHANNEL_HOLD = 1000;
	const unsigned int SETUP_MAX_CHANNEL_HOLD = 2000;
	const unsigned int SETUP_MIN_CHANNEL_OPTION = 1500;
	const unsigned int SETUP_MAX_CHANNEL_OPTION = 2000;
	const signed int SETUP_ZERO_PITCH = 38;
	const signed int SETUP_ZERO_ROLL = -11;
	const signed int SETUP_ZERO_YAW = -46;
	const unsigned int SETUP_FREQUENCY_ESC = 100;
	const unsigned int SETUP_HOLD_ESC = 950;
	const unsigned int SETUP_MIN_ESC = 1050;
	const unsigned int SETUP_MAX_ESC = 1950;
	const unsigned int SETUP_TRAVEL_PITCH = 250;
	const unsigned int SETUP_TRAVEL_ROLL = 250;
	const unsigned int SETUP_TRAVEL_YAW = 400;
	const unsigned int SETUP_SPEED_PITCH = 320;
	const unsigned int SETUP_SPEED_ROLL = 320;
	const unsigned int SETUP_SPEED_YAW = 320;
	const unsigned char SETUP_GAIN_PITCH = 93;
	const unsigned char SETUP_GAIN_ROLL = 88;
	const unsigned char SETUP_GAIN_YAW = 95;
	const unsigned char SETUP_THRUST_PROPELLER = 55;
	const unsigned char SETUP_INERTIA_PROPELLER = 100;
	
	Timer::pause (1000);
	
	slowChannelThrottle = Math::round (float (SETUP_MIN_CHANNEL_THROTTLE) + ((float (SETUP_MAX_CHANNEL_THROTTLE) - float (SETUP_MIN_CHANNEL_THROTTLE)) / float (10)));
	centerChannelThrottle = Math::round (float (SETUP_MAX_CHANNEL_THROTTLE) - ((float (SETUP_MAX_CHANNEL_THROTTLE) - float (SETUP_MIN_CHANNEL_THROTTLE)) / float (2)));
	centerChannelPitch = Math::round (float (SETUP_MAX_CHANNEL_PITCH) - ((float (SETUP_MAX_CHANNEL_PITCH) - float (SETUP_MIN_CHANNEL_PITCH)) / float (2)));
	centerChannelRoll = Math::round (float (SETUP_MAX_CHANNEL_ROLL) - ((float (SETUP_MAX_CHANNEL_ROLL) - float (SETUP_MIN_CHANNEL_ROLL)) / float (2)));
	centerChannelYaw = Math::round (float (SETUP_MAX_CHANNEL_YAW) - ((float (SETUP_MAX_CHANNEL_YAW) - float (SETUP_MIN_CHANNEL_YAW)) / float (2)));
	centerChannelHold = Math::round (float (SETUP_MAX_CHANNEL_HOLD) - ((float (SETUP_MAX_CHANNEL_HOLD) - float (SETUP_MIN_CHANNEL_HOLD)) / float (2)));
	centerChannelOption = Math::round (float (SETUP_MAX_CHANNEL_OPTION) - ((float (SETUP_MAX_CHANNEL_OPTION) - float (SETUP_MIN_CHANNEL_OPTION)) / float (2)));
	
	SoundWrite::pin (13);
	
	while (centerChannelThrottle == 0 || centerChannelPitch == 0 || centerChannelRoll == 0 || centerChannelYaw == 0 || centerChannelHold == 0 || centerChannelOption == 0)
	{
		delaySoundStartCondition.state();
		
		if (delaySoundStartCondition.update == true)
		{
			SoundWrite::play (200, 100);
		}
	}
	
	delaySoundStartCondition.reset();
	
	PwmRead::start (100);
	
	while (channelThrottle.us == 0 || channelPitch.us == 0 || channelRoll.us == 0 || channelYaw.us == 0 || channelHold.us == 0 || channelOption.us == 0)
	{
		channelThrottle.state();
		channelPitch.state();
		channelRoll.state();
		channelYaw.state();
		channelHold.state();
		channelOption.state();
		
		delaySoundStartCondition.state();
		
		if (delaySoundStartCondition.update == true)
		{
			SoundWrite::key (200, 100);
			SoundWrite::key (0, 100);
			SoundWrite::key (200, 100);
			SoundWrite::playKey();
		}
	}
	
	delaySoundStartCondition.reset();
	
	while (channelThrottle.us > slowChannelThrottle || channelHold.us < centerChannelHold)
	{
		channelThrottle.state();
		channelHold.state();
		
		delaySoundStartCondition.state();
		
		if (delaySoundStartCondition.update == true)
		{
			SoundWrite::key (200, 100);
			SoundWrite::key (0, 100);
			SoundWrite::key (200, 100);
			SoundWrite::key (0, 100);
			SoundWrite::key (200, 100);
			SoundWrite::playKey();
		}
	}
	
	Random::seed (15);
	
	for (n = 0; n < 16; n++)
	{
		if (n != 0)
		{
			SoundWrite::key (0, Random::integer (25, 75));
		}
		
		SoundWrite::key (Random::integer (70, 3000), Random::integer (25, 75));
	}
	
	SoundWrite::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);
	
	gyroscope.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);
	
	PwmWrite::start (SETUP_FREQUENCY_ESC);
	
	while (true)
	{
		gyroscope.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, gyroscope.rx + mixPitchOffsetGyro, mixThrustPitchGain, -mixMaxClearancePitch, 0, mixMinClearancePitch, 0, 0);
			mixMaxRxGyro = Math::wurve (-mixThrustPitchGain, gyroscope.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, gyroscope.ry - mixRollOffsetGyro, mixThrustRollGain, -mixMaxClearanceRoll, 0, mixMinClearanceRoll, 0, 0);
			mixMaxRyGyro = Math::wurve (-mixThrustRollGain, gyroscope.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, gyroscope.rz + mixYawOffsetGyro, mixInertiaYawGain, -mixMaxClearanceYaw, 0, mixMinClearanceYaw, 0, 0);
			mixMaxRzGyro = Math::wurve (-mixInertiaYawGain, gyroscope.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;
}
Vidéo: " onclick="window.open(this.href);return false;


N'hésitez pas si vous avez des questions ou des idées :)


Répondre

Retourner vers « Modules et Montages DIY »