ELECINF344/381

Partie interactive du site pédagogique ELECINF344/ELECINF381 de Télécom ParisTech (occurrence 2011).

Catégories

IRL : Settings !

In our last article we described some ways to enhance the display of a text scrolling smoothly.
We actually tried several possibilities of settings for the scrolling text and finally found a convenient one (as shown on the video above).

We did some major improvements concerning the speed of the code on the card succeeding in speeding it by a factor of 5. We deemed that a major issue of that program lays on the access time of the memory. Indeed it takes more than 20 seconds to write an ILDA file of a tweet from the ram to the flash. Samuel suggested that we could use a socket to directly send the ILDA file from the python script to the C program in charge of the FPGA communication. In fact, with such a strategy we would avoid the slow speed flash access and be able to send a tweet to the laser around 30 seconds after its validation.

In addition we’re going to add some bit stuffing to make the frames equally populated in terms of points so as to assure a constant frame rate. You can easily notice that disturbing effect on the video above.

In parallel, we’re getting familiar with the DMX protocol and are working on the DMX board.
We haven’t forgotten the software fifo between the C program and the FPGA. We deemed that a zeromq socket would be a interesting solution and we are currently working on it.

MB Led: Firmware, Bluetooth, bibliothèque graphique.

Depuis dimanche j’ai eu l’occasion d’avancer sur différentes parties:

Firmware:

Comme je l’explique dans mon précédent article nous mettons en place un système de mise à jour de firmware via IrDA. Mon travail a été d’implémenter, en utilisant les bibliothèques ST, les fonctions de déplacement de secteur de la flash depuis un bootloader situé en début de flash. J’ai effectué mes tests sur la carte de TP et utilisé objdump et openocd, ainsi que deux versions du « firmware » pour mes tests (un qui éclaire la LED en bleu et l’autre en vert). Une phase de débugage assez longue: des pages qui sont effacées sans le vouloir, la raison étant que la ligne de commande openocd faisait un « reset halt »  qui relancé l’ancien bootloader pour un nombre indétrerminé d’instructions, effaçant ainsi des mauvaises pages. Désormais on peut manipuler la flash à notre guise depuis le bootloader et effectuer la phase de recopie du nouveau firmware avant de l’exécuter sans problème.

Bluetooth:

J’ai commencer à implémenter réception/émission de commandes/réponses coté MB Led. Dès que je récupère un module bluetooth F2M03GLA, je pourrais faire des premiers tests de communication avec un client bluetooth sur mon pc.

Bibliothèque graphique:

Ecriture de premières fonction de manipulation des images, inspirées du code GLiP et d’autres plus adaptées au mode jeu (affichage de sprites, de lettres …).

A faire:

Nous devrions bientôt récupérer quelques unes de nos cartes avec les composants soudés. Je pourrais alors tester mon code pour le driver LED. En attendant je continue d’avancer sur les trois points précédents.

MB Led: Depuis la soutenance intermédiaire…

Notre dernier article datant de mardi dernier. Je vais faire un résumé de mes avancées des derniers jours:

Mercredi et jeudi:

J’ai terminé de coder les fonctions de communications avec le driver de LED. J’ai désormais un exécutable censé afficher une image décrite pour l’instant en dur (pixels écrit un par un à la main dans un tableau). Je ne peux pas avancer plus de ce côté sans nos blocs, une fois ceux-là soudés,  je pourrais passer au debugage

Voici comment fonctionne cet affichage dans les grandes lignes:

Initialisation:

  1. On initialise la communication SPI: messages de 16 bit, fréquence d’envoi de 18MHz, LSB transmis en premier.
  2. On initialise le DMA.
  3. On initialise l’horloge qui servira de référence pour le PWM du driver.
  4. On configure les différentes luminosités pour les trois groupes de couleur (rouge, vert et  bleu)
  5. On configure la fréquence de l’interruption qui rafraichira l’affichage de l’image. Cette fréquence n’est pas définitive, elle dépendra de la puissance des LED qui influe sur la persistance rétinienne. Plus cette puissance sera grande plus on pourra réduire la fréquence de rafraîchissement. Cette fréquence ne peut donc être réglée qu’empiriquement. Pour l’instant 80KHz en se basant sur le code des GLiP.

Routine d’affichage:

Les 8 lignes sont affichées les unes après les autres. Une seule ligne est allumée à un instant donné.

