Carte ATMEGA32 avec télécommande IR,télémètre IR, etc.

From Eric

Revision as of 15:42, 2 January 2011 by Ejenn (Talk | contribs)
Jump to: navigation, search

Contents

Objectifs

Cette première carte à base d'Atmega32 avait pour but initial de servir de carte de contrôle du robot roulant M1. En définitive, elle représente actuellement le "banc d'essais" de l'Atmega32, du capteur de distance Sharp, du bus I2C, etc.

Réalisation

Aperçu général de la carte

Exp atmega ir compas cpu board.png
Exp atmega ir compas display.png

Télécommande infrarouge

La carte est équipée d'un capteur à infrarouge du type TSOP4838 (gamme 38KHz) qui permet de capter le signal d'une télécommande de téléviseur (notamment).

Le capteur réalise le filtrage et la démodulation du signal de la télécommande. En sortie du capteur, la valeur du signal est binaire.

Le signal est codé selon le standard RC5. La structure d'une trame est donnée ci-après :

Rc5 frame.png

On trouvera sur internet de nombreuses versions de programmes permettant le décodage des trames RC5, dont une proposée par Atmel (rc5.pdf ici).

Notre implémentation utilise les interruptions. C'est un choix. Il nous a permis d'expérimenter la gestion des interruptions sur Atmega.

Le principe est de déterminer l'instant d'échantillonnage du signal du capteur de sorte que la valeur du signal à cet instant corresponde à la valeur du bit reçu.

Pour ce faire, on procède ainsi :

  • on détecte le premier front descendant correspondant à la réception du bit de start ;
  • on mesure la durée qui sépare cette première transition de la suivante, l'intervalle est appelé dt ;
  • à partir de cet instant, on échantillonnera le signal 3/2 dt après chaque front descendant.

Ce principe est illustré ci-dessous.

* -------------------------------------------------------------
* Le comportement est le suivant
*                     +-- 1er échantillon
*                     |
*          t0   t1    v               v 
*  -----+   +---+   +---+       +---+---+
*       |   |   |   | . |       |     . |
*       |   |   |   | . |     v |     . |
*       +---+   +---+ . +---+---+     . +---
*      start. start   . .     . .     .
*       1   .   2     . .     . .     .
*       .   .   .     . .     . .     .
*       .   .   .     . .     . .     .
*       .   .   .     . .     . .     .
*       .   .   .     . .     . .     .
*       <--->   .     . .     . .     .
*        dt     <-----> <-----> <----->
*                3/2dt   3/2dt   3/2dt

La gestion du décodage est réalisé par une machine à états dont les transitions sont réalisées lors de la réception :

  • de l'interruption INT1 qui est émise lors de toute transition du signal en provenance du capteur
  • de l'interruption TIMER1_COMPARE qui est émise lorsque le compteur du timer 1 atteint une valeur programmée


Le code du handler de l'interruption INT1 est donné ci-après :

ISR(INT1_vect) 
{ 
	uint16_t tmp;
	switch ( state )
	{
		case 0:  // Front milieu du premier bit de start
		{
			it_tmp=0;

			// Réinitialiser le compteur.
			TCNT1 = 0;
			// Configurer le timer en mode normal.
			TCCR1A = 0;
			// Configurer la source et faire démarrer le timer.
			// Le prescaler vaut 8.
   			TCCR1B |= ( (0 << CS12) | (1 << CS11) | (0 << CS10));
			state = 1;
			break;
		}
		case 1: // Front montant deuxième bit de start
			// Lire la valeur du timer (dt)
			tmp = TCNT1;
			// Et calculer la valeur de l'attente (3/2 largeur d'un bit)
			ir_dt = tmp;
			ir_dt += (tmp >> 1);

			// Stopper le timer.
   			TCCR1B = 0;

			// Initialiser le comparateur
			OCR1A   = ir_dt; 

			// Initialiser le timer
			TCNT1 = 0;

			// Activer l'interruption sur CTC 
   			TIMSK |= (1 << OCIE1A);
						
			state = 2;
			break;

		case 2:
		default: // Front milieu
			
			// Inhiber l'IT INT1.
			GICR ^= (1 << INT1);

			// Configurer le timer dans le mode CTC
			// et démarrer le timer.
   			TCCR1B |= ( (1 << WGM12) | (0 << CS12) | (1 << CS11) | (0 << CS10)); 

			break;
			
	}    
 }


Le code du handler d'interruption TIMER1 COMPARE est donné ci-après :

ISR(TIMER1_COMPA_vect) 
{ 

	// Capturer le bit.
   	it_tmp |= ( PIND & (1<<PD3)) >> PD3 ;
   	it_tmp <<= 1;

	// Stopper le timer (CS10..12 = 0).
	TCCR1B = 0;

	// Faire évoluer l'état.
	state++;

	// A-t-on fini d'échantillonner ?
	if ( state == 15 )
	{
		// OUI: Stocker le résultat
		ir_code = it_tmp;

		// Réinitialiser la machine à états
		state = 0;

		// Effacer le flag (éventuellement positionné) 
		GIFR |=  ( 1<< INTF1);
		// Réactiver l'IT sur front pour une prochaine acquisition
		GICR |= (1 << INT1);
	}
	else
	{	
		// Supprimer le flag de détection de front
		// éventuellement positionné pendant l'attente.
		GIFR |=  ( 1<< INTF1);

	  	// Réactiver l'IT sur front.
		GICR |= (1 << INT1);
	}
}

Actuellement, ce mode de gestion du décodage RC5 n'est pas robuste à la perte d'une transition puisque la machine à états attend un nombre fixe de bits avant de considérer la réception achevée. Une amélioration indispensable consisterait à introduire un délai maximum (timeout) entre la réception du bit de start et la réception du bit de stop et de rejeter la trame si ce délai vient à être dépassé.


Horloge temps-réel sur bus I2C

Compas sur bus I2C

Accéléromètre analogique

Télémètre à infrarouges

Conclusions et leçons