Cockpit KSP

Note

Pour ne rien vous cacher, il ne s’agit pas ici d’un tutoriel concernant la domotique mais j’ai passé tellement de temps sur ce cockpit que je voulais quand même partager mon expérience. Et comme on reste quand même dans du pur DIY, on peut considérer que ce tuto a presque toute sa place ici ! 🙂

Si vous ne connaissez pas le jeu Kerbal Space Program mais que la conquête spatiale vous intéresse (la vraie : avec ses mises en orbites, ses trajectoires de transfert et autres dockings de ravitaillement), je vous incite grandement à découvrir cette petite merveille unique en son genre. Le jeu vous propose ni plus ni moins que d’explorer tout un système solaire, à échelle réelle, et cela de manière réaliste (malgré la dégaine particulière des astronautes : les Kerbals).

Qu’est-ce qu’on va faire ?

Le but de ce tuto est donc de contrôler le jeu Kerbal Space Program avec des interrupteurs, des leds, des boutons poussoirs montés manuellement par nous-même sur un tableau de commande fait maison. Pour faire cela, on aura besoin de travailler sur 4 domaines principaux :

  • la construction en tant que telle avec scie, perceuse et marteau
  • la partie électronique avec le montage des composants à l’aide d’un fer à souder
  • la partie programmation au niveau du jeu qui se fera en Python via le mod kRPC
  • la programmation au niveau des composants électroniques qui se fera via l’Arduino

Vous l’aurez compris, il s’agit donc d’un projet plutôt ambitieux qui couvre beaucoup de champs de compétences. Il vous faudra donc être bien motivé pour mener votre construction au bout. Heureusement, je serai là pour vous simplifier la tâche en vous proposant directement une solution simple et fonctionnelle avec tout ce que vous aurez besoin de savoir ! 🙂

Au niveau de la forme, mon projet a pris celle d’un cockpit mais vous pouvez tout à fait faire plus simple en montant vos éléments sur un boîtier de commande d’un format plus modeste que vous placerez devant votre écran à la place de votre clavier. Une fois votre boîtier de commande terminé, vous connaîtrez alors la joie extrême de presser le bouton « Launch » pour voir votre fusée s’envoler vers l’espace tout en gérant son accélération en poussant la manette des gaz ! 😀

Comment on va le faire ?

Pour mettre en oeuvre un tel boîtier de commande, de nombreux chemins sont possibles (par la suite, on appellera le boitier « controller« , en anglais, pour faire plus simple ; je vous invite d’ailleurs à tester la recherche Google « ksp controller« ). Il existe plusieurs mods sur KSP qui peuvent communiquer avec l’Arduino et ceci peut se faire en plusieurs langages de programmation. Après avoir fait quelques recherches et de nombreux tests, j’ai bien dû faire un choix et donc m’arrêter sur une solution qui, avec le recul, a plutôt bien fonctionné. Je vous présenterai donc cette solution spécifique « clé en main » mais sachez que pour les plus téméraires d’entre vous, il est tout a fait possible de faire autrement en se renseignant sur internet et en se relevant les manches. 😉

La solution que j’ai choisie et qui fonctionne très bien (je suis sous Windows 10 pour info) consiste en l’utilisation de 3 outils : le trio gagnant Arduino/Python/kRPC !

Comment tout cela va se passer techniquement ? Eh bien en gros, les commandes du controller seront transmises à l’Arduino (qui gère la partie matérielle : leds et boutons) qui transmettra ensuite à Python qui, lui-même, transmettra à KSP via le mod kRPC installé sur le jeu. À l’inverse, les valeurs de retour (données d’altitudes, de vitesse…etc…) seront streamées par Python via le mod kRPC et ensuite transmises à l’Arduino qui les retranscrira sur le controller en commandant l’allumage de leds par exemple. Plutôt simple, non ? Hmm non d’accord, pas vraiment… 🙄

Arduino, Python et kRPC
Fonctionnement logiciel de notre controller

Faire son plan

Avant de se lancer dans la fabrication en tant que telle, il faut déjà définir quelles seront les fonctions de votre boîtier de commande. Pour cela, vous pouvez vous inspirer des modèles déjà conçus par d’autres geeks dont voici un petit florilège.

Différents controllers réalisés par des fans de KSP
Différents controllers réalisés par des fans de KSP

Pour plus d’infos, vous pouvez voir les liens suivants :

Vous trouverez ci-après une liste de composants que vous pouvez utiliser. Vous pouvez bien sûr compléter cette liste avec d’autres composants, je voulais ici vous donner déjà les bases. Il vous faudra ensuite passer tout ça à la moulinette et écumer internet pour faire vos choix et vous imaginer alors avec votre boîtier terminé, en étant sûr qu’il ne manquera rien.

Pour info, voici le plan complet de mon cockpit une fois cette étape terminée et après de nombreuses versions remaniées.

Plan complet du cockpit
Plan complet du cockpit

