Go Down

Topic: Maledette funzioni!! (Read 15074 times) previous topic - next topic

paolometeo2

Help software!  Scusate il titolo  :0, ma mi sono imbattuto in uno di quei problemi software che i vari siti che spiegano il C non trattano o io non sono stato bravo nel cercare.
Si tratta del passaggio di un risultato calcolato in una funzione al programma chiamante per mezzo degli argomenti.  In breve il programmino di prova con la funzione è il seguente:
Code: [Select]

#include <math.h>

  float dis ;
void setup(){
  Serial.begin(9600);
   float la1 = 45.78956;
   float lo1 =  9.36424;
   float la2 = 45.78997;
   float lo2 =  9.36514;
   float direct;
   float dis =  Distance(la1, lo1, la2, lo2, direct);
  Serial.println(dis,DEC);
  Serial.println(direct,DEC);
}
void loop(){
 
}
////////////////////////////////////////////////////////////////////////
  static float Distance(float lat1, float lon1, float lat2, float lon2, float dir){
  float rt = 6371000;  // raggio terra in m
  float pi = 3.141592654;
  float coslat = cos((lat1+lat2)*pi/360);
  float dx = rt*(lon2-lon1)*coslat*pi/180;
  float dy = rt*(lat2-lat1)*pi/180;
  float dist = sqrt(dx*dx + dy*dy);
  dir = atan2(dx,dy);  // da -pi a +pi  artg(dx/dy)
  Serial.println(dir,DEC);
  return(dist);
  }
 

I valori da passare al main sono: "dist", che viene passato tramite il return, e "dir", che viene passato tramite gli argomenti.
I numeri che escono sono:
0.9900114059
83.4928741455
0.0000000000
a dimostrazione che il valore della variabile dir non viene passato al main.

P.S.
per i curiosi, sto costruendo un GPS+bussola.
paolo
www.meteoenergia.it

gpb01

#1
Aug 04, 2013, 10:15 am Last Edit: Aug 04, 2013, 10:20 am by gpb01 Reason: 1
Ciao Paolo,
un paio di domande ...

1. Passi la variabile float direct, ma non l'hai inizializzata quindi, probabilmente, vale sempre zero.

2. Sei conscio del fatto che il float su Arduino ha una scarsa precisione (solo 32 bit e 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." ) e NON è adatto a fare calcoli di distanze tramite coordinate GPS senza una enorme perdita di precisione ?

Quindi, ad esempio, totalmente inutile scrivere :
Code: [Select]
float pi = 3.141592654;
dato che la precisione è comunque al massimo di 6-7 cifre (leggi bene la nota in inglese ... "... total number of digits") !

Per inciso, se prima di stampare il valore aggiungessi una Serial.print con una descrizione del valore che stai stampando ... renderesti più  comprensibili i risultati ;)

Guglielmo
Search is Your friend ... or I am Your enemy !

astrobeed


Help software!  Scusate il titolo  :0, ma mi sono imbattuto in uno di quei problemi software che i vari siti che spiegano il C non trattano o io non sono stato bravo nel cercare.
I numeri che escono sono:
0.9900114059
83.4928741455
0.0000000000
a dimostrazione che il valore della variabile dir non viene passato al main.


Premesso che questo calcolo richiede la matematica a 64 bit (double) che non è disponibile su Arduino, a meno che non ti accontenti di lavorare sulle grandi distanze con risoluzione kilometrica, dir non può essere restituito al main visto che la return è per dist, se dir deve essere disponibile anche al main allora deve essere una variabile globale.
Togli quello static alla funzione che non serve a nulla.
Scientia potentia est

paolometeo2

Sul problema della precisione ho riflettuto, concludendo che la quinta cifra decimale è sufficiente per una rappresentazione in gradi delle coordinate, infatti se un grado di latitudine corrisponde a circa 100 km, 1m (massima precisione per un GPS) sarà un 100000 esimo di grado. Per quanto riguarda i calcoli intermedi mi riprometto di fare delle prove. Le costanti le ho scritte con più cifre giusto per annotazione.
Ho letto che double e float sono sempre di 4 byte su Arduino, vero?
Per quanto riguarda i valori che una funzione restituisce al main, se ho capito bene, solo uno può ritornare con il nome della funzione, mentre negli argomenti non posso passare nient'altro. E' giusto? Altrimenti uso variabili globali.
paolo
www.meteoenergia.it

gpb01


Sul problema della precisione ho riflettuto, concludendo che la quinta cifra decimale è sufficiente per una rappresentazione in gradi delle coordinate, infatti se un grado di latitudine corrisponde a circa 100 km, 1m (massima precisione per un GPS) sarà un 100000 esimo di grado.


Paolo, ricorda che gli errori .... si accumulano ... su ogni operazione che fai tronchi il risultato ... non so alla fine che precisione ti rimane ...
Astro, che conosce bene l'argomento, ti ha indicato un errore di .... centinaia di Km ...


Per quanto riguarda i calcoli intermedi mi riprometto di fare delle prove. Le costanti le ho scritte con più cifre giusto per annotazione.
Ho letto che double e float sono sempre di 4 byte su Arduino, vero?


Se hai letto la mia risposta precedente hai tutte le indicazioni ... ;)


Per quanto riguarda i valori che una funzione restituisce al main, se ho capito bene, solo uno può ritornare con il nome della funzione, mentre negli argomenti non posso passare nient'altro. E' giusto? Altrimenti uso variabili globali.


In realtà il discorso è più complesso ... ad una funzione i parametri si possono passare "by value" o "by reference", e, nel secondo caso, la funzione può addirittura modificare il valore dei parametri ... ma ... credo di mettere "troppa carne al fuoco" ... ;)

