See site in english Voir le site en francais
Website skin:
home  download  forum  link  contact

Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

Author Topic: Arduino Uno + Orbiter  (Read 100754 times)

0 Members and 2 Guests are viewing this topic.

Offline Fox-Terrier

  • League of
  • Legend
  • ******
  • Posts: 1426
  • Country: Switzerland ch
  • Karma: 28
  • :D
Reply #100 - 17 February 2014, 16:00:53
*erreur de manip, j'ai tout bousillé en répondant dans l'édition de mon message :siffle:*

« Last Edit: 18 February 2014, 21:00:31 by Fox-Terrier »

Offline nulentout

  • Legend
  • ******
  • Posts: 3356
  • Country: France fr
  • Karma: 242
Reply #101 - 18 February 2014, 08:39:47
Tu peux traduire ton code en C utilisé sur Arduino STP, car je n'en saisi pas tout le sens ?
Les cas hostiles ... sont fonction du codage et des diverses procédures utilisées.
* Procédure pour lire la consigne sur le potentiomètre ... très simple. Mais suivie d'une procédure qui effectue des correctifs pour linéariser la courbe de variation de ce dernier car il est assez médiocre sur ce point.
* Procédure qui récupère le cap magnétique du capteur.
* Procédure qui ajoute une correction de symétrie à la barre, car pour une consigne de neutre (90°) la croix du palonnier du servomoteur n'est pas exactement dans l'axe longitudinal du bateau.
* Procédure qui introduit une correction à bâbord ou à tribord pour compenser la dérive, car le bateau envisagé est un voilier. Quand il navigue au près serré il dérape toujours latéralement.
* Procédure qui génère la consigne de barre pour dévier cette dernière inversement proportionnelle à l'écart par rapport à la route souhaitée.
* Procédure qui détermine le plus petit angle à balayer et le coté où se trouve cette altération de cap.
* Procédure qui génère une zone "neutre" de non correction de route pour éviter des surcompensations permanentes résultant de la houle (petites vagues sur le plan d'eau où évolue la maquette) et des instabilités de route inévitable sur un voilier, d'autant plus qu'il navigue "au portant".

J'en oublie certainement, mais avec le brassage joyeux de tout ce petit monde, ça fait une combinatoire de cas particuliers assez Meumeu. En particulier toutes les frontières de zones dans ces divers éléments qui présentent des plages de variations très fifférentes. Et dans tout ça je ne mentionne même pas les spécificité du compilateur qui génère des difficultés très piégeuses, obligeant à changer parfois le type de certaines variables, d'introduire des booléens dont je me serai passé etc.

C'est au cours des "campagnes d'essais" que se révèlent parfois des comportements imprévus ... et PAFFF, ton voilier empanne et va sur le récif, de Charybde en Scylla !

P.S : Charybde et Scylla étaient deux dangers dans le détroit de Messine entre l'Italie et la Sicile. Le premier était un vortex, le second un récif.
Les marins qui arrivaient à éviter le premier allaient se perdre corps et âme sur le second.

La sagesse est un trésor ... tellement bien caché.

Offline Fox-Terrier

  • League of
  • Legend
  • ******
  • Posts: 1426
  • Country: Switzerland ch
  • Karma: 28
  • :D
Reply #102 - 18 February 2014, 20:59:24
Alors faisons les choses comme il faut (j'ai corrigé la condition pour la marge)


Code: [Select]
#include <stdio.h>
#include <math.h>

#define MARGE 5 //marge +/- 5 (5 exclu)
#define TOUT_DROIT 0
#define DROITE 1
#define GAUCHE 2

int direction (int initiale, int finale, int* angle)
{
    if (abs(initiale - finale) < MARGE || abs(initiale - finale) > (360 - MARGE))
    {
        printf("A/ cas TOUT DROIT\n");
        *angle = 0;
        return TOUT_DROIT;
    }

    else if ((initiale - finale) < 0)
    {
        if ((initiale - finale + 360) > 180)
        {
            printf("B/ cas i-f < 0, i-f+360 > 180 DROITE\n");
            *angle = -initiale + finale;
            return DROITE;
        }
        else
        {
            printf("C/ cas i-f < 0, i-f+360 < 180 GAUCHE\n");
            *angle = initiale - finale + 360;
            return GAUCHE;
        }

    }
    else
    {
        if ((initiale - finale) > 180)
        {
            printf("D/ cas i-f > 0, i-f > 180 DROITE\n");
            *angle = -initiale + finale + 360;
            return DROITE;
        }
        else
        {
            printf("E/ cas i-f > 0, i-f < 180 GAUCHE\n");
            *angle = initiale - finale;
            return GAUCHE;
        }
     }
}

main()
{
    int angle = 0;
    int cote = 0;

    cote = direction(2,358, &angle);
    printf("i = 2, f = 358, coté = %d, angle = %d\n",cote,angle);
    cote = direction(356,1, &angle);
    printf("i = 356, f = 1, coté = %d, angle = %d\n",cote,angle);
    cote = direction(357,1, &angle);
    printf("i = 357, f = 1, coté = %d, angle = %d\n",cote,angle);
    cote = direction(4,360, &angle);
    printf("i = 4, f = 360, coté = %d, angle = %d\n",cote,angle);
    cote = direction(5,360, &angle);
    printf("i = 5, f = 360, coté = %d, angle = %d\n",cote,angle);
    cote = direction(360,5, &angle);
    printf("i = 360, f = 5, coté = %d, angle = %d\n\n",cote,angle);

    cote = direction(20,180, &angle);
    printf("i = 20, f = 180, coté = %d, angle = %d\n",cote,angle);
    cote = direction(20,270, &angle);
    printf("i = 20, f = 270, coté = %d, angle = %d\n",cote,angle);
    cote = direction(270,20, &angle);
    printf("i = 270, f = 20, coté = %d, angle = %d\n",cote,angle);
    cote = direction(190,140, &angle);
    printf("i = 190, f = 140, coté = %d, angle = %d\n",cote,angle);
    cote = direction(350,140, &angle);
    printf("i = 350, f = 140, coté = %d, angle = %d\n\n",cote,angle);

    cote = direction(10,190, &angle);
    printf("i = 10, f = 190, coté = %d, angle = %d\n",cote,angle);
    cote = direction(9,190, &angle);
    printf("i = 9, f = 190, coté = %d, angle = %d\n",cote,angle);
    cote = direction(11,190, &angle);
    printf("i = 11, f = 190, coté = %d, angle = %d\n",cote,angle);
    cote = direction(190,7, &angle);
    printf("i = 190, f = 7, coté = %d, angle = %d\n",cote,angle);
    cote = direction(340,20, &angle);
    printf("i = 340, f = 20, coté = %d, angle = %d\n",cote,angle);


    return 0;
}


et affiche
Code: [Select]
A/ cas TOUT DROIT
i = 2, f = 358, coté = 0, angle = 0
D/ cas i-f > 0, i-f > 180 DROITE
i = 356, f = 1, coté = 1, angle = 5
A/ cas TOUT DROIT
i = 357, f = 1, coté = 0, angle = 0
A/ cas TOUT DROIT
i = 4, f = 360, coté = 0, angle = 0
C/ cas i-f < 0, i-f+360 < 180 GAUCHE
i = 5, f = 360, coté = 2, angle = 5
D/ cas i-f > 0, i-f > 180 DROITE
i = 360, f = 5, coté = 1, angle = 5

B/ cas i-f < 0, i-f+360 > 180 DROITE
i = 20, f = 180, coté = 1, angle = 160
C/ cas i-f < 0, i-f+360 < 180 GAUCHE
i = 20, f = 270, coté = 2, angle = 110
D/ cas i-f > 0, i-f > 180 DROITE
i = 270, f = 20, coté = 1, angle = 110
E/ cas i-f > 0, i-f < 180 GAUCHE
i = 190, f = 140, coté = 2, angle = 50
D/ cas i-f > 0, i-f > 180 DROITE
i = 350, f = 140, coté = 1, angle = 150

C/ cas i-f < 0, i-f+360 < 180 GAUCHE
i = 10, f = 190, coté = 2, angle = 180
C/ cas i-f < 0, i-f+360 < 180 GAUCHE
i = 9, f = 190, coté = 2, angle = 179
B/ cas i-f < 0, i-f+360 > 180 DROITE
i = 11, f = 190, coté = 1, angle = 179
D/ cas i-f > 0, i-f > 180 DROITE
i = 190, f = 7, coté = 1, angle = 177
D/ cas i-f > 0, i-f > 180 DROITE
i = 340, f = 20, coté = 1, angle = 40

Point 1 et 2 ne semble pas trop compliqué, le 3 tu trouve par expérience le décalage et tu le définis avec un #define et t'y touche plus ...
Le 4 :damn: galère ! Je n'en sais malheureusement pas assez sur la voile ... J'imagine que tu considères la dérive nulle par vent arrière, maximale au près, puis encore nulle face au vent, mais ça dépend donc du réglage de la voile, qu'il faut optimiser en fonction de la provenance du vent par rapport au cap du voilier, ainsi que de la force du vent ... je te laisse voir jusqu'à où tu veux simuler ;)
point 5 facile
point 6 et 7 résolus dans le code ci dessus :flower:


Offline nulentout

  • Legend
  • ******
  • Posts: 3356
  • Country: France fr
  • Karma: 242
Reply #103 - 19 February 2014, 09:12:02
Houlala, tu m'en a tartiné du code !
Mon programme est terminé et fonctionne correctement. Mais dans ton programme il y a des formulations dont je ne connais pas la syntaxe, donc je vais m'y pencher pour en savoir plus.
Naturellement, par curiosité je vais soumettre ce code à Arduino et essayer de tout comprendre.
OUI, pour le point 3 de symétrisation de la barre c'est enfantin. J'ai défini la valeur comme une constante qu'il est facile de changer si on adopte un autre servomoteur.
>>> Tu utilises pour ça un define. Peux-tu me préciser l'avantage de cette écriture par rapport à la précision d'une constante ? (Gain d'un emplacement mémoire ?)
CORRECTION DE LA DERIVE : Deux phénomènes vont venir fausser la route magnétique moyenne d'un voilier. (Je dis moyenne car inévitablement son cap oscille en fonction des perturbations et des corrections de barre)
A) Le bateau évolue dans une zone avec du courant. Si la maquette est sur un lac on peut oublier, mais si tu veux lui faire traverser une rivière il faut compenser.
B) Quand il évolue, recevant le vent sur un coté, il se fait pousser latéralement. les formes de carène et l'éventuelle quille viennent minimiser ce dérapage qui est important quand le navire remonte au prés et diminue quand on va vers le vent de travers qui est l'allure la plus agréable pour un marin. Je me contente de l'estimer, un bouton gradué entre -15° et +15° vient ajouter un décalage angulaire au CAP désiré.
C) Gestion de la barre pour contrer avec une énergie inverse à la valeur de l'écart de route et une déviation maximale du gouvernail : Ben pas si facile que ça. J'ai procédé par tranches angulaires, mais une déviation proportionnelle serait peut être plus élégante ... je vais me contenter de la solution actuelle.
Les trois derniers points : Calculer l'écart de route ... facile, j'ai deux ou trois lignes de code.
Calculer le coté vers lequel tourner : J'ai vraiment cherché un bon moment et utilisé les idées des copains, car je me suis heurté à des calculs faux issus du comportement du compilateur qui n'est pas une calculatrice. Comme dans la formule qui gère le CAP + 180° j'ai introduit un "int" et un "long" je me retrouvais avec des erreurs de calcul dues à des "compléments à deux" issus du code compilé. C'est sournois car tu te retrouve avec des valeurs fausses alors que mathématiquement ta formule est bonne.
Pour ce qui est de la zone neutre, c'est facile. Un bouton me permet de choisir entre un minimum de 2° et un maximum de 15°. C'est la plage de chaque coté du CAP désiré où l'écart de route est ignoré. C'est pour éviter que le moteur ne "barbotte" sans interruption dès qu'une vaguelette ou une petite saute de vent altère ta route d'un fifrelin. Par temps calme 2° conviennent, mais avec du clapot et sous vent arrière il faut augmenter la tolérance si l'on veut calmer la nervosité du moteur. De toute façon, quand les circonstances deviennent difficiles ... on barre à la main.
Vla toute l'histoire, je vais donc me barrer pour analyses le fruit de tes cogitations. :)