L’affichage d’une ligne se fait de la façon suivante:

  1. On récupère la ligne dans l’image courante.
  2. On extrait, des pixels de cette ligne, les valeurs des 24 LED.
  3. Ces valeurs sont pour l’instant sur 4 bit, une fonction est chargée « d’étirer » ces valeurs sur 12 bits pour correspondre aux attentes du driver. C’est cette fonction qu’il faudra modifier lorsque nous déciderons d’élargir le champ de couleur disponible (pour l’instant on garde le format GLiP).
  4. On construit finalement, sous forme de 18 messages de 16 bit, le vecteur de 288 bit attendu par le driver pour piloter ses 24 sorties (24*12bit).
  5. Ces 18 messages sont envoyés en SPI par accès direct à la mémoire au driver de LED qui va afficher la ligne courante.

Vendredi et samedi:

Depuis vendredi je réfléchi à une façon de faire des mises à jour de firmware via l’IrDA. En effet si nous avons 36 blocs, dès qu’il s’agira de flasher une nouvelle version de notre code, cela s’avérera être une opération fastidieuse. Petit calcul: 30 secondes (au moins) pour flasher un bloc et 36 blocs. Soit un peu moins de 20 minutes à chaque fois!

Une organisation possible de la mémoire flash, pour la mise en place d’un système de mise à jour que je détaille plus bas, serait la suivante:



Les premières instructions du bloc Flash programmer font « sauter » en _firmware_begin.

Puis, le firmware pourrait être mis à jour de la façon suivante:

  1. Notre firmware courant s’exécute normalement sur un bloc B : affichage d’animations, jeux, etc…
  2. Nous souhaitons faire une mise à jour du firmware depuis la carte microSD d’un bloc A par exemple.
  3. En se reposant sur notre système de transmission de donné par IrDA que je ne détaille pas ici, le bloc A va d’abord envoyer une commande indiquant l’arrivé d’une mise à jour (broadcastée ou non)
  4. Un des blocs, B, recevant cette commande décide de l’accepter ou non.
  5. Si il accepte il va placer les différentes parties du firmware  envoyé par le bloc A (là encore en se reposant sur notre système de transmission IrDA gérant les problèmes de communication, les paquets corrompus, perdus etc.) en flash à partir de l’adresse _new_firmware_begin à la bonne position: _new_firmware_begin + (taille d’un paquet * position du paquet).
  6. Lorsque tous les paquets ont été reçu correctement (on peut redemander une confirmation à ce moment-là), le programme saute à l’adresse  dans le bloc Flash programmer de début de traitement de la copie.
  7. Le nouveau firmware est alors entièrement copié à la place de l’ancien.
  8. Une fois la copie terminée on retourne à l’adresse _firmware_beginn.

La mise à jour est terminée!

Je m’intéresse maintenant à l’implémentation de ce système de mise à jour ainsi qu’au fonctionnement du debugage via le port série prévu pour ça.

Référence :

Pour le flashage « in-application » : AN2557

 

Copterix : Topo sur Lucas and Kanade

L’algorithme de Lucas et Kanade

Principe

Nous disposons de deux images en niveau de gris, A et B, espacées dans le temps de δt.
Nous cherchons à déterminer les vecteurs déplacement de certains points d’intérêt, que nous pouvons par exemple soit choisir arbitrairement, soit trouver grâce à un filtre de Sobel (détection de contours), soit finalement rechercher d’une manière plus lourde mais qui donne des résultats plus efficaces que nous aborderons dans la dernière partie. Bien entendu, un grand nombre de points d’intérêt permettrait d’avoir une meilleure estimation de la vitesse globale de l’image, mais une quantité plus faible de points d’intérêt demanderait moins de ressources système et de temps de calcul : un compromis est donc nécessaire pour les systèmes embarqués.
Nous nous donnons pour cela une fenêtre de recherche pour chaque point d’intérêt trouvé de taille 2*ωx+1 par 2*ωy+1 (en nombre de pixels). Une fois encore, une plus grande fenêtre permettrait de trouver une plus grande amplitude du mouvement, mais demanderait plus d’itérations (ce problème est en grande partie pallié par la forme pyramidale, que nous aborderons par la suite).
Il ne reste plus qu’à trouver le déplacement qui minimise l’erreur :


Développements

Nous commençons donc par calculer la dérivée de l’erreur par rapport au déplacement :

pour ensuite lui appliquer un développement de Taylor à l’ordre 1 autour du déplacement [0, 0] (valide si nous estimons que le déplacement est petit , ce que nous allons admettre) :

