La carte émettrice reçoit le pulse de synchronisation émis par le robot via le zigbee, détermine si ce pulse lui est destiné ou non.

Si le pulse lui est destiné, la carte émet ou reçoit le message prévu par ultrason.

Synchronisation

Un octet envoyé par le robot contenant le numéro de la balise activée.

Emission ultrason

Les émetteurs utilisés émettent des ultrasons vers 200 kHz . Le message envoyé est un pulse, éventuellement codé.

Ces émetteurs ont besoin d'une tension assez élevée pour fonctionner, 40 Vpp semble convenir.

Les émetteurs sont attaqués par un signal carré à la fréquence voulue.

Réalisation

Génération d'un signal périodique: utilisation d'un timer de l'ATMEGA88 avec les interruptions.

L'ATMEGA88 dispose de plusieurs compteurs; on utilise ici le compteur 16 bits pour générer un créneau de fréquence 200 KHz.
Une fois activé le compteur fonctionne de manière cyclique: il compte de 0 à sa valeur maximale. On peut préciser une valeur de comparaison, ce qui permet de raccourcir la durée du cycle; définir cette valeur est donc un moyen de définir la fréquence du signal.

Le compteur est capable si on le souhaite de prendre le contrôle d'une pin du microcontrôleur: dans ce cas à chaque cycle du compteur la pin bascule de 0 à 1 et inversément. Cela suffit à générer un signal de type créneau sur cette pin.

Si on veut contrôler à l'aide du compteur un dispositif qui n'est pas connecté à la pin réservée au timer, on peut se servir des interruptions (interrupt). Une interruption permet d'effectuer des actions brèves (par exemple modifier un registre quelconque) à chaque cycle du compteur. C'est de cette façon que nous avons procédé.

On commence par sélectionner l'horloge du compteur: on peut utiliser l'horloge interne à la fréquence F0, ou bien des sous-multiples (F0/8, F0/64, F0/256, F0/1024) ou encore une horloge externe. Pour nous F0 convient:
/* CLOCK SELECT : values for TCCR1B[2,1,0] :
*   2 | 1 | 0 | effect
*  -----------------------------------------------------
*   0 | 0 | 0 | no clock signal (timer off)
*   0 | 0 | 1 | internal clock F0        (no prescaling)
*   0 | 1 | 0 | internal clock F0/8      (no prescaling)
*   0 | 0 | 1 | internal clock F0/64     (no prescaling)
*   0 | 1 | 1 | internal clock F0/256    (no prescaling)
*   1 | 0 | 0 | internal clock F0/1024   (no prescaling)
*   1 | 1 | 0 | external clock source on T1 pin
*   1 | 1 | 1 | external clock source on T1 pin             */
    TCCR1B =  1;

Ensuite on initialise le compteur à zéro (facultatif: c'est la valeur au démarrage)
/* Timer initial value 0 */
    TCNT1H = 0x00 ;
    TCNT1L = 0x00 ;

On définit les deux pins du pont en H en sorties dans le registre.
DDRB |= 1 << PB1 ;    // PB1 -> OC1A
    DDRB |= 1 << PB2 ;    // PB2 -> OC1B


  On définit les valeurs : 1 pour laquelle la comptage de A s'inverse (il monte puis descend après OCR1A)

                                            2 pour laquelle le comptage de B s'inverse (il descend puis remonte après OCR1B)

                                            3 pour laquelle le timer repart a zero.
OCR1AH = 0;
    OCR1AL = t_base;
    OCR1BH = 0;
    OCR1BL = t_base;

    ICR1H = 0;
    ICR1L = 2*t_base ;



On définit le mode de fonctionnement: ici un Fast PWM, avec un timer remis à zero sur comparaison à ICR1,  avec réactualisation de OCR1x en descente.

TCCR1B |= 1 << WGM13;
    TCCR1B |= 1 << WGM12;
    TCCR1A |= 1 << WGM11;
//    TCCR1A |= 1 << WGM10;



    /* COMPARE OUTPUT MODE : values for TCCR1A[7..4]
    * we set TCCR1A[7,6] to [1,0] to select 'OC1A on Compare match : Clear on Upcounting, Set on Downcounting'
    * we set TCCR1A[5,4] to [1,1] to select 'OC1B on Compare match : Set on Upcounting, Clear on Downcounting'
        */
On met  TCCR1A[7,6] à [1,0] pour selectionner la remise à zero de OC1A en montée, mise à 1 en descente.

On met  TCCR1A[5,4] à [1,1] pour selectionner la remise à zero de OC1B en descente, mise à 1 en montée.
TCCR1A |= (1 << 7 );
    TCCR1A |= (1 << 4 | 1 << 5);


On authorise les interruptions sur OC1A et OC1B, ici cela ne sert en rien au comptage mais nous a permis de faire clignoter des led lors du fonctionnement.

TIMSK1 |= 1 << 1 ; // allow interrupts on A
    TIMSK1 |= 1 << 2 ; // allow interrupts on B
   

On désactive la réduction de consommation pour activer le compteur (cf p 109 de la datasheet).
PRR = 0;

Remarque: TIMER1_COMPA_vect est le registre d'interrupt correspondant au canal A du compteur 1. On peut trouver ces noms en fouillant dans les header files du compilateurs à   /usr/avr/include/avr/iom88.h  .

La fonction toggle_creneau permet de faire basculer un signal de 0 à 1 et inversément. On remarquera que, contrairement à l'utilisation de la pin associée au timer, cette manière de procéder permet de gérer plusieurs signaux, par exemple pour générer deux créneaux de même période.