La sagesse est un trésor ... tellement bien caché.

Offline Fox-Terrier

  • League of
  • Legend
  • ******
  • Posts: 1426
  • Country: Switzerland ch
  • Karma: 28
  • :D
Reply #104 - 19 February 2014, 22:52:07
Houlala, tu m'en a tartiné du code !
Mon programme est terminé et fonctionne correctement. Mais dans ton programme il y a des formulations dont je ne connais pas la syntaxe, donc je vais m'y pencher pour en savoir plus.
Naturellement, par curiosité je vais soumettre ce code à Arduino et essayer de tout comprendre.
OUI, pour le point 3 de symétrisation de la barre c'est enfantin. J'ai défini la valeur comme une constante qu'il est facile de changer si on adopte un autre servomoteur.
>>> Tu utilises pour ça un define. Peux-tu me préciser l'avantage de cette écriture par rapport à la précision d'une constante ? (Gain d'un emplacement mémoire ?)


Personnellement j'ai appris à utiliser les #define pour remplacer les constantes qu'on trouvent un peu partout dans un code, au lieu d'écrire partout 5 pour la marge, je le remplace par MARGE, j'aurais pu faire pareil avec 360
Le but c'est de pouvoir modifier cette constante facilement quand tu programmes, et de lui donner un sens (parce que bon 5 tout seul ... ça veut pas dire grand-chose)
Techniquement, avant la compilation, le préprocesseur va lire les define et remplacera MARGE par 5, ce qui signifie qu'il n'y a pas de mémoire (celle pour les variables) allouée pour cette constante
Maintenant, vaut-il mieux écrire #define MARGE 5 ou déclarer static const int marge = 5; ... c'est un débat technique à nouveau :)

Sur StackOverflow, on dit la chose suivante :
Quote
(1) static const int var = 5;
(2) #define var 5
(3) enum { var = 5 };



Si tu dois passer un pointeur, utilise (1). (Mais comme tu ne peux pas changer la valeur d'une constante, tu n'utiliseras pas de pointeur ...)
(1) et (3) sont plus facile à debugguer que (2)
(1) ne peut être utilisé comme dimension pour des tableaux au niveau global, mais (2) et (3) le peuvent.
(1) ne peut être utilisé comme dimension pour des tableaux "static" au niveau d'une fonction,mais
(2) et (3) le peuvent.
Depuis C99, les 3 méthodes peuvent être utilisées pour dimensionner des tableaux locaux, même si
techniquement, (1) signifierait déclarer un tableau de taille variable (même si la variable est une
constante), ce que C n'aime pas ...
(1) ne peut pas être utilisé dans un switch (... case [...]: ...), mais (2) et (3) le peuvent.
Tu peux voir si (2) a été initialisé par le préprocesseur, mais ni (1) ni (3) le peuvent

Quote
Calculer le coté vers lequel tourner : J'ai vraiment cherché un bon moment et utilisé les idées des copains, car je me suis heurté à des calculs faux issus du comportement du compilateur qui n'est pas une calculatrice. Comme dans la formule qui gère le CAP + 180° j'ai introduit un "int" et un "long" je me retrouvais avec des erreurs de calcul dues à des "compléments à deux" issus du code compilé. C'est sournois car tu te retrouve avec des valeurs fausses alors que mathématiquement ta formule est bonne.

Intéressant ! J'ai jamais eu affaire à une erreur de ce style ! Mais que fais tu avec un long ?

Quote
Pour ce qui est de la zone neutre, c'est facile. Un bouton me permet de choisir entre un minimum de 2° et un maximum de 15°. C'est la plage de chaque coté du CAP désiré où l'écart de route est ignoré. C'est pour éviter que le moteur ne "barbotte" sans interruption dès qu'une vaguelette ou une petite saute de vent altère ta route d'un fifrelin. Par temps calme 2° conviennent, mais avec du clapot et sous vent arrière il faut augmenter la tolérance si l'on veut calmer la nervosité du moteur. De toute façon, quand les circonstances deviennent difficiles ... on barre à la main.
Vla toute l'histoire, je vais donc me barrer pour analyses le fruit de tes cogitations. :)

Oui et puis faut aussi tenir compte de la marge d'aléas de tes capteurs qui ne restent pas figés :)


Offline nulentout

  • Legend
  • ******
  • Posts: 3356
  • Country: France fr
  • Karma: 242
Reply #105 - 20 February 2014, 08:52:05
Oui, pourquoi utiliser un long alors que l'on ne va pas dépasser la taille d'un int ?
Le problème réside dans les calculs. Prenons un exemple simple :
Je désire allumer une LED par une sortie PWM en fonction de la position d'un potentiomètre placé sur une entrée analogique ... fastoche ça. ANALYSE :
* Le convertisseur AN retourne entre [0 et 1024] : Donc un int.
* La PWM veut des valeurs entre [0 et 255]. Il faut donc effectuer la transposition.
* Transposition : PWM = (Valeur AN * 255)/1024.
Voici mon programme :
===========================================
unsigned int Commande; // Valeur mesurée pour éclairer.
unsigned long Eclairage_LED; // Valeur pour PWM.
void loop() {
  Commande = analogRead(Commande_lumiere);
  Eclairage_LED = Commande * 255 / 1024;
  analogWrite(LED,Eclairage_LED); }
===========================================
Commande varie entre [0 et 1024] donc choisir unsigned int pour rester dans la plage des valeurs et travailler avec des entiers positifs.
Eclairage_LED doit varier entre [0 et 255] mais choisir le type unsigned long car le calcul rouge peut arriver à la valeur calculée de 1024 * 255 = 261120. Pour transposer [0 à 1024] en [0 à 255] le calcul consiste à diviser par 1024 et multiplier par 255, mais il faut commencer par la multiplication car on travaille avec des entiers et 255 / 1024 donnerait 0,25 donc zéro.
===========================================
unsigned int : Valeurs possible = [0 à 65535]
unsigned long : Valeurs possible = [0 à 4294967295]
Donc des intervalles de valeurs théoriquement compatibles.
===========================================

Le résultat du calcul et la valeur envoyée à PWM sont incorrect car les deux coté de l'expression d'affectation ne sont pas de types homogènes. Eclairage_LED varie de 0 à 30 pour 635 puis saute à 4294967268 à partir de 655 environ. (Quatre fois sur la course du potentiomètre)
Testes sur ton Arduino, le programme n’a pas un comportement correct, pourtant tout est logique. C’est « une faiblesse » du compilateur. Dans le calcul d’une expression il faut que tous les éléments soient de même type, ou forcer le calcul avec un « cast ».
Imagines que ce problème soit dans une expression calculée par un if :
If ()X*Y/Z)) > 55) {traitement}
Ton expression est correcte mathématiquement, les variables X,Y et Z sont des entiers, mais optimisés en taille, (byte, int, long) donc cohérente au point de vue logique. Mais comme le calcul est faux le test ne fonctionne pas toujours, et tu n’arrives pas à savoir pourquoi.
C’est d’autant plus sournois que rien ne te prévient. Tu imagines pour un débutant comme Môamôa qui découvre tout juste le langage C. Ben C pas facile ! (Jeu de mots stupide)
Voila le genre de problèmes que j’ai rencontré.
Ben, ça s’appelle de l’expérience. 