À partir d’ici, nous pouvons arrêter les calculs pour faire quelques considérations.
Tout d’abord, l’expression A(x, y) – B(x, y) fait penser à la dérivée de l’image dans le temps au point (x, y), que nous noterons dI(x, y).
Ensuite, les dérivées partielles de B en x et en y ressemblent à un gradient. Nous pouvons de plus considérer que la fenêtre étant grande en comparaison du vecteur mouvement, la dérivée de l’image dans la fenêtre sur l’image B sera la même que sur l’image A. Nous avons donc le gradient suivant :

pour tout (x, y) appartenant à la fenêtre :
Avec ces notations, nous obtenons :

Enfin, une légère transformation nous permet d’obtenir :

Si nous nous donnons :
et

nous pouvons réécrire l’équation précédente sous la forme :

Or, ne l’oublions pas, le but de cette démarche étant d’annuler la dérivée de l’erreur afin de la minimiser, nous avons


G est inversible si le gradient de A est défini, c’est-à-dire si la fenêtre se trouve dans l’image et que nous disposons d’un contraste suffisamment élevé dans la fenêtre (se référer à la dernière partie pour un choix correct des bons pixels à suivre).

Nous avons ici le moyen de calculer le vecteur déplacement ‘le plus cohérent’ qui permet de passer de l’image A à l’image B dans la fenêtre donnée.

Itérations sur k pour affiner la recherche

Le calcul précédent représente un unique passage de l’algorithme. Nous pouvons affiner le résultat en effectuant plusieurs passages, jusqu’à ce que, par exemple, la norme du déplacement soit inférieure à une valeur que nous pouvons choisir.
Pour un indice d’itération k, si nous avons un résultat , nous transformons B ainsi :


pour calculer :

Nous voyons ici l’intérêt de calculer le gradient sur A et non sur B car ainsi nous n’avons qu’à calculer b à chaque itération.
Nous obtenons le déplacement final suivant :

Du problème des déplacements de plus grande amplitude : la mise en pyramide

Nous avons vu dans la première partie que la fenêtre ne suffisait pas à obtenir un compromis satisfaisant entre vitesse de calcul et détection des grands mouvements.
Une solution à ce problème est l’utilisation de pyramides.

Nous nous donnons m niveaux de pyramide (souvent égal à 3) et nous appliquons l’algorithme entier à chaque niveau de Lm à 0.
À chaque niveau de la pyramide, nous construisons une image de résolution 2^L fois inférieure à l’image originale.
Nous gardons la fenêtre de la même taille et transformons les coordonnées des pixels à suivre pour rester cohérent avec la nouvelle résolution.
Pour obtenir le déplacement final, il ne reste plus qu’à sommer tous les déplacements trouvés mis à l’échelle :

Voici une petite illustration du procédé :

Certains pixels sont plus faciles à suivre que d’autres

Nous pouvons déterminer les meilleurs pixels à suivre en nous basant sur l’utilisation que nous souhaitons en faire.
Ici, ce sera le calcul de l’inverse de G qui sera déterminant, il nous faut donc un déterminant non nul pour chaque pixel de la fenêtre, ou bien, pour rester plus mathématique, une valeur propre minimale maximale.
Nous pouvons donc procéder de la manière suivante :

  1. Calculer G et sa valeur propre minimale λ pour chaque pixel de l’image A
  2. Retenir la plus grande valeur λ sur toute l’image (et s’arranger pour éviter que son pixel soit trop au bord pour faciliter les problèmes de fenêtrage)
  3. Garder les pixels qui ont un λ supérieur à un certain pourcentage de ce maximum (5 ou 10 % par exemple)
  4. Parmi les pixels sélectionnés, choisir ceux dont λ est le maximum dans leur voisinage 3×3
  5. Ne garder que les pixels qui ont une distance suffisante (5 ou 10 pixels par exemple)
  6. Enfin, supprimer les pixels de λ minimal pour respecter un seuil maximal de nombre de pixels à suivre que nous nous serons fixés

Cette procédure est un petit peu lourde, d’autant plus qu’il faudrait théoriquement la répéter à chaque nouveau couple d’images à traiter, c’est pourquoi nous pouvons garder les pixels suivis d’une image à l’autre sur par exemple 10 itérations avant de les rechercher à nouveau.

Conclusion

Nous avons vu la version de l’algorithme de Lucas et Kanade implémentée en openCV. Cet algorithme se révèle facile à comprendre et à implémenter, et est personnalisable à souhait pour s’adapter aux besoins exigeants des systèmes embarqués.

