HC-SR04 e rilevamento distanza: Max/min Range

Sto utilizzando un sensore HC-SR04 insieme ad un ARDUINO UNO rev3.

Non ho avuto problemi nel collegare il sensore e leggere i diversi valori da monitor seriale che si presentano in questa maniera:

...
durata: 5012 , distanza: 85cm
durata: 2860 , distanza: 48cm
durata: 2962 , distanza: 50cm
...

Il problema che ho riscontrato è che se avvicino troppo la mano i valori durata e distanza si azzerano, e ciò ha senso MA rimangono nulli se tolgo la mano, se resetto arduino e se ricarico il codice a meno che non stacco da breadboard il sensore e lo ricollego.
Lo stesso problema si presenta se il sensore rileva una distanza (o tempo superiore alla sua sensibilità).

Per valori intermedi non riscontro problemi.

Il codice da me utilizzato è il seguente:

//HC RS04 Sensore ultrasuoni
int triggerPort = 7;
int echoPort = 8;
 
void setup() {
 
pinMode( triggerPort, OUTPUT );
pinMode( echoPort, INPUT );
Serial.begin( 9600 );
Serial.println( "Sensore ultrasuoni: ");
 
}
 
void loop() {
//porta bassa l'uscita del trigger
digitalWrite( triggerPort, LOW );
 
//invia un impulso di 10microsec su trigger
digitalWrite( triggerPort, HIGH );
delayMicroseconds( 10 );
digitalWrite( triggerPort, LOW );
 
long duration = pulseIn( echoPort, HIGH );
 
long r = 0.034 * duration / 2;
 
Serial.print( "durata: " );
Serial.print( duration );
Serial.print( " , " );
Serial.print( "distanza: " );
 
//dopo 38ms è fuori dalla portata del sensore
if( duration > 38000 ) Serial.println( "fuori portata");
else { Serial.print( r ); Serial.println( "cm" );}
 
//aspetta 1.5 secondi
delay( 1500 );
}

Astrat

Ti conviene dichiarare duration come unsigned long e r come float.

Grazie per la risposta cyberhs!

Ho apportato le modifiche da te suggerite. Purtroppo l'errore, se così si può chiamare persiste:

durata: 298 , distanza: 5.07cm
durata: 415 , distanza: 7.06cm
durata: 758 , distanza: 12.89cm
durata: 280 , distanza: 4.76cm
durata: 112 , distanza: 1.90cm
durata: 158 , distanza: 2.69cm
durata: 607 , distanza: 10.32cm
durata: 1784 , distanza: 30.33cm
durata: 3071 , distanza: 52.21cm
durata: 4306 , distanza: 73.20cm
durata: 4952 , distanza: 84.18cm
durata: 0 , distanza: 0.00cm
durata: 0 , distanza: 0.00cm
durata: 0 , distanza: 0.00cm
durata: 0 , distanza: 0.00cm
durata: 0 , distanza: 0.00cm
durata: 0 , distanza: 0.00cm

oltre gli 84 cm non rileva più nulla !

EDIT

il problema si verifica anche a diversi valori sia maggiori che minori di 84 e si risolve solo nel momento in cui il sensore viene rimosso e successivamente rimontato nella breadboard.
Non si risolve nei seguenti modi:
ricaricando il codice
resettando la scheda arduino

Prova a cambiare così:

float r = float(duration / 2 * 0.034);

Modificato ma senza risultati non riesco a capire quale possa essere il problema!
Dal monitor seriale si vedono i diversi valori cambiare fino a quando non ne scrive altri per qualche secondo e poi da solo valori nulli!

Strano... prova a cambiare il pin ECHO

Grazie cyberhs della disponibilità!
Proveró a cambiare entrambi i pin ! Ad ogni modo ho anche provato diversi sketchs con lo stesso risultato!

EDIT

Ho modificato i pin trigger e echo ma senza nessun miglioramento. E' possibile un difetto hardware?

Controllando il datasheeet del sensore ho desunto la formula:

float r = duration / 58; // cm

A parte questo, il sensore ha un range tra 2 e 400 cm, quindi almeno 300 cm dovrebbe misurarli.

Prova anche ad imporre il timeout (default 1 s) per il pulseIn:

long duration = pulseIn(echoPort, HIGH, 1000000UL);

Buone notizie cyberhs!

Il sensore funziona come dovrebbe grazie all'introduzione del timeout per il pulseIn.
Se ho capito bene il timeout specificato impone al pin Echo di rilevare ogni tot. Giusto?

Per chi non ha noti l'utilizzo di UL nella formula di pulseIn lascio questo link.

Il codice di prova da me utilizzato lo potete trovare qua con tanto di spiegazione del funzionamento del sensore HC-SR04

Lascio anche il codice finale modificato grazie al gentilissimo cyberhs:

/*HC RS04 Sensore ultrasuoni
Il sensore utilizza due capsule Trigger e Echo, la prima emette un segnale 
acustico che una volta riflesso è captato da Echo.
*/
//Dichiarazione delle costanti Trigger e Echo 
const unsigned int triggerPort = 9; 
const unsigned int echoPort = 8;
 
void setup() {
 
pinMode( triggerPort, OUTPUT ); //Trigger emette
pinMode( echoPort, INPUT ); //Echo riceve
Serial.begin( 9600 ); //Inizializzo la comunicazione seriale
Serial.println( "Sensore ultrasuoni: ");
 
}
 
void loop() {
//porta bassa l'uscita del trigger
digitalWrite( triggerPort, LOW );
delayMicroseconds( 10 );
//invia un impulso di 10microsec su trigger
digitalWrite( triggerPort, HIGH );
delayMicroseconds( 10 );

digitalWrite( triggerPort, LOW );
 delayMicroseconds( 200 );
 unsigned long duration = pulseIn( echoPort, HIGH, 1000000UL );
 
float r = float(duration / 58); // Converte il tempo di volo in spazio, 58 è il valore suggerito dal datasheet
 ( echoPort, LOW );

Serial.print( "durata: " );//Mostra i risultati ottenuti sul monitor seriale
Serial.print( duration );
Serial.print( " , " );
Serial.print( "distanza: " );
 
//dopo tot tempo di volo: è fuori dalla portata del sensore
if( duration > 20000 ) 
Serial.println( "fuori portata");
 else { 
Serial.print( r ); Serial.println( "cm" );
}
 
//aspetta 1.5 secondi
delay( 1500 );
}

Grazie ancora cyberhs per la disponibilità!

Astrat

Se ho capito bene il timeout specificato impone al pin Echo di rilevare ogni tot. Giusto?

Non proprio: il timeout impone un un tempo massimo per l'attesa dell'evento.

Lo strano è che se non metti nulla, di default vale 1000000 (un milione) μs cioè un secondo, quindi dovrebbe essere la stessa cosa.

Sospetto che, invece, sia la formula che ti ho dato a risolvere il problema.

mah, questo è un cast inutile:

... = float(duration / 58);

Perchè il compilatore prima divide un long con un int (quindi no virgole) e poi lo converte in float.
Ha senso o così:

...= float(duration) / 58.0;

Poi fare duration/58 oppure 0.034 * duration / 2 il calcolo è molto simile
perchè equivale a "duration* 34/2000" quindi "duration * 1/58.82" => "duration/58.82" quasi uguale