Collegare un sensore di prossimità ad Arduino per calcolare la distanza da un oggetto.
Esistono diversi circuiti integrati che assolvono questo compito.
Le tecnologie utilizzate sono sostanzialmente due: infrarossi ed ultrasuoni. La mia scelta è caduta sul Sonic SRF05 che impiega la seconda tecnologia: dal datasheet e dai vari post che ho visto in giro, sembrava quello più affidabile, più economico e più semplice da impiegare.
Ho acquistato l’integrato in Italia su Robot-Italy
Il circuito si presenta così:



Il funzionamento è semplice, avviene inviando un impulso ad ultrasuoni (frequenza attorno ai 40Khz), attendendo che l’impulso ritorni dopo aver colpito un oggetto. Misurando il tempo impiegato fra il momento in cui l’impulso è stato emesso e quello in cui questo ritorna, viene calcolata la distanza fra il sensore e l’oggetto. Le distanze misurabili vanno dai 3 cm ai 4 metri.

Interfacciare il sensore ad Arduino è veramente molto semplice, ci sono solo 4 connettori di cui preoccuparsi: alimentazione, massa, trigger ed echo. L’alimentazione richiesta è pari a 5V, esattamente la tensione emessa da Arduino, per cui per alimentarlo è sufficiente collegarlo al controllore senza l’ausilio di alimentazioni esterne.

Schema di collegamento

Colleghiamo il connettore ‘echo’ al Pin 2 del controllore, quello trigger al Pin 3 e, in fine, i due Pin di alimentazione (+5V e GND).
Fatti i dovuti collegamenti hardware passiamo alla parte software, useremo questo algoritmo per la lettura della misura: dopo aver inizializzato le variabili e i PIN del controllore, eseguiamo 10 letture consecutive, ne calcoliamo le media e prendiamo quella come valore della distanza in cm.

Di seguito il codice sorgente:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/*
 * Autore: Corrado Ignoti
 *
 * Descrizione: Interfaccia un SFR05 con Arduino
 *
 * Maggiori informazioni su: http://www.corradoignoti.it
 */


const int numOfReadings = 10;                   // numero di letture
int readings[numOfReadings];                    
int arrayIndex = 0;                             // contatore per ciclare nell'array
int total = 0;                                  
int averageDistance = 0;                        // distanza media

// inizializzo i PIN per collegare la scheda SFR05
int echoPin = 2;                                // echo (digital 2)

int initPin = 3;                                // trigger  (digital 3)
unsigned long pulseTime = 0;                    
unsigned long distance = 0;                     // distanza in cm

//setup
void setup() {
  pinMode(initPin, OUTPUT);                    
  pinMode(echoPin, INPUT);    
 
  // inizializza un array delle letture
  for (int thisReading = 0; thisReading < numOfReadings; thisReading++) {
    readings[thisReading] = 0;
  }
     Serial.begin(9600);  //inizializza la seriale
}

// loop principale
void loop() {
  //manda un impulso di ampiezza 10 us
  digitalWrite(initPin, HIGH);                    
  delayMicroseconds(10);                          
  digitalWrite(initPin, LOW);                    
  pulseTime = pulseIn(echoPin, HIGH);             // Aspetta l'eco di risposta
  distance = pulseTime/58;                        // Distance = tempo impulso / 58 per calcolare i [cm] di distanza.
 
 //Per diminuire l'errore crea un array con le letture e calcola la media
  total= total - readings[arrayIndex];            
  readings[arrayIndex] = distance;              
  total= total + readings[arrayIndex];            
  arrayIndex = arrayIndex + 1;                    
 
  if (arrayIndex >= numOfReadings)  {
      arrayIndex = 0;
  }
  averageDistance = total / numOfReadings;      //Media dei valori delle distanze acquisite
 
  //Scrive il valore della distanza media sulla seriale
  Serial.print ("Distanza (media): ");
  Serial.println(averageDistance, DEC);        
  delay(100);                                  
}

All’inizio del ciclo loop() questa porzione di codice:

1
2
3
4
5
  digitalWrite(initPin, HIGH);                    
  delayMicroseconds(10);                          
  digitalWrite(initPin, LOW);                    
  pulseTime = pulseIn(echoPin, HIGH);            
  distance = pulseTime/58;

manda un impulso per 10us aspetta e si mette in ascolto aspettando l’eco di risposta. Attraverso la primitiva pulseIn(), calcola il tempo fra l’emissione del segnale e la ricezione dell’impulso di risposta. La distanza in cm si ottiene dividendo per 58 questo valore.
La seconda parte del codice, esegue 10 letture consecutive, le mette in un array. Calcola la media delle letture e stampa questo valore sulla seriale.