Anda di halaman 1dari 14

TP camra CCD

Fonctionnement
Ce TP doit permettre de comprendre comment fonctionne une chane d'acquisition d'image
numrique. Dans un premier temps, on tudiera le fonctionnement gnral du capteur de lumire, le
CCD (Capteur Charges Dfilantes = Charge Coupled Device). Dans un deuxime temps, on
tudiera la mise en forme des horloges permettant de lire l'image contenue dans le CCD. Cette tude
sera illustre par l'analyse du listing du logiciel de pilotage. Dans un troisime temps, on tudiera
une partie des diffrents signaux avec un oscilloscope.
Mise sous tension : bouton +15/-15 Volt. Ne pas allumer le refroidissement Peltier.

1. Fonctionnement gnral d'une camra CCD


Cette partie fournit les notions de base du fonctionnement d'un capteur CCD.

1.1. Le composant CCD


Composant lectronique de technologie MOS (Mtal Oxyde Silicium). Le but du CCD est de
convertir des photons en lectrons dans une matrice de photosites abusivement appels pixels. La
lecture de l'image est effectue photosite par photosite, en srie. Le composant CCD tudi dans ce
TP est un Kaf-400 de Kodak.

1.1.1 Le photosite
La surface de silicium est divise en une matrice de photosites. Sensible la lumire, le photosite
peut tre grossirement assimil un condensateur qui absorbe l'nergie des photons incidents en
gnrant des lectrons (les charges). Les lectrons sont pigs dans le puits de potentiel du
photosite.

1.1.2 Le transfert des charges


Dans la figure ci-dessous, chaque photosite de la matrice a reu une certaine quantit de lumire et
gnr des lectrons nots par des lettres de l'alphabet. La sortie des lectrons est constitue de deux
tapes importantes :
1) Le transfert vertical (cf. figure du milieu) transfre toutes les charges d'une ligne vers le bas dans
une ligne, masque la lumire, appele registre horizontal.
2) Le transfert horizontal (cf. figure de droite) transfre toutes les charges du registre horizontal
d'une colonne vers la gauche.

1/14

C'est l'enchanement des oprations lmentaires des horloges V et H qui va conditionner l'ordre de
sortie des charges. Dans l'exemple ci-dessus, le listing suivant (langage C) permet de rcuprer une
image dont chaque pixel sera reprsente par un photosite de la matrice CCD :
/* --- lecture et digitalisation simple (binning 1x1) ---*/
int kl,kc;
int nl=4,nc=6;
unsigned short p;
p=(unsigned short*)calloc(nl*nc,sizeof(unsigned short));
for (kl=1;kl<=nl;kl++) {
1_transfert_vertical;
for (kc=1;kc<=nc;kc++) {
1_transfert_horizontal;
p[nl*kc+kl]=numrisation;
}
}
La fonction calloc permet d'allouer de la place mmoire pour y stocker l'image.
Sous chaque photosite, le puits de potentiel se compose de 4 parties couples deux deux dans la
technologie du transfert deux phases relles. Le KAF400 utilise le principe du transfert des
charges deux phases.

2/14

A gauche en haut : reprsentation schmatique de la coupe d'une ligne de photosites CCD. Les
horloges 1 et 2 sont des tensions appliquer aux lectrodes. A gauche en bas, reprsentation des
niveaux de potentiels associs aux photosites. Au cours des trois tapes t1, t2 et t3, les charges Q1
Q5 sont dplaces vers la droite. A droite, reprsentation schmatique des niveaux des horloges 1
et 2 correspondant aux trois tapes. Ce schma s'appelle chronogramme. La dnomination de ces
horloges devient V1 et V2 lorsqu'il s'agit du transfert vertical (H1 et H2 lorsqu'il s'agit du
transfert horizontal)

1.1.3. La matrice
A partir document ci-dessous, reprer les caractristiques (nombres de pixels) et les diffrentes
zones de la matrice CCD (pixels cachs la lumire, etc.) pour le Kaf400.

3/14

1.1.4. Le registre horizontal


Montrer le rle primordial du registre horizontal. Comme pour la matrice, montrer quels sont les
caractristiques (nombres de pixels et zones inactives) du registre horizontal.