La sagesse est un trésor ... tellement bien caché.

Offline Fox-Terrier

  • League of
  • Legend
  • ******
  • Posts: 1426
  • Country: Switzerland ch
  • Karma: 28
  • :D
Reply #106 - 20 February 2014, 20:37:27
Et bien j'arrive pas à reproduire ce bug sur un ordinateur malheureusement, (et je n'ai pas de carte Arduino)
Cependant : lors d'un calcul entre deux variables de type différent, une conversion implicite à lieu selon la hiérarchie suivante :
int -> long -> float -> double
Le calcul se poursuit en gardant le type le plus important
C'est comme ça que ça devrait marcher, mais à mon avis, le problème est ailleurs : l'Arduino ne travaille peut-être pas directement avec le code compilé, il y a peut-être encore une étape supplémentaire que tu ne vois pas ... Normalement on programme en assembleur sur les micro-contrôleurs, mais c'est une horreur :arg: ... Je n'ai absolument aucune idée pourquoi ça ne marche pas ...

Quote
Eclairage_LED doit varier entre [0 et 255] mais choisir le type unsigned long car le calcul rouge peut arriver à la valeur calculée de 1024 * 255 = 261120.
Tu peux très bien mettre un int si tu es sûr que le résultat final rentre dedans. Durant le calcul, il s'en fiche du type de la variable qui reçoit la valeur


