Rileva velocità al passaggio di due sensori (HC-SR04)

Salve a tutti ragazzi,
Come da titolo sto cercando di rilevare una velocità quando un corpo attraversa due sensori ultrasuoni, una funzione molto semplice, catturo il tempo del 1° sensore con millis(), poi il secondo e dalla differenza dei due ricavo il tempo. In realtà la velocità non mi serve a molto, la uso solo per rilevare un corpo che sta attraversando i due senso perchè al passaggio di un corpo (quindi con vel>0) devo far muore un servo.

Allego il mio codice:

#include <Servo.h> 
#include <NewPing.h>

//HC RS04 Sensore ultrasuoni
int triggerPort = 6;
int echoPort = 7;
int triggerPort2 = 8;
int echoPort2 = 9;

void setup() {
pinMode(13, OUTPUT);
pinMode( triggerPort, OUTPUT );
pinMode( echoPort, INPUT );
pinMode( triggerPort2, OUTPUT );
pinMode( echoPort2, INPUT ); 
Serial.begin( 9600 ); 
}

void loop() {
delay(10); // Wait 50ms between pings

 
int t1 = 0;
  
digitalWrite( triggerPort, LOW );
delayMicroseconds (10); 
//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;
int t;
   if ( (r>=0 && r<150) ) { // ok. l'oggetto è passato dal via
      t = millis();  // Mi segno il tempo di partenza
      while ( (millis() - t ) < 10000 ) // tempo massimo ammesso 10 secondi
        {
          //porta bassa l'uscita del trigger
          digitalWrite( triggerPort2, LOW );
          delayMicroseconds (10); 
          //invia un impulso di 10microsec su trigger
          digitalWrite( triggerPort2, HIGH );
          delayMicroseconds( 10 );
          digitalWrite( triggerPort2, LOW );
 
          long duration2 = pulseIn( echoPort2, HIGH );
 
          long r2 = 0.034 * duration2 / 2;
      
            if ( (r2>=0 && r2<150) ) { // Ok e' arrivato al secondo sensore
              t1 = millis(); // segno il tempo di arrivo
              break ; // esco dal while prima che scada
            }
      t1 = 0 ;
    }
    
    if ( !t1  ) {
      Serial.println("fuori tempo massimo");
       digitalWrite(13, HIGH);
    }
  }
  
int  tempo = (t1 - t ) ;
//int vel=((3.2*0.01)/(tempo*0.001));
  if (tempo  > 0  ) {
    Serial.print ("Metri/sec  ");
    Serial.println(tempo);
    digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level) 
  }
  
  else digitalWrite(13, LOW);

 }

PROBLEMA: Il codice pare funzionare, se passo la mano con una certa velocità si accende la lampadina (uso un led per simulare la funzione del servo e poi in tal caso sostituirò) il problema è che anche quando non c'è nessun movimento e quindi la velocità=0 segna ugualmente una velocità e di conseguenza il LED si accende anche quando non ce ne è bisogno, quindi anche senza il passaggio di nessun corpo.

GRAZIE in anticipo per il vostro aiuto.

Prima di tutto, nella sezione in lingua Inglese si può scrivere SOLO in Inglese ... quindi, per favore, la prossima volta presta più attenzione ...