1.1.5. Le binning
En reprenant la matrice dcrite au paragraphe 1.1.2., le listing a t modifi pour regrouper les
lectrons de plusieurs photosites pour ne faire qu'un seul pixel.
/* --- lecture et digitalisation en binning 2x2 ---*/
int kl,kc;
int nl=2,nc=3;
unsigned short p;
p=(unsigned short*)calloc(nl*nc,sizeof(unsigned short));
for (kl=1;kl<=nl;kl++) {
1_transfert_vertical;
1_transfert_vertical;
for (kc=1;kc<=nc;kc++) {
1_transfert_horizontal;
1_transfert_horizontal;
p[nl*kc+kl]=numrisation;
}
}
Identifier quels sont les photosites qui sont ainsi regroups. Ecrire la matrice dans laquelle ont
notera les lettres rassembles dans chaque pixel.

1.2. Ralisation d'images


4/14

Faire l'acquisition d'images en binning 4x4, 2x2 et lx1. Faire le bilan des ce que l'on gagne et de ce
que l'on perd (temps de lecture, dfinition, temps de pose, stockage de l'image, etc.) lors d'une
acquisition en binning 4x4 compar une acquisition en binning lx1.

2. Le chronogramme
Le chronogramme est l'enchanement des variations des tensions appliques aux bornes du capteur
CCD. Il s'agit de tensions en crneaux (un tat haut et un tat bas). Ces signaux permettent de
dcaler les charges dans les cellules du capteur CCD afin de les faire sortir par une broche de sortie.
Ci-dessous, le chronogramme gnral de lecture de la matrice CCD (document Kodak) :

Le tableau ci-dessous, indique les dures minimales respecter pour assurer un bon transfert des
lectrons:

5/14

Les deux chronogrammes ci-dessus, montrent les dtails du chronogramme respecter pour une
lecture en binning 1x1. Vout correspond la tension en sortie du composant CCD.

2.1. Fonctionnement des horloges


Montrer comment agissent les horloges Vl, V2. Expliquer la forme du chronogramme propos par
le constructeur et comparer cela avec la fonction zi_zh du listing du logiciel (tp.c). Mmes questions
avec HI et H2 et la fonction readpel_fast.

2.2. Vidage
Le vidage consiste en l'vacuation rapide des charges de la matrice CCD, sans numrisation. Ainsi,
on dcharge la matrice CCD et une nouvelle image peut s'y former. Expliquer la fonction
fast_vidage du listing.

2.3. Lecture
La lecture consiste faire sortie les pixels aprs le temps d'intgration (temps de pose). A la sortie
de chaque pixel, on va numriser le signal de faon transformer les charges lectriques en units
convertisseur. Expliquer la fonction read_win du listing et dessiner la forme attendue du signal
vido d'un pixel la sortie du CCD en prcisant chacune des tapes. Rpondre aux questions
suivantes

Expliquer pourquoi et comment un pixel est caractris par trois paliers : reset, rfrence,
vido.
6/14

3. L'analyse des signaux l'oscilloscope


Dans cette partie nous allons utiliser une camra Audine, quipe d'un capteur Kaf400, dont les
signaux sont directements mis et transmis sur le port parallle d'un PC.
Aidez vous des points tudis dans le chapitre du chronogramme pour reporter et pour expliquer,
sur votre copie, la forme des signaux observs l'oscilloscope dans les cas suivants (on prcisera
notamment quel point du listing cela correspond):

3.1. Analyse de V1 V2
Statuts de loscilloscope

VI sur l'entre 1,

V2 sur l'entre 2,

chercher l'chelle horizontale et l'chelle verticale

trigger sur la monte de V1

En binning 1x1, temps de pose 10 secondes, reprer la squence de vidage et la squence de lecture.
Idem en binning 4x4 puis en binning 2x2. Noter la dure de chaque palier dans chacune des
squences. En dduire le temps mis par une opration libcam_out dans le listing.

3.2. Analyse de H1 et H2
Analyser, en binning 1x1, les diffrents signaux suivants (en distinguant les squences de vidage et
de lecture). On remarquera que H2 est toujours en opposition avec H1.
Statuts de loscilloscope

H1 sur l'entre 1,

R sur l'entre 2,

Statuts de loscilloscope

V2 sur l'entre 1,

H1 surl'entre2,

A quoi sert l'horloge R ?

7/14

3.3. Analyse du signal vido


Analyser, en diffrents binnings, les diffrents signaux suivants (en distinguant les squences de
vidage et de lecture)
Statuts de loscilloscope