Astuce : 1024 est considéré par le programme comme un int tandis que 1024. est considéré comme un double

Et je crois que commande varie plutôt de 0 à 1023 (1024 possibilités, 10 bits)

Et félicitations pour tes 3000 messages !! :friend:

« Last Edit: 20 February 2014, 20:46:16 by Fox-Terrier »

Offline nulentout

  • Legend
  • ******
  • Posts: 3356
  • Country: France fr
  • Karma: 242
Reply #107 - 21 February 2014, 13:04:28
GLUPPPSSSsssss, mais je n'avais pas vu que j'étais PILEPOILE à 3000 !
Le "normalement" pour un compilateur, c'est du théorique. Un langage étant défini, chaque implémentation du compilateur va forcément avoir des spécificités en fonction des choix effectués par les programmeurs.
Pour le [0 à 1023] tu as raison, il ne faut pas confondre le nombre de combinaisons et la plus forte valeur rencontrée. Du reste j'ai bien vu quand j'ai fais afficher les valeurs issues du convertisseur A/N que la butée était bien 1023 et non 1024. Par contre, la façon dont fonctionne le compilateur C engendre bien ce "détail" de non homogénéité des variables. On peut forcer les calculs à une taille désirée, c'est ce que l'on nomme "le cast". Mais si tu ne le sais pas au départ, bonjour les problèmes de mise au point de ton programme.
Vas sur : http://forum.arduino.cc/index.php?topic=219848.0
J'ai détaillé un peu le résultat de ma petite étude.
Amicalement : Môamôa. :)

La sagesse est un trésor ... tellement bien caché.

Offline Fox-Terrier

  • League of
  • Legend
  • ******
  • Posts: 1426
  • Country: Switzerland ch
  • Karma: 28
  • :D
Reply #108 - 21 February 2014, 17:10:38
GLUPPPSSSsssss, mais je n'avais pas vu que j'étais PILEPOILE à 3000 !
Le "normalement" pour un compilateur, c'est du théorique. Un langage étant défini, chaque implémentation du compilateur va forcément avoir des spécificités en fonction des choix effectués par les programmeurs.
Pour le [0 à 1023] tu as raison, il ne faut pas confondre le nombre de combinaisons et la plus forte valeur rencontrée. Du reste j'ai bien vu quand j'ai fais afficher les valeurs issues du convertisseur A/N que la butée était bien 1023 et non 1024. Par contre, la façon dont fonctionne le compilateur C engendre bien ce "détail" de non homogénéité des variables. On peut forcer les calculs à une taille désirée, c'est ce que l'on nomme "le cast". Mais si tu ne le sais pas au départ, bonjour les problèmes de mise au point de ton programme.
Vas sur : http://forum.arduino.cc/index.php?topic=219848.0
J'ai détaillé un peu le résultat de ma petite étude.
Amicalement : Môamôa. :)

Ça complique drôlement la tâche, s'il faut connaître les spécificités du compilateur à l'avance ... C'est dommage je trouve, la conversion implicite lors des calculs est quand même plutôt fondamental dans le fonctionnement habituel du langage C ... Sur ce point les langages interprétés ont un avantage, mais ils sont souvent bien plus lent, ce qui est problématique s'ils sont utilisés pour du calcul ou un algorithme en boucle, sauf si c'est pour un programme qui converse avec l'utilisateur, ça ne pose pas trop de soucis


Offline nulentout

  • Legend
  • ******
  • Posts: 3356
  • Country: France fr
  • Karma: 242
Reply #109 - 21 February 2014, 18:22:22
Non, il ne faut pas dramatiser. Certe, quelques points sur Arduino sont déroutants au début, mais sur le forum en Français on trouve pratiquement toujours des "Arduinautes" qui te dépannent. Par ailleurs, sur le site d'Arduino il y a déjà beaucoup de documentation, alors l'un dans l'autre on y arrive.
De toute façon, quand on a programmé toute sa vie en binaire pur, puis en hexadécimal, puis en assembleur, alors des langages comme BASIC, PASCAL, PROLOG, C deviennent "un pur bonheur".

La sagesse est un trésor ... tellement bien caché.

Offline Mars Bleu

  • Hero Member
  • *****
  • Posts: 638
  • Karma: 33
Reply #110 - 21 February 2014, 21:05:38
J'ai regardé pour le pilote auto, mais vous êtes bien plus loin
que moi, les gars.
Dans les scripts Lua fournis dans le dossier "Script", on a un pilote auto
pour le DG dans  le script "aap".

Sinon, je m'escrime à faire marcher un accéléromètre, en fonction de
la variation de vitesse en x y z, du champ de pesanteur, et de la trajectoire
orbitale. Si mon modèle fonctionne pour un vol atmosphérique, et un vol
0G, il ne marche plus pour un vol  orbital. S'il marche en vol orbital (0G), ça
n'ira pas malgré tout pour un burn de changement de plan orbital.