Source

Pyramidal Implementation of the Lucas Kanade Feature Tracker

RoseWheel fait des simulations

Cet article a été rédigé hier soir…

Nous avons terminé ce week-end le PCB de notre carte capteurs. Nous avons fait le schéma de notre carte principale mais Alexis va y ajouter la partie puissance et la router pour nous.

Carte Capteurs [avant]

Carte Capteurs [arrière]

Aujourd’hui nous avons travaillé en parallèle sur l’utilisation du banc de tests et sur le simulateur qui intègre le filtre de Kalman et l’asservissement.

Le simulateur commence à fournir des résultats mais nous avons encore des problèmes de valeurs numériques. Notre simulation fait intervenir des tensions de plusieurs milliers de Volts (alors que nos moteurs n’en acceptent que 24) pour réussir à redresser le gyropode. Cela est certainement dû à une mauvaise estimation de nos constantes km (constante de couple en N.m/A) et ke (constante force contre-électromotrice en V.s/rad).

Pour les calculer nous avons récupéré les caractéristiques du moteur sur le site du distributeur :

À charge nominale on a

  • Vitesse angulaire : VA = 3751 rpm
  • Couple : T = 0.88 N.m
  • Intensité : I = 18.36 A
  • Résistance : R = 0.66 Ohm
  • Tension : U = 24.09 V

Or

  • km = T / I = 0.048 N.m / A
  • ke = (U -- R * I) / VA = 0.030 V.s / rad

Mais avec ces valeurs nous rencontrons les problèmes mentionnés plus haut. Ces problèmes viendraient-il d’ailleurs ? Alexis nous a conseillé de faire un simulateur des moteurs seuls pour déterminer vérifier nos constantes. À suivre…

Par ailleurs, comme le montre la figure suivante, le filtre de Kalman se comporte bien. Même avec un rapport signal sur bruit médiocre nous arrivons à reconstituer assez fidèlement l’angle d’inclinaison. Pour l’asservissement nous avons testé deux techniques : PID puis LQR. Le PID s’avère être délicat à régler et ne nous a pas donné de résultat satisfaisant (divergence de l’erreur au bout d’un certain temps). Le LQR se comporte beaucoup mieux et propose un réglage moins empirique. Couplé au filtre de Kalman, et problèmes de valeurs numériques exclus, notre système se comporte vraiment comme nous le souhaitons. Reste donc à vérifier si nous observons le même comportement avec les bonnes valeurs numériques pour les moteurs. Notons que pour l’instant nous incluons le déplacement et la vitesse dans nos variable d’état ce que nous ne pourrons faire que si nous arrivons à monter des encodeurs sur la mécanique du projet zzaag.

Simulateur RoseWheelCliquez sur l’image pour voir l’animation.

Concernant le banc de tests nous avons terminé sa réalisation. Nous avons monté une vidéo tournée vendredi pour le montrer en action :

Cette première version du banc de tests fonctionne ainsi :

  • on communique avec la carte de TP en RS232
  • la carte de TP commande le servo qui incline la carte capteurs du projet Wheely
  • on récupère les données des capteurs via RS232 sur l’ordinateur
  • on affiche conjointement les courbes de la commande et de la mesure

Pour les mouvements lents, nous procédons par rotations successives. La précision du servomoteur étant assez faible, cela entraîne des mouvements saccadés et introduit un bruit non négligeable lors des transitions. Par ailleurs, la calibration du banc s’avère insuffisante ce qui se traduit par un offset sur les valeurs mesurées. Nous aurions aimé présenter des courbes (superposition commande / mesure du banc de test) mais nous avons été chassés d’A405 avant d’avoir pu les exporter… No comment. Nous travaillerons demain à l’amélioration de ces résultats.

RoseWheel : PCB, banc de tests

Après deux jours de travail, nous avons fini les schémas de nos PCB et, à l’heure où cet article est écrit, nous parachevons le routage de la carte capteurs (autrefois appelée « carte logique »). Parmi les changements clé que nous avons faits, nous pouvons citer notamment l’inclusion d’une alimentation exclusive pour les références des convertisseurs analogique-numériques à l’intérieur du gyroscope et de l’accéléromètre – cela permet d’avoir des conversions plus fiables et donc de réduire le bruit des mesures.

