Lunette à vision augmentée

De Wiki de Projets IMA

Introduction

Dans le cadre de notre dernière année à Polytech, nous avons dû nous atteler à un projet de fin d’étude durant le mois et demi qui a suivi le retour de notre semestre à l’étranger. Dans ces conditions, nous avons choisi le sujet "Lunette à vision augmentée". En effet, ce sujet est plus dans une optique Systèmes Communicants et a attiré notre curiosité (suite, par exemple, à l’annonce des Google glasses, de l’Oculus Rift de Valve...). Nous allons donc voir à travers ce Wiki le déroulement par semaine de ce projet.

Présentation du projet

Le but de ce projet est de mettre en œuvre une caméra à l'aide d'un Arduino et/ou d’une nanoboard FPGA XILINX (carte Altium). L’objectif étant d’afficher l’image soit sur un écran LCD prévu pour Arduino soit sur un moniteur d'ordinateur. L’un des objectifs finaux étant d’afficher, en surimpression, du contenu comme l'état de capteurs (accéléromètre, température, ...) sous forme de texte, d'images, dynamiques ou non.

Matériel à disposition

Texte alternatif
OV662 Image Sensor

Pour effectuer ce projet, nous avions plusieurs instruments et matériaux à disposition. En voici une liste détaillée:

  • Caméra CA88 : caméra 1/4” avec sortie digitale 8 ou 16 bits. Le capteur d’image OV6620 est de type CMOS. Cette caméra est configurable via un bus I2C (résolution, FPS, Gamma, gain, balance des blancs...).
  • Nanoboard Xilinx, Spartan 3 (FPGA).
  • Arduino Atméga 2560.
  • Ecran LCD Color Shield Phillips (de chez Sparkfun) pour arduino.
  • Un analyseur logique.
  • Un accéléromètre ADXL3xx (pour Arduino).
  • PC + 2 moniteurs.
  • logiciel Altium Designer version 9 puis 10 (différents problèmes sont intervenus lors des compilations…)
  • logiciel Arduino.

Séance

Semaine du 14/01 au 18/01

  • Etude du matériel
  • Etablissement d'un cahier des charges
    • Etudes des possibilité
    • plus tendance à travailler sur le FPGA, à longs termes, que sur le arduino (capacité de calculs)
  • Fonctionnement de la caméra:
    • mode RGB
    • Résolution 352x288
    • Un pixel de caméra par couleur
    • Chaque pixel est codé sur un octet
    • Organisation spatiale et envoie de données pas très intuitif
    • Configuration par I2C => utilisation d'un arduino atméga pour le faire car c'est plus simple que sur FPGA
  • Fonctionnement de l'écran LCD
    • un pixel est RGB => envoie de 12 bits, 4 bits par couleur

Semaine du 21/01 au 25/01

  • Configuration I2C de la caméra
 void config_cam(){      //I2C pour config camera
 Wire.begin(); // join i2c bus (address optional for master)
 
 Wire.beginTransmission(0xc0); // transmit to device #192 CA88
 Wire.write((uint8_t) 0x12);     // soft reset
 Wire.write((uint8_t) 0xa4);
 delay(100);
 
 Wire.write((uint8_t) 0x12);
 Wire.requestFrom( 0xc0, 1);
 Serial.print("lecture : ");
 Serial.println("%d", Wire.read());
 
 Wire.write((uint8_t) 0x11);     // vitesse = 2 i/s
 Wire.write((uint8_t) 0x3F);
 //delay(1000);
 Wire.write((uint8_t) 0x12);     // RGB
 Wire.write((uint8_t) 0x2C);
 //delay(1000);
 Wire.write((uint8_t) 0x13);     // 8 bit mode
 Wire.write((uint8_t) 0x21);
 //delay(1000);
 Wire.endTransmission();
 }
  • Test de lecture des données via le port série du Arduino.

=> on voit des données mais le logiciel plante après un peu de temps, cela est surement du à la vitesse de transmission.

On décide donc de passer sous Altium Designer avec un embeded projet pour avoir accès à un terminal (et programmation en C). => on affiche des données. On analysera cela la semaine suivante.

Semaine du 28/01 au 1/02

À partir des résultats de la semaine précédente, nous avons tenté d'obtenir uniquement une image (toujours sur le terminal). Pour cela, on s'est synchronisé sur une nouvelle image en attendant un front montant de VSYN (signal de synchronisation d'une nouvelle image). Puis il a fallu prendre en compte le signal HREF (un niveau haut indique qu'on se situe toujours sur une même ligne de l'image et un front descendant indique la fin d'une ligne). Après ce test, nous n'avons plus rien observé sur le terminal. Il semblerait que la synchronisation ne fonctionne pas.