@ Nulentout: wowowo! t'as programmé en binaire? Avec les cartes perforées?
Ça devait pas être facile.  :wor:


Offline Mars Bleu

  • Hero Member
  • *****
  • Posts: 638
  • Karma: 33
Reply #111 - 22 February 2014, 22:45:22
Dans mes calculs pour un accéléromètre, j'ai enfin compris pourquoi
je n'obtenais pas 0G une fois la mise en orbite achevée. Le vecteur
obtenu avec v:get_horizonairspeed() donne les vitesses en xyz par
rapport à la surface de la planète ou de la lune survolée. Or, pour estimer
l'accélération centripète donnée par v2/r, la valeur v doit
comprendre la vitesse orbitale, plus la vitesse de rotation de la planète
ou de la lune survolée multiplié par le cosinus de l'inclinaison de l'orbite
par rapport à l'équateur. Comme l'OAPI ne permet pas d'accéder au temps
de rotation sur 360° de ladite planète ou lune il faudrait aller chercher cette
donnée dans le fichier cfg de l'astre considéré.
Ça compliquerait pas mal le script, juste pour avoir le plaisir d'afficher les G
subis.

Je retourne donc à l'utilisation de registres à décalage couplés à la UNO, qui
vont gérer de multiples interrupteurs.


Offline Mars Bleu

  • Hero Member
  • *****
  • Posts: 638
  • Karma: 33
Reply #112 - 11 March 2014, 20:53:07
C'est pas un déterrage!
Juste que j'ai pas mal galéré pour gérer les registres à décalage Parallel Input Serial Output.
Il y avait de l'instabilité sur deux bits, lorsque l'on utilisait la fonction shiftIn d'Arduino. J'ai refait
les câblages, cherché les parasites, pensé à mettre des câbles blindés, rien n'y faisait, mes deux
derniers bits étaient instables.
Au final, j'ai remplacé :
Code: [Select]
Byte1=shiftIn(dataPin_in, clockPin_in, MSBFIRST);par:
Code: [Select]
for i=0;i<8;++i
{
Byte1=Byte1⎢(digitaRead(dataPin_in)<<i); //on pousse d'un rang les bits entrant
digitalWrite(clockin_in,HIGH);
digitalWrite(clockin_in,LOW);
}
et là, ça marche.
La suite est de déterminer quel switch est actionné, en tenant compte de la marche de l'APU
et des sécurité associées.
Je regarde déjà comment faire des câblages propres...

Mars Bleu


Offline nulentout

  • Legend
  • ******
  • Posts: 3356
  • Country: France fr
  • Karma: 242
Reply #113 - 19 March 2014, 08:28:04
Morbleu ... il cogite fort notre Mars Bleue ! :)

La sagesse est un trésor ... tellement bien caché.

Offline Mars Bleu

  • Hero Member
  • *****
  • Posts: 638
  • Karma: 33
Reply #114 - 19 March 2014, 21:03:48
Quote
Morbleu ... il cogite fort notre Mars Bleue ! :)

Merci, Nulentout!

Mes cogitations ont produit:
Code: [Select]
#include <HIDKeyboard.h>            //chargement de la bibliothèque. Attention, il faut au préalable
HIDKeyboard keyboard;              //flashouiller la Uno comme écrivait hysot dans la première
                                   //page de ce topic
const int dataPin_out=2;
const int latchPin_out=3;
const int clockPin_out=4;
const int dataPin_in=5;
const int latchPin_in=6;
const int clockPin_in=7;                  //donc 6 sorties utilisées sur la Uno pour 8 interrupteurs
byte switchStatus;                      //et 16 leds. Avec davantage de registres à décalage, on
byte previousswitchStatus=0;          // peut en mettre bien plus
byte i;
byte Byte1;
long switchtime;

void setup()
  {
    pinMode (dataPin_out,OUTPUT);
    pinMode (latchPin_out,OUTPUT);
    pinMode (clockPin_out,OUTPUT);
    pinMode (dataPin_in,INPUT);
    pinMode (latchPin_in,OUTPUT);
    pinMode (clockPin_in,OUTPUT);
    Serial.begin(9600);
    keyboard.begin();
    delay(2000);
  }

  void loop()
{
    digitalWrite(latchPin_in,LOW);   //mise en lecture
    delayMicroseconds(20);            //attendre 20 μsecondes
    digitalWrite(latchPin_in,HIGH); //bloquer la lecture
    for (i=0;i<8;++i){                                                                 //boucle qui va "pousser" les états
       switchStatus=switchStatus|(digitalRead(dataPin_in)<<i);                        //des switches dans la mémoire
       digitalWrite(clockPin_in,HIGH);                                                //switchStatus
       digitalWrite(clockPin_in,LOW);
       }

    if (switchStatus!=previousswitchStatus) // si un switch a été manoeuvré=>
    {

    switchtime=millis();
    if ((switchStatus^previousswitchStatus)==128) //manoeuvre APU
    {
    i=updateRegister(switchStatus);    // aller à fonction mise à jour des registres
    keyboard.pressKey(CTRL,'a');       // simuler un "CTRL a" pour toggler l'APU
    temporelease();                   // aller  à fonction touche relâchée
    }
    if (((switchStatus^previousswitchStatus)==64)&&((switchStatus&128)==128))
    { //baydoors
    i=updateRegister(switchStatus);
    keyboard.pressKey(CTRL,'u');
    temporelease();
    }
    if (((switchStatus^previousswitchStatus)==32)&&((switchStatus&128)==128))
    { //nosecone
    i=updateRegister(switchStatus);
    keyboard.pressKey(CTRL,'k');
    temporelease();
    }
    if (((switchStatus^previousswitchStatus)==16)&&((switchStatus&128)==128))
    { //outerdoor
    i=updateRegister(switchStatus);
    keyboard.pressKey(CTRL,'o');
    temporelease();
    }
    if (((switchStatus^previousswitchStatus)==8)&&((switchStatus&128)==128))
    { //innerdoor
    i=updateRegister(switchStatus);
    keyboard.pressKey(ALT,'o');
    temporelease();
    }
    if (((switchStatus^previousswitchStatus)==4)&&((switchStatus&128)==128))
    { //airbrake
    i=updateRegister(switchStatus);
    keyboard.pressKey(CTRL,'b');
    temporelease();
    }
    if (((switchStatus^previousswitchStatus)==2)&&((switchStatus&128)==128))
    { //cabin hatch
    i=updateRegister(switchStatus);
    keyboard.pressKey(CTRL,'Y');
    temporelease();
    }
    if (((switchStatus^previousswitchStatus)==1)&&((switchStatus&128)==128))
    { //radiator
    i=updateRegister(switchStatus);
    keyboard.pressKey(ALT,'r');
    temporelease();
    }
}// fin manoeuvre d'un switch
                                     
    previousswitchStatus=switchStatus;
    switchStatus=0;
    delay(150);
}
// sous programme de remplissage des registres
    int updateRegister(byte Byte1)
    {
    digitalWrite(latchPin_out,LOW); //début écriture dans les registres
    shiftOut(dataPin_out, clockPin_out, LSBFIRST, Byte1);
    shiftOut(dataPin_out, clockPin_out, LSBFIRST, Byte1); //on remplit les 2 registres
    digitalWrite(latchPin_out, HIGH);  // fin écriture dans les registres
    }