J’étais d’abord parti sur un controller « classique » constitué d’un boîtier et puis, chemin faisant, je me suis dit que ce serait mieux d’intégrer tout ça dans un gros cockpit. J’ai donc petit à petit séparé les éléments de mon controller en modules et panneaux différents : joystick et souris en bas à droite, gaz et staging en bas à gauche, altitudes et ressources en face et enfin panneau de commandes en haut. Dans un esprit de récup, j’ai essayé d’utiliser un maximum de pièces que j’avais déjà sur de vieux appareils inutilisés, ce qui explique que je me sers parfois de potentiomètres comme de simple bouton on/off ou que mes leds sont un peu petites… Bref, on fait avec ce qu’on a ! 😉

Liste de course

« Je fais confiance à Tutomotique les yeux fermés, qu’est-ce qu’il me faut ? »
En tout et pour tout il vous faudra :

  • Une (ou plusieurs) carte Arduino ou équivalent : Uno, Mega
  • Une breadboard et des fils
  • Une résistance de 220 Ω par led utilisée (si vous prenez des leds classiques)
  • Une résistance de 4.7 KΩ (si vous avez un potentiomètre)
  • Un condensateur de 10μF (si vous avez un potentiomètre)

Pour tout cela, je vous conseille le starter kit suivant qui contient le tout : Starter kit

Niveau prix, le montant total de l’addition va évidemment beaucoup dépendre de vos choix de composants. Pour vous donner une idée, mon projet m’aura coûté en tout 260€ (80€ de cartes/kit Arduino + 50€ d’interrupteurs/leds + 100€ de 7 segments + 30€ de joystick USB, le reste étant de la récup).

Les composants électroniques

Pour les commandes de bases, vous avez en gros le choix entre 3 types de boutons :

Différents types de boutons
Les différents types de boutons, poussoirs ou à bascule

Il existe aussi des boutons spéciaux, comme les boutons à led intégrée ou encore les boutons avec clapet de verrouillage… à vous de regarder aussi ce qui vous plaît.

Pour la commande des gaz, vous voudrez sans doute vous servir d’un potentiomètre à glissière grâce auquel vous pourrez doser la valeur de « throttle » envoyée comme sur une manette de gaz en bonne et due forme.

Pour les commandes de NavBall (directions), vous pouvez utiliser un joystick USB traditionnel ou alors intégrer un joystick en tant que matériel électronique à votre boîtier, solution un peu plus compliquée (et que je ne connais pas) mais plus classe ! 🙂

Joysticks et potentiomètres
Joysticks et potentiomètres

En ce qui concerne les valeurs à afficher (altitude, vitesse…), vous avez le choix entre les afficheurs LCD, qui permettent de regrouper beaucoup d’infos sur un même écran, les plus traditionnels 7 segments ou encore les VU-Mètre (cadrans à aiguille).

LCD, 7 segments et VU-mètre
LCD, 7 segments et VU-mètre

Sachant tout cela vous pouvez maintenant commencer à esquisser ce qui vous plairait pour votre propre controller. À vos plans !

La mode des pins

Je vous rassure on ne parlera pas ici des pin’s TF1 du début des années 90 mais bien des pins (pour « épingles » en français) de l’Arduino. C’est à dire ce qui constitue les entrées et sorties de notre carte Arduino. Celles-ci peuvent être de 2 types : numériques ou analogiques.

Parce que oui, il y a un truc que je ne vous avais pas dit, c’est qu’il faut aussi compter le nombre de pins nécessaires à votre projet en fonction de ses composants. En gros, il vous faut un pin par led et un pin par bouton (voir plus bas le détail sur chaque composant). Sachant cela vous reverrez donc peut être vos ambitions à la baisse sachant qu’il vous faudra au moins autant de pins sur votre/vos carte(s) Arduino pour contrôler tout ça. Adieu donc les projets à 350 leds individuelles pour former une tête de mort en cas de grave avarie dans le vaisseau ! 😀 À moins bien sûr de se payer 7 Arduino Mega à 50 pins. Pour mon projet, sachez que j’utilise une carte Uno ET une carte Mega pour atteindre un nombre de pins suffisant (80).

Comparatif Arduino Mega et Uno
Le nombre de pins disponibles sur les Arduino Uno et Mega, celles que j’utilise

Pour plus d’infos, voyez ici le détail de toutes les cartes.

 ❗ Note
Les pins analogiques serviront pour les potentiomètres et les pins numériques pour les boutons et leds. Sachez que vous pouvez aussi utiliser les PIN analogiques en tant que PIN numériques ; par contre l’inverse n’est pas vrai. 😉

Mise en place de l’Arduino

Toujours motivé ? Vous êtes bien décidé à réaliser aussi votre propre controller ? Alors voyons déjà le nécessaire à installer sur votre pc.

