Acquisition directe du signal vidéo issu d'une caméra analogique N&B
From Eric
Contents |
Objectifs
Acquérir une image vidéo à partir d'une caméra analogique.
Voici la caméra utilisée (jolie et pas chère...) :
Réalisation
On trouvera un peu de théorie sur la page signaux vidéo.
La carte électronique est très simple : un dsPIC 30F4011 et un LM1881 pour extraire les signaux de synchronisation (on pourrait le faire "à la main" avec un intégrateur et un comparateur). L'ADC du PIC est suffisamment rapide pour échantillonner le signal de luminance (le seul qui m'intéresse puisque la caméra est NB).
Pour une résolution temporelle maximale (j'échantillonne toutes les lignes), la résolution spatiale est faible : aux alentours de 100 points (l'ADC du dsPIC est capable d'atteindre le 1MSPS). Mais ça suffit pour ce que je veux en faire.
Le principe d'acquisition est très simple puisqu'il consiste à échantillonner et convertir le signal vidéo à l'aide de l'ADC rapide du dsPIC. Pour la couleur, inutile d'y penser, celle-ci étant codée par la phase d'une porteuse à quelques MHz.
Le t0 d'échantillonnage est déterminé par le top de début de ligne (donné par un LM1881) et un retard qui permet, en combinant plusieurs images, d'acquérir plusieurs pixels par ligne.
L'ADC du dsPIC30
Cette première photo montre l'appel de la routine d'interruption ligne (courbe du bas). On observe le délai entre le top de début de ligne et l'appel de la routine. Ca n'est pas un problème car le signal vidéo démarre bien plus tard.
La photo suivante montre l'échantillonnage proprement dit, une fois son démarrage décalé pour "coller" au démarrage de l'émission de l'image. L'échantillonnage dure un peu plus de 40us. Le signal est inversé après chaque échantillon, donc chaque front (montant et descendant) correspond à un échantillon.
D'un peu plus près...
Il se passe environ 1.5us/2 entre deux échantillons. (C'est trop rapide, la configuration de l'horloge de l'ADC est à revoir.)
La dernière image montre le signal de synchro trame (/2) et le signal d'échantillonnage.
Voici la fonction de configuration de l'ADC. Notez le registre ADPCFG qui permet de configurer une entrée en analogique ou en discret.
/* * Configuration de l'ADC video. */ void setup_adc() { // Toutes les entrées du port B sont discretes, à l'exception du port RB2 (AN2) ADPCFG = 0xFFFB; // SSRC bit = 111 : le compteur interne est utilisé pour réaliser l'échantillonage et // le lancement de la conversion. Le format est 0000 bbbb bbbb bbbb ADCON1 = 0x00E0; // Connecte RB2/AN2 au canal CH0 ADCHS = 0x0002; ADCSSL = 0; // Temps d'échantillonnage = 31Tad, d'ou un temps total de 12+31=43TAD avec TAD=TCYC ADCON3 = 0x1F01; // On utilise VRef+ externe et VRef- interne (VSS). Interruption après chaque échantillon ADCON2 = 0x0000; ADCON2bits.VCFG= 001; // Activation de l'ADC ADCON1bits.ADON = 1; }
La génération VGA
L'horloge du dsPIC est programmée de façon à atteindre les performances max (120MHz) : Mode = FRC w/ PLL 16x, soit 7.5Mhz internal RC x 16 = 120Mhz.
La configuration réelle est la suivante :
// Horloge interne à 7.42Mhz, x16 par la PLL # 120Mhz _FOSC(CSW_FSCM_OFF & FRC_PLL16); _FWDT(WDT_OFF); /* Watch dog Timer OFF */ _FBORPOR(PBOR_OFF ); /* Brown Out OFF, MCLR Enabled */ _FGS(CODE_PROT_OFF); /* Code Protect OFF */
On vise une résolution de 640x480 à 60Hz.
Les données de timing pour cette résolution sont les suivantes (elles sont issues de [1]).
Timing horizontal
- Horizonal Dots 640
- Vertical Scan Lines 480
- Horiz. Sync Polarity NEG
- A (us) 31.77 Scanline time
- B (us) 3.77 Sync pulse lenght
- C (us) 1.89 Back porch
- D (us) 25.17 Active video time
- E (us) 0.94 Front porch
______________________ ________ ________| VIDEO |________| VIDEO (next line) |-C-|----------D-----------|-E-| __ ______________________________ ___________ |_| |_| |B| |---------------A----------------|
Timing vertical
- Horizontal Dots 640
- Vertical Scan Lines 480
- Vert. Sync Polarity NEG
- Vertical Frequency 60Hz
- O (ms) 16.68 Total frame time
- P (ms) 0.06 Sync length
- Q (ms) 1.02 Back porch
- R (ms) 15.25 Active video time
- S (ms) 0.35 Front porch
______________________ ________ ________| VIDEO |________| VIDEO (next frame) |-Q-|----------R-----------|-S-| __ ______________________________ ___________ |_| |_| |P| |---------------O----------------|
On trouve aussi le timing décrit en termes de pixels et de lignes.
Pour ce qui concerne les lignes :
- Clock frequency 25.175 MHz
- Line frequency 31469 Hz
- Field frequency 59.94 Hz
- One line
- 8 pixels front porch
- 96 pixels horizontal sync
- 40 pixels back porch
- 8 pixels left border
- 640 pixels video
- 8 pixels right border
soit un total de 800 pixels par ligne.
Pour ce qui concerne les trames :
- 2 lines front porch
- 2 lines vertical sync
- 25 lines back porch
- 8 lines top border
- 480 lines video
- 8 lines bottom border
Soit un total de 525 lignes.
Réalisation
On utilise qu'un timer "ligne", qui servira à générer les signaux de synchro verticale. La génération du signal de ligne repose sur le timer1 dont la fréquence d'entrée est Fosc/4 (prescaler à 1:1). A noter que le temps de cycle du processeur est aussi Fosc/4, ce qui signifie que le timer, programmé en compteur, va compter les cycles instruction. Au passage, cela signifie aussi que pour un fosc=120MHz, par exemple, on atteint les 30MIPS.
On a
Fosc=(frequence de l'oscillateur source * multiplicateur PLL)/(postscaler *4)
La fréquence de l'oscillateur interne est de 7.37Mhz. Attention, cet oscillateur est un RC ; il n'est pas précis et varie avec la température. Il est ainsi inutilisable avec le CAN.
La configuration du timer est obtenu ainsi :
/* * Configuration du timer de génération des synchro ligne */ void setup_timers() { // Timer1 en reset T1CON = 0; // Configuration de l'IT timer1 (synchro ligne) // Reset du status d'IT IFS0bits.T1IF = 0; // Priorité à 7: IPC0, bits T1IP<2:0> IPC0bits.T1IP=7; // DeActivation : IEC0, bit T1IE (bit 0) IEC0bits.T1IE=0; // Periode PR1 = 940; // Source interne T1CONbits.TCS = 0; // Prescaler à 1 T1CONbits.TCKPS = 0; // Activation de l'IT sync IEC0bits.T1IE = 1; }
Conclusions
A la date du 21/02/2012, toutes dernières de faire fonctionner cette $@# caméra NB avec un DsPic ont échouées... J'ai modifié le soft pour ne conserver que les pixels format les plages connexes les plus grandes (je compte le nombre de voisins de la même couleur). J'ai aussi rajouté une phase de calibration : au démarrage, caméra couverte, je cherche le plus bas niveau de détection qui conduit à la luminosité minimale. J'arrive bien à acquérir quelques pixels (32*32) mais c'est pratiquement inexploitable.