// sous programme de tempo/release d'une touche
    void temporelease()
    {
    delay(100);
    keyboard.releaseKey();
    delay(50);
    }


Mais il ne faut pas en rester là, car le sketch ne tient pas encore compte
des durées de mise en route de l'APU, et des temps de transit entre ouverture
et fermeture des différents auxiliaires. La mise au point est en cours.


Mars Bleu


Offline nulentout

  • Legend
  • ******
  • Posts: 3356
  • Country: France fr
  • Karma: 242
Reply #115 - 20 March 2014, 07:52:28
Coucou les Amis,
Toujours très naïf dans l'utilisation du langage C, je n'ai pas trouvé la signification de "^" que tu as employé dans tes expressions pour certains tests. Peux-tu préciser s'il te plait ?

La sagesse est un trésor ... tellement bien caché.

Offline Mars Bleu

  • Hero Member
  • *****
  • Posts: 638
  • Karma: 33
Reply #116 - 20 March 2014, 08:50:29
Je ne sais pas si ^ est utilisé en C.
Dans le langage Arduino, ^ est le "ou excusif" (XOR) qui me
permet de savoir s'il y a eu changement d'état du bit considéré.
C'est pour déterminer quel switch a été manoeuvré avec un
minimum de mémoire.

Mars Bleu


Offline nulentout

  • Legend
  • ******
  • Posts: 3356
  • Country: France fr
  • Karma: 242
Reply #117 - 20 March 2014, 11:12:37
Ben Voui, je me l'étai noté en plus !
OK, merci pour l'info.

La sagesse est un trésor ... tellement bien caché.

Offline Mars Bleu

  • Hero Member
  • *****
  • Posts: 638
  • Karma: 33
Reply #118 - 23 March 2014, 10:11:44
Pas mal de fil à retordre pour gérer le paramètre temps,
en particulier pour une manoeuvre de switch intervenant avant
la fin d'un déploy/retract d'un auxiliaire. Mais j'avance...


Offline jacquesmomo

  • Le budget !!!
  • Legend
  • ******
  • Posts: 7408
  • Country: France fr
  • Karma: 598
  • Plus on rate, plus on a de chances de réussir !..
Reply #119 - 23 March 2014, 17:05:06
Juste en passant, comme ça (ça peut être utile)

Dans le dernier n° de MicroSim, il y a l'interview du m'sieur qui a fait un cockpit pour FlightSim
(celui qu'on voit dans la pub pour gou-gueule)
C'est assez intéressant... et je suis sûr qu'il peut être de bon conseil...



Mes add-ons sont là !

Offline antoo

  • Legend
  • ******
  • Posts: 3659
  • Country: France fr
  • Karma: 179
  • MSFS ❤️
Reply #120 - 23 March 2014, 17:32:08
Ça va être grandiose!

---------------------------------------------------------------------------------------------------
"ET C´EST PARTI!!" Youri Gagarine au lancement de vostok 1 le 12 avril 1961

Offline Mars Bleu

  • Hero Member
  • *****
  • Posts: 638
  • Karma: 33
Reply #121 - 23 March 2014, 19:15:59
Faut que je trouve ce journal, ça peut me donner des idées.
Merci, Jacquesmomo, pour cette info!


Offline jacquesmomo

  • Le budget !!!
  • Legend
  • ******
  • Posts: 7408
  • Country: France fr
  • Karma: 598
  • Plus on rate, plus on a de chances de réussir !..
Reply #122 - 23 March 2014, 19:21:11
Faut que je trouve ce journal, ça peut me donner des idées.
Merci, Jacquesmomo, pour cette info!
De rien ;)

C'est le n° 242 du mois de mars

Mes add-ons sont là !

Offline Mars Bleu

  • Hero Member
  • *****
  • Posts: 638
  • Karma: 33
Reply #123 - 23 April 2014, 19:45:01
Salut, tout le monde,
J'ai passé pas mal de temps dans la doc, noirci des pages d'algorithmes,
affronté les insanités que me recrachait le compilateur, corrigé, renoirci
des pages d’algorithmes, et j'ai fini par obtenir quelque chose qui fonctionne
à peu près.
L'objectif poursuivi était donc d'envoyer des raccourcis clavier pour commander
les auxiliaires d'un Xr2 tels le train d'atterrissage, les scramdoors, etc...
Ça, j'y étais arrivé (cf #114).
La suite était d'associer des lumineux aux positions des auxiliaires:
                          -vert fixe=>auxiliaire rentré/porte fermée
                          -vert clignotant=>auxiliaire en train de rentrer/fermer
                          -jaune fixe=>auxiliaire sorti/ouvert
                          -jaune clignotant=>auxiliaire en train de sortir/ouvrir
J'ai choisi de confier la fonction clignotement à un dispositif extérieur à la Uno,
le reste étant déjà assez compliqué comme ça. Quelques porte NAND et une capa
font un circuit oscillant qui fera clignoter la LED considérée par l'intermédiaire de
quelques portes logiques.
Il fallait bien entendu subordonner le transit à l'ouverture ou a la fermeture à la marche
de l'APU.
Voici le code, qui est encore perfectible:
Code: [Select]
#include <HIDKeyboard.h>
HIDKeyboard keyboard;
//Version pour l'APU, baydoors et nosecone
        //la gestion du transit subordonnée à la marche de l'APU semble fonctionnel pour nosecone //
