Dan's Orbiter page

Orbiter Francophone => Orbiter Francophone => Topic started by: Mars Bleu on 08 November 2016, 08:44:24

Title: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 08 November 2016, 08:44:24

L’idée de construire un simucockpit pour mieux profiter d’Orbiter est présente dans ma tête depuis déjà un bon moment. J’avais les connaissances en électricité, en électronique, en dépannage, et en programmation pour commencer à m’aventurer dans ces terrains là. Il fallait seulement se lancer, ce que j’ai fini par faire depuis la fin de 2013.

LA GENÈSE:

J’ai commencé par rechercher plein de doc sur le Net, tant sur les simpits FSX que sur ceux dédiés à Orbiter. Sans idée préconçue, j’ai même envisagé l’utilisation de cartes SIOC dédiées à Flight Simulator.

J’ai suivi les travaux d’Antoo et de son frère; ils m’ont fait part de leur expérience qui a alimenté ma réflexion. Mais je voulais aller plus loin que les raccourcis clavier, et utiliser d’autres fonctions permettant d’afficher des valeurs telles que le cap, l’altitude, les fréquences radio, les jauges de carburant, etc… Le problème de la synchronisation des commutateurs du cockpit avec le scénario chargé au démarrage d’Orbiter était aussi à résoudre.

            La lecture des blogs consacrés au sujet des simpits montre que la concrétisation d’un tel projet est rare.

PRINCIPES GÉNÉRAUX:

Je pense que pour réussir, il faut poser des jalons :
                                                    -étudier la faisabilité
                                                    -faire quelques essais sur des fonctions principales
                                                    -passer à la construction proprement dite
                                                    -rester modulaire

Pour garder le fil de mes idées, j'utilise deux cahiers; l'un pour la partie programmation, et l'autre pour la construction des cartes électroniques associées à la carte Arduino.


Avant d’entamer un petit historique de mes travaux, je tiens à dire que les solutions que j'ai choisies sont possibles parmi d’autres. Ce ne sont que des indications qui pourront peut-être donner des idées à d’autres orbinautes. Aux yeux de codeurs avertis, j'aurai peut-être produit du vilain code (mais qui en principe doit fonctionner). C'est parfois intentionnel, car ça a été la seule façon que j'ai trouvée pour pouvoir m'en sortir.
La maître mot est compacité du code: il y peu de place dans nos microcontrôleurs préférés et les fréquences d'horloge ne sont pas très rapides.

 Mes premières lignes de code remontent il y a déjà bien longtemps, au temps du BASIC spaghetti, avec des numéros de ligne et des GOTO partout.

J'aurais bien aimé construire un vrai poste de pilotage déménageable, mais faute de place disponible, je pense m'orienter comme Hysot vers la réalisation d'un tableau de commande plus compact et plus léger.

LES PRINCIPAUX CHALLENGES:

Afin de parvenir à mes fins, plusieurs challenges se présentaient(liste non exhaustive):
                                 * Lire de manière automatique un fichier scn
                                 * Envoyer à Orbiter une commande simple avec la UNO
                                 * Multiplier les entrées/sorties sur la UNO
                                 * Commander des leds branchées sur la UNO au moyen d'un script Lua
                                 * Construction des modules Parallel Input Serial Output (PISO)
                                 * Construction des modules Serial Input Parallel Output (SIPO)
                                 * Construction des cartes de servitudes (Alims électriques, support de la UNO)
                                 * Gestion des leds associées aux auxiliaires APU
                                 * Gestion des signalisations liées à l'équilibre de l'engin (gimbal, gravityshift)

                  Il y aura d'autres challenges, mais ceux cités ci-dessus ont été déjà réussis.

                                                 A bientôt pour le premier challenge.


Title: Re: Le tableau de commande de Mars Bleu
Post by: nerofox on 08 November 2016, 13:19:25
Génial je ne serai pas seul à me lancer dans cette aventure  :beer:
J'ai hate de voir les premières photos ou éventuel croquis, schéma ou autre de ce que tu compte mettre en place  :badfinger:

J'ai plus qu'envisager d'utiliser lua pour la programmation j'en avais même parlé sur mon topic de tableau de bord, en revanche pour ma part le programme peut être assez conséquent et donc il serait préférable d'utiliser un langage plus modulable et qui s'organise de meilleur façon (le C++ notamment) c'est juste plus complexe a mettre en œuvre  :badsmile:

N'hésite pas a échanger sur la partie logiciel si tu a des questions ou autre  :wonder:

Good luck !
Title: Re: Le tableau de commande de Mars Bleu
Post by: antoo on 08 November 2016, 15:12:51
Trop cool ! Bienvenue au club :beer: !

Hâte de voir l'avancement de ton projet.

A+
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 08 November 2016, 17:38:27
Merci, les gars. C'est en échangeant les idées qu'on avance le mieux.

Pour les photos et schémas, ne vous inquiétez pas, ça viendra. Faudra que je les uploade.
Title: Re: Le tableau de commande de Mars Bleu
Post by: nulentout on 10 November 2016, 11:46:22
Coucou les copains,
Si je devais me refaire un tableau de bord, je pense que j'opterais pour plusieurs cartes Arduino. Vu le coût de quelques Euros d'une carte Nano qui a autant, sinon plus de possibilités que la Uno, en introduire plusieurs augmente le nombre d'entrées/Sorties, d'entrées analogiques etc. De plus, le logiciel réparti en plusieurs modules sera plus facile à dominer. Il ne faut pas oublier que certaines commandes sont prioritaires et doivent être prises en compte immédiatement. Par exemple une carte s'occupe en priorité des commandes de pilotage. Avec six entrées analogiques on peut déjà gérer les poussées principales. Mais pour les RCS une deuxième sera certainement la bienvenue. Une troisième carte prendrait en charge les requêtes moins urgentes, par exemple les inverseurs, les boutons poussoir etc. En multiplexant on peut facilement gérer 8 x 8 boutons, ce qui ouvre pas mal de possibilités. Sans compter que les deux premières cartes qui assurent les commandes de vol peuvent aussi s'occuper des afficheurs, de diverses LEDs etc.
Bref, avant de foncer, il me semble salutaire de réfléchir assez loin à l'architecture électronique future, et ne pas oublier de diviser les difficultés pour vaincre !
Quoi qu'il en soit, cogitez, percez, soudez ... il en restera forcément ... un superbe vaisseau !
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 12 November 2016, 12:51:37
Tout à fait d'accord avec toi, ô Nulentout. Dans l'avancement de mon projet,
je tiens à rester modulaire.
Pour l'instant, mon sketch Arduino tient dans moins de 10 Ko, alors qu'il gère pour l'instant
20 switches ou BP, et 100 lumineux. Ce qui fait qu'une UNO ou Léonardo convient encore.  Je ne sais pas combien de temps quelle taille de simpit ça pourra gérer.
Mais la DUE me semble indiquée pour amplifier un projet déjà devenu imposant.

Tu soulèves un point intéressant en parlant de priorité de certaine commandes par rapport à d'autres.
Je me demande pour l'instant comment on peut programmer des priorités. Je sais que le soft du LEM
avait été basé sur cette gestion des priorités, ce qui leur avait permis de se poser en sécurité
malgré l'avalanche de "stack overflow".
Title: Re: Le tableau de commande de Mars Bleu
Post by: nulentout on 15 November 2016, 11:13:44
Coucou les copains,
Ben ... pour gérer des priorités deux approches sont envisageables :
Confier les plus hautes priorités à un microcontrôleur qui s’en occupe en temps réel et « ne fait que ça ».
Charger un processeur de tout, mais les actions prioritaires sont traitées par interruptions.
L’ATmega328 se prête bien aux interruptions, mais il faut te « cogner » la théorie pour pouvoir mettre en pratique.  :wall:
 
Title: Re: Le tableau de commande de Mars Bleu
Post by: Bibi Uncle on 15 November 2016, 17:57:45
Pour une gestion des priorités efficaces, le mieux est de quitter le nid douillet de l'environnement Arduino, et de faire du "bare-metal" programming avec un RTOS. Ceci va te permettre d'avoir plusieurs tâches qui s'exécutent en même temps, d'avoir des tâches qui se réveillent par interruption et, si programmé correctement, d'avoir un environnement déterministe. C'est beaucoup plus complexe à programmer, mais ça peut être vraiment plus efficace à l'exécution.

Je te suggère de regarder FreeRTOS et TI-RTOS. Il y a aussi quelques projets de librairies pour simplifier la programmation bare-metal, notamment xpcc qui est une jolie librairie écrite en C++11.
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 15 November 2016, 18:31:07
Hou là!! Dans mon cours déjà lointain sur les microprocesseurs, ce que j'avais trouvé
le plus difficile était bien les interruptions.
Quant au "bare metal", alors là, je n'en suis pas là. Ça se programme en C++, ce truc là?

Disons que, pour l'instant, là où j'en suis, les réactions de mon système se font sans délai.
Mais je jetterai un œil là dessus, car c'était quelque chose dont j'ignorais l'existence...
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 20 November 2016, 20:43:07
Allez, on attaque:
                                      PREMIER CHALLENGE: Lire un fichier SCN


Dans un premier temps, je voulais savoir s'il était possible pour moi de récupérer des données d'un fichier SCN, de façon à pouvoir les charger dans le simpit. Le moyen d'y arriver est bien entendu d'utiliser la console Lua d'Orbiter.

Elle s’obtient avec F4, puis bouton « Custom ». On sélectionne « Lua console window », et la console va s’ouvrir. A partir de là, on peut entrer des lignes de commande. Par exemple, pour l’altitude :
         
Code: [Select]
Term.out(oapi.get_altitude()) va donner l’altitude du vaisseau
Pour d’autres valeurs, il faut d’abord avoir le handle du vaisseau. Il faut faire en premier :
         
Code: [Select]
v=vessel.get_focusinterface()Puis, si on veut connaître par exemple l’état des RCS :
         
Code: [Select]
term.out(v :get_rcsmode()) va renvoyer 0, 1 ou 2 selon la position du commutateur RCS.
Dans ce domaine, j’ai bidouillé pour connaître la valeur des jauges de carburant (Main Fuel, RCS, SCRAM Fuel). En regardant la doc, j’ai pu trouver tout ce que je cherchais.

Après cette première prise de contact avec la console LUA, j’ai éprouvé le besoin de lancer un script Lua depuis un scénario. Comme je ne savais pas trop comment faire, j’ai regardé le scénario "Atlantis/launch".



Au début du scénario, on a:
Code: [Select]
BEGIN ENVIRONMENT
System Sol
Date MJD
Script Demos/Atmautopilot
END ENVIRONMENT

Donc, on peut appeler un script Lua, en l'occurrence "Atmautopilot" à exécuter au lancement du scénario. C'est parfait pour lire l'état  du vaisseau, à condition de pouvoir ouvrir et lire ce dont on a besoin dans le fichier SCN. Mais comment faire?

Dr Spock m'a donné un début de solution en écrivant un script Lua pour des HiScores dans le cadre de Orbiter Challenge.

Code: [Select]
Data.path='Script/Challenges/Challenge1.dat'
max_score=10

slist=hscore_read(data_path, max_score)

function hscore_read(file, n)
local slist={}         
local f=io.open(file, "r")
if f~=nil then
for i=1, n do
local t=f:read()
if t==nil then break end
local name, fuel
_,_,name, fuel=string.find(t, "(._):(.+)")
slist[i]={name, to number(fuel)}
end
f:close()
end
return slist
     end

En cherchant à afficher en surimpression à l'écran les valeurs liées à mon vaisseau, je finis par avoir:
Code: [Select]
-- ******************************************
-- ********read number lines from scn file***
-- ******************************************
function line_read (file)
    number_lines=0
    local g = io.open(file,"r")
    if g ~= nil then
        repeat
            t = g:read()
            number_lines=number_lines+1
        until t == nil
    g:close()
    end