En premier lieu, il vous faudra une carte Arduino, non seulement pour faire les tests de chacun de vos éléments, mais aussi au final pour laisser sur votre engin. Lors de la réalisation de votre plan, vous verrez à peu près le nombre de pins dont vous avez besoin et donc la (ou les) carte(s) à choisir. Je vous conseille les cartes Arduino Uno et Arduino Mega  (ou leurs équivalents moins chers) qui sont les plus répandues et adaptées aux débutants. Pour faire les tests dans de bonnes conditions, il vous faudra au moins un bouton, des leds et des résistances d’environ 200 Ω donc si vous n’avez pas déjà tout ça en stock je vous conseille l’achat d’un Starter kit Arduino avec tout le contenu nécessaire.

Une fois la carte en votre possession, il vous faut installer et configurer l’IDE pour votre carte. Si vous êtes un habitué de ce site vous devez déjà savoir faire cela, sinon rendez-vous sur cet article. Voyez la partie « Arduino : mise en route » et également la partie « Breadboard » si ce terme ne vous dit rien. 😉

À ce stade, assurez vous que tout fonctionne correctement côté Arduino car il faudra naturellement que chaque composante fonctionne afin de faire fonctionner par la suite toute la chaine Arduino-Python-kRPC. Vous pouvez par exemple téléverser le programme de base « Blink » dans votre carte. Le programme est disponible par défaut dans le logiciel Arduino : Fichier -> Exemples -> 01.Basics -> Blink.

Montage Arduino pour le programme Blink
Montage Arduino pour le programme Blink

Faites le montage électronique ci-contre composé d’une simple led et d’une résistance. Pour une led classique, prenez une résistance de 220 Ω. Notez que les leds ont un sens de montage (une patte + et une patte -), si vous la mettez à l’envers, elle ne s’allumera pas. Les résistances, quant à elle, n’ont pas de polarité et peuvent donc être montées dans n’importe quel sens. 😉

Une fois le montage ok, remplacez dans le programme les 3 « LED_BUILTIN » par le numéro du pin utilisé, ici 13.
Téléverser le programme dans l’Arduino, vous verrez votre led clignoter, ça veut dire qu’on est bon !

Le point résistance

Ici Londres… crrr… Si comme moi vous êtes une bille en électronique, vous vous poser surement des questions sur l’utilité et le fonctionnement des résistances (électriques !). Je vais donc vous faire un topo très grossier et ultra-condensé (si un électronicien lit ces lignes, merci de passer directement au paragraphe suivant afin d’éviter la crise cardiaque… 🙂 ).

Bon, en gros sachez déjà que vous n’aurez pas besoin de résistance pour tout ce qui est bouton (poussoir ou bascule). Cela va principalement servir à ne pas griller les leds de vos circuits. Il en faudra donc généralement une par led. La valeur d’une résistance se calcule grâce à la fameuse formule U = RI.

Loi d'Ohm
Loi d’Ohm : U = RI et donc ici R = U/I

Dans l’exemple ci-dessus, pour une led de base montée sur un Arduino en 5V, on trouve R = 145 Ω.

« Alors pourquoi on a pris du 220 Ω précédemment pour notre test ? »

Car 145 Ω est la valeur théorique, on dit que c’est bien de toujours prendre une résistance un peu plus forte (enfin, j’crois…), donc aux alentours de 200 Ω, or 220 Ω est une résistance très répandue. Après, il faut voir que c’est un ordre de grandeur : si vous mettez du 1000 Ω (1 kΩ) ou même pas de résistance du tout ça fonctionnera aussi (et sans exploser ! 😀 ), mais votre led ne s’allumera que très faiblement ou alors s’usera carrément plus vite.

kRPC et Python

Une fois l’Arduino ok, la seconde étape sera d’installer le mod kRPC sur le jeu. Pour cela vous pouvez consulter l’excellente documentation dédiée de kRPC (celle-là vous pouvez la mettre direct dans vos favoris car vous y reviendrez environ 150 fois dans votre projet !). Comme je suis sympa je vous fais un résumé :

  • Téléchargez les fichiers depuis Curse ou autre
  • Copiez le contenu du répertoire GameData de l’archive dans le GameData de votre installation KSP (si vous utilisez Steam, le chemin doit être quelque chose comme C:\Program Files (x86)\Steam\steamapps\common\Kerbal Space Program\)
  • Lancez le jeu et chargez une partie, vous devriez voir une nouvelle fenêtre avec un bouton Start server, cliquez dessus, si tout se passe bien, la petite lumière de la fenêtre passera au vert.

Enfin, la dernière étape va être d’installer Python sur votre machine. Rendez-vous sur le site de Python pour télécharger la dernière version et l’installer sur votre poste. Vous pouvez changer le répertoire d’installation (ne décochez rien par contre) pour quelque chose comme c:\python37\ car sinon le programme vous propose par défaut un emplacement à coucher dehors…

Ensuite, il faut ajouter les 3 librairies Python dont on aura besoin pour nos travaux, à savoir kRPC, pySerial et keyboard. Pour cela, rendez-vous dans l’invite de commande Windows (raccourci : win+x puis c) et tapez les 3 commandes suivantes en faisant « Entrée » à chaque fois :

c:/python37/scripts/pip.exe install krpc
c:/python37/python -m pip install pyserial
c:/python37/scripts/pip.exe install keyboard

