Club robotique de Sophia-Antipolis

Accueil > Projets, études > Nos réalisations > Projets spéciaux > Hacking du module wifi avec caméra embarqué Walkera

Hacking du module wifi avec caméra embarqué Walkera

samedi 18 janvier 2014, par Frédéric Bernat

Ce module provient du petit quadcopter QR W100 de chez Walkera. Cet Hélico est fait pour être piloté par un smartphone.

On trouve le module wifi sur ebay pour 24 euros, frais de port compris.

Je recherchais depuis longtemps une petite caméra wifi pour l’installer, soit dans mes robots, soit sur mon quadcopter CrazyFlie. Je suis tombé par hasard sur ce quad Walkera en regardant les nouveautés sur le web et en recherchant les pièces détachées, j’ai eu la joie de voir que le module était disponible.

Ce module est basé sur le micro serveur wifi Ralink RT5350F, chip que l’on retrouve dans beaucoup de serveur wifi, de caméra de surveillance de différentes marques.

Le quad copter étant alimenté par un batterie lipo à 1 élément, j’ai tout naturellement pensé que c’était la même chose pour le module. Un fil noir un fil blanc un fil rouge, voyons… Noir la masse, rouge le VCC et blanc le signal !? j’ai branché l’alimentation, sortie mon DSO nano, allumé mon téléphone, downloadé l’appli permettant de piloter le quad copter (C_REMOTE) connecté le wifi, et la que vois apparaitre…

Des trames PPM… Moi qui croyais que j’aurais un bon vieux signal série. En fait, au début j’ai directement branché le module sur mon arduino port RX et dumper les trames.
J’avais bien un signal à 2400 baud mais très étrange, du coup j’ai utilisé mon petit oscilloscope. Ce sont les gap sync régulières entre chaque impulsion qui m’ont mis la puce à l’oreille.

Le signal PPM est utilisé depuis très longtemps en radiocommande.

Petit rappel sur les trames PPM :

Le PPM - Pulse Position Modulation

Dans ce système il n’y a pas de détection d’erreur réalisée, donc si une erreur se produit dans la transmission elle est transmise directement à l’organe concerné (servo de direction, commande de la vitesse…) et entraînera un disfonctionnement mais là on s’en fout puisque la transmission est assurée par liaison WIFI.

• Les impulsions fines durent 300 µs environ. ( c’est le temps de séparation de voie ou inter-voie ). C’est ce qui permet au système de décodage (désérialiseur) de comprendre qu’une nouvelle voie arrive.
• Les temps de voies se mesurent d’impulsion à impulsion (de front à front) : t1, t2 ... Les 300µs sont compris dans la durée de la voie. Donc chaque voie sera comprise dans une durée allant de 0.3 ms à 2 mS.
• La distance entre deux impulsions de même repère ( de "1" à "1" par ex.) est la durée de séquence Ds.
• Le temps séparant la dernière impulsion d’une séquence de la première de la suivante est le temps de synchronisation Tsy. On a bien sûr : Tsy = Ds - ( T1 + T2 + T3 + T4 + .. ). Ce temps est essentiel car il va permettre au décodeur la reconnaissance sûre de l’impulsion du début de séquence.
• Tsy doit donc être nettement plus grand que la durée maximale d’une voie ( 2 ms ) Il sera souvent de 7 à 8 ms.
Deux solutions sont envisageables et ont été utilisées :
• Ds constant : Par exemple 20 ms. Dans ce cas le temps Tsy varie avec la durée des temps de voies et leur nombre, et peut devenir trop petit. C’était le cas des codeurs de 1ére génération .
• Tsy constant : Par exemple 8 ms. Cette fois le décodeur n’a pas de problème car c’est Ds qui varie en fonction des temps de voies et de leur nombre. ( Codeurs de 2ème .... génération ) . Cette valeur ne doit pas excéder 30ms ( sinon risque d’instabilité des servos ).

Bien j’ai rebranché le module sur mon arduino :

J’ai écrit un petit prog de décodage de trame PPM : et TADAA, La trame PPM possédant 6 impulsions.

