Problema di variabili

Salve a tutti,
mentre perdevo un po di tempo ordinando la scrivania mi è arrivato sotto mano un hc sr 04 (rilevatore di distanza ad ultrasuoni), quindi ho deciso di creare una specie di autovelox di cui allego lo skech:

int echoPin = 2;                 
int initPin = 3;
unsigned long pulseTime1 = 0;
unsigned long pulseTime2 = 0;
unsigned long mis1=0;
unsigned long mis2=0;

void setup() {
  pinMode(initPin, OUTPUT);                     
  pinMode(echoPin, INPUT);    
  Serial.begin(9600);  //inizializza la seriale
}

void loop() {
  digitalWrite(initPin, HIGH);                    
  delayMicroseconds(10);                          
  digitalWrite(initPin, LOW);                     
  pulseTime1 = pulseIn(echoPin, HIGH);             
  mis1 = pulseTime1/58;                       
  unsigned long time1=millis();
  Serial.print("mis1= cm ");
  Serial.println(mis1);
  
  delay(1000);

  digitalWrite(initPin, HIGH);                    
  delayMicroseconds(10);                          
  digitalWrite(initPin, LOW);                     
  pulseTime2 = pulseIn(echoPin, HIGH);            
  mis2 = pulseTime2/58;
  unsigned long time2=millis();
  float deltat=(float(time2-time1));

  Serial.print("mis2= cm ");
  Serial.println(mis2);
  Serial.print("Time1= millisec ");
  Serial.println(time1);
  Serial.print("Time2= millisec ");
  Serial.println(time2);
  Serial.print("DELTA T = millisec  ");
  Serial.println(float(deltat));
  Serial.print("VELOCITA' (cm/ms)= cm/ms");
  Serial.println(float((mis2-mis1)/deltat));
  Serial.print("VELOCITA' (M/S)= mt/sec ");
  Serial.println(float(((mis2-mis1)/100)/(deltat/1000)));

  mis1=0;
  mis2=0;
}

Ora tralasciando gli errori dell'hardware per le misurazioni e concentrandosi solo ed esclusivamente sulla parte matematica del problema, gradirei che qualcuno mi illuminasse su come poter ottenere cifre di velocità con piu numeri decimali possibili, e come sia possibile che arduino sbagli i calcoli (per modo di dire è evidente che deve esserci un errore di programmazione) della velocità in cm/ms e m/sec.
Ad esempio stampando la seriale esce:

mis1= cm 170
mis2= cm 3726
Time1= millisec 171627
Time2= millisec 172849
DELTA T = millisec 1222.00
VELOCITA' (cm/ms)= cm/ms2.91
VELOCITA' (M/S)= mt/sec 28.64

che è corretto (anche se non capisco come un 2,91cm/ms*10 diventi un 28,64m/s invece di 29,10m/s), mentre:

mis1= cm 173
mis2= cm 171
Time1= millisec 573144
Time2= millisec 574157
DELTA T = millisec 1013.00
VELOCITA' (cm/ms)= cm/ms4239849.50
VELOCITA' (M/S)= mt/sec 42398492.00

non ha nessun senso ed è palesemente sbagliato. :fearful: :fearful:
Invece se sto fermo mi esce tipo:

mis1= cm 172
mis2= cm 173
Time1= millisec 1140804
Time2= millisec 1141819
DELTA T = millisec 1015.00
VELOCITA' (cm/ms)= cm/ms0.00
VELOCITA' (M/S)= mt/sec 0.00

ma come mi sono mosso di 1 cm in oltre 1 sec e la velocitò è 0??? (per questo chiedevo piu numeri decimali)
grazie

I calcoli in virgola mobile (float) non sono proprio il massimo per un processore a 8bit. :frowning:

Ok, lo so che arduino non è il massimo con i calcoli in virgola mobile, ma io sto chiedendo 4 cifre decimali (il minimo per apprezzare la velocità ) e non 40. Inoltre se consideri che non uso un arduino uno, ma una mega 2560, non sto chiedendo la luna.
Cmq la mia domanda finale è: ho usato correttamente la variabile float?
Come posso estirpare altre 2 cifre decimali? (anche per capire come funziona float)

Attento nibbio99, se vai nel reference e guardi il tipo float scopri che :

Floats have only 6-7 decimal digits of precision. That means the total number of digits, not the number to the right of the decimal point. Unlike other platforms, where you can get more precision by using a double (e.g. up to 15 digits), on the Arduino, double is the same size as float.

Quindi, il tipo float, su Arduino UNO e anche Mega 2560, ha in TUTTO 6 o 7 cifre significative tra parte intera e parte decimale !!! Quindi ... 2 cifre decimali = massimo 4 o 5 cifre intere :frowning:

Vedi tu se ci stai dentro ...

Guglielmo

Raggruppa tutti i calcoli dopo le letture dei sensori e prima della stampa, aggiungi qualche altra variabile se necessario.