On a donc décidé de lire les signaux de synchronisation à la place des données. On a bien observé des valeurs qui varient, il y a donc bien des changements d'état de ces signaux. On a tenté de comptabiliser le nombre de changement de ces signaux sur un nombre de lecture donnée. On a remarqué que pclk gardait toujours l'état 1. Nous avons, par la suite tenter d'obtenir une bonne synchronisation mais sans succès.

Semaine du 4/02 au 8/02

  • Etude des signaux sur l'analyseur logique afin de régler les problèmes de synchronisation.

=> cette étude montre bien le lien entre les 3 signaux href, vsyn et pclk.

  • On a donc recherché d'éventuelles erreurs dans notre programme.

On a fini par se rendre compte que la configuration par I2C n'avait pas fonctionné car on était toujours à 50 images par seconde. => on s'est donc repenché sur l'I2C pour trouver ce qui n'allait pas.

  • Il s'est avéré que c'était la bibliothèque Wire.h du logiciel Arduino qui ne fonctionnait pas.

On a donc cherché une alternative et on directement écris dans les registres voulus à l'aide de la fonction

    write_Register(registre, valeur);

=> on a réussi à configurer la caméra (vérification à l'analyseur logique ok)

On envisage de passer sous VHDL si la synchronisation ne marche toujours pas.

Semaine du 11/02 au 15/02

  • On a retenté le programme en C avec la nouvelle configuration I2C, sans succès.

On a donc pris deux chemins différents:

-un a poursuivi en VHDL

-l'autre sur Arduino

  • VHDL
    • établissement d'un plan en deux parties:

-synchronisation sur une image mais obtention de plusieurs erreurs : deux évènements consécutifs pas possibles (on ne peut surveiller à la suite vsyn'event et href'event). On a donc essayé avec des wait() mais sans succès (car non compatible avec liste de sensibilité) =>plusieurs tentatives de corriger (sans les wait): sans résultat. On envisage de stocker toutes les valeurs dans un tableau.

-synchronisation sur le moniteur qui sera utilisé

  • Arduino
    • tentative de synchronisation des signaux en lisant sur les pin digitales configurées en entrée.

On obtient des valeurs comprises entre 0 et 255, mais elles varient beaucoup trop pour que ça soit cohérent. De plus l'affichage sur l'écran ne donne rien de concret.

Semaine du 18/02 au 22/02

  • VHDL

On a mis de côté pour le moment la synchronisation sur une image afin de travailler plus sur la synchronisation du module VGA du moniteur d'ordinateur. Pour le tester il a fallu créer une table et la remplir avec des valeurs afin d'afficher une image (dans notre cas ce sera un carré vert avec 2 points rouge à l'intérieur de 32x32 px). La résolution de notre image est petite étant donnée qu'on est limité en "block ram". Il faudra réduire le nombre de pixels capturés par la caméra (On a à disposition 576k bits et pour une résolution complète, il faudrait 352x288x8x3/2 = 1,2M bits). La synchronisation s'est faite avec deux compteurs (un ligne et un colonne) afin de déterminer la position du spot lumineux du moniteur. Après de multiples erreurs lié au logiciel altium et au langage VHDL, on fini par obtenir l'image sur l'écran.

On décide donc de retenter la récupération des données pour remplir la table. On décide de prendre un pixel sur deux et une ligne sur deux afin de ne pas dépasser le nombre de block ram. Cependant cela ne fonctionne pas, il y a une erreur à la compilation. Il semblerait qu'Altium n'arrive pas à compiler la table d'une dimension de 38016. Ceci est étrange car dans un test précédent nous avions réussi à créer une table de 101376.

Malheureusement nous n'avons pas eu le temps de régler ce problème.

  • Arduino

Dans un premier temps, nous avons fait fonctionner l'accéléromètre : tout marche bien et on affiche bien les valeurs sur l'écran lcd.

Après l’échec de la semaine passé, nous nous somme rendu compte que la synchronisation de signaux ne pouvait pas se faire même en lisant directement dans les registres : cela prend beaucoup trop de temps. Nous avons donc cherché et décidé d'utiliser les pins d'interruption du Arduino. Dans la théorie le code est bon : pour une interruption de vsyn, on passe à un un booléen test, de même pour href. Ainsi, si les deux booléens de test sont à un et que l'on a une interruption sur pclk, alors on pourra faire une lecture convenable et l'envoyer sur l'écran lcd. Cela n'a pas marché car la valeur 8 est toujours retournée. Nous essayerons, jusqu'au dernier moment de le faire fonctionner pour pouvoir présenter un résultat concret.