... poi, essendo il tuo primo post, nel rispetto del regolamento (… punto 13, primo capoverso), ti chiedo cortesemente di presentarti QUI (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con MOLTA attenzione il su citato REGOLAMENTO ... Grazie.

Guglielmo

P.S.: Il tuo post è stato spostato nell'opportuna sezione del forum "Italiano"

Dopo che avrai fatto la presentazione richiesta, il mio consiglio è sempre quello di BUTTARE gli HC-SR04 e usare sempre gli SRF05. Costano poco (ma proprio poco) di più, ma sono moooolto più affidabili. Io ho smesso da 2 anni di prendere SR04.

Io invece avrei una domanda: Cosa te ne fai del secondo sensore? Perché non usi due volte il primo? Se misuri la distanza di una macchina in corsa da un unico albero prendendo 2 spazzi c'è velocità solo se si muove rispetto all'albero. Se misuri la velocità dalla distanza tra la macchina e due alberi due avrai sempre una differenza, se non é esattamente in centro tra gli alberi, ed il non avere differenze non é indice di quiete. Me lo puoi spiegare?

Prima di tutto mi scuso se ho sbagliato sezione, ma non riuscivo a trovare la sezione in italiano, grazie per avermela linkata.

giovepluvio, ho deciso di utilizzare due ultrasuoni per questi motivi: Devo rilevare il passaggio di un corpo che passa all'interno di un cilindro, quindi ho pensato di mettere i due sensori all'estremità del cilindro.

docdoc, grazie mille del consiglio, provvedo subito a disfarmene.

joe95it:
docdoc, grazie mille del consiglio, provvedo subito a disfarmene.

Però prima ho due osservazioni.
Primo, per sapere se i tuoi SR04 sono quelli "bacati" (nel mio caso TUTTI quelli che ho provato e anche qui nel forum in tanti hanno riportato lo stesso problema), ossia che molto spesso si "bloccano" e non leggono più le distanze, prova a usare uno sketch che semplicemente misura la distanza e la mostra sul monitor seriale, e poi prova ad avvicinare e allontanare un oggetto o la mano, fino a farlo puntare nel vuoto (basta che non ci siano ostacoli entro qualche metro) e quindi verificare che ripetendo queste misurazioni ad un certo punto riporta "0" in ogni condizione, fino a che non scolleghi e ricolleghi l'alimentazione dell'SR04.
Prova eventualmente ad usare QUESTA libreria che creai a suo tempo proprio per gestire correttamente i sensori ad ultrasuoni.

Seconda osservazione: non conosco bene l'esigenza, comunque perché degli ultrasuoni e non dei più semplici sensori ottici ad infrarossi che rilevano semplicemente la presenza o meno di un ostacolo entro la distanza da te impostata?

Anche perche' in genere i sensori ad ultrasuoni hanno un "cono" di lettura di circa 40 gradi (si puo ridurlo a circa 25 usando un "tromboncino" accordato, ma per scendere di piu serve un'array dinamico ed un circuito di elaborazione specifico), quindi possono facilmente dare false letture ... mentre un banale sensore IR, sia a riflessione che a traguardo, in genere ha una zona di rilevazione paragonabile ad una linea diritta ... :wink:

docdoc:
Però prima ho due osservazioni.
Primo, per sapere se i tuoi SR04 sono quelli "bacati" (nel mio caso TUTTI quelli che ho provato e anche qui nel forum in tanti hanno riportato lo stesso problema), ossia che molto spesso si "bloccano" e non leggono più le distanze, prova a usare uno sketch che semplicemente misura la distanza e la mostra sul monitor seriale, e poi prova ad avvicinare e allontanare un oggetto o la mano, fino a farlo puntare nel vuoto (basta che non ci siano ostacoli entro qualche metro) e quindi verificare che ripetendo queste misurazioni ad un certo punto riporta "0" in ogni condizione, fino a che non scolleghi e ricolleghi l'alimentazione dell'SR04.
Prova eventualmente ad usare QUESTA libreria che creai a suo tempo proprio per gestire correttamente i sensori ad ultrasuoni.

Seconda osservazione: non conosco bene l'esigenza, comunque perché degli ultrasuoni e non dei più semplici sensori ottici ad infrarossi che rilevano semplicemente la presenza o meno di un ostacolo entro la distanza da te impostata?

No, i miei SR04 non sono bacati se uso il semplice skatch della lettura dei sensori, vanno alla grande invece direi, il problema è questo sketch

#include <Servo.h> 
#include <NewPing.h>
#include <avr/io.h>
#include <avr/wdt.h>

#define Reset_AVR() wdt_enable(WDTO_30MS); while(1) {}

Servo myservo;

int triggerPort = 6;
int echoPort = 7;
int triggerPort2 = 8;
int echoPort2 = 9;
int pos=-1;
int tempo=0;

void setup() {
pinMode(11, OUTPUT);
myservo.attach(12);
pinMode( triggerPort, OUTPUT );
pinMode( echoPort, INPUT );
pinMode( triggerPort2, OUTPUT );
pinMode( echoPort2, INPUT ); 
Serial.begin( 9600 ); 

}