(Les commandes sont à adapter en fonction de votre répertoire d’installation de Python, of course ! 😉 )

Tester kRPC

Je vous invite maintenant à faire un premier test de kRPC comme indiqué sur leur site. En gros, il s’agit de faire un simple « Hello World » depuis Python vers le jeu.

Fonctionnement de kRPC et Python
Fonctionnement de kRPC et Python

Pour cela, lancez l’IDLE de Python (à mettre en raccourci sur votre bureau également). Une fois dans le programme vous pouvez faire File -> New File pour ouvrir un nouveau programme. Copiez collez le programme suivant :

import krpc
conn = krpc.connect(name=’Hello World’)
vessel = conn.space_center.active_vessel
print(vessel.name)

Sauvegardez-le puis cliquez sur le menu Run -> Run Module.
Python va alors exécuter le programme.
Retournez sur KSP (qui doit toujours tourner pendant ce temps), vous devriez avoir un message dans la fenêtre de kRPC indiquant : « Hello World @ 127.0.0.1 ».
Côté python, le programme a aussi dû vous donner le nom du vaisseau actuel sous KSP. Cela veut dire que la communication passe bien dans les 2 sens.

Si c’est bien le cas, tout est ok, vous pouvez continuer ! 😉 Sinon je vous invite à lire la doc fournie par le site officiel (en anglais) et notamment le paragraphe sur la configuration.

Procédure globale

Maintenant que toutes les composantes du système sont au vert, c’est le grand jour ! Nous allons pouvoir faire un test « grandeur nature » du système global. Le but de la manœuvre ici va être de déclencher le décollage d’une fusée via un bouton connecté à l’Arduino. Coooool ! 😮

Bouton décollage fusée
Prêt à décoller ? Appuyez sur le bouton !

Voyons d’abord la procédure globale qu’il faut utiliser pour tous vos tests de composants :

  1. Réalisation du montage électronique sur la breadboard reliée à l’Arduino
  2. Écriture du code pour l’Arduino et téléversement dans celui-ci
  3. Écriture du code Python sous l’IDLE
  4. (avoir KSP lancé sur votre poste avec un vaisseau sur le pas de tir)
  5. Éxecution du code Python

Il faut toujours avoir ce schéma-là en tête et réfléchir « côté boutons » en lien avec le code Arduino et « côté jeu » en lien avec le code Python. Arduino et Python communiquent entre eux par le port série (Serial port).

Note
Si vous utilisez le moniteur série ou le traceur série sur l’Arduino, vous ne pourrez pas lancer le script Pyhton car celui-ci utilise le même port série. Il faudra donc choisir entre le débogage côté Arduino ou côté Python.

Alors c’est parti pour le test du bouton !

Le bouton

Montage bouton seul
Montage bouton seul

On connectera pour cet exemple l’un des côtés du bouton au GND de l’arduino et l’autre au pin n°7. Au niveau de l’Arduino, on aura le code suivant :

//initialisation des 2 variables d’état du bouton dont on aura besoin
int etatNowBoutST = 0;
int etatLastBoutST = 0;

void setup(){

Serial.begin(9600);//initialisation port série
pinMode(7,INPUT_PULLUP);//pin n°7 en entrée (bouton)

}

//à chaque boucle
void loop(){

etatNowBoutST = digitalRead(7);//on lit la valeur du pin 7

if(etatNowBoutST != etatLastBoutST){//si l’état du bouton est différent de précédemment

Serial.println(« boutST »);//on envoie le message « boutST » au port série
etatLastBoutST = etatNowBoutST;//on met à jour la variable d’état actuel
delay(100);//délai de 100ms par sécurité

}

}

Ce code envoie le message de staging (changement d’étage sur la fusée) à chaque changement d’état du bouton (on/on). Si vous souhaitez que le message ne soit envoyé que lorsque le bouton est sur 1 et non sur 0, vous pouvez remplacer le code ligne 12 par le suivant :

if(etatNowBoutST == 1){Serial.println(« boutST »);}

Côté Python on a le code suivant :

#import des librairies dont on aura besoin
import time, serial, krpc, keyboard
#initialisation port série (utilisez le n° de COM de l’arduino)
arduino = serial.Serial(‘COM5’, 9600, timeout=.1)
#on attend 1 sec le temps que la connection se fasse
time.sleep(1)
#on se connecte à kRPC dan le jeu
conn = krpc.connect(name=’Soyouz’, address=’127.0.0.1′, rpc_port=50000, stream_port=50001)

#BOUCLE
while True:

#on lit la donnée de l’arduino
data = arduino.readline()[:-2].decode(‘utf-8’)
#si la donnée existe et qu’elle vaut « boutST »
if data and data == « boutST »:

#simulation d’un appui sur la touche espace
keyboard.press_and_release(‘space’)
#200ms de temps mort par sécurité
time.sleep(.200)

Le code Arduino a bien été téléversé ? Le script Python est en cours d’exécution ? KSP est paré avec la connexion kRPC ok ? Alors appuyez sur le bouton !

