[Résolu] Fonctions trigonométriques et variables à virgule flottante

Bonsoir,

Je dois écrire un code nécessitant l'utilisation de fonctions trigonométriques simple (genre sin, cos) et aussi l'utilisation de variables à virgule flottante.

Pour commencer, j'ai d'abord fait les calculs suivant à l'aide d'une calculatrice dont j'ai noté les résultats sur une feuille :
M = 357 + 0,9856 x 140 ce qui m'a donné : 494, 984
C = 1,914 x sin(M) + 0,02 x sin(2M) ce qui m'a donné : 1,3337

Ensuite j'ai rentré les même formules dans mon code Arduino puis j'ai affiché les résultats via le moniteur série. Cependant je n'obtient pas les même résultats que les calculs fait sur papier.
Arduino me renvoi :

  • M = 494,98 (sans le 4 mais ça ce n'est pas un problème, je peux spécifier les nombres de chiffre après la virgule)
  • C = 1.89 (ce qui ne concorde pas du tout avec l'opération précédente sachant que j'ai des tonnes d'autres calculs à faire nécessite l'utilisation de fonction trigonométrique)

Au vu de cela j'en ai conclu que cela venait de la ligne de code avec le "SINUS". Mon problème étant mit en évidence, je vous laisse me donner quelques éléments de réponses. Merci.

PS : J'ai prit soins de déclarer C et M comme des variables de type "float".

Bonjour les copains,
Oui, les calculs avec Arduino peuvent présenter des pièges dans lesquels j'ai pas mal pateaugé. Soit la limite à 7 chiffres significatifs, mais surtout des problèmes d'homogénéité de type dans les éléments d'un calcul, soit des débordements intermédiaires dans des expressions numériques.
Rassures-toi, une fois avoir codé pour parrer ces problèmes, on obtient des résultats corrects, avec toutefois une limitation à 7 chiffres significatifs ce qui en général est suffisant "en robotique".
Pour pouvoir trouver la source des imprécisions de calcul que tu constates, peux-tu nous fournir le code de ton programme. Ainsi il nous sera possible de déterminer la source de ton problème et surtout te proposer des lignes d'instructions qui conduisent au comportement attendu du code généré. (Choix de types homogène, forçage des calculs avec une "taille" suffisante etc)

Bonjour,
les fonctions trigonométriques de la libc attendent des valeurs d'angles en radians, or il est probable que lors de tes calculs manuels ta calculatrice était en mode degrés.

Essaie de définir M de cette façon :

float M = (357 + 0.9856 * 140) * M_PI / 180.;

pour voir ce que cela donne.

Tu cherches à calculer les heures de lever / coucher du soleil ?

haifger:
Bonjour,
les fonctions trigonométriques de la libc attendent des valeurs d'angles en radians, or il est probable que lors de tes calculs manuels ta calculatrice était en mode degrés.

Essaie de définir M de cette façon :

float M = (357 + 0.9856 * 140) * M_PI / 180.;

pour voir ce que cela donne.

Calcul fait, l'erreur vient bien d'un mélange radians/degrés

Bonjour,

Merci pour ces quelques réponses.

nulentout:
Pour pouvoir trouver la source des imprécisions de calcul que tu constates, peux-tu nous fournir le code de ton programme.

Comme je l'ai dit, ce n'était qu'un petit bout de code pour comparer les résultats :

float M, C;

Void  setup()
{
   Serial.begin(9600);
}

void loop()
{
   M = 357 + 0.9856 * 140;
   C = 1.914 * sin(M) + 0.02 * sin(2*M);
   Serial.println(M);
   Serial.println(C);
   delay(10000);
}

haifger:
Essaie de définir M de cette façon :

float M = (357 + 0.9856 * 140) * M_PI / 180.;

pour voir ce que cela donne.

J'ai essayé mais j'ai comme réponse 8.64 à la place de 494.984. J'aimerais préciser que les valeurs de M et de C doivent être en degré. Et oui effectivement quand j'ai utilisé la calculatrice elle était en mode degré.

bricoleau:
Tu cherches à calculer les heures de lever / coucher du soleil ?

Wouah bravo pour ta perspicacité. Et oui effectivement je cherche à calculer les heures de lever et de coucher du soleil.

fdufnews:
Calcul fait, l'erreur vient bien d'un mélange radians/degrés

Je n'ai pas conclu de la même manière puisqu'il semblerait que nous n'ayons pas trouvé les même résultats. Comment dois-je m'y prendre ?

C'est bien une erreur de degré / radian

Ta fonction sinus doit prendre une entrée exprimée en radians pour donner un résultat correct.
Avec M=8,64 tu obtiendras bien C=1,33 d'après ta formule

Essaye ça :

float M, Mrad, C;

Void  setup()
{
   Serial.begin(9600);
}

void loop()
{
   M = 357 + 0.9856 * 140;
   Mrad = M * 3.141592654 / 180.0;
   C = 1.914 * sin(Mrad) + 0.02 * sin(2*Mrad);
   Serial.println(M);
   Serial.println(Mrad);
   Serial.println(C);
   delay(10000);
}

Pour les calculs de lever et coucher du soleil, je suis en train de regarder ça en ce moment.

J'ai reconnu les premières équations, bien que tu utilises une version simplifiée.
Après avoir pas mal farfouillé sur le net, je me suis fixé cette page comme référence :
http://aa.quae.nl/en/reken/zonpositie.html
A mon sens, tout y est.

Tu n'en n'es qu'au début, donc toi t'es pas encore couché :wink:

Il te faudra aussi au moins une fonction trigonométrique inverse (arc-cosinus)

De mon côté, j'arrive à des résultats corrects (calcul de l'éphéméride en fonction de la date et des coordonnées latitude / longitude)... au moins sous excel !! :slight_smile:

Je ne suis pas encore passé au coding sous arduino.
Juste un doute sur la précision des calculs.

bricoleau:
C'est bien une erreur de degré / radian

Oui merci, je viens de constater l'erreur à l'instant en essayant d'utiliser la formule dans excel. C'est comme tu as dit ou encore Sin(M*PI/180).

bricoleau:
Pour les calculs de lever et coucher du soleil, je suis en train de regarder ça en ce moment.

J'ai reconnu les premières équations, bien que tu utilises une version simplifiée.
Après avoir pas mal farfouillé sur le net, je me suis fixé cette page comme référence :
Astronomy Answers: Position of the Sun
A mon sens, tout y est.

Merci je vais jeter un coup d’œil. J'utilise actuellement les formules fourni sur ce site : http://www.jean-paul.cornec.pagesperso-orange.fr/heures_lc.htm et comme tu l'as si bien dit c'est une version simplifiée. Cependant j'ai obtenu une heure de lever avec une erreur de 30 min environ. J'ai utilisé ceci entre temps : IMCCE - Services - Ephemerides mais faute de compréhension sur le calcul de l’ascension droite et de déclinaison je l'ai mit de côté.

J'aimerais sollicité ton aide pour le calcul de ces heures puisque toi tu en es arrivé à des résultats tout de même satisfaisant.

En moins indigeste que le lien exhaustif ci-dessus :

http://users.electromagnetic.net/bu/astro/sunrise-set.php

C'est le mode d'emploi simplifié (mais précis) pour le calcul qui t'intéresse

Uzuma:
J'aimerais sollicité ton aide pour le calcul de ces heures puisque toi tu en es arrivé à des résultats tout de même satisfaisant.

Si tu es pressé :
Prends le fichier xml joint et ouvre-le dans excel.
C'est là où j'en suis actuellement. Y a toutes les formules de calcul.
A partir de là, ce n'est que du code en c à produire pour obtenir la même chose.
NB : j'ai utilisé les facilités excel de manipulation de dates. Y a un peu de taf pour reproduire ça en c
NB2 : faisabilité certaine, sous réserve du niveau de précision offert par arduino sur les float et les fonctions trigonométriques.

Si tu n'es pas pressé :
Tu attends quelques jours (délai non garanti) que je mette au point la librairie qui va bien

ephemeride.xml (12.6 KB)

Bonsoir,

bricoleau:
Si tu es pressé :
Prends le fichier xml joint et ouvre-le dans excel.

Merci, je suis en train de le voir actuellement.

bricoleau:
Si tu n'es pas pressé :
Tu attends quelques jours (délai non garanti) que je mette au point la librairie qui va bien

Je vais me contenter de ton fichier pour le moment en attendant que tu finisses de créer ta librairie. Encore merci.

si ça vous dit voici une lib que j'ai fait peut'etre que ça vous ira pour moi elle fonctionne de magniere plutot correcte
et pour le calcule de l'heure de lever et de coucher :
bon j'ai extrai de mon code sans trop d'arengement

 int n =rangJour(rtcD->j,rtcD->m,rtcD->a);
  float HO=angleHoraireSoeil(n,(latD+(latM/60))); //lat D=latitude degree //latM Minute
  float ET=equationDuTemps(n);
heure de lever
 hOn=int(12-(HO/15)+((lonD+(lonM/60))/15)+(ET/60)+fuso);//lon D=laongitude degree //lonM Minute
minute de lever
  hOn.m=int(((12-(HO/15)+((lonD+(lonM/60))/15)+(ET/60)+fuso)-(hOn.h))*60);
 heure de couché