const int dataPin_out=2; //vérifier pour baydoors, et le reste
const int latchPin_out=3;
const int clockPin_out=4;
const int dataPin_in=5;
const int latchPin_in=6;
const int clockPin_in=7;
byte switchStatus;
byte previousswitchStatus=0;
byte i;
byte bit_rank;
byte transitStatus;
byte greenlit;
byte greenblink;
byte yellowlit;
byte yellowblink;
int transitTime [2][8]={
  {320,66,33,100,100,200,330,25},       //durée de transit en dixièmes de secondes
  {0,0,0,0,0,0,0,0}
};
int transitDelay [8]={0,0,0,0,0,0,0,0};
unsigned long switchTime[8]={0,0,0,0,0,0,0,0};
unsigned long deltaTime[8]={0,0,0,0,0,0,0,0};
unsigned long timeSwitch;
unsigned long deltat;


void setup()
  {
    pinMode (dataPin_out,OUTPUT);
    pinMode (latchPin_out,OUTPUT);
    pinMode (clockPin_out,OUTPUT);
    pinMode (dataPin_in,INPUT);
    pinMode (latchPin_in,OUTPUT);
    pinMode (clockPin_in,OUTPUT);
    Serial.begin(9600);
    keyboard.begin();
    delay(2000);
  }

  void loop()
{
    digitalWrite(latchPin_in,LOW);//latch à LOW pour lire l'état des switches)
    delayMicroseconds(20);
    digitalWrite(latchPin_in,HIGH);//latch à HIGH, verrouillage
    for (i=0;i<8;++i){ //on "pousse" 8 fois les valeurs lues dans la mémoire switchStatus; c'est le shiftIn
       switchStatus=switchStatus|(digitalRead(dataPin_in)<<i);
       digitalWrite(clockPin_in,HIGH);
       digitalWrite(clockPin_in,LOW);
       }

    if (switchStatus!=previousswitchStatus) // si un switch a été manoeuvré=>
    {
   
    if ((switchStatus^previousswitchStatus)==128) //manoeuvre APU
    {
    //keyboard.pressKey(CTRL,'a');    pour l'instant, raccourci clavier inactivé durant la mise au point
    //temporelease();
    bit_rank=7;                  //transmission du rang de bit à traiter
    timeSwitch=switchTime[bit_rank];
    LEDmanagement1(bit_rank, timeSwitch);     //appel fonction de gestion des LED avec le bit 8 correspondant à l'APU
    switchTime[bit_rank]=millis();
    }
    if (((switchStatus^previousswitchStatus)==64)&&((switchStatus&128)==128))
    { //baydoors
    //keyboard.pressKey(CTRL,'u');
    //temporelease();
    bit_rank=6;                  //transmission du rang de bit à traiter
    timeSwitch=switchTime[bit_rank];
    LEDmanagement1(bit_rank, timeSwitch);     //appel fonction de gestion des LED avec le bit 7 correspondant à baydoors
    switchTime[bit_rank]=millis();
    }
    if (((switchStatus^previousswitchStatus)==32)&&((switchStatus&128)==128))
    { //nosecone
    //keyboard.pressKey(CTRL,'k');
    //temporelease();
    bit_rank=5;                  //transmission du rang de bit à traiter
    timeSwitch=switchTime[bit_rank];
    LEDmanagement1(bit_rank, timeSwitch);     //appel fonction de gestion des LED avec le bit 6 correspondant à nosecone
    switchTime[bit_rank]=millis();
    }
    if (((switchStatus^previousswitchStatus)==16)&&((switchStatus&128)==128))
    { //outerdoor
    //i=updateRegister(switchStatus);
    keyboard.pressKey(CTRL,'o');
    temporelease();
    }
    if (((switchStatus^previousswitchStatus)==8)&&((switchStatus&128)==128))
    { //innerdoor
    //i=updateRegister(switchStatus);
    keyboard.pressKey(ALT,'o');
    temporelease();
    }
    if (((switchStatus^previousswitchStatus)==4)&&((switchStatus&128)==128))
    { //airbrake
    //i=updateRegister(switchStatus);
    keyboard.pressKey(CTRL,'b');
    temporelease();
    }
    if (((switchStatus^previousswitchStatus)==2)&&((switchStatus&128)==128))
    { //cabin hatch
    //i=updateRegister(switchStatus);
    keyboard.pressKey(CTRL,'Y');
    temporelease();
    }
    if (((switchStatus^previousswitchStatus)==1)&&((switchStatus&128)==128))
     { //radiator
    //i=updateRegister(switchStatus);
    keyboard.pressKey(ALT,'r');
    temporelease();
    }
}// fin manoeuvre d'un switch
    // Début de gestion des registres lié au passage du temps.
    bit_rank=7;                  //transmission du rang de bit
    timeSwitch=switchTime[bit_rank];//envoi de switchTime[bit_rank]
    LEDmanagement2(bit_rank,timeSwitch);     //appel fonction de gestion des LED avec le bit 8 correspondant à l'APU
   
    bit_rank=6;                  //transmission du rang de bit
    deltat=millis()-deltaTime[bit_rank];//calcul du temps écoulé depuis dernier passage
    deltaTime[bit_rank]=millis();        //mise à jour de deltaTime[bit_rank]
    switchTime[bit_rank]=switchTime[bit_rank]+(deltat*(yellowblink&64)==0); //switchTime rendu "glissant" si APU non en fonction
    timeSwitch=switchTime[bit_rank];//envoi de switchTime[bit_rank]
    LEDmanagement2(bit_rank,timeSwitch);     //appel fonction de gestion des LED avec le bit 7 correspondant à baydoors
   
    bit_rank=5;                  //transmission du rang de bit
    deltat=millis()-deltaTime[bit_rank];//calcul du temps écoulé depuis dernier passage
    deltaTime[bit_rank]=millis();        //mise à jour de deltaTime[bit_rank]
    switchTime[bit_rank]=switchTime[bit_rank]+(deltat*((yellowblink&64)==0)); //switchTime rendu "glissant" si APU non en fonction
    timeSwitch=switchTime[bit_rank];//envoi de switchTime[bit_rank]
    LEDmanagement2(bit_rank,timeSwitch);     //appel fonction de gestion des LED avec le bit 6 correspondant à nosecone
   
    // Fin de gestion des registres lié au passage du temps.
    previousswitchStatus=switchStatus;
    switchStatus=0;
    delay(150);
} //fin loop
// sous programme de remplissage des registres
    int updateRegister(byte Byte1, byte Byte2, byte Byte3, byte Byte4)
    {
    digitalWrite(latchPin_out,LOW); //d√©but √©criture dans les registres
    shiftOut(dataPin_out, clockPin_out, LSBFIRST, Byte2);
    shiftOut(dataPin_out, clockPin_out, LSBFIRST, Byte4); //on remplit les 2 registres
    digitalWrite(latchPin_out, HIGH);  // fin √©criture dans les registres
    }