end
-- *****************************************
-- *********end function line_read *********
-- *****************************************
Cette première fonction a pour but de connaître le nombre de lignes à lire.

Ensuite,
Code: [Select]
-- *******************************************
-- ********load lines from scn file***********
-- *******************************************
function load_scnfile (file,n)
    slist={}
    local f = io.open(file,"r")
    if f ~= nil then
        for i=1,n do
            t = f:read()
            if t == nil then break end
            slist[i]=t
        end     
        f:close()
    end
    return slist
end
-- ******************************************
-- *********end function load_scnfile *******
-- ******************************************
Celle-ci va remplir le tableau slist[] ligne par ligne avec le contenu du fichier SCN.

Une fois le tableau chargé, on veut connaître les valeurs concernant les auxiliaires du vaisseau. Chacun aura compris qu'on parle ici du Xr2 Ravenstar.
Code: [Select]
-- *******************************************
-- ***********load ship status****************
-- *******************************************
function load_xr2_status (pattern)
    for i=1,number_lines-1 do
       s1 = slist[i]
       _,_,name,classname = string.find (s1, "(.-):(.+)")
       if (classname=='XR2Ravenstar') and (ship=='XR2Ravenstar') then
           name_ship=name
           for j=i, number_lines-1 do
               if string.match (slist[j], 'NOSECONE')~=nil then
                   _,_,_,status,level = string.find(slist[j],"(.+) (.+) (.+)")
                   note:set_text('NOSECONE=>'..status..' '..level)
                   proc.wait_sysdt(0.41)
               elseif string.match (slist[j], 'GEAR')~=nil then
                   _,_,_,status,level = string.find(slist[j],"(.+) (.+) (.+)")
                    note:set_text('GEAR=>'..status..' '..level)
                   proc.wait_sysdt(0.41)
               elseif string.match (slist[j], 'RADIATOR')~=nil then
                   _,_,_,status,level = string.find(slist[j],"(.+) (.+) (.+)")
                   note:set_text('RADIATOR=>'..status..' '..level)
                   proc.wait_sysdt(0.41)
               elseif string.match (slist[j], 'HATCH')~=nil then
                   _,_,_,status,level = string.find(slist[j],"(.+) (.+) (.+)")
                   note:set_text('HATCH=>'..status..' '..level)
    elseif slist[j]=='END' then
                   flag_out=1
                   break
               end                     
           end
       

Cette partie de script lit les lignes du fichier SCN et extrait les valeurs associées au nosecone, gear, radiator, hatch. Status contient une valeur comprise entre 0 et 3 (0 pour replié; 1 pour déployé; 2 pour en repli; 3 pour en déploiement), tandis que level contient une valeur à 4 chiffres après la virgule comprise entre 0 et 1. Les valeurs extrêmes de level sont 0 pour replié, 1 pour déployé. Ce sont ces valeurs qui devront ensuite être transmises à la Uno Arduino afin de synchroniser le cockpit sur l'état du Xr2 dans le SCN. Mais nous n'y sommes pas encore. Pour l'instant, le script ne fait qu'afficher ces valeurs à l'écran, une fois le scénario lancé.

J'ai aussi vérifié qu'il était possible d'afficher à l'écran les valeurs de réservoir et celles concernant d'éventuels conteneurs de cargaison chargés dans la soute.
Il fallait aussi envisager le cas où on aurait deux Xr2 dans le scénario, et ne se charger que du vaisseau à bord duquel on se trouve.

Ces trois fonctions(compter le nombre de lignes du scn, charger ces lignes dans un tableau, lire les valeurs qu'on y trouve) sont appelées par ce qui suit:
Code: [Select]
--****************************************************************************
-- ********** begin program ************************* begin program *********
--*****************************************************************************
note = oapi.create_annotation()
note:set_pos (0.35,0.1,0.8,0.95)
note:set_colour ({r=0.9,g=0.5,b=0.2})

data_path = 'Scenarios/(Current state).scn'
intro = 'Load scn data'

note:set_text(intro)
proc.wait_sysdt(0.5)

note:set_colour ({r=0.9,g=0.0,b=0.0})

v=vessel.get_focusinterface()
ship=v:get_classname()
name_ship_focused=v:get_name()


-- ******************************************************
-- ***********begin call functions for scn file**********
-- ******************************************************

sfirst = line_read (data_path)

slist = load_file (data_path,number_lines)


if  ship=='XR2Ravenstar' then
    lstatus = load_xr2_status (ship)
elseif ship=='Xr5Vanguard' then
    note:set_text('Toward function loop load of XR5Vanguard')
    proc.wait_sysdt(2.01)
elseif ship=='ShuttleA' then
    note:set_text('Toward function loop load of ShuttleA')
    proc.wait_sysdt(2.01)
else
    note:set_text('vessel not implemented, simpit not activated')
    proc.wait_sysdt(2.01)
end
-- ******************************************************
-- ************ end call functions for scn file**********
-- ******************************************************
note:set_text('End of program')
proc.wait_sysdt(1)
note:set_text('  ')
proc.wait_sysdt(1)

J'ai arrangé quelque chose de façon à ce qu'on puisse avoir autant de classe de vaisseau qu'on veut. Ca dépendra ensuite du simpit qu'on a construit.

Ces quelques lignes de script Lua ont validé mon idée qu'il est possible d'aller chercher des données dans le fichier SCN, de façon à pouvoir les envoyer dans le simpit. Ce dernier pourra donc être synchronisé avec le scénario chargé au préalable.

Le prochain challenge consistera en l'envoi d'une commande simple par la UNO à Orbiter.
Title: Re: Le tableau de commande de Mars Bleu
Post by: nerofox on 21 November 2016, 18:30:41
excellente infos
lua est un langage de script avant tout il existe des librairies pour tout  :badfinger:
cherche du coté luars232 pour la communication série avec une Arduino

bon courage pour ta recherche :)
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 23 November 2016, 18:06:21
Oui, Luars232 est bien utile. Il faut simplement mettre la dll au bon endroit.
J'avance bien dans mes travaux. Je sors d'une phase programmation et
débogage intensive pour attaquer une nouvelle phase de construction.
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 05 December 2016, 18:22:51
DEUXIÈME CHALLENGE: faire envoyer à la Arduino UNO une commande simple à ORBITER