void loop() {
myservo.write(pos);

long duration2=0;
int t=0; 
int t1 = 0;
long duration=0;
long r2=0;
long r=0;

delay(30); // Wait 50ms between pings

digitalWrite( triggerPort, LOW );
delayMicroseconds (10); 
//invia un impulso di 10microsec su trigger
digitalWrite( triggerPort, HIGH );
delayMicroseconds(10);
digitalWrite( triggerPort, LOW );
 
  duration = pulseIn( echoPort, HIGH );
 
r = 0.034 * duration / 2;

   if (r>=0 && r<50) { // ok. l'oggetto è passato dal via
      Serial.print("      AGGANCIATO SENSORE 1:");
       Serial.println(r);
      t = millis();  // Mi segno il tempo di partenza
      while ( (millis() - t ) < 10000 ) // tempo massimo ammesso 10 secondi
        {
          //porta bassa l'uscita del trigger
          digitalWrite( triggerPort2, LOW );
          delayMicroseconds (10); 
          //invia un impulso di 10microsec su trigger
          digitalWrite( triggerPort2, HIGH );
          delayMicroseconds( 10 );
          digitalWrite( triggerPort2, LOW );
 
          duration2 = pulseIn( echoPort2, HIGH );
 
          r2 = 0.034 * duration2 / 2;
      
            if (r2>=0 && r2<50) { // Ok e' arrivato al secondo sensore
              Serial.print("      AGGANCIATO SENSORE 2:");
              Serial.println(r2);
              t1 = millis(); // segno il tempo di arrivo
              break ; // esco dal while prima che scada
            }
      Serial.println("!!!...NON AGGANCIATO SENSORE 2...!");      
      t1 = 0 ;
    }
    }
    
    if ( !t1  ) {
      
      //Serial.println("fuori tempo massimo");
       digitalWrite(13, HIGH);
       //----INIZIO FUNZIONE SERVO-----
   
  while(pos!=0){
  for(pos = 1; pos <= 180; pos += 1) // goes from 0 degrees to 180 degrees 
  {                                  // in steps of 1 degree 
    myservo.write(pos);              // tell servo to go to position in variable 'pos' 
    delay(15);                       // waits 15ms for the servo to reach the position 
  } 
  
  delay(3000);
  
  for(pos = 180; pos>=0; pos-=1)     // goes from 180 degrees to 0 degrees 
  {                                
    myservo.write(pos);              // tell servo to go to position in variable 'pos' 
    delay(15);                       // waits 15ms for the servo to reach the position 
  } 
  break;
 }
   Serial.println("RESET ARDUINO...");
   Reset_AVR();
    //---- FUNZIONE SERVO-----
    }
  
  
  
  tempo = (t1 - t ) ;
  if (tempo  > 0  ) {
    //----INIZIO FUNZIONE SERVO-----
   
  while(pos!=0){
  for(pos = 1; pos <= 180; pos += 1) // goes from 0 degrees to 180 degrees 
  {                                  // in steps of 1 degree 
    myservo.write(pos);              // tell servo to go to position in variable 'pos' 
    delay(15);                       // waits 15ms for the servo to reach the position 
  } 
  
  delay(3000);
  
  for(pos = 180; pos>=0; pos-=1)     // goes from 180 degrees to 0 degrees 
  {                                
    myservo.write(pos);              // tell servo to go to position in variable 'pos' 
    delay(15);                       // waits 15ms for the servo to reach the position 
  } 
  break;
 }
    //---- FUNZIONE SERVO-----
  
  
  }
  
  


}

