Outils pour utilisateurs

Outils du site


robotics:electronics:utiliser_un_capteur_ultrason_srf04

Présentation du capteur ultrason SRF04

Le capteur SRF04 est un capteur qui utilise les ultrasons pour détecter les obstacles. Il est relativement compact (taille équivalente à un SHARP IR). Il permet de détecter les obstacles de 3 cm à 3 m. Il est très simple d'utilisation : il est alimenté en 5 V et possède une entrée Trigger et une sortie Echo .

Principe des ultrasons

Le son est une onde mécanique qui se propage sur un support matériel (ici l'air). Les ultrasons sont des ondes ayant une fréquence inaudible pour l'homme (supérieur à 20kHz). La vitesse de propagation des ondes dépend de leur milieu d'évolution (300m/s dans l'air, 1500m/s dans l'eau). Lorsqu'une onde rencontre un obstacle, une partie de cette onde est réfléchie (elle rebondie sur cet obstacle) alors que l'autre partie est transmise (absorbée par l'obstacle). C'est cette onde réfléchie qui nous intéresse (on l'appelle également echo). Le capteur SRF04 est composé d'un émetteur et d'un récepteur. En mesurant le temps entre l'émission et la réception de l'onde et la vitesse de propagation de l'onde dans le milieu, on peut en déduire la distance de l'obstacle.

Exemple : une onde émise dans l'air (300m/s) met 10ms à revenir. L'onde a parcouru 0,01×300/1 = 3 m donc l'obstacle est situé à 3/2 = 1,5m (puisque l'onde a parcouru l'aller et retour donc 2 fois la distance de l'obstacle)

Fonctionnement du capteur

Le SRF04 a besoin de recevoir une impulsion de 10 µs sur l'entrée Trigger pour commencer la détection. Il génère alors 8 impulsions ultrason à 40 Hz et attend l'echo. Le SRF04 renvoit sur la sortie Echo un signal proportionnel à la distance le séparant de l'obstacle. Si rien n'est détecté, le SRF04 revoit un signal de 36 ms.

Pour connaître la distance, il suffit de mesurer la largeur du signal retourné par le SRF04 en µs et de le diviser par 58 pour avoir une distance en cm (ou 148 pour l'avoir en inch).

Exemple : un signal de 5ms donne un obstacle à 5000/58 = 86 cm.

Mise en oeuvre

Electronique

Nous avons utiliser une ARDUINO UNO pour tester ce capteur. Le SRF04 doit être alimenté en 5 V (via la ARDUINO). L'entrée « Trigger » est mise sur la sortie PB1 (broche 9) et la sortie « Echo » sur l'entrée PB0/ICP (broche 8).

Informatique

L'algorithme est très simple.

Timer 1

Nous allons utiliser le timer 1 (16 bits) et les interruptions « OverFlow » et « Input Capture ».

OverFlow

Le Timer 1 est chargé avec une valeur (par défaut 0) et compte de cette valeur à 0xFFFF. Une fois arrivé à 0xFFFF, le timer repasse à 0 (débordement) et continue de compter. Le flag TOV1 est alors mis à 1 ce qui génère une interruption (si celle si sont activées : mettre à 1 le bit TOIE1 du registre TIMSK1 et le bit I du registre SREG). Nous allons utiliser la fonction débordement du timer (Overflow) pour compter la largeur de l'impulsion trigger (10µs) et le temps d'attente après la réponse du SRF04 (10ms).

Input Capture

Cette fonction du timer 1 permet de relever le temps du timer 1 à la réception d'un événement. En effet, dès qu'un événement (front montant ou descendant) est détecté sur l'entrée ICP (PB0), la valeur du compteur (TCNT1) est copié dans le registre ICR1. Le flag ICF1 est alors mis à 1 ce qui génère une interruption (si celle si sont activées : mettre à 1 le bit ICIE1 du registre TIMSK1 et le bit I du registre SREG). Nous allons utiliser la fonction Input Capture du timer pour détecter le début et la fin de l'Echo.

Configuration

Registre TCCR1A : permet de configurer le timer 1. Nous utilisons le mode normal WGM12:0 = 0 TCCR1B : permet d'activer les fonctions du timer1. Il faut activer la fonction Input Capture (ICES1 = 1). Il est également intéressant d'activer le filtre Noise Canceler (ICNC1 = 1). Ce registre permet aussi de configurer le prescaler. Choix du prescaler Nous devons compter au maximum 36ms avec un timer 16 bits. Nous avons un quartz de 16MHz. Pour cela, il faut un prescaler de 36ms/65535*16MHz = 8,8 minimum. En prenant un prescaler de 64, on aura une précision de 16MHz/64 = 4µs soit 4/58 = 0,7 mm. CS12:0 = 011

TCNT1 contient la valeur du compteur

ICR1 est chargé à la valeur du compteur à chaque événement sur ICP (PB0).

TIMSK1 permet d'activer les interruptions relative au timer 1. Il faut activer les interruptions overflow (TOIE1 = 1) et Input Capture (ICIE1 = 1).

TIFR1 contient les flags d'interruption. C'est flags sont remis à 0 à l'exécution de l'interruption.

Chronogramme

D'après le chronogramme de la datasheet, l'impulsion d'entrée Trigger doit durer 10 µs minimum puis le SRF04 génère 8 impulsions ultrason à 40 kHz. Ensuite le signal de sortie Echo peut durer au maximum 36ms (si aucun obstacle n'est détecté) et il faut attendre 10 ms après la fin du signal Echo pour générer à nouveau une impulsion d'entrée Trigger.

  1. interruption OVERFLOW. On met TCNT1 = 0xFFFC (pour compter 3 * 4µs = 12 µs)
  2. interruption OVERFLOW. On met TCNT1 = 0.
  3. interruption INPUT CAPTURE. On sauvegarde TCNT1.
  4. interruption INPUT CAPTURE. On sauvegarde TCNT1, on convertit en distance ((finEcho-debutEcho) /58) et on met TCNT1 = 63035 (pour compter 2500 * 4 µs = 10 ms).