Pour la carte principale (ancienne « carte de puissance »), les plans ont été un peu modifiés : finalement, le circuit de puissance, responsable du contrôle des moteurs en courant, sera intégré par Alexis à la carte, principalement à cause de problèmes d’intégrité du signal (utiliser le bus CAN en entrée permet d’être plus robuste face aux bruits induits par les moteurs à courant continu) et économiques (l’intégration élimine la nécessité de fabriquer une troisième carte qui ne ferait qu’accepter un PWM en entrée et le transmettre aux moteurs).

Côté banc de test, nous avons réussi à contrôler le servomoteur en angle avec la carte de TP, en utilisant les broches originalement assignées au bus SPI pour sortir du PWM. Nous avons commencé alors à le calibrer, puisque la position horizontale (à 0°) ne se trouve pas forcement au milieu de l’échelle du PWM ; pour faire cela, nous avons utilisé une application Android qui nous indiquait l’angle d’inclinaison du téléphone portable. Voici notre dispositif expérimental :

Après cela, nous avons  fini la partie mécanique en fixant une planche de balsa pour tenir la carte dans sa place pendant que nous faisons les tests. Le montage final est celui-ci :

Par rapport à la simulation physique, nous hésitons encore entre continuer à la développer en Octave ou passer à Matlab, étant donné que certaines bibliothèques utiles pour l’implémentation du filtre de Kalman ne sont pas disponibles dans le logiciel libre.

MB Led: Article post communication challenge.

Aujourd’hui j’ai enfin réussi à flasher quatre modules conçus par l’équipe GLiP de l’an dernier. J’ai flashé le code maitre pour un bloc contrôlable avec un PC et minicom pour la sélection des animations ainsi que le code pour trois esclaves.

Lors de la compilation de ces codes sont incluses les différentes animations préalablement convertis grâce au script python gif2glip (conçu par l’équipe GLiP).

Nous avons donc pu faire tourner des petites animations sur un réseau carré de quatre GLiP tout en constatant que les animations étaient bien affichées après mélange des blocs.

Cette étape m’a permis de me familiariser avec l’architecture du code de GliP et de m’imprégner de leurs algorithmes pour la réorganisation du réseau ainsi que pour l’affichage des images via les drivers de LED. La compréhension de ce code nous permettra de faire des premiers tests notamment pour les communications IRDA et nos algorithmes réparties en attendant d’avoir nos propres modules.

Ce soir je me suis consacré à la réorganisation de nos PSSC et à la création d’un diagramme de Gant pour une meilleur répartition des ressources dans notre équipe. Le temps passé sur le TP sur le STM32 nous a obligés de décaler les différentes deadlines pour nos PSSC.

====== Reprise du projet GLiP : ======
- A partir de GIF convertibles par gif2glip nous savons les charger via le bloc maître et les jouer sur un réseau de bloc en utilisant leur matériel ⇒ Fait

====== Conception de la carte et test : ======
- Choix des composants terminé : Fait

- Image PCB prête (on peut passer la commande du circuit imprimé) ⇒ 25 mars

Puis en supposant que nous recevons les PCB au plus tard le 4 avril :

- Soudage des composants sur les cartes => 6 avril

- Contrôle de la matrice de LED (affichage d’image) ⇒ 15 avril

====== IRDA ======
- Echange de messages entre deux blocs ⇒ 11 avril

- Ecriture via Irda sur la sdcard => 22 avril

====== Bluetooth: ======
- Communication Bluetooth avec un ordinateur ⇒ 16 avril
- Exécution de commandes reçu en Bluetooth ⇒ 21 avril
- Application de contrôle Android ⇒ 26 avril

====== Gestion de la mémoire : ======
- Lecture sur la SD Card. ⇒ 12 avril
- Ecriture sur la SD Card. ⇒ 17 avril
- Exécution d’un programme stocké en SD Card. ⇒ 22 avril
- Mise à jour du firmware depuis la SD Card. ⇒ 24 avril

====== Système réparti : ======
- Environnement de simulation en place ⇒ 3 avril
- Gestion dynamique du réseau de bloc⇒ 15 avril

====== Jeux sur l’ensemble : ======
- Jeu du morpion fonctionnel (sans Bluetooth) ⇒ 24 avril
- Jeu du morpion fonctionnel (avec Bluetooth) ⇒ 27 avril

 

Tutoriel GIT

Bonsoir,

Vous trouverez ici notre tutoriel sur git. Pour des raisons techniques ce n’est pas encore une page du blog, mais cela le sera bientôt.

Bonne lecture,

Bertrand, Clément, Laurent et Vaibhav.