La fusée s’envole ? Weeeeell done !!! 😛

Nous allons voir maintenant les montages et les codes nécessaires pour les principaux types de commandes. Let’s go !

Boutons à leds

Bouton à double leds
Bouton à double leds

Lorsque l’on souhaite associer l’allumage d’une led à un bouton (on/off), la technique classique consiste à raccorder à l’Arduino le bouton puis la led et de commander ensuite l’allumage avec un morceau de code. Par exemple : « Si le SAS est sur on : alors -> allumer la led n°5 ».

Cependant si, comme moi, vous comptez appliquer ce schéma sur un grand nombre de boutons (SAS, RCS, Lights, Panels, Breaks…), vous aurez vite besoin de beaucoup de pins, ce qui est problématique car ceux-ci sont en nombre limité sur nos cartes… Je vous présente donc ici une astuce maison qui vous permettra, avec le bon montage électronique, d’économiser un précieux pin et donc de réduire de moitié le nombre de pins nécessaires à vos boutons à leds, bon à savoir !

Schéma électronique avec bouton à led
Montage avec bouton à led

Avec ce montage, vous n’aurez donc pas à vous occuper du code de la led, appliquez simplement le même code que pour un bouton classique. L’inconvénient est que l’allumage de la led n’est pas directement lié à l’état du jeu lui-même. Je m’explique, la led s’allumera quoi qu’il arrive quand vous actionnerez le bouton même si le jeu n’est pas lancé. Cela implique de penser à remettre les boutons sur off avant de lancer le jeu afin que celui soit en phase avec vos leds. Un petit désagrément, je trouve, pour une solution qui nous fait économiser des pins et du code ! Après, c’est à vous de voir ! 😉

Dans le même esprit, un montage est également possible pour un interrupteur à bascule avec deux leds. J’utilise ce type d’interrupteur pour alterner par exemple entre les 2 vues du jeu : map et vaisseau. Par défaut, le jeu est sur la vue du vaisseau, la led 1 est allumée. Si je bascule l’interrupteur le jeu passe en mode map, la led 1 s’éteint et c’est la 2 qui s’allume.

Montage du bouton à double leds
Montage du bouton à double leds

Potentiomètre

Potentiometre
Le potentiomètre fait office de manette des gaz

Voyons maintenant le fonctionnement du potentiomètre, dont nous nous servirons pour créer la manette (analogique) des gaz, l’équivalent des touches MAJ et CTRL dans le jeu. Personnellement, j’utilise un potentiomètre à glissière mais cela fonctionnerait exactement pareil avec les modèles rotatifs.

Montage du potentiomètre
Montage du potentiomètre avec résistance et condensateur

Le potentiomètre est le gros élément à gauche. Nous avons aussi sur ce montage une résistance et un condensateur (attention au sens de celui-ci). On connectera le potentiomètre sur le pin analogique A1. Voyons le code Arduino :

int etatNowBoutTH = 0;
int etatLastBoutTH = 0;

void setup(){

Serial.begin(9600);
pinMode(A1,INPUT_PULLUP);//pin analogique n°A1 en entrée

}

//à chaque boucle
void loop(){

etatNowBoutTH = analogRead(A1);//on lit la valeur du pin A1

//si la valeur est différente de précédemment (avec un écart de plus de 10)
if(etatNowBoutTH > etatLastBoutTH+10 || etatNowBoutTH < etatLastBoutTH-10){

Serial.println(etatNowBoutTH);//on envoie la valeur au port série
etatLastBoutTH = etatNowBoutTH;//on met à jour la valeur actuelle
delay(100);//délai de 100ms pour ne pas surcharger

}

}

Vous pouvez voir que le code est très similaire à celui du simple bouton, si ce n’est qu’on envoie directement la valeur que le potentiomètre enregistre et non pas un message textuel. La valeur du potentiomètre par défaut varie entre 0 et 1024. Ici, la valeur est envoyée seulement lorsque l’écart avec la valeur précédente est supérieur à 10. Le nombre d’envois par seconde est ainsi grandement réduit, ce qui permet de ne pas saturer le port série tout en gardant une fluidité dans les commandes. Vous pouvez essayer de modifier ce nombre pour en voir les effets et mieux vous rendre compte. Vous pouvez voir cela notamment avec le Traceur Série (Outils) de l’interface Arduino qui vous dessinera une jolie courbe avec les valeurs mesurées. 🙂

Niveau Python :

#initialisation
import time, serial, krpc, keyboard
arduino = serial.Serial(‘COM5’, 9600, timeout=.1)
time.sleep(1)
conn = krpc.connect(name=’Soyouz’, address=’127.0.0.1′, rpc_port=50000, stream_port=50001)

#on définit le vaisseau
vessel = conn.space_center.active_vessel

#BOUCLE
while True:

data = arduino.readline()[:-2].decode(‘utf-8’)
#si la donnée existe et que la longueur est inférieure à 5
if data and len(data) < 5:

#on convertit la donnée en un nombre à 2 décimales compris entre 0 et 1
throttle_valeur = round(float(data) / 1000, 2)
#si la valeur est presque à 0 -> on la met à 0.00
if throttle_valeur < 0.05 : throttle_valeur = 0.00
#si la valeur est presque à 1 -> on la met à 1.00
elif throttle_valeur > 0.95 : throttle_valeur = 1.00
#on dit au jeu : régle les gaz du vaiseau sur cette valeur
vessel.control.throttle = throttle_valeur

Pour différencier toutes mes autres données de bouton (SAS, Stage…) des données de gaz, j’utilise la condition « longueur inférieur à 5« . En effet, la valeur reçue du potentiomètre est toujours comprise entre 0 et 1024, donc inférieure à 5 « caractères ». Je me débrouille ensuite pour que tous mes messages de boutons fassent 5 caractères ou plus : « boutSAS », « boutST »

Bon d’accord ici ça ne sert à rien car il n’y a que les données du potentiomètre qui arrivent 🙂 mais ce sera utile lorsque vous voudrez combiner ce code avec le code du bouton vu précédemment.

Le fait de forcer le passage à 1 ou à 0 lorsque l’on est proche de ces valeurs est aussi indispensable, surtout pour la valeur 0. On s’assure ainsi que le moteur est bien coupé quand le curseur du potentiomètre est tout en bas ! En effet, vous aurez rarement une valeur tombant « naturellement » sur 0 tout en bas du curseur. Idem pour la pleine puissance monsieur Sulu ! 😀

Voici donc un exemple typique de la communication de l’Arduino vers le jeu. Arduino récupère la valeur analogique du potentiomètre et l’envoie à Python qui se charge de la retransmettre au jeu en temps réel. Nous allons maintenant voir le schéma inverse avec une communication de Python vers l’Arduino pour l’allumage de leds sous certaines conditions.

Les leds

Jauge de carburants en leds
Mes 3 jauges de ressources en leds

Commençons par un exemple simple : nous allons tenter d’allumer une led si le « Warp time » du jeu est engagé, c’est à dire si la vitesse du jeu est supérieure à x1.

Montage d'une led
Montage d’une led simple

On connectera la led sur le pin n°11. Commençons cette fois par le code Python car c’est plus logique dans ce sens cette fois-ci :

#initialisation
import time, serial, krpc, keyboard
arduino = serial.Serial(‘COM5’, 9600, timeout=.1)
time.sleep(1)
conn = krpc.connect(name=’Soyouz’, address=’127.0.0.1′, rpc_port=50000, stream_port=50001)

#BOUCLE
while True:

#on détecte la valeur actuelle du warp
warp = str(int(conn.space_center.warp_rate))
#on envoie cette valeur à l’arduino
arduino.write(warp+’.’)

Lors de la transmission d’une donnée à l’Arduino, nous allons prendre l’habitude de faire suivre la donnée transmise par un séparateur : ici le « . ». Ce sera utile lorsque l’on souhaitera transmettre plusieurs données à la fois. Voyons le code Arduino :

void setup(){

Serial.begin(9600);
pinMode(11,OUTPUT);//pin n°11 en sortie

}

void loop(){

//si on a une donnée transmise
if (Serial.available() > 0) {

//on récupère le premier nombre entier lisible (en l’occurrence la valeur transmise du warp)
float warp = Serial.parseInt();
//si il est plus grand que 1, on allume la led, sinon on l’éteint
if(warp > 1){digitalWrite(11, HIGH);}else{digitalWrite(11, LOW);}
Serial.read();//on lit le « . » séparateur sans rien en faire

}

}

Et voilà, la led s’allume désormais lorsque l’on accélère le temps dans le jeu.

Continuons par un deuxième exemple un peu plus complexe. Nous avons 8 leds représentant le réservoir de carburant de notre fusée. Au départ, toutes les leds sont allumées et on souhaite que les leds s’éteignent une par une au fur et à mesure que le réservoir se vide. Pour simplifier, nous considérerons que la fusée n’a qu’un seul et unique réservoir et donc qu’il s’agit du carburant total de la fusée. Voyons comment faire ça.

Au niveau du montage électrique nous avons la même chose que précédemment sauf qu’il faut cette fois connecter 8 leds à 8 pins différents. Nous utiliserons les pins n°3 à 10 dans l’ordre.

import time, serial, krpc, keyboard
arduino = serial.Serial(‘COM5’, 9600, timeout=.1)
time.sleep(1)
conn = krpc.connect(name=’Soyouz’, address=’127.0.0.1′, rpc_port=50000, stream_port=50001)

#création d’un stream
lf_total = conn.add_stream(vessel.resources.amount, ‘LiquidFuel’)

#BOUCLE
while True:

#on passe la valeur en entier puis en string
fuel_total = str(int(lf_total()))
#puis transmission à Arduino
arduino.write(fuel_total+’.’)