Code

/* ARDUINO UNO
 * 8 - PB0 (ICP) : Echo Pulse Output
 * 9 - PB1 : Trigger Pulse Input */
 
#include <avr/io.h>
#include <avr/interrupt.h>
 
#define DISTANCE_CM	58
 
#define TIME_TRIGGER_PULSE	65532	//65535 - 3 (3*4 = 12 us)
#define TIME_NEXT_TRIGGER_PULSE	63035	//10ms (65535-2500*4)
#define TRIGGER_PULSE	1
#define WAIT_NEXT_TRIGGER_PULSE	2
 
volatile unsigned int startEcho, endEcho, timeEcho;
volatile unsigned int distance;
volatile unsigned char phase;
 
/* interruption sur un evenement sur ICP */
ISR(TIMER1_CAPT_vect)
{
	/* If ICP interrupt was for falling edge) */
	if ((PINB & 0x01) == 0)
	{
		TCCR1B |= (1 << ICES1);	/* Reverse sense of ICP interrupt edge */
		endEcho = ICR1;
		timeEcho = endEcho - startEcho;
		timeEcho *= 4; /* the width of the pulse is mesured in µs */
		distance = timeEcho / DISTANCE_CM; /* then dividing by 58 will give you the distance in cm */
 
		TCNT1 = TIME_NEXT_TRIGGER_PULSE; /* attente 10 ms */
		phase = WAIT_NEXT_TRIGGER_PULSE;
	}
	/* rising edge */
	else
	{
		TCCR1B &= ~(1 << ICES1);	/* Reverse sense of ICP interrupt edge */
		startEcho = ICR1;
	}
}
 
ISR(TIMER1_OVF_vect)
{
	/* phase 1 : generation impulsion Trigger */
	if (phase == WAIT_NEXT_TRIGGER_PULSE)
	{
		TCNT1 = TIME_TRIGGER_PULSE;
		phase = TRIGGER_PULSE;
		PORTB = 0x02;
	}
	/* attente de la reponse */
	else// (phase == TRIGGER_PULSE)
	{
		TCNT1 = 0;//TIME_NEXT_TRIGGER_PULSE;
		//phase = WAIT_NEXT_TRIGGER_PULSE;
		PORTB = 0;
	}
}
 
/* le TIMER1 doit compter toutes les 4 µs pendant 50 ms */
void initTimer1(void) {
	/* TCCR1A - Timer/Counter1 Control Register A */
	TCCR1A = 0; /* normal mode */
	/* TCCR1B - Timer/Counter1 Control Register B */
	TCCR1B = (1 << ICES1) /* a rising edge will trigger the capture */
			| (1 << CS11) | (1 << CS10); /* prescaler 64 */
	/* TCCR1C - Timer/Counter1 Control Register C */
	TCCR1C = 0;
	/* TIMSK1 - Timer/Counter1 Interrupt Mask Register */
	TIMSK1 = (1 << ICIE1) | (1 << TOIE1); /* Timer 1 Input Capture and overFlow interrupt enable */
	/*TCNT1 - Timer/Counter1 */
	TCNT1 = 0;
}
 
void initPort(void) {
	/* PB0 : input - PB1 : output */
	DDRB = 0x02;
	PORTB = 0x00;
	DDRD = 0xFF;
	PORTD = 0x00;
}
 
void init(void)
{
	initPort();
	initTimer1();
	usartInitialise();
	SREG = (1 << SREG_I); /* The Global Interrupt Enable bit must be set for the interrupts to be enabled */
}
 
int main(void)
{
	init();
	TCNT1 = TIME_NEXT_TRIGGER_PULSE;
	phase = WAIT_NEXT_TRIGGER_PULSE;
 
	while (1)
	{
 
	}
}
robotics/electronics/utiliser_un_capteur_ultrason_srf04.txt · Dernière modification: 2012/09/20 10:52 (modification externe)