Guglielmo
Search is Your friend ... or I am Your enemy !

leo72

Ti posso confermare che Arduino proprio litiga con float con tanti numeri decimali.
Potresti provare a convertire tutto in unsigned long, tipo a 32 bit, e poi in fase di stampa mettere il punto decimale dove ti serve. Oppure, usare unsigned long long, a 64 bit. Non è un tipo nativamente supportato dal micro per cui la dimensione dello sketch cresce molto, però se necessiti di grossa precisione, potrebbe essere una soluzione rapida.

nid69ita

#6
Aug 04, 2013, 11:45 am Last Edit: Aug 04, 2013, 11:56 am by nid69ita Reason: 1


Per quanto riguarda i valori che una funzione restituisce al main, se ho capito bene, solo uno può ritornare con il nome della funzione, mentre negli argomenti non posso passare nient'altro. E' giusto? Altrimenti uso variabili globali.

In realtà il discorso è più complesso ... ad una funzione i parametri si possono passare "by value" o "by reference", e, nel secondo caso, la funzione può addirittura modificare il valore dei parametri ... ma ... credo di mettere "troppa carne al fuoco" ... ;)
Guglielmo


Quotone.
Praticamente, devi usare i puntatori se vuoi poter modificare una variabile passata come parametro. Perciò occhio che con i puntatori è un attimo fare casino.  
Se vuoi saperne di più, cerca su libri di C o su internet,  il classico esempio dello swap (cambio) dei contenuti di due variabili passati ad una funzione.

In Swap1 lo scambio non avviene perchè in a e b ci sono le copie dei valori passati
Code: [Select]

int x=1,y=3;
swap1(x,y);      // contenuto delle variabili swap non funziona
Serial.print(x); Serial.print(" ");Serial.println(y);
swap2(&x,&y);    // indirizzo delle variabili
Serial.print(x); Serial.print(" ");Serial.println(y);
...
void swap1(int a,int b)
{ int tmp=a;
 a=b;
 b=tmp;            
}
void swap2(int *a,int *b)
{ int tmp=*a;
 *a=*b;
 *b=tmp;            
}
my name is IGOR, not AIGOR

nid69ita

#7
Aug 04, 2013, 11:58 am Last Edit: Aug 04, 2013, 11:59 am by nid69ita Reason: 1
Il C++ ammette poi questa sintassi che semplifica:
Code: [Select]
int x=1,y=3;
swap3(x,y);      // sembra che passi il contenuto delle variabili ma i parametri prendono l'indirizzo perchè così vuole la funzione
                     // non dipende più dal chiamante ricordarsi di mettere &x e &y come per swap2()
...
void swap3(int &a,int &b)
{ int tmp=a;
 a=b;
 b=tmp;            
}
my name is IGOR, not AIGOR

gpb01

#8
Aug 04, 2013, 12:08 pm Last Edit: Aug 04, 2013, 12:10 pm by gpb01 Reason: 1
Nid ... ma secondo te la mia frase ...

Quote
... credo di mettere "troppa carne al fuoco" ...


era buttata li a caso o sapevo quello che dicevo (dato che conosco Paolo) ???

Provaci a ragionare va ...

Guglielmo
Search is Your friend ... or I am Your enemy !

nid69ita

Ho scritto la prima frase, poi  ... non ho resistito :D

Ma @paolo non è abbastanza skillato? Fà molti interventi nel forum
my name is IGOR, not AIGOR

paolometeo2

@nid69ita, grazie per lo skillato, ma purtroppo nel software sono rimasto a vecchi concetti. In passato usavo molto le "subroutine" dove passavo tutte le variabili che volevo in input e output. Adesso devo dimenticare quel modo di programmare semplice  =(!
Quote
Quotone.
Praticamente, devi usare i puntatori se vuoi poter modificare una variabile passata come parametro. Perciò occhio che con i puntatori è un attimo fare casino. 
Se vuoi saperne di più, cerca su libri di C o su internet,  il classico esempio dello swap (cambio) dei contenuti di due variabili passati ad una funzione.

Volevo proprio evitare di usare i puntatori e concentrarmi più sul problema numerico, infatti Guglielmo mi ha capito.
@leo72, ascolterò i tuoi consigli e proverò ad usare i diversi tipi di variabile, per ora ho risolto il problema della funzione usando una variabile globale e una restituita tramite il nome della funzione. Oppure userò tutte variabili globali, che per far le prove di precisione va bene lo stesso.
Intanto vi ringrazio tutti e vi farò sapere presto cosa tiro fuori.
ciao
paolo
paolo
www.meteoenergia.it

gpb01


...
Volevo proprio evitare di usare i puntatori e concentrarmi più sul problema numerico, infatti Guglielmo mi ha capito.
...


Paolo, hai i miei contatti e sei piuttosto vicino ... se ti serve una mano, veramente NON fare complimenti ... in un'ora e mezza sei qui da me, magari, se è un fine settimana, ci facciamo una bella grigliata e ... ti do tutto il supporto che ti serve ;)

Guglielmo
Search is Your friend ... or I am Your enemy !

paolometeo2

Grazie Guglielmo dell'invito. Lascio passare le vacanze e poi ci sentiamo.
paolo
www.meteoenergia.it

pablos71

Anch'io voglio venire alla grigliata !!!  XD XD XD XD
L'esperienza è il tipo di insegnante più difficile ....
Prima ti fa l'esame e poi ti spiega la lezione.

gpb01


Anch'io voglio venire alla grigliata !!!  XD XD XD XD


Tu mica abiti qui vicino ...

Guglielmo
Search is Your friend ... or I am Your enemy !

Go Up