Nell’ultimo caso hai 1 cm su oltre 1000 ms quindi velocità < 1 millesimo di cm / ms per cui è normale che avendo due cifre dopo la virgola ti venga zero.
Metti i risultati in variabili, e dopo stampali.
Inoltre…
((mis2-mis1)/100)/(deltat/1000)
semplifica la formula!

lascia deltat unsigned long invece di forzarlo a float e fai deltas=mis2-mis1 sempre unsigned long
quindi

(float) v = 10*deltas/deltat ti darà v in m/s

Dopo aver letto un po in giro e fatta qualche riflessione ho fatto alcuni accorgimenti allo skech che vado ad elencare:
-utilizzo libreria ultrasonic
-utilizzo di medie e non di misurazioni singole
-utilizzo di medie dei tempi
-creata nuova variabile (Velocita massima misurabile)
-inserito potenziometro per controllo del delay
-utilizzo micros invece di millis (per migliore la precisione di misura del tempo)
allego Skecth:

/*skech con hc04 ultrasuoni.
Autovelox con media dei tempi e a doppio campionamento di 10 misure l'una.
potenziomentro per settare il delay e quindi la massima velocità 
misurabile. 
*/
#include "Ultrasonic.h"
Ultrasonic ultrasonic(3,2);
int array1[10];
int array2[10];
int num=0;
int total1=0;
int total2=0;
int media1=0;
int media2=0;
int pot=0;
unsigned long time1[10];
unsigned long time2[10];
unsigned long deltat[10];

void setup(){
  for (int i=0;i<10;i++){
    array1[i]=0;
    array2[i]=0;
  }
  Serial.begin(9600);
}

void loop(){
  for(num=0;num<10;num++){
    total1=total1-array1[num];
    array1[num]=ultrasonic.Ranging(CM);
    time1[num]=micros();
    total1=total1+array1[num];
    media1=total1/10;

    pot=analogRead(8);
    pot=map(pot,0,1023,0,10);
    delay(pot*100);

    total2=total2-array2[num];
    array2[num]=ultrasonic.Ranging(CM);
    time2[num]=micros();
    total2=total2+array2[num];
    media2=total2/10;
    Serial.println(num);
    deltat[num]=time2[num]-time1[num];
  }
  float tempomedio=(deltat[1]+deltat[2]+deltat[3]+deltat[4]+deltat[5]+deltat[6]+deltat[7]+deltat[8]+deltat[9]+deltat[0])/10;

  float deltas=media2-media1;
  float velocita1=deltas*1000/tempomedio;
  float velocita2=velocita1*10;
  float velocita3=velocita2*3.6;
  float velmax=400*10*3.6*1000/tempomedio;

  if(num=10){
    num=0;
    if(abs(velocita1)<velmax && media1<400 && media2<400 ){
      Serial.print("mis1= cm ");
      Serial.println(media1);
      Serial.print("mis2= cm ");
      Serial.println(media2);
      Serial.print("DELTA T = microsec  ");
      Serial.println(float(tempomedio),DEC);
      Serial.print("VELOCITA' (cm/ms)= cm/ms");
      Serial.println(float(velocita1),DEC);
      Serial.print("VELOCITA' (M/S)= mt/sec ");
      Serial.println(float(velocita2),DEC);
      Serial.print("VELOCITA (KM/h)= km/h ");
      Serial.println(float(velocita3),DEC);
      Serial.print("VELOCITA MASSIMA MISURABILE IN KM/H:");
      Serial.println(float(velmax),DEC);

    } 
    else{
      Serial.println("errore");
      Serial.print("mis1= cm ");
      Serial.println(media1);
      Serial.print("mis2= cm ");
      Serial.println(media2);
    }
  }
}

Dai conti fatti posso misurare velocità da 0 a oltre 1400KM/H (almeno sulla carta impostando il delay a 0 e media dei tempi vicina a 10000 microsec se percorro 400 cm, ovvero la massima distanza misurabile ottengo 400/10=40 cm/millisec ovvero 400 m/sec ovvero ovvero 1440 KM/H) se i conti sono giusti.
Invece da prove effettuate (stando fermo) con valori di delay alti le misurazioni sono abbastanza corrette, mentre se velocizzo la cosa la differenza tra le 2 medie passa da 0 anche a 5 cm ed oltre.
L’utilizzo di un delay dinamico mi permette di avere maggiore precisione in base alla velocità da misurare o e solo un vezzo?
Come posso gestire l’errore con delay bassi per evitare cose del genere (considerando che sono fermo):

mis1= cm 162
mis2= cm 166
DELTA T = microsec 10514.0000000000
VELOCITA’ (cm/ms)= cm/ms0.3804451179
VELOCITA’ (M/S)= mt/sec 3.8044511795
VELOCITA (KM/h)= km/h 13.6960239410
VELOCITA MASSIMA MISURABILE IN KM/H:1369.6024169921