On a donc six voies différentes, chacune oscillant entre la valeur 1060 et 1876, en fonction de la position des commandes sur mon smartphone, (1060-1876 = 816, beaucoup plus que nécessaire pour contrôler un servo). Sachant que le petit quad ne commande que 4 moteurs il reste deux sorties supplémentaires non utilisées.

Voici mon programme permettant le décodage des trames.

Et voilà, si vous voulez commander un robot à distance et recevoir la vidéo embarquée de ses déplacements, il vous suffit d’acheter ce petit module.

C’est déjà bien mais on peut faire mieux :
Une fois alimenté le module va créer un réseau WiFi nommé WKxxxxxxxx, où xxxxxxxx est un nombre aléatoire de 8 digit. Notez que ce n’est pas un point d’accès à part entière ( ie un seul appareil peut se connecter), seule le premier pourra obtenir le flux vidéo. Donc, si vous ne recevez pas de vidéo, vérifiez vos autres appareils.

Vous pouvez aussi recevoir la vidéo directement sur votre ordinateur en utilisant VLC, en effet le module possède une adresse ip 192.168.10 .123 la vidéo est accessible sur le port TCP 7060.

Pour le savoir il m’a suffi d’analyser la connexion wifi de mon téléphone avec une petite appli pour smartphone qui s’appelle SHARK Native, il en existe une autre tPacketCapture Pro.
Pour voir la vidéo sur le PC il suffit de lancer VLC, cliquer sur le menu Media et ensuite Ouvrir un flux réseau. Là vous tapez l’adresse 192.168.10.123 :7060, puis lancer la lecture.

Les commandes sont envoyées sur le port UDP 60034. Du coup je me suis dit qu’il devait être possible d’écrire un code python permettant de lire les trames vidéo et d’envoyer des commandes au module.
Par chance j’ai trouvé un forum, où quelqu’un avait commencé a faire le boulot de décryptage des signaux wifi.

La vidéo est constituée d’une suite d’images au format JPEG de 640x480 en streaming.
Chaque trame débute par l’élément séparateur suivant :
 markmarkmark
de sorte qu’il est possible de synchroniser le décodeur, ou encore plus rapide , parcourir le buffer d’entrée pour trouver le marqueur JPEG de fin d’image ( FF D9) .

Lee trames de commande ont le format suivant :

AA 55 est l’entête de la trame

Voici la trame complète :

AA 55 60 01 7F 7F 7F 7F 01 01 01 5F

AA 55 6e tt rr ee aa gg kk 01 01 cc

e = 1 - > activer le contrôle de wifi ( à bord LED devrait vous dire sa limite après l’envoi de ce )
tt = gaz , 01 = min, ff = max
rr = gouvernail, 01 = min , 7f = centre , ff = max
ee = élévation
aa = aileron
gg = autre voie
kk = autre voie
cc = checksum
Le checksum se calcul assez simplement en additionnant tous les octets et en effectuant un ET logique avec FF.

(AA + 55 + 60 + 01 + 7F + 7F + 7F + 7F + 01 + 01 + 01) & FF = 5F

Pour décoder les images JPEG et pour afficher la vidéo, j’ai utilisé la librairie python cv2. Pour les commandes j’ai utilisé la librairie TKinter déjà présente dans Python 2 .7.6. Au début j’ai utilisé PIL pour les images et pygame pour la vidéo mais c’était plus compliqué.

J’ai utilisé Python 2.7 en 32 bit alors que mon PC tourne sous windows 7 en 64 bits, pour la simple et bonne raison que beaucoup de librairies n’existent qu’en 32 bit, et que WIN7 64 le supporte très bien.

Pour pouvoir recevoir et afficher la vidéo dans une fenêtre tout en utilisant des slider pour envoyer des commandes, j’ai créé une fenêtre racine (root) TKinter.

Voici mon programme python, il est assez simple mais il fournit une base pour un véritable centre de contrôle sur PC.

Je me suis bien amusé à hacker ce module et en plus j’ai encore progressé en Python.
Mon prochain boulot sera de réaliser une application en python sous Android qui fait la même chose.
(Euh.. c’est-à-dire de refaire l’appli C_REMOTE…)

Vos commentaires

Un message, un commentaire ?

modération a priori

Attention, votre message n’apparaîtra qu’après avoir été relu et approuvé.

Qui êtes-vous ?

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.