L’intérêt de créer un stream est que les valeurs seront transmises en continue sans ralentissement et en fonction des ressources disponibles du port série. C’est une méthode bien plus stable que la transmission en boucle sans stream et, dans le cas où on transmet de nombreuses données (altitude, vitesse…), elle est également bien plus rapide. Bref, il faut le faire systématiquement pour toutes les valeurs numériques que vous transmettrez sans interruption et durant toute votre partie de KSP à l’Arduino.

int fuel_total;
int fuel_total_max;

void setup(){

Serial.begin(9600);
//création d’une boucle pour déclarer les pins led en sortie
for (int i=3; i <= 10; i++){pinMode(i,OUTPUT);}
//état de départ : on allume les leds ressources
for (int i=3; i <= 10; i++){digitalWrite(i, HIGH);}

}

void loop(){

if (Serial.available() > 0) {

//lecture de la donnée transmise
fuel_total = Serial.parseInt();
Serial.read();// passsage du séparateur

//au passages suivants (voir ci-dessous) on gère les leds
if(fuel_total_max != NULL){

if(digitalRead(10) == 1 && fuel_total <= 0){digitalWrite(10, LOW);}
else if(digitalRead(9) == 1 && fuel_total < fuel_total_max*1/9){digitalWrite(9, LOW);}
else if(digitalRead(8) == 1 && fuel_total < fuel_total_max*2/9){digitalWrite(8, LOW);}
else if(digitalRead(7) == 1 && fuel_total < fuel_total_max*3/9){digitalWrite(7, LOW);}
else if(digitalRead(6) == 1 && fuel_total < fuel_total_max*4/9){digitalWrite(6, LOW);}
else if(digitalRead(5) == 1 && fuel_total < fuel_total_max*5/9){digitalWrite(5, LOW);}
else if(digitalRead(4) == 1 && fuel_total < fuel_total_max*6/9){digitalWrite(4, LOW);}
else if(digitalRead(3) == 1 && fuel_total < fuel_total_max*7/9){digitalWrite(3, LOW);}
else if(digitalRead(2) == 1 && fuel_total < fuel_total_max*8/9){digitalWrite(2, LOW);}

}

//au premier passage on définit la quantité max de fuel
else{fuel_total_max = fuel_total;}

}

}

Et voilà un premier jet pour une jauge de fuel en leds ! 😉 Bon ensuite, il faudra ajouter les jauges de monopropellant, d’électricité, de fuel solide et tout ça au niveau du stage ou du vaisseau complet… Bref, on est pas au bout de nos peines (enfin, moi si ! 😀 ) mais on a la base ! Je vous laisse donc développer aussi selon vos besoins.

Sachez au passage qu’il existe dans le commerce des « Bar Graph » qui sont en fait des jauges de leds pré-assemblées, ce qui peut être pratique dans notre cas. De plus, on peut souvent en contrôler la couleur : vert, jaune ou rouge.

Afficheur 7 segments

Afficheurs 7 segments
Les afficheurs 7 segments indiquent l’altitude et la vitesse

Voyons maintenant un composant un peu particulier dont je me suis servi pour tout ce qui est affichage d’altitudes et de vitesses : l’afficheur 7 segment. Pour me simplifier la vie, j’ai utilisé les afficheurs de chez Adafruit qui sont fournis avec tout ce qu’il faut pour être raccordés et utilisés sur l’Arduino. En effet, il faut savoir que sans ces modules tout fait, si vous utilisez des 7 segments classiques, il vous faudra 7 pins (et 7 résistances) par chiffre utilisé ! Imaginez donc la quantité de travail pour afficher une altitude de 38 451 123 m !!! (Réponse : 8 chiffres x 7 pins = 56 pins et autant de résistances à raccorder, soit une carte Mega par afficheur 8 chiffres) 🙁

Vous l’aurez compris, il est donc plus simple (et pas vraiment plus cher) de partir sur une solution toute prête type Adafruit. Vous pourrez même choisir la couleur de vos chiffres : rouge, vert, jaune ou blanc.

Voici comment ça se passe : une fois que vous aurez soudé votre afficheur sur son « backpack » dédié (contenant toutes les résistances qui vont bien), vous n’aurez plus qu’à le raccorder à 2 pins sur votre Arduino (en plus des pins 5V et GND). Mieux : si vous utilisez plusieurs afficheurs, tous se relieront sur les 2 mêmes pins de l’Arduino et on fera appel aux différents afficheurs via un simple bout de code. Hyper pratique et ultra économique en pins ! 😀

Je vous laisse consulter la page dédiée pour la mise en place niveau soudure, raccordement Arduino et installation des librairies nécessaires.

Maintenant que votre matériel fonctionne, voyons la suite : je vais vous montrer comment récupérer l’altitude du vaisseau et l’afficher sur 2 modules Adafruit de 4 chiffres.

import time, serial, krpc, keyboard
arduino = serial.Serial(‘COM5’, 9600, timeout=.1)
time.sleep(1)
conn = krpc.connect(name=’Soyouz’, address=’127.0.0.1′, rpc_port=50000, stream_port=50001)