Come già anticipato il mio scopo è quello di rilevare il passaggio di un corpo che attraversa un cilindro, quindi ho pensato di mettere i due SR04 alle estremità del cilindro per rilevare il passaggio (dovresti accorgerti meglio delle miei intenzioni guardando l'if in cui consegue il while(1000+t)).
(*)Il codice "dovrebbe essere semplice", quando il sensore1 rileva il passaggio cattura il millis()=t, un while ripete il ciclo di lettura del sensore2 per 10 sec e se anche il sensore2 rileva un passaggio cattura il millis()=t1, se il la differenza dei millis>0 allora c'è stato movimento.

PROBLEMA 1: In realtà quello che succede è che quando faccio partire tutto il sistema il sensore1 "si inventa" (perchè in realtà non c'è stato alcun movimento) di aver rilevato un corpo da distanza<50 e quando lo inventa il sensore1 il sensore2 (quasi come il fratellino più piccolo che imita il più grande) lo fa anche.

PROBLEMA 2: Quando si rivela la prima distanza dal sensore 1 pare che il sensore 2 si sia preimpostato un valore, infatti facendo riferimento a (*) se il passaggio c'è stato solo nel sensore 1 non dovrebbe succedere nulla, ma dovrebbe succedere solo se il passaggio avviene in entrambi, invece se metto il dito sul sensore 1 il sensore 2 inventa una distanza e quindi parte il servo.

Sono tre giorni che cerco di risolvere! HELP ME PLEASE

joe95it:
PROBLEMA 1: In realtà quello che succede è che quando faccio partire tutto il sistema il sensore1 "si inventa" (perchè in realtà non c'è stato alcun movimento) di aver rilevato un corpo da distanza<50 e quando lo inventa il sensore1 il sensore2 (quasi come il fratellino più piccolo che imita il più grande) lo fa anche.

Scusa, puoi provare a vedere il valore che registra il sensore (per ora il primo) mettendo una Serial.print(duration); prima della "if (r>=0 && r<50)" e dire cosa leggi quando parte e non c'è alcun ostacolo?

Io non ho più gli SR04 da 2 anni quindi non posso simulare il tuo sketch :wink:

10850
10837
10865
10918
10898
10924
10873
10837
10912
10861
10961
10960
10862
10871
10892
10891
11015
10850
10888
10835
10868
10942
10960
10877
10918
10967
10841
10868
10910
10895

Mi da questi valori e continua all'infinito..

E questo è successo improvvisamente.. senza alcuno passaggio di mano e nient'altro

10964
10915
10966
2903
AGGANCIATO SENSORE 2
RESET ARDUINO...
10879
10840
10897
10945
10945

Come nel problema 1

Ma con quei valori non dovrebbe entrare mai nella if(), ad esempio con 10865 avrai r = 184.

Ora se affermi che il test ping sui singoli sensori rileva correttamente sempre la distanza senza mostrare problemi di "sbalzi" anomali o, peggio, di "blocco" come quelli che provai io, e con i dati che hai postato, posso solo fare qualche ipotesi.

Se hai l'output "AGGANCIATO SENSORE 2" significa necessariamente che prima c'è stato anche quello per il sensore 1. Quindi potresti riprovare (mettendo la Serial.print() dentro l'if questa volta) e su "AGGANCIATO SENSORE1" vedere che valore ha fatto entrare nella if()? Un valore basso come questo, o addirittura zero?

Poi potrebbero forse esserci problemi di interferenza tra i due sensori? Come sono montati/puntati? Potrebbero ricevere ping anche solo di riflesso (ricorda che gli ultrasuoni sono abbastanza direzionali e "rimbalzano")? Hai provato a distanziare maggiormente i ping del primo e del secondo (supponendo ad esempio che la velocità di attraversamento tra sensore 1 e 2 non porti a tempi minori di un paio di decimi di secondo, mettere un delay(200) prima di iniziare ad attendere il secondo rilevamento)?

docdoc:
Ma con quei valori non dovrebbe entrare mai nella if(), ad esempio con 10865 avrai r = 184.

Ora se affermi che il test ping sui singoli sensori rileva correttamente sempre la distanza senza mostrare problemi di "sbalzi" anomali o, peggio, di "blocco" come quelli che provai io, e con i dati che hai postato, posso solo fare qualche ipotesi.

Se hai l'output "AGGANCIATO SENSORE 2" significa necessariamente che prima c'è stato anche quello per il sensore 1. Quindi potresti riprovare (mettendo la Serial.print() dentro l'if questa volta) e su "AGGANCIATO SENSORE1" vedere che valore ha fatto entrare nella if()? Un valore basso come questo, o addirittura zero?

Poi potrebbero forse esserci problemi di interferenza tra i due sensori? Come sono montati/puntati? Potrebbero ricevere ping anche solo di riflesso (ricorda che gli ultrasuoni sono abbastanza direzionali e "rimbalzano")? Hai provato a distanziare maggiormente i ping del primo e del secondo (supponendo ad esempio che la velocità di attraversamento tra sensore 1 e 2 non porti a tempi minori di un paio di decimi di secondo, mettere un delay(200) prima di iniziare ad attendere il secondo rilevamento)?

RISPOSTA 1° IPOTESI: Come puoi notare nell'ultimo post ti ho riportato i valori di un'improvvisa reazione del sistema, la duration si è abbassata a 2000 (da sola) e poi hai attivato il servo. Quindi magari il problema 1 sarà anche dato da alcuni sbalzi, ma questi non sono frenquentissimi e succedono raramente, pur di non acquistare altro materiale e attese di spedizione e quant'altro sono anche pronto ad accettarlo. Il problema è che dopo il primo rilevamento mi basta toccare il sensore1 per far abbassare il servo e non devo necessariamente andare a toccare il sensore2(come invece dovrebbe essere), perchè il sensore2 "inventa" subito un rilevamento appena il sensore1 lo rileva.

RISPOSTA 2° IPOTESI: Nel codice all'inizio di tutto c'è un delay(30), ho provato anche con 1500 ma non risolvo il problema..