R sur l'entre 1,

CL sur l'entre 2,

Reprer les trois paliers : reset, rfrence et vido.

8/14

/*
* tp.c
*
* Fichier pour travaux pratiques de maitrise
* Universite Paul Sabatier
*
* --- rappel des bits de donnes du port parallele pour Audine
*
ordre : 87654321
*
bit 1 : horloge V1
*
bit 2 : horloge V2
*
bit 3 : horloge H1
*
bit 4 : horloge R (reset)
*
bit 5 : horloge CL (clamp)
*
bit 6 : horloge Start Convert (CAN)
*
bit 7 : horloge Select Byte (CAN)
*
bit 8 : horloge Select Nibble
*
* N.B. Si le bit est 0 alors la tension est au niveau haut.
*
Si le bit est 1 alors la tension est au niveau bas.
*/
#include "sysexp.h"
#if defined(OS_WIN)
#include <windows.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "camera.h"
#include "libcam.h"
#include "camtcl.h"
#include "util.h"
/* declaration des fonctions locales ce fichier .c */
void
void
void
void
void
void
void
void
void
/*
/*
/*
/*
/*

fast_vidage(struct camprop *cam);


zi_zh(struct camprop *cam);
read_pel_fast(struct camprop *cam);
read_pel_fast2(struct camprop *cam);
read_win(struct camprop *cam,unsigned short *buf);
fast_line(struct camprop *cam);
fast_line2(struct camprop *cam);
read_win2(struct camprop *cam,unsigned short *buf);
read_win3(struct camprop *cam,unsigned short *buf);

==================================================================
==================================================================
=== Fonctions appeles par l'interface pour piloter la camera ===
==================================================================
==================================================================

*/
*/
*/
*/
*/