// sous programme de tempo/release d'une touche
    void temporelease()
    {
    delay(100);
    keyboard.releaseKey();
    delay(50);
    }
// sous programme de gestion des LEDs lié à un mouvement de switch
int LEDmanagement1(byte bit_rank, unsigned long SwitchTime)
{
         //switchTime[bit_rank]=SwitchTime;                          //transmission du temps de mvtswitch à switchTime[bit_rank]
         transitTime[1][bit_rank]=((millis()-switchTime[bit_rank])/100) ;  //calcul temps écoulé depuis dernier
            //mouvement switch  en 1/10° de sec. Calcul au cas où le transit serait encore en cours

if ((transitStatus&(1<<bit_rank))==0)
     {
transitDelay[bit_rank]=transitTime[0][bit_rank] ;   //réglage du temps de transit
     }

if ((transitStatus&(1<<bit_rank))==(1<<bit_rank))                // si transit encore en cours
              {
transitDelay[bit_rank]=transitTime[1][bit_rank] ; //réglage du temps de transit
            }
bitWrite(transitStatus, bit_rank,HIGH) ; // positionne le transit pour l'APU

  if ((switchStatus&(1<<bit_rank))==(1<<bit_rank))       //si démarrage en cours
     {
//bitWrite(greenlit, bit_rank,LOW) ; //|
//bitWrite(greenblink, bit_rank,LOW) ; //| traitement des values qui seront
//bitWrite(yellowlit, bit_rank,LOW) ; //| envoyées aux registres
//bitWrite(yellowblink, bit_rank,HIGH) ; //|
bitWrite(greenblink, bit_rank-1,LOW) ; //|
bitWrite(greenblink, bit_rank,LOW) ; //| traitement des values qui seront
bitWrite(yellowblink, bit_rank-1,LOW) ; //| envoyées aux registres
bitWrite(yellowblink, bit_rank,HIGH) ; //|(lignes actives pour le montage actuel)
      }

if ((switchStatus&(1<<bit_rank))==0)       //si arrêt en cours
     {
//bitWrite(greenlit, bit_rank,LOW) ; //|
//bitWrite(greenblink, bit_rank,HIGH) ; //| traitement des values qui seront
//bitWrite(yellowlit, bit_rank,LOW) ; //| envoyées aux registres
//bitWrite(yellowblink, bit_rank,LOW) ; //|
bitWrite(greenblink, bit_rank-1,LOW) ; //|
bitWrite(greenblink, bit_rank,HIGH) ; //| traitement des values qui seront
bitWrite(yellowblink, bit_rank-1,LOW) ; //| envoyées aux registres
bitWrite(yellowblink, bit_rank,LOW) ; //|(lignes actives pour le montage actuel)
      }

updateRegister(greenlit, greenblink, yellowlit, yellowblink);    //envoi aux registres
}
// fin sous programme LEDmanagement1 (gestion des LEDs lié à un mouvement de switch)

//sous programme de gestion des LEDs lié au temps
int LEDmanagement2(byte bit_rank,long SwitchTime)
{

        // ligne du dessous : si on est en transit depuis un temps supérieur √† transitDelay...
       
if (((transitStatus&(1<<bit_rank))==(1<<bit_rank))&&(((millis()-SwitchTime)/100)>transitDelay[bit_rank]))
        {
 
          bitWrite(transitStatus, bit_rank,LOW) ; //remise à 0 du transit APU
           if ((switchStatus&(1<<bit_rank))==(1<<bit_rank)) // si démarrage terminé
  {
//bitWrite(greenlit, bit_rank,LOW) ; //|
//bitWrite(greenblink, bit_rank,LOW) ; //| traitement des values qui seront
//bitWrite(yellowlit, bit_rank, HIGH) ; //| envoyées aux registres
//bitWrite(yellowblink, bit_rank,LOW) ; //|
bitWrite(greenblink, bit_rank-1,LOW) ; //|
bitWrite(greenblink, bit_rank,LOW) ; //| traitement des values qui seront
bitWrite(yellowblink, bit_rank-1, HIGH) ; //| envoyées aux registres
bitWrite(yellowblink, bit_rank,LOW) ; //|(lignes actives pour le montage actuel)
  }

        if ((switchStatus&(1<<bit_rank))==0) // si arrêt terminé
  {
//bitWrite(greenlit, bit_rank,HIGH) ; //|
//bitWrite(greenblink, bit_rank,LOW) ; //| traitement des values qui seront
//bitWrite(yellowlit, bit_rank,LOW) ; //| envoyées aux registres
//bitWrite(yellowblink, bit_rank,LOW) ; //|
bitWrite(greenblink, bit_rank-1,HIGH) ; //|
bitWrite(greenblink, bit_rank,LOW) ; //| traitement des values qui seront
bitWrite(yellowblink, bit_rank-1,LOW) ; //| envoyées aux registres
bitWrite(yellowblink, bit_rank,LOW) ; //|(lignes actives pour le montage actuel)
  }
          updateRegister(greenlit, greenblink, yellowlit, yellowblink);    //envoi aux registres

    }

}//fin LEDmanagement2 (automatisme lié au temps écoulé)

Déjà, je ressens le besoin d'une synchro avec l'état du cockpit. Afin d'assurer une meilleure
visibilité des switches à aligner avec l'état logique du cockpit, je pense ajouter une LED rouge
de discordance. Normalement, une comparaison avec l'état du switch et l'état des LEDs jaunes
et vertes devrait fonctionner.

Voilà, voilà. Si des habitués du C pouvaient commenter mon code, et me donner des pistes
pour l'optimiser, je serai tout à fait réceptif.
Allez, j'y retourne.

Mars Bleu


Offline nulentout

  • Legend
  • ******
  • Posts: 3356
  • Country: France fr
  • Karma: 242
Reply #124 - 24 April 2014, 08:04:15
Coucou les copains,
En ce moment, je suis toujours en train de trifouiller plein plein de code sur Arduino pour apprendre le langage C.
Dans le listage de ton post, tu as :
const int dataPin_out=2;
Pourquoi utilises-tu un int au lieu d'un byte ?
Personnellement j'aurais préféré :

const byte dataPin_out=2; ou
#define dataPin_out 2

C'est juste pour mieux cerner les subtilités de ce langage.

La sagesse est un trésor ... tellement bien caché.