La deuxième chose à valider est l'utilisation d'une carte Arduino Uno configurée en clavier afin d'envoyer des caractères en fonction d'un switch manœuvré. (Par exemple "G" pour manœuvrer le train d'atterrissage.)
Les posts de Hysot ont été très, très utiles pour me guider.
Pour cela, voir à:  http://orbiter.dansteph.com/forum/index.php?topic=12877.0 (http://orbiter.dansteph.com/forum/index.php?topic=12877.0)


J'ai effectué ma première commande de matériel, comprenant bien sûr une UNO. J'avais commandé un kit de base (quelques résistances, condensateurs, leds, etc…)
L'idée est que la manœuvre du switch va ouvrir ou fermer un circuit électrique. Selon que le circuit est ouvert ou fermé, on applique ou non Vcc aux bornes de la résistance de 10KΩ. Il suffit de connecter la borne où Vcc est appliquée à un pin  configuré en entrée de la UNO.

On commence simple...

(http://img4.hostingpics.net/pics/486296Intergear.jpg)

Dans la UNO, on charge un sketch qui enverra le caractère "g" à chaque changement d'état du switch:
Code: [Select]
#include <HIDKeyboard.h>                    // Inclut la librairie HIDKeyboard au programme

HIDKeyboard keyboard;                       // Initialise la librairie

int Buttonpin = 7;                          //Le bouton est branche sur la pin 7
int ButtonState = 0;                        //L'etat du bouton: ON (HIGH) ou OFF (HIGH). On lui donne pour le moment la valeur 0
int PreviousButtonState = 0;                //Le precedent etat du bouton

void setup()
{
  pinMode(Buttonpin, INPUT);                //On initialise la pin 7 comme une entree
 
  keyboard.begin();                         // Commence la communication
  delay(2000);                              // Attend que le peripherique soit reconnue comme un clavier
}

void loop()
{
  ButtonState = digitalRead(Buttonpin);     //On lit l'etat de la pin 7 et on le stocke dans la variable ButtonState
 
  if (ButtonState != PreviousButtonState)   //On compare les deux états. Si ils différents, la condition est validée et on écrit la lettre A
  {
    PreviousButtonState = ButtonState;      //On enregistre le nouvel état du bouton dans la variable PreviousButtonState pour
                                                             //la prochaine boucle.
    keyboard.pressKey('g');
    delay(100);
    keyboard.releaseKey();
    delay(50);
  }
}

Ensuite, il faut configurer la UNO en Keyboard selon la procédure indiquée par Hysot.

Il n'y a plus qu'à lancer Orbiter avec un DG en orbite, et manœuvrer le switch. Le train va suivre les mouvements du switch.

Ce petit montage a validé la possibilité de commander un auxiliaire d'un vaisseau d'Orbiter avec un raccourci clavier envoyé par une UNO. Ce n'était pas une première scientifique, mais j'étais bien content d'y être arrivé.


MAIS en avançant dans le projet, je me suis aperçu que la UNO une fois configurée en clavier ne peut pas
recevoir des données. Normal: un clavier n'est pas un périphérique qui reçoit des données, il en envoie.
Pour contourner la difficulté, il faut un Arduino capable d'être tant un périphérique capable de recevoir
des données, qu'un clavier (ou vu comme tel). c'est pour ça que je suis passé à la Leonardo. Du coup, plus
de librairie Keyboard à charger, ni de flashouillage de la UNO.

Le prochain challenge sera de multiplier les entrées/sorties connectées à la Arduino.

Title: Re: Le tableau de commande de Mars Bleu
Post by: nerofox on 05 December 2016, 19:24:32
Ta progression est intéressante et apporte de l'aide futur à d'autres personnes qui souhaiteraient se lancer dans l'aventure  :wor:

A noter que tu peux paramétrer ton switch non pas en mode INPUT mais en INPUT_PULLUP, cela évite d'ajouter une résistance au montage et donc simplifie l'électronique  :badfinger:

ce qui nous donne:
Code: [Select]
void setup()
{
  pinMode(Buttonpin, INPUT_PULLUP);                //On initialise la pin 7 comme une entree
 
  keyboard.begin();                         // Commence la communication
  delay(2000);                              // Attend que le peripherique soit reconnue comme un clavier
}
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 05 December 2016, 19:47:11
 :friend: Merci, Nerofox :friend:

Je ne connaissais pas cette commande INPUT_PULLUP; ce qui fait que
j'ai assemblé mes cartes d'élaboration de signal en incluant à chaque canal
une résistance de 10kOhms. 144 entrées en tout! Comme ça fonctionne,
je ne change rien :badsmile:
Title: Re: Le tableau de commande de Mars Bleu
Post by: nulentout on 17 December 2016, 07:19:54
Coucou les copains,
Je ne suis pas certain d'avoir tout compris dans le détail, mais il me semble que tu comptes affecter une entrée binaire par inverseur. Si il s'agit de boutons poussoir, tu peux en placer 5 ou 6 par entrée analogique, mais je suppose que tu sais faire ...
Bonne continuation : Nulentout
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 18 December 2016, 10:11:33
Effectivement, je vais faire ça. Mais la voie analogique a été une impasse pour moi. Je suis passé
par la voie numérique, avec succès.
Je voulais poursuivre les descriptions de mes travaux, mais hostingpics a l'air surchargé, ce matin.
Pas moyen d'uploader les photos destinées à illustrer mon propos. A suivre...


Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 18 December 2016, 12:23:00
Eeeet voici le....
              TROISIÈME CHALLENGE: multiplier les entrées/sorties connectées à la UNO

En suivant le chemin ouvert par Hysot, j'ai cherché à connecter plusieurs switches sur une même entrée analogique de la UNO, en faisant varier la tension d'entrée par des ponts diviseurs. Avec deux ou trois switches et des résistances associées, j'arrivais à peu près à mes fins, mais avec une dizaine de switches, je ne m'en sortais plus. J'ai noirci des pages et des pages, fait des tas d'essais de sketches Arduino pour arriver à la conclusion que j'étais dans une impasse technique. Il fallait faire autrement.

En remettant le nez dans la doc du web, j'ai trouvé: il faut faire du numérique. Le composant qui va me permettre d'avancer est le 74HC165, shift register PISO (Parallel Input Serial Output). Ce registre est cascadable, on peut donc avoir une multitude de switches dont on peut observer l'état. Ca tombe bien, car les raccourcis claviers du Xr2 sont nombreux (une bonne centaine).
D'un autre côté, les lumineux dont je vais avoir besoin vont être nombreux. Il y a déjà 12 auxiliaires APU sans compter les jauges de carburant, les afficheurs 7 segments, et tout un tas de signalisations.

Le site Arduino parle bien des 74HC165, et aussi des 74HC595 (registres SIPO). Avec ce qu'on y trouve, on peut apprendre facilement à s'en servir.


Nota:
A contrario, je commence par les registres de sortie 74HC595 afin de pouvoir matérialiser ce qu'on détecte des registres d'entrée 74HC165.



Les registres SIPO (Serial Input Parallel Output, 74HC595) vont permettre de gérer de multiples sorties, parce que cascadables tout comme le 74HC165.
Afin de tester, j'ai fait un montage provisoire sur breadboard, afin de matérialiser l'état des registres par l'allumage de leds.

(http://img4.hostingpics.net/pics/942690BrouillonSIPO1.jpg)

La photo ci-dessus montre le montage à deux 74HC595 chaînés. Dans un premier temps, j'avais utilisé seulement un seul registre SIPO et les leds rouges.

Pour commander l'allumage de 8 leds:

Code: [Select]
const int dataPin_out=2;   
const int latchPin_out=3;   
const int clockPin_out=4;
int byte1=0;
void setup()
{
pinMode(dataPin_out, OUTPUT);
pinMode(latchPin_out, OUTPUT);
pinMode(clockPin_out, OUTPUT);
Serial.begin(9600);
}

void loop()
{
byte1=byte1+1;
shiftOut(dataPin_out,clockPin_out,LSBFIRST,byte1);
delay(1000);
if byte1=255
{
Byte1=0;
}
}

Ca fait un compteur binaire dont l'état est matérialisé par l'allumage des leds.

Huit lumineux, c'est bien, mais il me fallait plus. L'étape suivante a été de chaîner un deuxième 74HC595, et d'y connecter huit leds supplémentaires, comme sur la photo.

Attention au bilan électrique du 74HC595: le circuit supporte une intensité totale de 70mA. Donc, pour au maximum 8 leds allumées, il faut au plus 8.75 mA par led. Pour cela, il faut une résistance d'atténuation de 300Ω pour chaque led. Dans la pratique, j'ai mis des résistances de 330 Ω, et je n'ai pas encore détruit de 74HC595.

Pour le remplissage des registres, j'ai voulu me passer de la commande shiftOut(), et utiliser des commandes plus élémentaires.

J'ai fini par arriver à cette fonction, où le tableau SIPOreg[ ] contient les valeurs commandant l'allumage ou l'extinction de leds. NumberSIPOreg est le nombre de registres à remplir divisé par deux. Cette division par deux est rendue nécessaire car j'utilise des mots de 16 bits (unsigned int) avec des registres de 8 bits.

Le principe est qu'on va pousser chaque bit dans la chaîne de registres, autant de fois qu'il le faut pour caler l'ensemble dedans. Si on a deux registres chaînés, on pousse 16 fois à chaque fois qu'on accède à cette fonction.

Code: [Select]
  // Fonction de remplissage des registres
  void updateRegister(unsigned int SIPOled[])
  {
      digitalWrite(latchPin_out, LOW); //déverrouillage des registres
      unsigned int value; //déclaration mémoire tampon pour scrutation SIPOreg[]
      for (byte Ii=0;Ii<NumberSIPOreg;Ii++)// traitement du nombre de registres divisé par 2:
      {                            // on marche en 16 bits sur des registres à 8 bits
        value=SIPOled[Ii];
        for (byte j=0;j<16;j++)          // scrutation des 16 bits de chaque élément de SIPOled[]
        {   
          digitalWrite(clockPin_out, HIGH); un coup d'horloge
          digitalWrite(dataPin_out, ((value&32768)==32768)); //détermination et écriture de DATA à 0 ou 1 sur pin 2 de la UNO
          digitalWrite(clockPin_out, LOW); fin du coup d'horloge
          value=value<<1;// décalage des bits
        }// fin de la boucle for j
      }//fin de la boucle for Ii
      digitalWrite(clockPin_out, HIGH); //ce coup d'horloge a été rajouté pour arriver à caler les bits
      digitalWrite(clockPin_out, LOW);// dans les registres. Je ne sais pas pourquoi c'est indispensable
                                      // mais ça marche comme ça
      digitalWrite(latchPin_out, HIGH);// verrouillage des registres
  }//fin remplissage des registres

Attention, ce code ne marche pas tout seul, il faut les déclarations, le setup, et le loop. C'est juste une fonction.


Si je rajoute un paquet de registres, il me suffit de changer la valeur de NumberSIPOreg dans la déclaration des variables, pour maintenir le calage.

Voilà, plus besoin de la fonction shiftOut(), et je peux multiplier les lumineux commandés par la UNO.

L'état des registres de sortie pouvant ainsi être très facilement matérialisé, on va pouvoir s'intéresser aux registres d'entrée en grand nombre
Title: Re: Le tableau de commande de Mars Bleu
Post by: Bibi Uncle on 20 December 2016, 05:57:03
Le coup d'horloge que tu ajoutes à la fin est dû au fait que SRCLK (ton clockPin_out) est activé sur un front montant (rising edge), ce qui décale tout ton encodage. Ainsi, ton premier bit est introduit dans le shift register lors du deuxième passage dans ta boucle, au front montant de SRCLK en prenant la valeur qui est toujours sur SER (ton dataPin_out).

J'ai refait un peu ton code:
Code: [Select]
// Fonction de remplissage des registres
void updateRegister(unsigned int SIPOled[], byte numSIPOreg)
{
    // Déverouillage des registres
    digitalWrite(latchPin_out, LOW);

    // On s'assure que l'horloge est dans un état connu
    digitalWrite(clockPin_out, LOW);

    // On parcourt chaque bloc de 16 bits
    for (byte i = 0; i < numSIPOreg; ++i)
    {
        unsigned int value = SIPOled[i];

        // On parcourt chaque bit
        for (byte j = 0; j < 16; ++j)
        {
            // Écriture de la valeur.
            unsigned int mask = 0x8000 >> j;
            digitalWrite(dataPin_out, value & mask)

            // Un coup d'horloge
            digitalWrite(clockPin_out, HIGH);
            digitalWrite(clockPin_out, LOW);
        }
    }

    // Verrouillage des registres
    digitalWrite(latchPin_out, HIGH);
}

Description des changements:

1. Ta variable NumberSIPOreg est maintenant passée en paramètre au lieu d'être une constante. Ça te permet de réutiliser ta fonction n'importe où.

2. Au début de la fonction, après avoir latché le shift register, c'est bien de réinitialiser l'horloge à LOW. Ainsi, si jamais ton code laisse par inadvertance l'horloge à HIGH, ta fonction est blindée.

3. La variable value est maintenant créée à l'intérieur de ta première boucle for. C'est une bonne pratique de limiter le scope de tes variables. Puisque celle-ci n'est utile qu'à l'intérieur de ta boucle, autant la déclarée à l'intérieur de celle-ci. Une nouvelle variable sera instanciée à chaque itération de ta boucle et elle ne sera jamais dans l'état non-initialisé (comme c'était le cas avant). N'est pas peur pour les performances, c'est une variable allouée sur la pile. Mon code est donc tout aussi performant que le tiens.

4. Au lieu de shifter la variable value, je préfère utiliser un masque. Comme ça, la variable value n'est jamais modifiée et représente toujours tes données. C'est seulement le masque (qui est en fait un 1 que je place à vis-à-vis le bit voulu, pour ensuite faire un AND avec la valeur pour l'extraire). Si tu n'es pas familier avec les masques, l'article Wikipédia en anglais donne de bonnes explications : https://en.wikipedia.org/wiki/Mask_(computing)

5. Mon masque utilise le 32768 que tu utilisais auparavant (pour mettre le 1 à la fin complétement). Quand tu as affaire à des valeurs comme celle-ci, je te suggère d'utiliser la notation hexadécimale, car c'est plus évident de retrouver l'utilité de ta valeur. 0x8000, pour quelqu'un avec un peu d'expérience est facilement décodable. Avec 32768, il faut sortir la calculatrice.... Aussi, à partir C++14, tu peux utiliser des binary literals comme 0b10000000 par exemple, qui est très facile à lire. Toutefois, je ne sais pas trop quel compilateur est utilisé sur la plateforme Arduino, donc je suis resté à du C++ classique.

6. Les coups d'horloge ont été déplacés comme je l'ai expliqué plus tôt. Ainsi, tu écris ta valeur sur ton SER, puis le front montant de l'horloge (créé quand tu la fais passer à HIGH) enregistre cette variable. Ensuite, on remet l'horloge à LOW pour se préparer à l'autre insertion.

7. J'ai aéré le code, ça fait du bien aux yeux. Particulièrement les paramètres des boucles qui sont gênants a lire lorsqu'ils sont tous collés. C'est toujours une question de préférence, mais certains standards rendent le code plus lisible.
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 20 December 2016, 14:20:30
Merci, Bibi Uncle de visiter mon humble cabane! :)

La clarté du code que tu as réaménagé est éclatante. Je suis bien content d'avoir le point de vue
de quelqu'un qui a été formé à coder. Pour ma part, j'ai appris à programmer sur le tas, et en
électronique, ma formation remonte aux années 80. :sage:
Au moins, je comprends maintenant le coup d'horloge supplémentaire qu'il fallait envoyer
pour avoir un bon calage de mes bits.

Tous tes points d'explications sont autant de nouveaux objectifs pour apprendre à coder plus
proprement. Afin de tenir compte de tes conseils, je vais avoir pas mal de réécriture à faire.

Dans mon code, je fais beaucoup de bitwise. J'utilise des masques assez souvent, donc, j'ai beaucoup
de valeurs à remettre en hexa ou en binary litteral. Le lien wiki est intéressant: en fait,
je faisais du common bitmask functions sans m'en rendre compte.

Je me demande si un code à base de bitwise est plus efficace en temps machine qu'un code
sans bitwise. Je serais enclin à penser que oui....
Title: Re: Le tableau de commande de Mars Bleu
Post by: Bibi Uncle on 20 December 2016, 19:48:21
Je me demande si un code à base de bitwise est plus efficace en temps machine qu'un code
sans bitwise. Je serais enclin à penser que oui....

Si tu écris du code qui sera exécuté sur une machine moderne, de manière générale, c'est mieux d'éviter les opérations bit à bit. En effet, les architectures modernes sont hautement optimisées pour faire des opérations sur leur "unité de base" (généralement des mots de 32 bits pour des machines modernes). Ainsi, il est souvent préférable d'utiliser un booléen enregistré dans un mot de 32 bits que de fusionner 32 booléens dans un seul mot. Il y a un gaspillage de mémoire, mais ça nécessite moins d'instructions.

Par contre, dans ton cas, tu programmes un système embarqué qui a peu de mémoire et un jeu d'instructions probablement réduit (je connaît pas beaucoup les microcontrôleurs d'Atmel, donc je suppose). Il est donc probablement préférable d'utiliser des opérations bit à bit dans ton cas.

Parfois on n'a pas le choix de les utiliser. Notamment, si tu implémentes un protocole de communication de couche un peu plus basse (couche transport et en dessous), tu n'auras pas le choix d'utiliser ce genre d'instructions pour extraire tes données des champs. Prends une paquet IP par exemple. Pour savoir la longueur de ton en-tête, il faut extraire les bits 4 à 7 à partir du premier mot que tu reçois. Dans ce cas, pas le choix de les extraire avec des opérations bit à bit.
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 04 January 2017, 17:11:28
J'ai un peu tardé, car pas trop le temps de me connecter pendant les fêtes.

Merci pour tes explications. Sur un Arduino, il vaut mieux donc être économe.
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 04 January 2017, 17:47:43
                                              Registres d'entrée
Dans l'élaboration de mon tableau de commande, il faut aussi des switches et boutons poussoirs.

Avec 8 switches connectés, le sketch de base pour collecter l'état de switches et le transférer sur un registre d'entrée devient:
Code: [Select]
const int dataPin_out=2;
const byte latchPin_out=3;
const byte clockPin_out=4;
const byte dataPin_in=5;
const byte latchPin_in=6;
const byte clockPin_in=7;
byte value;

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);
}