/*
* cmdCamAcqNormal()
*
* La structure cam est definie dans le fichier libcam.h
* au niveau de la definition #define COMMON_CAMSTRUCT
*
* Les fonction commenant par libcam sont dfinies dans
* le fichier util.c
*
* La fonction atoi transforme le contenu d'une chaine de carateres
* de type char* en un nombre entier de int.
*
* La fonction sprintf a le meme effet que fprintf mais elle envoie
* la chaine de caracteres vers un pointeur char*.
*
*/
int cmdCamAcqNormal(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
{
struct camprop *cam;

9/14

char s[256];
int i;
int nb_vidages = 4;
int naxis1, naxis2,t;
unsigned short *p;
float *pp;
cam = (struct camprop*)clientData;
/* =============================================== */
/* === Etape de rincage de la matrice CCD
=== */
/* =============================================== */
/* Bloquage des interruptions */
if (cam->interrupt==1) { libcam_bloquer();}
/* vidage de la matrice */
for (i=0;i<nb_vidages;i++) fast_vidage(cam);
/* Debloquage des interruptions */
if (cam->interrupt==1) { libcam_debloquer();}
/* Remise a l'heure de l'horloge du PC */
update_clock();
/* =============================================== */
/* === Integration de l'image (attente)
=== */
/* =============================================== */
/* Delais du temps de pose (en millisecondes) */
libcam_sleep((int)(1000*cam->exptime));
/* =============================================== */
/* === Etape de lecture de la matrice CCD
=== */
/* =============================================== */
/* Bloquage des interruptions */
if (cam->interrupt==1) { libcam_bloquer();}
/* Parametres de dimensions pour allouer le pointeur image */
naxis1 = cam->nb_photox/cam->binx;
naxis2 = cam->nb_photoy/cam->biny;
/* Allocation memoire du pointeur image */
p = (unsigned short*)calloc(naxis1*naxis2,sizeof(unsigned short));
/* Lecture et numrisation de l'image vers le pointeur p */
read_win(cam,p);
/* Debloquage des interruptions */
if (cam->interrupt==1) { libcam_debloquer();}
/* Remise a l'heure de l'horloge du PC */
update_clock();
/* =============================================== */
/* === Copie des valeurs des pixels a partir
=== */
/* === du pointeur local vers le pointeur Tcl === */
/* =============================================== */
/* Allocation memoire du buffer image (pour l'interface) */
sprintf(s,"buf%d format %d %d",cam->bufno,naxis1,naxis2);
Tcl_Eval(interp,s);
/* Recupere l'adresse du pointeur buffer */
sprintf(s,"buf%d pointer",cam->bufno);
Tcl_Eval(interp,s);
pp = (float*)atoi(interp->result);
/* Transfere les donnes du pointeur *p vers le pointeur *pp */
t = naxis1 * naxis2;
while (--t>=0) {
*(pp+t) = (float)*((unsigned short*)(p+t));
}
/* Liberation du pointeur local *p */
free(p);
/* =============================================== */
/* === Complete le buffer Tcl
=== */
/* =============================================== */
/* Assigne le type de donnes qui seront enregistres sur le disque */
sprintf(s,"buf%d bitpix ushort",cam->bufno);
Tcl_Eval(interp,s);
/* Mots cls pour l'entete du fichier image */

10/14

sprintf(s,"buf%d setkwd {NAXIS1 %d int \"nombre de pixels sur X\" \"\"}",cam>bufno,naxis1);


Tcl_Eval(interp,s);
sprintf(s,"buf%d setkwd {NAXIS2 %d int \"nombre de pixels sur Y\" \"\"}",cam>bufno,naxis2);
Tcl_Eval(interp,s);
return TCL_OK;
}
/*
* cmdCamAcqSpecial()
*
* A modifier par les tudiants ...
*
*/
int cmdCamAcqSpecial(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
{
return TCL_OK;
}
/*
/*
/*
/*
/*
/*
/*

================================================================
================================================================
===
Fonctions de base pour le pilotage de la camera
===
================================================================
================================================================
Ces fonctions sont tres specifiques a chaque camera.
================================================================

*/
*/
*/
*/
*/
*/
*/

/*
fast_vidage(struct camprop *cam) -Vidage rapide de la matrice. Le decalage des lignes s'effectue
ici par groupe de 32, mais est le seul parametre a regler ici.
*/
void fast_vidage(struct camprop *cam) {
int i, j;
int imax, jmax, decaligne;
#ifdef __linux__
int toto;
#endif
/* Nombre de lignes decalees a chaque iteration.*/
decaligne = 32;
/* Calcul des constantes de vidage de la matrice. */
imax =
cam->nb_photox + cam->nb_deadbeginphotox + cam->nb_deadendphotox ;
jmax = ( cam->nb_photoy + cam->nb_deadbeginphotoy + cam->nb_deadendphotoy ) /
decaligne + decaligne;
/* Demande d'acces aux ports pour linux */
#ifdef __linux__
toto=iopl(3);
if(toto!=0) {
fprintf(stderr,"Impossible d'acceder au port parallele.\n");
exit(1);
}
#endif
for(j=0;j<jmax;j++) {
/* Decalage des lignes. */
for(i=0;i<decaligne;i++) zi_zh(cam);
/* Lecture du registre horizontal. */
/* sans reset */
for(i=0;i<imax;i++) read_pel_fast2(cam);
}
}
/*
zi_zh(struct camprop *cam) -Decalage vertical de toutes les lignes d'un cran vers le bas.

11/14

La premiere ligne du bas est donc transferee dans le registre


horizontal.
*/
void zi_zh(struct camprop *cam) {
unsigned short port = cam->port;
int i,n_iter;
n_iter = 4;
for(i=0;i<n_iter;i++) libcam_out(port,0xFB);
for(i=0;i<n_iter;i++) libcam_out(port,0xFA);
for(i=0;i<n_iter;i++) libcam_out(port,0xF9);
for(i=0;i<n_iter;i++) libcam_out(port,0xFA);
for(i=0;i<n_iter;i++) libcam_out(port,0xFB);
}

/*
/*
/*
/*
/*

11111011
11111010
11111001
11111010
11111011

*/
*/
*/
*/
*/

/*
read_pel_fast(struct camprop *cam) -Lecture rapide d'un pixel : decalage du registre horizontal
avec Reset, mais sans lecture du CAN,
*/
void read_pel_fast(struct camprop *cam)
{
unsigned short port = cam->port;
libcam_out(port,0xF7); /* 11110111 */
libcam_out(port,0xFF); /* 11111111 */
libcam_out(port,0xFB); /* 11111011 */
}
/*
read_pel_fast2(struct camprop *cam) -Lecture rapide d'un pixel : decalage du registre horizontal
sans Reset, mais sans lecture du CAN,
*/
void read_pel_fast2(struct camprop *cam)
{
unsigned short port = cam->port;
libcam_out(port,0xFF); /* 11111111 */
libcam_out(port,0xFB); /* 11111011 */
}
/*
fast_line_() -Lecture rapide du registre horizontal, avec la fonction read_pel_fast.
*/
void fast_line(struct camprop *cam)
{
int i, imax;
imax = cam->nb_photox + cam->nb_deadbeginphotox + cam->nb_deadendphotox ;
for (i=0;i<imax;i++) read_pel_fast(cam);
}
/*
fast_line2() -Lecture rapide du registre horizontal, avec la fonction read_pel_fast2.
*/
void fast_line2(struct camprop *cam)
{
int i, imax;
imax = cam->nb_photox + cam->nb_deadbeginphotox + cam->nb_deadendphotox ;
for (i=0;i<imax;i++) read_pel_fast2(cam);
}
/*
read_win(struct camprop *cam,short *buf) -Lecture normale du CCD, avec un fenetrage possible.
*/
void read_win(struct camprop *cam,unsigned short *buf)
{
int i,j;
int k,l;
int imax,jmax;
int cx1,cx2,cy1;

12/14

unsigned short int port0, port1;


unsigned short buffer[2048];
unsigned short *p0;
int x;
int a1,a2,a3,a4;
p0=buf;
port0 = cam->port;
port1 = port0+1;
/* calcul des dimensions de l'image */
imax = cam->nb_photox/cam->binx;
jmax = cam->nb_photoy/cam->biny;
/* nombre de colonnes de dbut ne pas digitaliser */
cx1 = cam->nb_deadbeginphotox;
/* nombre de colonnes de fin ne pas digitaliser */
cx2 = cam->nb_deadendphotox;
/* nombre de lignes de dbut ne pas digitaliser */
cy1 = cam->nb_deadbeginphotoy;
/* On supprime les cy1 premieres lignes */
for(i=0;i<cy1;i++) {
zi_zh(cam);
fast_line(cam);
fast_line(cam);
}
/* boucle sur l'horloge verticale (transfert) */
for (i=0;i<jmax;i++) {
/* Cumul des lignes (binning y) */
for(k=0;k<cam->biny;k++) zi_zh(cam);
/* On retire les cx1 premiers pixels avec reset */
for (j=0;j<cx1;j++) read_pel_fast(cam);
/* boucle sur l'horloge horizontale (registre de sortie) */
for(j=0;j<imax;j++) {
libcam_out(port0,247); /* reset 11110111 */
libcam_out(port0,255); /* dlai critique 11111111 */
libcam_out(port0,255);
libcam_out(port0,255);
libcam_out(port0,239); /* clamp 11101111 */
for(l=0;l<cam->binx;l++) {
libcam_out(port0,255);
libcam_out(port0,251); /* palier vido 11111011 */
}
libcam_out(port0,251);
libcam_out(port0,251);
libcam_out(port0,251);
/* numerisation et selections des nibbles a lire */
libcam_out(port0,219); /* start convert + select 11011011 */
/* recupere le nibble de poids faible de l'octet de poids faible */
a1 = libcam_in(port1) & 0x00F0;
libcam_out(port0,91); /* select 01011011 */
/* recupere le nibble de poids fort de l'octet de poids faible */
a2 = libcam_in(port1) & 0x00F0;
libcam_out(port0,155); /* select 10011011 */
/* recupere le nibble de poids faible de l'octet de poids fort */
a3 = libcam_in(port1) & 0x00F0;
libcam_out(port0,27); /* select 00011011 */
/* recupere le nibble de poids fort de l'octet de poids fort */
a4 = libcam_in(port1) & 0x00F0;
/* On reconstitue la valeur du pixel sur 16 bits. */
/* Le masque 0x8888 vient du registre de lecture du port parallele */
/* qui inverse la valeur du bit de poids fort de chaque nibble. */

13/14

x = ((a1>>4)+a2+(a3<<4)+(a4<<8))^0x8888;
if (x>32767) x=32767;
/* Stockage dans un buffer dans la meme page mem */
buffer[j] = (unsigned short)x;
}
/* On retire cx2 pixels la fin */
for (j=0;j<cx2;j++) read_pel_fast(cam);
/* On transfere le tableau vers la matrice image */
if (i!=0) {
p0[(i-1)*imax]=buffer[0];
}
for(j=1;j<imax;j++) {
p0[(i+1)*imax-j]=buffer[j];
}
}
}

14/14

Anda mungkin juga menyukai