#Vaisseau
vessel = conn.space_center.active_vessel
#création du stream
alti = conn.add_stream(getattr, vessel.flight(ref), ‘mean_altitude’)

#BOUCLE
while True:

#on passe la valeur en entier puis en string
altitude = str(int(alti()))
#puis transmission à Arduino
arduino.write(altitude+’.’)

//INCLUDES
#include <Wire.h>
#include <Adafruit_GFX.h>
#include « Adafruit_LEDBackpack.h »

//DEFINITION 7SEGMENTS
Adafruit_7segment matrix70 = Adafruit_7segment();
Adafruit_7segment matrix71 = Adafruit_7segment();

//DEFINITION VAR
long altitude;

void setup(){

//SERIAL
Serial.begin(9600);

//INITIALISATION 7SEGMENTS
matrix70.begin(0x70);
matrix71.begin(0x71);

//état de départ : on affiche des traits sur les 7 segments
matrix70.print(10000, DEC); matrix70.writeDisplay();
matrix71.print(10000, DEC); matrix71.writeDisplay();

}

void loop(){

if (Serial.available() > 0) {

//récup de l’altitude transmise
altitude = Serial.parseInt();
//appel de la fonction d’affichage sur les 2 modules
afficheDouble(altitude, matrix70, matrix71);
Serial.read();//séparateur

}

}

//FONTION POUR AFFICHER SUR 2 CADRANS AVEC POINT AU MILLIERS
void afficheDouble(long datarecu, Adafruit_7segment cadran1, Adafruit_7segment cadran2){

//au dessus de 10 000 : affichage sur les 2 cadrans
if(datarecu > 9999){

//cadran gauche
int data1 = int(datarecu / 10000);
cadran1.print(data1, DEC);
if(data1 > 99){cadran1.writeDigitNum(1, (data1 / 100), true);}//ajout du point décimal n°2
cadran1.writeDisplay();//affichage des dizaine de milliers

//cadran droite
int data2 = datarecu – (data1 * 10000);
cadran2.print(data2);
cadran2.writeDigitNum(0, (data2 / 1000), true);//ajout du point décimal
cadran2.writeDisplay();

}

//en dessous de 10 000 : affichage sur un seul cadran + on efface autre cadran
else if(datarecu >= 0){

cadran1.print(10000, DEC); cadran1.writeDisplay();//on efface le cadran 1

cadran2.print(datarecu, DEC);
cadran2.writeDigitNum(0, (datarecu / 1000), true);//ajout du point décimal
if(datarecu < 10){cadran2.writeDigitNum(3, 0);}//zéro supplémentaires si besoin
if(datarecu < 100){cadran2.writeDigitNum(1, 0);}//zéro supplémentaires si besoin
cadran2.writeDisplay();

}

//données incohérente : on efface
else{cadran1.print(10000, DEC); cadran1.writeDisplay();cadran2.print(10000, DEC); cadran2.writeDisplay();}

}

Côté Arduino, j’ai créé une fonction spéciale permettant d’afficher sur 2 cadrans n’importe quelle valeur sous le format XX.XXX.XXX ! Et pour mes indicateurs de durée (minutes, secondes), j’en ai une autre qui affiche les infos au format 01:12.42:23 pour 1 jour, 12 heures, 42 minutes et 23 secondes.

Montage final

Maintenant, à vous de composer le controller de vos rêves « en kit » à partir des éléments donnés plus haut !

Concernant la fabrication du « meuble/boîtier » en tant que tel, je ne m’attarde pas sur cette partie qui est très souvent bien commentée sur les forums et autres tutos. Sachez juste qu’il va vous falloir jouer de la perceuse et de la scie sauteuse, dans du bois ou du métal, donc à vos outils ! Une bonne solution également consiste à imprimer en 3D votre boîtier et les autres éléments dont vous avez besoin (cadrans, manette…).

Pour la finition, vous pouvez faire imprimer des motifs (les indications à coté des boutons par exemple) sur adhésif transparent que vous collerez ensuite sur votre controller. De mon côté, j’ai eu bien du mal à trouver ce genre d’article pour pas trop cher et qui accepte d’imprimer moins de 50 exemplaires (quand on en a besoin de 1 ! 😀 ). J’ai finalement trouvé mon bonheur chez PrintShot pour une vingtaine d’euros.

Voilà, ce long tutoriel s’achève ici, j’espère vous avoir donné de bonnes bases pour imaginer votre propre projet. J’aurai moi-même appris plein de choses (et pris plein de plaisir ! 😀 ) en réalisant le mien, j’espère donc qu’il en sera de même pour vous !

En bonus, je vous mets l’archive complète de mon projet avec mon code Python, Arduino et le schéma qui va avec pour voir la correspondance composants – pins. Faîtes-en bon usage !

Sur ce, je vous dis : Good night and good luck ! 😉

(Ci-dessous quelques images de la construction du cockpit)

LAISSER UN COMMENTAIRE

Please enter your comment!
Please enter your name here