void loop()
{
digitalWrite(latchPin, HIGH);
delayMicrosecond(10);
digitalWrite(latchPin, LOW);
value=shiftIn(dataPin,clockPin);
shiftOut(dataPin_out,clockPin_out,LSBFIRST,value);
delay(10);
}

La valeur value va contenir la valeur binaire de la position 0 ou 1 des switches scrutés. La valeur variera de 0 à 255 (8 bits).

L'état de mon montage provisoire avec un 74HC165 et deux 74HC595, plus deux afficheurs 7 segments.
(Question fouillis, je m'arrêterai là pour passer à des montages plus rangés.)
(http://img4.hostingpics.net/pics/294263BrouillonSIPO3.jpg) (http://www.hostingpics.net/viewer.php?id=294263BrouillonSIPO3.jpg)


En voulant chaîner un deuxième 74HC165, j'ai eu des problèmes de stabilité sur le MSB du deuxième registre.
J'ai à peu près tout essayé tant en soft que sur mon montage, rien n'y faisait.
J'ai alors choisi de me passer de la commande shiftIn(). Voici ce que j'ai codé.

@BibiUncle: j'ai soigné la présentation, mais n'hésites pas à me corriger.

Code: [Select]
   // Fonction de lecture des registres PISO (switches et boutons poussoir)

  void get_PISO_register()
  {
    //latch à LOW pour lire l'état des switches, et on attend 10 microsecondes
    digitalWrite(latchPin_in,LOW);
    delayMicroseconds(10);

    //latch à HIGH, verrouillage
    digitalWrite(latchPin_in,HIGH);

    for (unsigned int i=0;i<Data_width+1;++i){             //data_width est le nombre de bits à lire (multiple de 8)

//on "pousse" Data_width fois les valeurs lues dans la mémoire switchStatus; c'est le shiftIn
       unsigned int switchStatus=(switchStatus<<1)|(digitalRead(dataPin_in));

       //un coup d'horloge
       digitalWrite(clockPin_in,HIGH);
       delayMicroseconds(10);
       digitalWrite(clockPin_in,LOW);
       delayMicroseconds(10);

       //j est un modulo 16 de i, afin de cadencer le remplissage du tableau PISOreg[]
       byte j=i%16;
       if ((i>0)&&(j==15)){
        // envoi de la valeur dans le tableau PISOreg[]
        PISOreg[i/16]=switchStatus;
       }//Endif
      } //Next i
     
  }// fin lecture des registres PISO

Avec cette fonction, je peux scruter un grand nombre de switches ou boutons poussoirs et avoir une image de leur état dans le tableau PISOreg[ ].
Dans ma configuration actuelle (Janvier 2017), j'utilise 15 switches, 9 boutons-poussoir(s?), 4 joysticks à 2 ou
4 contacts, et le gros coup-de-poing du "undock". Mais j'ai de la réserve, ayant à ma disposition 144 entrées.

Mais avant d'aborder le montage de tout ça, il faut encore s'assurer de la possibilité de transmettre des
données, en vue de la synchronisation du tableau de commande avec le scénario chargé.
Title: Re: Le tableau de commande de Mars Bleu
Post by: Bibi Uncle on 04 January 2017, 19:18:49
Tes délais de 10 microsecondes sont-ils vraiment nécessaires ? L'Arduino a une horloge assez lente (j'ai trouvé 16 Mhz, mais ça reste à confirmer puisque Atmel spécifie une fréquence maximale de 20 Mhz pour le ATMega328p). Si on émet l'hypothèse très généreuse qu'un digitalWrite est atomique (un seul coup d'horloge du microcontrôleur pour l'exécuter), ce qui serait assez impressionnant, ton coup d'horloge sans délai sera à 16 Mhz. Selon la documentation de TI pour le SN74HC165, à température ambiante à 4.5V, la fréquence max est de 31 Mhz. Bref, je crois que le délai n'est pas nécessaire.

Sinon, j'ai regardé rapidement ton code et ça me semble très bien :top:
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 04 January 2017, 20:47:47
 Effectivement, en y réfléchissant, ça n'est pas nécessaire, étant donné la fréquence
d'horloge qui est de 16Mhz.
Merci pour le :top:  :)
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 14 January 2017, 10:17:55
      QUATRIÈME CHALLENGE: commander des leds à partir de Lua


Le premier challenge consistait à extraire des données d'Orbiter avec un script Lua. Ce challenge fait la deuxième partie du transfert de données vers la UNO elle-même programmée pour piloter les lumineux.

Le grand principe est qu'un script Lua doit fonctionner dans Orbiter, et échanger des données avec la UNO contenant le sketch qui les traite.