hOff=int(12+(HO/15)+((lonD+(lonM/60))/15)+(ET/60)+fuso);
minute du couché
hOff.m=int(((12+(HO/15)+(.lonD+.lonM/60))/15)+(ET/60).fuso)-(hOff.h))*60);

perso je l'ai intégré depuis pas mal de temps j'ai un décalage par raport au valeur donné sur certain site qui vien du fait que je n'est pas pris les meme valeur pour le crépuscule
je vous joint le lien a partir du quel j'ai construit les equationde la lib
http://jean-paul.cornec.pagesperso-orange.fr/heures_lc.htm

ephemeride.rar (1.42 KB)

ha je vien de voir que je vous ai pas joint l'autre lib pour la manipulation des date et heure :grin: sans ça ma lib ephemeride marchera moin bien

il y notament la formule pour verifier si l'année est bisextil car du coup le rang du jour N change !

date_heure.rar (2.42 KB)

Bonjour,

merci pour ton bon vouloir. Cependant, pourrais-tu faire un exemple avec ta lib, genre un exemple de calcul en prenant la date d'aujourd'hui comme exemple ?!

oui pas de souci !

alors:

#include <Date_heure.h>
#include <ephemeride.h>

#define _latD 48
#define _latM 47
#define _lonD 2
#define _lonM 26
#define _J 23
#define _M 5
#define _A 2014
#define _fuso 1

void setup(){
Serial.begin(9600);

int  n =rangJour(_J,_M,_A); 
float HO=angleHoraireSoeil(n,(_latD+(_latM/60))); //lat D=latitude degree //latM Minute
float ET=equationDuTemps(n);
//heure de lever
Serial.print("heure de lever : \t");
int hOnh=int(12-(HO/15)+((_lonD+(_lonM/60))/15)+(ET/60)+_fuso);
Serial.print(hOnh);
Serial.print(":");
int hOnm=int(((12-(HO/15)+((_lonD+(_lonM/60))/15)+(ET/60)+_fuso)-(hOnh))*60);
Serial.print(hOnm);
Serial.println();

Serial.print("heure de coucher : \t");
int hOffh=int(12+(HO/15)+((_lonD+(_lonM/60))/15)+(ET/60)+_fuso);
Serial.print(hOffh);
Serial.print(":");
int hOffm=int(((12+(HO/15)+((_lonD+(_lonM/60))/15)+(ET/60)+_fuso)-(hOffh))*60);
Serial.print( hOffm);
Serial.println();

Serial.print("duree du jour : \t");

Serial.print(hOffh-hOnh);
Serial.print(":");
Serial.print(hOffm-hOnm);
Serial.println();
}
void loop(){}

le resultat :

heure de lever : 	5:12
heure de coucher : 	20:41
duree du jour : 	15:29

je vien de modifier pour avoir la duree! pour comparaison j'ai 7 minute de diference par raport a une aplication sur mon tel " LUNASOLCAL"

en esperant que ça t'ira !

Hello,

Ne serait-il pas plus avantageux de créer une table d'éphémérides au lieu de faire ces calculs lourds sur l'arduino ?

dans mon cas les calcul sont fait une seul fois a 0.00H du coup ça bouffe pas beaucoup de temps de calcule et apres je peut ultiliser la fonction pour traçé des graphe de la duree du jour en fonction de la latitude et de la longitude sinon il me faudrai une table pour chaque valeur que je rentre ( ça risque de faire lour aussi non?)

XavierMiller:
Hello,

Ne serait-il pas plus avantageux de créer une table d'éphémérides au lieu de faire ces calculs lourds sur l'arduino ?

Ben ça dépend des besoins.
Si c'est par exemple pour piloter un éclairage exterieur sans capteur de luminosité, c'est-à-dire calculer l'éphéméride pour un lieu constant, alors oui, une table en eeprom peut faire l'affaire.
A voir avec la précision requise, car d'une année sur l'autre l'éphéméride varie pour un même jour calendaire (années bissextiles etc.).

De mon côté je cherche à reproduire de manière artificielle un éclairage pour un biotope captif, en respectant la photopériode du lieu d'origine (recentrée sur la photopériode naturelle du lieu de captivité).
Dans ce cas, la longitude / latitude est variable et l'usage de tables ne me semble plus faisable.
D'autant qu'un même arduino peut avoir à piloter simultanément des éclairages pour plusieurs biotopes de différentes localisations d'origine.

Bonjour,
Pour ceux qui veulent tout savoir sur le calcul astronomique.
Il existe 3 ouvrages remarquables de Jean Meeus (auteur Belge mais en anglais)

  • Astronomical Algorithms
  • Mathematical Astronomy
  • More Mathematical Astronomy
    @+