Il a fallu que je remette le nez dans le Web pour trouver quelque chose ("the nose buried in documentation" comme j'ai pu lire). C'est Widdernix dans le forum américain d'Orbiter qui m'a donné la solution dans le fil "talking with serial devices". Voir à: http://orbiter-forum.com/showthread.php?t=17847 (http://orbiter-forum.com/showthread.php?t=17847)

Pour échanger des données, on a besoin d'une librairie, luars232.dll. J'ai cherché six semaines durant comment y accéder, avant de trouver qu'il fallait simplement mettre cette dll dans le répertoire d'Orbiter. Une fois cette dll bien positionnée, la commande rs232=require("luars232") ne faisait  plus planter le script Lua.
Nota: en ce qui me concerne, le plantage d'un script Lua sur Orbiter est tout à fait discret. En fait, on s'en aperçoit lorsque le défilé des note:set_text()ne fige plus à l'endroit du plantage présumé.

Après quelques mises au point, j'ai essayé le sketch Arduino suivant sur ce montage:

(http://img4.hostingpics.net/pics/942690BrouillonSIPO1.jpg)

Code: [Select]
byte dataPin=2;
byte latchPin=3;
byte clockPin=4;
byte data=255;
byte byte1;


void setup()
  {
    pinMode (dataPin,OUTPUT);
    pinMode (latchPin,OUTPUT);
    pinMode (clockPin,OUTPUT);
    Serial.begin(9600);
  }
 
void loop()
{

    if (Serial.available()>0)
    {
    byte1=Serial.read();
    digitalWrite(latchPin,LOW);
    shiftOut(dataPin, clockPin, LSBFIRST, byte1);
    digitalWrite(latchPin, HIGH);

    }

   delay(150);
}

Le script Lua associé est le suivant:

Code: [Select]
note = oapi.create_annotation()
note:set_pos (0.35,0.1,0.8,0.95)
note:set_colour ({r=0.9,g=0.5,b=0.2})


rs232=require("luars232")
local port_name="COM4"
local e,p=rs232.open(port_name)
if e ~= rs232.RS232_ERR_NOERROR then
term.out('',string.format("can't open serial port '%s', error: '%s'\n", port_name, rs232.error_tostring(e)))
    return
end
-- set port settings
assert(p:set_baud_rate(rs232.RS232_BAUD_9600) == rs232.RS232_ERR_NOERROR)
assert(p:set_data_bits(rs232.RS232_DATA_8) == rs232.RS232_ERR_NOERROR)
assert(p:set_parity(rs232.RS232_PARITY_NONE) == rs232.RS232_ERR_NOERROR)
assert(p:set_stop_bits(rs232.RS232_STOP_1) == rs232.RS232_ERR_NOERROR)
assert(p:set_flow_control(rs232.RS232_FLOW_OFF)  == rs232.RS232_ERR_NOERROR)

byte1='U'
err, len_written = p:write(string.char(byte1))
  end

note:set_text('Longueur écrite='..len_written)
proc.wait_sysdt(1)

assert(p:close() == rs232.RS232_ERR_NOERROR)-- this closes the COM

note:set_text('End of program')
proc.wait_sysdt(1)
note:set_text('  ')
proc.wait_sysdt(1)

Et là, VICTOIRE, j'ai réussi à écrire dans le registre à décalage et à afficher un octet sur 8 leds. Le caractère 'U' correspondant à 85, c'est-à-dire 01010101 en binaire, soit une led sur deux. Changeons le contenu de la variable byte1, et les leds s'allumeront autrement.

Je vous laisse digérer tout ceci, avant de vous montrer un petit TP dont l'objet sera d'afficher le machmètre
d'un XR2.
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 27 January 2017, 14:48:02
Pour ceux qui suivent, et tous les autres qui dorment au fond de la classe  :rant: :badfinger:, voici le petit TP
que je vous annonçais il y a quelques jours:

Pour ce faire, j'ai étoffé mon montage provisoire en adjoignant une bredboard supplémentaire comprenant deux afficheurs 7 segments branchés sur un 4543 ( entrée 4 bits=>afficheur 7 segments). Avec ces deux afficheurs, je voulais donc avoir un machmètre, en allant chercher la valeur par:

                                                      m=v:get_machnumber()

Puis avec une mise en forme, l'envoyer  par le port USB à la UNO qui la renverrait aux registres de sortie.

Ci dessous, le script Lua:
Code: [Select]
function send_data(n1,n2)
  e,p=rs232.open(port_name)
  if e ~= rs232.RS232_ERR_NOERROR then
    term.out('',string.format("can't open serial port '%s', error: '%s'\n", port_name, rs232.error_tostring(e)))
      return
  end
  -- set port settings
  assert(p:set_baud_rate(rs232.RS232_BAUD_9600) == rs232.RS232_ERR_NOERROR)
  assert(p:set_data_bits(rs232.RS232_DATA_8) == rs232.RS232_ERR_NOERROR)
  assert(p:set_parity(rs232.RS232_PARITY_NONE) == rs232.RS232_ERR_NOERROR)
  assert(p:set_stop_bits(rs232.RS232_STOP_1) == rs232.RS232_ERR_NOERROR)
  assert(p:set_flow_control(rs232.RS232_FLOW_OFF)  == rs232.RS232_ERR_NOERROR)
  err, len_written = p:write(string.char(n2)..string.char(n1))
  assert(p:close() == rs232.RS232_ERR_NOERROR)-- this closes the COM
end

note = oapi.create_annotation()
note:set_pos (0.35,0.1,0.8,0.95)
note:set_colour ({r=0.9,g=0.5,b=0.2})


intro = "Machmètre sur 2 displays 7 segments"

note:set_text(intro)
proc.wait_sysdt(1.0)
v=vessel.get_interface('XR2-01')
rs232=require("luars232")
port_name="COM4"



repeat
  alt=oapi.get_altitude()
  mach = v:get_machnumber()
  mach_display=math.floor(10*mach)
  centaine=math.floor(mach_display/100)
  mach_display=mach_display-100*centaine
  dizaine=math.floor(mach_display/10)
  mach_display=mach_display-10*dizaine
  unite=mach_display
  char1=unite+16*dizaine
  char2=centaine
  note:set_text(char2.."  "..char1.."  "..centaine..dizaine..unite)
  if unite~=old_unite then
    send_data(char1, char2)
    old_unite=unite
  end
  proc.skip()
until alt>300000 -- sortie dès qu'on atteint 300 kms d'altitude

note:set_text('Longueur écrite='..len_written)
proc.wait_sysdt(1)


note:set_text('End of program')
proc.wait_sysdt(1)
note:set_text('  ')
proc.wait_sysdt(1)


Le sketch Arduino reçoit les données en boucle, envoyées par le script Lua, et les envoie dans les
registres à décalage pilotant les displays 7 segments par l'intermédiaire des 4553:
Code: [Select]
int dataPin=2;
int latchPin=3;
int clockPin=4;
int data=255;
byte octet1;
byte octet2;



void setup()
  {
    pinMode (dataPin,OUTPUT);
    pinMode (latchPin,OUTPUT);
    pinMode (clockPin,OUTPUT);
    Serial.begin(9600);
  }
 
void loop()
{

    if (Serial.available()>0)
    {
    octet1=Serial.read();
    octet2=Serial.read();
    digitalWrite(latchPin,LOW);
    shiftOut(dataPin, clockPin, LSBFIRST, octet1);
    shiftOut(dataPin, clockPin, LSBFIRST, octet2);
    digitalWrite(latchPin, HIGH);

    }

   delay(150);
}

On lance un SCN contenant l'ordre d'accès au script LUA, et on peut suivre la valeur des Machs
sur les deux afficheurs numériques 7 segments.

Envoyer des données d'Orbiter aux registres de sortie m'est désormais possible. Cela signifie aussi
que je peux synchroniser le simpit avec l'état du Xr2 au lancement du scénario.

Tout ceci est encore assez provisoire et expérimental. Dans mon prochain post, je vous exposerai comment j'ai optimisé ces bouts de code de façon simple.



 
Title: Re: Le tableau de commande de Mars Bleu
Post by: Bibi Uncle on 28 January 2017, 04:38:15
Continue Mars Bleu! Ton projet avance bien et j'adore lire les avancements au fur et à mesure!

Je suis plus ou moins sûr de comprendre la mise en forme que tu fais avant de l'envoyer à l'Arduino. Tu n'aurais pas pu faire un printf (ou la fonction équivalente en Lua, je n'ai jamais programmé avec ce langage) afin d'obtenir un string déjà formatée ? Ensuite, il suffirait d'envoyer les caractères les uns après les autres par UART et voilà. Dans ton code, tu sembles essayer de calculer manuellement les caractères nécessaires alors qu'une fonction standard aurait pu faire le travail à ta place.
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 28 January 2017, 19:44:38
 :salut: Merci, Bibi Uncle pour tes encouragements. :salut:
 J'ai encore plein d'avancements en réserve, tout en continuant à souder, découper, assembler, programmer.

Pour la mise en forme, j'ai fait en mode "artillerie lourde". Pour être plus subtil, j'ai demandé à un de mes fistons de me faire quelque chose, et il m'a pondu un bout de code que je n'ai pas encore eu le temps de
décortiquer. Je te le poste dès que je rentre à la maison (je ne l'ai pas pour l'instant).
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 28 January 2017, 19:58:37
Complément d'information:
Le principe que je mets en oeuvre pour la mise en forme est le suivant: on a besoin de quatre bits
pour piloter un 4553. Quatre bits, c'est un demi-octet, donc, avec un octet, je peux piloter deux
4553. C'est pour ça que je mets les dizaines avec un coeff de 16 (décalage des bits de quatre rangs).
Ainsi, je transmets dizaine et unités dans un seul registre à décalage 74HC595.

Je ne sais pas si je suis bien clair....
Title: Re: Le tableau de commande de Mars Bleu
Post by: Bibi Uncle on 30 January 2017, 19:22:25
Ah d'accord je comprends. Ça me semble légitime comme technique :top:
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 11 February 2017, 19:04:29
J'envoie un dernier chapitre sur la transmission des données entre l'ordinateur et la carte Arduino.
A mes yeux, c'est assez important, c'est pour ça que j'insiste un peu.

En fait, j'ai repris ce qui figure dans mes précédents posts, mais avec un peu de mises en forme,
et de séparation des éléments principaux.

En Lua, on doit en premier lieu ouvrir le port. J'ai appelé cette fonction: widdernixopen()
Code: [Select]
function widdernixopen()
     e,p=rs232.open(port_name)
      if e ~= rs232.RS232_ERR_NOERROR then
  note:set_text('Problème...')
  proc.wait_sysdt(1.41)
              return
      end
  -- set port settings
    assert(p:set_baud_rate(rs232.RS232_BAUD_9600) == rs232.RS232_ERR_NOERROR)
    assert(p:set_data_bits(rs232.RS232_DATA_8) == rs232.RS232_ERR_NOERROR)
    assert(p:set_parity(rs232.RS232_PARITY_NONE) == rs232.RS232_ERR_NOERROR)
    assert(p:set_stop_bits(rs232.RS232_STOP_1) == rs232.RS232_ERR_NOERROR)
    assert(p:set_flow_control(rs232.RS232_FLOW_OFF)  == rs232.RS232_ERR_NOERROR)
end

En deuxième lieu, la fermeture du port:
Code: [Select]
function widdernixclose()
    assert(p:close() == rs232.RS232_ERR_NOERROR)-- this closes the COM
end

Entre les deux (ouverture et fermeture) Lua doit envoyer les données vers Arduino. Elles soit sont contenues dans un tableau, ou bien en valeurs discrètes. Dans le cas d'un tableau, j'ai mis au point:

Code: [Select]
function init_data(data,start,width)
for i=start,width do
high_byte=math.floor(data[i]/256)
low_byte=data[i]-high_byte*256
err,len_written=p:write(string.char(high_byte)..string.char(low_byte))
end
end
J'ai mis dans ce tableau les valeurs donnant la position des auxiliaires dits APU (gear, airbrake,
baydoors, etc...). Cela permet de transmettre leur état, que ce soit en position déployée, rétractée ou intermédiaire, en vue de synchroniser les lumineux pilotés par l'Arduino et l'état logique de  l'engin chargé dans le fichier .scn.

Il y a bien sûr des données additionnelles (de plus en plus, à mesure que le cockpit s'amplifie). Pour les transmettre, j'ai écrit la fonction: init_status()
Pour l'instant, il y a trois valeurs int à transmettre, soit 6 octets supplémentaires:
Code: [Select]
function init_status()

        [color=grey]--envoi sur deux octets de la valeur SIPOstatus contenant l'état des 12 switches APU (dont l'APU lui même)[/color]
high_byte=math.floor(SIPOstatus/256)
low_byte=SIPOstatus-high_byte*256
err, len_written = p:write(string.char(high_byte)..string.char(low_byte))

        [color=grey]--envoi sur deux octets de la valeur SIPOtransit_status contenant l'état de position des 12 auxiliaires APU [/color]
high_byte=math.floor(SIPOtransit_status/256)
low_byte=SIPOtransit_status-high_byte*256
err, len_written = p:write(string.char(high_byte)..string.char(low_byte))

        [color=grey]--envoi sur deux octets de la valeur Miscstatus contenant l'état logique des RCS (OFF/ROT/LIN), ainsi que l'état
        Docké ou non du XR2. Il reste encore 13 bits dispos dans cette valeur[/color]
high_byte=math.floor(Miscstatus/256)
low_byte=Miscstatus-high_byte*256
err, len_written = p:write(string.char(high_byte)..string.char(low_byte))
end

Dans le script Lua, toutes ces fonctions sont appelées par:   
   widdernixopen()
   init_data(position,3,18)—transmission du tableau position[]
   init_status()
   widdernixclose()


Du côté de l'Arduino, , on doit recevoir ce qui est en provenance du sketch Lua. Un tableau de valeurs:

Code: [Select]
for (byte i=3;i<19;i++)
   {
//réception des données envoyées par Orbiter/Lua-----2*16=32 octets--------
      data=get_data(data);
      Pos[i]=data;
   }

Les données additionnelles:
Code: [Select]
//réception des données envoyées par Orbiter/Lua-----2 octets+les 32 déjà extraits---34 octets
    data=get_data(data);
    Switch_status=data;
 
//réception des données envoyées par Orbiter/Lua-----2 octets+les 34 déjà extraits---36 octets
    data=get_data(data);
    Transit_status=data;

//réception des données envoyées par Orbiter/Lua-----2 octets+les 36 déjà extraits---38 octets
    data=get_data(data);
    Miscstatus=data;

La fonction de réception et de transformation en int est:

Code: [Select]
  unsigned get_data(unsigned int value)
  {

    // réception des deux octets:
    byte high_byte=Serial.read();
    byte low_byte=Serial.read();

    //reconstitution de la valeur sur 2 octets
    value=256*high_byte+low_byte;
    return value;
  }//fin get_data()


J'ai dû me pencher sur la fonction réciproque: c'est-à-dire faire envoyer des données de l'Arduino vers Lua. En effet, le buffer d'entrée de la Leonardo ou de la Uno n'est que de 64 octets, ce qui n'est pas beaucoup. Si on a des paquets de données supérieurs à 64 octets, l'idée est de pouvoir envoyer un premier paquet, attendre une réponse, puis d'envoyer la suite.

Pour ce faire, dans le script Lua, j'initialise une variable: data_read="Z", et j'ai écrit une nouvelle fonction, la fonction copythat()
Code: [Select]
function copythat()
read_len=1
err, data_read, size=p:read(read_len)
end


Cette fonction va lire un octet en provenance de la carte Arduino. La valeur data_read ne va plus contenir "Z", mais la valeur envoyée par la carte Arduino, donnant un signal pour remplir de nouveau le petit buffer de l'Arduino avec de nouvelles données.

Voilà, voilà, j'espère que vous n'êtes pas trop :sick: :sick: :sick: :sick: J'ai essayé de faire léger!! :badsmile:

Dans un prochain post, je vous parlerai de l'assemblage de mes modules Parallel Input Serial Output. Il y aura plus d'illustrations!!
Title: Re: Le tableau de commande de Mars Bleu
Post by: jacquesmomo on 12 February 2017, 23:22:19
Voilà, voilà, j'espère que vous n'êtes pas trop :sick: :sick: :sick: :sick: J'ai essayé de faire léger!! :badsmile:

(http://img11.hostingpics.net/thumbs/mini_414692Tetemalade.gif)
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 12 February 2017, 23:49:13
 JacquesMomo:
Quote
(http://img11.hostingpics.net/thumbs/mini_414692Tetemalade.gif)

J'aime bien la Coccinelle, même quand elle est vaseuse! :)
Et aussi les smiley "hors forum" que tu nous déniches
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 28 February 2017, 09:09:55
CINQUIÈME CHALLENGE: construire les cartes PISO et les circuits d'élaboration de signal

Etant donné le nombre de raccourcis clavier du Xr2, et la nécessité d'être à l'aise, j'ai assemblé deux cartes, l'une supportant six circuits 74HC165, et l'autre douze circuits 74HC165. Cela me donne une capacité de traitement de 8x18=144 switches et boutons poussoirs.
Associées à ces deux cartes, les circuits d'élaboration de signal permettent d'envoyer 0 ou 5volts aux entrées des 74HC165:
                                (http://img11.hostingpics.net/pics/559925Elaborationsignal.jpg)Pas pu faire mieux pour le shéma...

Si l'interrupteur est ouvert, pas de tension, la sortie Signal PISO est à zéro volts.
Si l'interrupteur est fermé, on a 5 volts aux bornes de la résistance, parcourue par un courant de 0.5 mA. La sortie Signal PISO est à 5 volts.

Assembler de telles cartes est plus vite écrit que fait, car c'est un travail minutieux de soudage et, surtout, de vérifications (câblage correct, continuités électriques). Du boulot de neurochirurgien. Tout n'a pas été évident dès  le départ et il a fallu faire des changements d’organisation en cours de route.

Ensuite, une fois toutes les vérifications effectuées, j'ai fait les premières mises sous tension. Bien entendu, rien ne marchait comme prévu. De plus, en cas de disfonctionnement, il faut toujours se poser la question: est-ce mon montage, ou bien le programme qui l'anime?

Ci-dessous, la carte à douze 74HC165 et quatre groupes de 24 circuits d'élaboration de 5 volts. On relie l'ensemble avec des nappes à 26 pôles.

                (http://img15.hostingpics.net/pics/767800CartesPISOetsignal.jpg)

Une fois ce montage effectué, je me suis aperçu qu'il fallait installer les prises 26 pôles sur le fond du module, afin de pouvoir brancher/débrancher plus facilement. J'ai donc rajouté le petit panneau du fond, et les câblages qui vont bien (là, c'est mon montage à six 74HC165):

                (http://img11.hostingpics.net/pics/267558ModulePISO.jpg)

Une fois repliées, les deux platines forment un module que je peux installer dans un rack de hauteur 3U.
Si les modules dont on a besoin ne tiennent pas dans un seul rack, on peut en empiler autant qu'on veut pour faire une baie qu'il faudra ventiler.

Dans la mise au point de mes cartes PISO, j'ai eu pas mal de galères qui consistaient essentiellement en des soudures sèches (ne laissant pas passer le courant). J'ai eu aussi un tout petit morceau de métal qui s'était coincé entre une piste 5 volts et une autre piste LATCH. LATCH étant toujours à HIGH, plus moyen de lire les registres qui restaient verrouillés en permanence. J'ai passé un Dimanche après midi dans son entièreté à chercher avant de finir par trouver.
Ce n'est pas parce qu'une carte fonctionne correctement toute seule qu'elle marchera correctement associée à une autre carte du même type. Par exemple, si l'on inverse LATCH et CLK sur deux cartes, le fonctionnement des deux cartes va être parfaitement erratique.

Attention au sens de montage des circuits intégrés. A la mise sous tension, le fusible 5 volts a sauté immédiatement. Une mesure d'intensité avec un seul circuit 74HC165 a donné 2,4 Ampères! Après investigation, je me suis rendu compte que je les avais mis à l'envers sur leur support. Une fois tout remis comme il fallait, l'intensité absorbée était infiniment moins importante, tout à fait compatible avec le calibre du fusible.

Une fois mes 18 registres PISO correctement câblés, il a fallu mettre en place le sketch Arduino pour cadencer la scrutation des 144 entrées, et mettre les valeurs binaires associées dans un tableau[ ] afin de pouvoir les exploiter. (Cf #17)

Title: Re: Le tableau de commande de Mars Bleu
Post by: Kerguelen on 01 March 2017, 14:25:58
Jolie travaille ! Je soutiens ton projet, j'avais une idée un peu semblable pendant une certaine période mais, décidément, j'imagine que mon apprentissage en elec n'est pas assez poussé ahah...  :???:
Bon courage pour la suite!  :top:
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 01 March 2017, 19:17:00
 Merci, Kerguelen, et bienvenue sur le fofo! :beer:
J'alimente ce fil pour donner des idées aux "simpinautes".

Quote
Bon courage pour la suite!  :top:
Oui, des fois, ya besoin. En ce moment, je peine sur des circuits
comprenant des encodeurs rotatifs.
Title: Re: Le tableau de commande de Mars Bleu
Post by: nulentout on 14 March 2017, 11:57:52
Hé bé, tout ce PATAKÈSSSS me rappelle l'époque où je créais mon propre tableau de bord. Disposer de 255 entrées/sorties posait les mêmes problèmes de connectique et surtout d'encombrement. Je vois que notre copain avance de façon magistrale, et je m'en réjouis. Il démontre une fois de plus le plaisir qui émerge forcément d'un projet aussi ambitieux, quand on arrive à faire "tourner" des solutions qui après coup peuvent sembler à certains évidentes, mais qui imposent au concepteur des heures de recherche.  :wall:
Félicitations cher copain, tes élucubrations vont certainement inciter des internautes à te suivre sur cette voie passionnante de la création.  :wor: Chapeau bas ... je le pense vraiment : Môamôa.
Title: Re: Le tableau de commande de Mars Bleu
Post by: jacquesmomo on 14 March 2017, 14:36:09
200 ème karma pour Nulentout (donné par moi !)  :badsmile: Bien mérité !!!
Title: Re: Le tableau de commande de Mars Bleu
Post by: nulentout on 14 March 2017, 16:50:56
HHHYYYYYOOOOUUUUUPPPPPYYYYYY, ça fait un compte rond !
Plus que 32 de retard, je vais te rattraper à donf Môamôa !  :flower:
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 14 March 2017, 18:43:27
Merci à tôatôa, Nulentout pour ton élogieux #37.
Et aussi:
Quote
...quand on arrive à faire "tourner" des solutions qui après coup peuvent sembler à certains évidentes, mais qui imposent au concepteur des heures de recherche.  :wall:

Ah oui, alors; je viens de passer un mois de recherches pour une solution technique( :rant: :wall: :rant: :wall: :rant:) . Et, enfin
                                          :youpie: :youpie: j'ai pu aboutir! :youpie: :youpie:
                                                                Ça fait du bien!

Du coup, ça va me faire une réserve supplémentaire d'"élucubrations" que je vous garde bien au chaud
avant de servir...

Et puisqu'on parle de karmas, voici pour Nulentout (comme ça, plus de compte rond avant 300 :), eet aussi pour Jacquesmomo, un autre karma. Làààà...
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 17 March 2017, 20:01:47
Il est grand temps de continuer mes élucubrations: on s'accroche, les gars!

Avant de parler des modules SIPO, il faut que j'évoque l'ensemble des servitudes liées à la bonne marche de mon environnement. Il fallait bien sûr que ces servitudes soient mises en rack, tout comme les autres modules.


                PREMIÈRE SERVITUDE: L'ALIMENTATION ELECTRIQUE

Dès que j'ai eu plus d'un module à alimenter électriquement, j'ai vu qu'il fallait une alimentation électrique digne de ce nom. Il me fallait du 5 volts pour les modules PISO et SIPO, et du 8 volts pour la carte Arduino. J'ai trouvé que la meilleure alim était celle d'un PC, qui fournit du 5 volts et du 12 volts. Il a simplement fallu changer la petite prise fournissant le 12v et le 5v afin de pouvoir connecter cette alim de PC à mon répartiteur d'alimentation.

Le 12 volts passant par un L7808 est mis à 8 volts, ce qui est tout à fait convenable pour alimenter la carte Arduino.

J'ai utilisé une plaque 100x160 mm à bandes de cuivre pour pouvoir faire une bonne répartition du 5 volts pour chacun de mes modules. J'ai bien sûr installé des fusibles tant pour le 5 volts que pour le 12 volts. A juste raison, car il est arrivé souvent que je les transforme en chaleur et en lumière…

(http://img4.hostingpics.net/pics/288965DSC0565.jpg)

Leur emplacement est à revoir, car situés sur la carte, il faut tout débrancher et extraire la carte du rack pour pouvoir les remplacer. Je songe à des porte-fusibles en face avant.

Pour avoir une référence de clignotement de environ 1hz, et aussi me donner la possibilité de multiplexage, j'ai réalisé des petits circuits oscillants avec des 555. Le 1hz servira à piloter le clignotement de certaines leds, en fonctions des besoins. Le but étant de simplifier le sketch tournant dans l'Arduino. J'ai installé cette petite carte sur la carte d'alimentation pour gagner de la place dans mon rack.

Pour la face avant des modules, j'ai fait des projets que je voudrais faire réaliser en fablab, avec gravure laser, de façon à faire du rétroéclairé. Mais ça sera traité plus tard...

Dans un prochain post je vous expliquerai comment j'ai installé la petite carte Uno, (remplacée ensuite par une Leonardo) dans mon rack.
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 09 April 2017, 19:37:24
Scusez, j'ai pas eu le rythme, ayant dû m'éloigner  quelques jours....

Il est temps d'aborder la....

                   DEUXIÈME SERVITUDE: LE SUPPORT POUR LA carte Arduino.

On peut y installer indifféremment une UNO ou une Léonardo. L'avantage de la Léonardo est qu'elle permet
d'envoyer des caractères sans configuration particulière, contrairement à la UNO.


J'avais donc besoin d'un support facile à utiliser pour la Leonardo, qui est assez petite. J'ai trouvé une solution qui m'a a parue pratique, en soudant des broches sur une plaque 100x160 à pastilles de cuivre aux bons endroits pour pouvoir enficher la Leonardo dessus. Ça forme un module que je peux ensuite installer dans mon rack.

Les broches au-delà de la broche 13 m'on donné du fil à retordre, car l'espacement par rapport aux autres broches n'est pas du 2,54 mm.
Il restait à réaliser le câblage rampant et à souder les connecteurs pour relier la Leonardo à son alimentation électrique et aux modules supportant les registres à décalage.

Sur la face avant de ce module, j'ai mis, outre des leds matérialisant la présence du 5 et 8 volts, des groupes de leds pour LATCH, CLK et DATA SIPO/PISO, figurant la circulation des données et la pulsation commandant les registres. Pour ralentir tout cela afin de le rendre visible, j'ai ajouté six circuits décompteurs CD 4020 dans un coin de la carte supportant la Léonardo.

                           Ci dessous, la carte supportant le microcontrôleur Arduino:
(http://img4.hostingpics.net/pics/886776DSC0566.jpg) (http://www.hostingpics.net/viewer.php?id=886776DSC0566.jpg)

Les fils bleus sont DATA, jaunes=>LATCH, gris=>CLK. J'ai choisi ces couleurs au hasard, mais je m'y tiens.


Dans un prochain post, je reprendrai le cours de mes constructions en vous parlant de mes modules SIPO, utilisant des 74HC595, afin de multiplier les sorties. Bonne lecture!
Title: Re: Le tableau de commande de Mars Bleu
Post by: antoo on 09 April 2017, 20:39:07
Génial!
Title: Re: Le tableau de commande de Mars Bleu
Post by: jacquesmomo on 09 April 2017, 23:00:59
Captivant.... (chuis jaloux !)  :badsmile:
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 10 April 2017, 20:19:18
Merci, les gars. Ça fait plaisir d'avoir du retour. Je vois aussi le compteur des vues qui tourne,
donc il y a du monde qui vient voir, même s'il ne dit rien.

J'ai trouvé un site qui permet de dessiner des schémas en ligne. C'est : https://easyeda.com/ (https://easyeda.com/)
Je le trouve bien fait. Il faut juste ouvrir un compte si on veut sauvegarder ses créations.
Ça va me permettre de documenter tous mes circuits.

Allez, je retourne à la préparation de mes élucubrations.... :prof:
Title: Re: Le tableau de commande de Mars Bleu
Post by: jacquesmomo on 10 April 2017, 23:18:53
Merci, les gars. Ça fait plaisir d'avoir du retour. Je vois aussi le compteur des vues qui tourne,
donc il y a du monde qui vient voir, même s'il ne dit rien.
Voui, je suis tout ça...

C'est bien qu'il y ait encore des passionnés comme toi (et nous) car il me semble que ça devient plus rare....  :(
Title: Re: Le tableau de commande de Mars Bleu
Post by: antoo on 11 April 2017, 14:40:10
Ouép, je confirme. Ça s'endort un peu...
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 11 April 2017, 18:57:56
C'est un peu pour ça que je me suis décidé à partager l'ensemble de mes travaux:
pour donner envie, avec quelques solutions techniques qui peuvent être autant de
pistes de réflexion pour faire mieux.
Faisons vivre Orbiter avec de beaux add-on et/ou de belles réalisations!!
Title: Re: Le tableau de commande de Mars Bleu
Post by: jacquesmomo on 12 April 2017, 00:16:24
 :eek: C'est mon avis et je le partage !!!!
Title: Re: Le tableau de commande de Mars Bleu
Post by: antoo on 12 April 2017, 10:59:12
C'est top que tu partages tout ça! Avec notre simu Apollo, on avance tranquillement, on vous mettra des infos avant l'été :eek: .
A+
Title: Re: Le tableau de commande de Mars Bleu
Post by: nulentout on 12 April 2017, 16:36:09
Elles sont belles tes cartes électroniques, visiblement tu aimes le travail bien fait.  :top:
La réussite sera forcément la conclusion de ton entreprise avec la satisfaction qui va avec ...
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 12 April 2017, 22:37:45
@Antoo: simu Apollo? J'ai hâte de voir. Ça doit être bien pointu, ça.
Ce qui m'intéressera particulièrement de voir, ce sont les commandes qui n'ont pas
de raccourci clavier.
@ Nulentout: merci! Et, oui, j'essaie de faire de mon mieux, en utilisant
mon expérience professionnelle passée. Quelque chose de bien organisé
est clair et dépannable. Je devrais y arriver, même si, parfois, je galère un
peu. (En ce moment, je bute toujours sur mes roues codeuses...)
Title: Re: Le tableau de commande de Mars Bleu
Post by: antoo on 13 April 2017, 01:03:20
Quote
Ce qui m'intéressera particulièrement de voir, ce sont les commandes qui n'ont pas
de raccourci clavier.
C'est en effet le plus gro défi... et je me réjouis de vous dire que ça le fait :turning:. On vous partagera tout ça quand on aura trouvé de quoi imprimer un EMS en ABS. Il est question de faire un mod, qui prend cela en charge. N'hésite pas à demander si tu veux plus d'infos ;) .

A+
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 13 April 2017, 16:06:57
 :top: :top: :top:
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 29 April 2017, 12:37:17
Voici la suite de mes élucubrations, avec le.....
                                        SIXIÈME CHALLENGE: construire les cartes SIPO

Tout comme les modules PISO, il y a un gros travail de soudure, de vérification des continuités électriques, de vérification d'absence de court-circuit, du sens de montage des circuits intégrés, du bon fonctionnement en général. Pour l'instant j'ai monté trois modules SIPO, ce qui me donne la possibilité de piloter 8x12x3=288 sorties.
Pour le premier module, j'ai soudé les 96 résistances de 330Ω sur la plaque ne supportant pas les registres SIPO.

(https://img4.hostingpics.net/pics/363380DSC0564.jpg) (https://www.hostingpics.net/viewer.php?id=363380DSC0564.jpg)


L'expérience montre que ça multiplie les connecteurs, et donc complication et temps passés: à éviter. Je recommande donc de mettre les résistances en série avec les leds directement sur la carte où se trouvent les leds.
Voilà le module SIPO simplifié:

(https://img4.hostingpics.net/pics/824809DSC0528.jpg) (https://www.hostingpics.net/viewer.php?id=824809DSC0528.jpg)

Je mets la petite plaque ci-dessous au cul de la led, en faisant attention au sens de branchement. Pas brancher en direct les leds à la sortie des 74HC595 sinon, led fichue, mais ça vous le savez déjà.

(https://img4.hostingpics.net/pics/863179SupportLED.jpg) (https://www.hostingpics.net/viewer.php?id=863179SupportLED.jpg)

Pour la mise au point, j'ai bien sûr, commencé avec une seule série de 12 registres 74HC595, puis avec deux, et enfin avec les trois séries de 12 registres.
Avec deux séries de registres, j'ai commencé à avoir des problèmes de transmission de DATA à travers l'ensemble des 74HC595. J'ai équipé l'ensemble des 74HC595 de capas de découplage de 1μF entre Vcc et GND, mais je n'ai pas obtenu d'amélioration. En fait, la solution venait par l'agencement des câbles CLK et LATCH: je faisais passer de module en module les fils CLK et LATCH, alors qu'il fallait à chaque fois partir de la carte de support de la UNO. Cette modification de câblage effectuée, il n'y a plus eu de problème dans mes registres SIPO.

La fonction de remplissage des registres a été montrée plus haut. Si on doit rajouter des registres, parce que 288 sorties ne sont pas suffisantes, il faut juste changer la valeur de NumberSIPOreg à la déclaration des variables, afin de l'ajuster au nombre de 74HC595.

Je vous laisse profiter de tout ça. La suite, ça va être de voir comment on initialise tout ça en soft. Amateurs de C, préparez vous!!
Title: Re: Le tableau de commande de Mars Bleu
Post by: antoo on 29 April 2017, 12:56:12
Quel travail de pro! Bravo :top: !
Title: Re: Le tableau de commande de Mars Bleu
Post by: jacquesmomo on 30 April 2017, 00:07:56
Bravo pour le "rangement" des fils et connecteur ! comme le dis antoo : travail de pro...
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 30 April 2017, 15:50:55
Merci, les gars, ça fait toujours plaisir de lire de tels posts.
Maintenant, faut voir la table où je monte tout ça, c'est assez
fouillis (c'est le principe entropique!  :blbl:).
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 16 May 2017, 22:55:58
                          :hurle: Et voici la suite de mes élucubrations! :hurle:

J'ai donc obtenu un système à 144 entrées et 288 sorties. On va pouvoir aborder la programmation de l'initialisation du cockpit en ce qui concerne les auxiliaires fonctionnant avec l'APU. Sur le Xr2, c'est :

   -Gear                            -Airbrakes
   -Radiator                       -Hatch
   -Retrodoors                   -Hoverdoors
   -Scramdoors                  -Baydoors
   -Innerdoor                     -Chamber (ici, pas de raccourci clavier)
   -Outerdoor                    -Nosecone
             Et enfin, l'APU.



Au total 11 auxiliaires dont il faut connaître l'état, et la position. Chamber est un cas particulier, car on n'a pas de raccourci clavier pour la gestion de ce paramètre. APU aussi, car il commande tout le reste, et on ne tient pas compte du temps d'un éventuel démarrage ou arrêt à l'initialisation. (Constatation faite sur le terrain)

L'idée étant d'avoir un code aussi compact que possible, le mieux a été de stocker les états des auxiliaires dans des unsigned int codés sur deux octets, soit 16 bits. En donnant un poids à chaque marqueur d'auxiliaire, on part du MSB pour l'APU, et on descend en poids. Treize bits vont être nécessaires, et on va avoir trois bits disponibles (les trois LSB)

Plusieurs variables vont être nécessaires, car on doit savoir si chaque auxiliaire est à l'arrêt/fermé, en cours de démarrage/ouverture, démarré/ouvert, ou en cours d'arrêt/fermeture, soit quatre possibilités. Or dans les scn, on a:

                                   Valeur scn          Valeur scn en binaire       Transit_status      Switch_status

Arrêté/Fermé                        0                              00                          0                        0
Démarrage/Ouverture           3                              11                          1                         1
Démarré/Ouvert                   1                              01                          0                         1
Arrêt/Fermeture                   2                              10                          1                         0

On voit qu'on peut tirer de ce petit tableau deux valeurs: Transit_status qui va caractériser le mouvement et Switch_status qui va caractériser un ordre: ouvert/déployé ou fermé/replié. On élabore  Transit_status et Switch_status en fonction du poids donné à chaque auxiliaire. Par exemple, pour l'APU en marche, c'est le MSB de Switch_status qui sera positionné à 1.

Toujours pour la compacité du sketch Arduino, j'ai choisi de mesurer une durée avant fermeture complète. La position d'un auxiliaire va être comptée en millisecondes avant la fermeture complète, et c'est la valeur transmise par le script Lua à partir d'une règle de trois tenant compte de la valeur comprise entre 0 et 1 trouvée dans le scn, et de la durée de transit total refPosition[ ] en millisecondes de l'auxiliaire considéré (par exemple, 6.7 secondes, soit 6700 ms pour Gear => valeur fournie par la doc du Xr2).
La durée de transit la plus longue est celle du radiateur, qui est de 32 secondes, soit 32000 ms, ce qui est inférieur à la valeur max de 65535 (les 16 bits d'un unsigned int à 1)

La séquence d'initialisation doit attendre un flux d'octets en provenance du script Lua. Ce flux doit bien sûr être élaboré selon un protocole bien précis. Dans ce but, le script Lua envoie au port USB les éléments du tableau des positions d'auxiliaires, plus les deux derniers éléments contenant respectivement Transit_status et Switch_status. Du côté Arduino, les données arrivent dans le buffer d'entrée (24+2+2=28 octets), et sont chargées dans un tableau Position[3 à 14], plus les valeurs Transit_status, et Switch_status.

Les 28 (ou plus) octets sont envoyés par le script Lua (ce sont les fonctions "widdernix"=>voir le#31).

La carte Arduino réceptionne ces données, et connaît donc la position et l'état des auxiliaires.

C'est tout pour aujourd'hui: bonne digestion!!! Et pas de  :sick:, ni de  :arg: et encore moins de  :wall: dans le fond!

                          Si vous avez des questions, je suis là pour vous renseigner avec plaisir.

Dans un prochain post, j'expliquerai comment le sketch Arduino traite les données réceptionnées, afin de synchroniser le cockpit avec le scénario chargé.



Title: Re: Le tableau de commande de Mars Bleu
Post by: antoo on 17 May 2017, 06:49:02
Cool :top: !
Title: Re: Le tableau de commande de Mars Bleu
Post by: jacquesmomo on 18 May 2017, 19:16:43
(https://www.surlatoile.com/smileys/repository/Respect/respect-chapeau.gif) hébédisdonc....
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 18 May 2017, 22:23:39
Merci les gars pour votre présence. Ça me soutient et m'encourage pour
expliquer le déroulé de la conception de mes montages.
Title: Re: Le tableau de commande de Mars Bleu
Post by: antoo on 18 May 2017, 22:39:54
Avec plaisir l'ami. On attend la suite avec impatience :) !
Title: Re: Le tableau de commande de Mars Bleu
Post by: Gingin on 20 May 2017, 10:07:24
Wow, très solide aussi de ce coté là .  :beer:
Tes explications sont intéressantes, je n'y connais pas grand chose dans ce milieu, et ca me pousse à aller m'informer un peu plus sur tous ca.

Chapeau en tout cas. Est ce déjà opérationnel en partie?
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 20 May 2017, 16:12:49
@Gingin: Oui, oui. Tout ce que je décris est fonctionnel. Les auxiliaires fonctionnant avec la
marche de l'APU, le gimbal des moteurs, le COG (center of gravity) sont gérés. Le contrôle d'attitude
de l'engin également(RCS LIN et ROT, Undock); c'est bien pratique pour les appontages en orbite.
Pour l'instant, je travaille sur le contrôle des pilotes auto. Ça n'avance pas très vite, car je fais
des modifs en permanence, afin de m'adapter aux caprices de l'électronique. Mais ça avance...

J'ai aussi à faire les plans à partir du site  https://easyeda.com/
pour m'y retrouver plus tard pour dépannage ou modif.

Plus voir avec un fablab pour me faire des faces avant rétroéclairées qui soient un peu jolies.

Et pour montrer le fonctionnel, éditer quelques vidéos. Programme chargé!
Title: Re: Le tableau de commande de Mars Bleu
Post by: Gingin on 21 May 2017, 09:24:30
Super  :top: :top:

Tu as des photos des faces rétro éclairées?
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 02 June 2017, 17:48:38
Désolé de te décevoir, mais pour l'instant, je n'ai pas de faces rétroéclairés.  :sad:
C'est encore à l'état de projet, sous forme de dessin vectoriel.
Je suis en mode provisoire, avec des bouts de contreplaqué percés pour y installer 
les divers switches et autres boutons-poussoirs.

      :explique: De patience, preuve tu dois faire!  :explique:
Title: Re: Le tableau de commande de Mars Bleu
Post by: jacquesmomo on 02 June 2017, 23:59:13
:explique: de patience preuve nous ferons... :explique: :hot: impatient moi je suis de voir...
 :badsmile:
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 05 June 2017, 08:22:30
Pour les :hot: impatients :hot:
Ça fait quelque chose comme ça:

(https://img15.hostingpics.net/pics/614221APUfull.jpg) (https://www.hostingpics.net/viewer.php?id=614221APUfull.jpg)

Quelques explications:
Le rectangle situé sous "APU fuel" sera découpé, afin de laisser voir quatre afficheurs 7 segments
donnant la quantité d'APU fuel restante en pourcentage du plein.

Les cercles "mismatch" sont des leds rouges de discordance allumées en cas de différence entre l'état
logique de tel ou tel auxiliaire, et la position du switch correspondant. En cas de discordance, manœuvrer
le switch l'alignera sur l'état logique de l'auxiliaire considéré. Le but étant qu'à l'initialisation, on éteigne
toutes les discordances par la manœuvre des switches discordants.

La rangée de cercles située immédiatement en dessous est de couleur jaune, tandis que la suivante
sera verte, indiquant la position "rentrée atmosphérique": tout est vert, tout est clair.

Enfin, la rangée de cercles inférieure correspond au passage des switches de commande.

Je n'ai pas de calendrier précis pour la confection d'un tel synoptique... C'est qu'il y a énormément à faire par
ailleurs, surtout dans la confection du câblage des cartes.
Title: Re: Le tableau de commande de Mars Bleu
Post by: antoo on 05 June 2017, 13:35:37
Ulta stylé ! En gros tu nous fais un XR2 complet quoi :) !
T'as plus qu'à chercher une vieille carlingue de A-6E americain :badsmile: (chasseur 2 places un peu comme le xr2 ...) .

A+
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 05 June 2017, 14:26:09
Ouais, mais mon épouse y trouverait à redire :badsmile:
Déjà qu'elle rouspète gentiment quand elle s'approche
de ma table atelier...
Mais c'est vrai que ça serait bien. Il y aurait moyen de prendre un passager, et on aurait
des belles tenues de vol! ( Spacesuit-casque-gants pour les décollages et rentrées; combi bleu
NASA pour la croisière)
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 11 June 2017, 14:11:17
 :explique: Dans le #59, j'élucubrais que dans un prochain post, j'expliquerai comment le sketch Arduino traite les données réceptionnées, afin de synchroniser le cockpit avec le scénario chargé.
Cela consiste à la....

                                                        Gestion des leds des auxiliaires APU



Un auxiliaire APU en mouvement doit être caractérisé par le clignotement de sa led associée: verte pour repli/fermeture, jaune pour déploiement/ouverture. Afin d'éviter de coûteuses et compliquées lignes de commandes dans le sketch, j'ai choisi d'utiliser le 1hz dont j'ai déjà parlé. Ce 1hz élaboré à partir d'un 555 est connecté à une entrée de la UNO, et va être exploité dans le sketch par une fonction booléenne ET.

Dans Orbiter, les switches ne sont pas concrets. A l'initialisation du simpit, les vrais switches peuvent se retrouver en discordance par rapport à l'état logique (issu du scn) du vaisseau. J'ai choisi de monter des leds rouges clignotantes qui vont être activées en cas de XOR entre l'état des switches, et celui du vaisseau dans Orbiter. Ces leds sont aussi activées en cas de manœuvre switch alors que l'APU est arrêté.

Si une discordance apparaît, la manœuvre du switch associé fait disparaître cette discordance: on aligne le cockpit sur l'état du vaisseau issu du scn Orbiter.

En résumé, à chaque switch va être associé un groupe de trois leds: verte (replié/repli), jaune (déployé, déploiement), et rouge (discordance).
                  Les leds vertes sont associées à PISOreg[0]
                  Les leds jaunes sont associées à PISOreg[1]
                  Les leds rouges sont associées à PISOreg[2]


Plutôt que de traiter chaque switch séparément, j'ai préféré traiter l'ensemble des données unsigned int avec des bitwise. Cela permet d'éviter tout un tas de if...else if , et de faire un code compact. Après bien des essais et mises au point pour tenir compte de toutes les possibilités, j'ai obtenu:

    Mismatch_status=(PISOreg[0]^Switch_status);//élaboration des discordances entre l'état logique et physique du simpit
    APU_mismatch=(Transit_status&(65535*(Position_APU==0)));//élaboration des discordances liées à un mvt de switch alors que APU indisponible
    SIPOreg[0]=((~Switch_status&~Transit_status)|(Transit_status&Onehz))&(~Switch_status);// Gestion des leds vertes
    SIPOreg[1]=((Switch_status&~Transit_status)|(Transit_status&~Onehz))&(Switch_status);//   Gestion des leds jaunes
    SIPOreg[2]=Mismatch_status|APU_mismatch;// Gestion des leds rouges
    survey_Position();// envoi à la gestion des fin de course des auxiliaires APU     




Nota:   & correspond à l'opérateur booléen AND
           |  correspond à l'opérateur booléen OR
          ~ correspond à l'opérateur booléen NOT
          ^ correspond à l'opérateur booléen XOR


Pour produire ces petites équations logiques, il a fallu que je revoie mes notions sur les tableaux de Karnaugh, de lointains souvenirs…

Ces quelques lignes de codes placées dans un boucle d'initialisation permettent aux valeurs Switch_status et Transit_status envoyées par le script Lua et reçues par le sketch Arduino  de commander dans un premier temps l'allumage des 3x13=39 leds du panneau auxiliaires APU.


Nous verrons plus tard comment tenir compte de l’écoulement du temps afin faire rendre compte au panel de la variation de l'état des auxiliaires APU.
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 01 July 2017, 09:57:11
Il est grand temps de vous expliquer comment je m'y suis pris pour tenir compte de l'écoulement du temps dans le mouvement des auxiliaires animés par l'APU.

En effet, il se peut que le scénario comprenne des mouvements d'auxiliaires en cours. Il faut donc mettre à jour les états des leds pour tenir compte de l'évolution de la situation. C'est la raison d'être de la fonction survey_Position();

Cette fonction va, entre autres, comparer bit à bit l'état de Switch_status et Transit_status, afin de déterminer si l'auxiliaire associé est en fermeture/fermé ou en ouverture/ouvert. Selon le cas, on va incrémenter ou décrémenter la valeur Position[ ] jusqu'à ce qu'on arrive à une valeur de "fin de course", égale à zéro ou bien à refPosition[ ].


for (byte rank=3;rank<15;rank++)                   // Nota:la marche de l'APU devra aussi être liée au niveau de carburant APU
    {
      if ((bitRead(Switch_status,rank)==1)&(bitRead(Transit_status,rank)==1))
      {                //  si auxiliaire en ouverture
       Position[rank]=Position[rank]+((millis()-mem_time)*(APUrunning*(bitRead(interswitch_control, rank))));//incrémentation: on est en ouverture, à la condition que APU soit en fonction
        if (Position[rank]>(refPosition[rank]-50))//si dépassement position(à 50 ms près),...
        {
          Position[rank]=refPosition[rank];// ...recalage à la valeur max
          bitClear(Transit_status,rank);//marque la fin du mouvement. 
        }//endif
      }//endif
      if ((bitRead(Switch_status,rank)==0)&(bitRead(Transit_status,rank)==1))
      {                //si auxiliaire en fermeture
        Position[rank]=Position[rank]-((millis()-mem_time)*(APUrunning*(bitRead(interswitch_control, rank))));//décrémentation: on est en fermeture, à la condition que APU soit en fonction
        if (Position[rank]<50)// on est à 5/100° de seconde de la fermeture; c'est pour éviter de passer <0 car on est en "unsigned int"
        {
          Position[rank]=0;//si dépassement position, recalage à la valeur min, c a d zéro
          bitClear(Transit_status,rank);//marque la fin du mouvement.
        }//endif
      }//endif      
    }//"next rank, on passe au mouvement de l'auxiliaire suivant"



Pour rappel, le tableau Position[] contient une valeur numérique unsigned int étant une distance temporelle en ms de la position fin de course basse de l'auxiliaire APU désigné par rank.
Le tableau refPosition[] contient les valeurs en ms de durée de transit total entre fin de course basse et fin de course haute de chaque auxiliaire. Ce tableau est essentiel pour connaître le moment où un auxiliaire est complètement ouvert ou déployé. Pour l'état rétracté ou fermé complètement c'est la même valeur pour tout le monde: zéro. Pas la peine de faire un tableau pour ça. :badfinger:

La valeur(millis()-mem_time) mesure l'intervalle de temps écoulé entre deux passages dans la boucle.

Vous aurez aussi remarqué la valeur interswitch_control. Elle sert à autoriser ou inhiber en dernier ressort un mouvement. En effet, nous savons que si le Xr2 est posé au sol sur son train d’atterrissage, on ne peut pas le replier. De même, si nosecone fermé, pas d'ouverture possible de outerdoor. D'où interswitch_control.

Une fois tous ces calculs faits, on envoie le contenu de SIPOreg[0 à 2] dans les registres par la fonction déjà évoquée, updateRegister(SIPOreg);  c'est une mise à jour des registres à décalage de sortie: on rafraîchit l'affichage de toutes les leds APU.
Tout ceci n'est qu'un début, qui ne s'est pas mis au point tout à fait facilement. Mais un des principaux obstacles qu'était la synchronisation du cockpit avec le fichier scn a été surmonté. J'ai essayé toutes les configurations de départ possibles, y compris celles les plus improbables, et je n'ai pas réussi à prendre en défaut mes algorithmes pour l'instant.

Mais on n'est pas encore au bout de nos peines: il faut encore pouvoir envoyer un raccourci clavier (ou non) à chaque mouvement de switch. Ça a l'air simple comme ça, mais c'est plus compliqué qu'il n'y paraît.

 :explique: Bonne lecture, en attendant la suite!! :salut:
Title: Re: Le tableau de commande de Mars Bleu
Post by: antoo on 01 July 2017, 13:56:17
Intéressant!

A+
Title: Re: Le tableau de commande de Mars Bleu
Post by: jacquesmomo on 03 July 2017, 08:19:37
(...)
 Ça a l'air simple comme ça, mais c'est plus compliqué qu'il n'y paraît.
:trucdeouf: hébé...
Title: Re: Le tableau de commande de Mars Bleu
Post by: Mars Bleu on 03 July 2017, 08:39:34
@ Jacquesmomo, ne t'inquiètes pas, si j'ai réussi à faire fonctionner tout ça,
alors tout le monde peut le faire!!

@Antoo,  j'espère que ton projet avance bien.

@ tous les lecteurs, j'espère que la balade vous plaît.
Title: Re: Le tableau de commande de Mars Bleu
Post by: antoo on 03 July 2017, 21:14:32
Quote
@Antoo,  j'espère que ton projet avance bien.

Oui, vous aurez des news serieuses et photos demain soir :) .