Go Down

Topic: étourderie (Read 658 times) previous topic - next topic

patsol

Bonjour,
Je butte sur un problème ridicule:
Code: [Select]
void loop(void)
{
  Theta = Theta + inc;
  if (Theta >= 2*pi) {
    Theta = -2*pi;}
  long sinus = sin(Theta)*1000;
  long cosinus = cos(Theta)*1000;
  char trame[12];
  int n = sprintf (trame,"%d;%d;%d",cosinus,sinus,cosinus);
  Serial.println(trame);
  delay(50);
}


C'est pas compliqué, hein?  :smiley-slim:
Le résultat sur la console me sidère un peu:

Quote
-291;-1;-956
-194;-1;-980
-95;-1;-995
4;0;-999
104;0;-994
202;0;-979
299;0;-954


:smiley-eek:
Comprends pas!

al1fch

en écrivant
Code: [Select]
  long sinus = sin(Theta)*1000.0;
  long cosinus = cos(Theta)*1000.0;

peut être.
Comment sont déclarées Theta et inc ?

patsol

Code: [Select]
#define pi 3.1416
#define inc 0.1
float Theta;

patsol

Quote
long sinus = sin(Theta)*1000.0;
  long cosinus = cos(Theta)*1000.0;

euh... non.

il vaut peut être mieux ne pas utiliser sfprintf?
Code: [Select]
  int n = sprintf (trame,"%d;%d;%d",cosinus,sinus,cosinus);
renvoie
-291;-1;-956 (par ex.).
c'est à dire cosinus, -1 et sinus. Je m'attendais à:
-291;-956;-291!

c'est un prodige, non?


al1fch

pas sûr que sprintf() soit pris en charge sous Arduino... et si oui il y a probablement des limites !!

Si trame[] n'a d'autre utilité que l'affichage on peut faire de manière plus 'arduinesque', dans le style  :
Code: [Select]
     
     double sinus   = sin(Theta)*1000;
     double cosinus = cos(Theta)*1000;

     Serial.print(Theta,DEC);
     Serial.print('\t');
     Serial.print(long(sinus),DEC);
     Serial.print('\t');
     Serial.println(long(cosinus),DEC);

patsol

Quote
Si trame[] n'a d'autre utilité que l'affichage

Non, trame me sert ensuite:
Code: [Select]
  n = FileLogger::append("data.csv",(byte*) trame,n);
(je récupère ensuite le csv avec un tableur, par exemple...)
Quote
pas sûr que sprintf() soit pris en charge sous Arduino... et si oui il y a probablement des limites !!

y a-t-il un moyen pour savoir:

  • quelles fonctions sont prises en charge sous Ardino? (Mon Sketch compile!)

  • quelles sont les probables limites (faut-il tâtonner?)



merci pour vos lumières 8)

skywodd

#6
Aug 13, 2011, 10:51 pm Last Edit: Aug 14, 2011, 10:23 am by skywodd Reason: 1
Bonjour,

sprintf (et presque 99.9% des fonctions de la libc) est prise en charge par le compilateur/l'ide arduino.

Pour cette ligne :
Code: [Select]

int n = (trame,"%d;%d;%d",cosinus,sinus,cosinus);

Dans n ce trouve le nombre de caractères de trame (ou 0 si la fonction plante), ok pas de probléme.
Mais là ou je pense que cela bug c'est l'utilisation de %d ! Pour un long ça devrait être un %ld !?
Tente :
Code: [Select]

int n = (trame,"%ld;%ld;%ld",cosinus,sinus,cosinus);
Des news, des tutos et plein de bonnes choses sur http://skyduino.wordpress.com !

patsol

Bonjour Skywodd,

Quote
Tente :
int n = (trame,"%ld;%ld;%ld",cosinus,sinus,cosinus);

le résultat est encore plus troublant:
19595264;-62521344;19660799

  • On ne devrait rien avoir au dessus de 1000

  • Les deux valeurs affichées du même "cosinus" sont encore différentes :smiley-eek-blue:


Avant d'écrire
Code: [Select]
  long sinus = sin(Theta)*1000;
  long cosinus = cos(Theta)*1000;

j'avais voulu utiliser des float avec l'option /3f et je n'avais obtenu que des ? :smiley-roll:
si sprintf est prise en charge par le compilateur, elle ne fonctionne pas ici comme comme à mon habitude, ou bien j'ai fait une grosse bêtise (d'où le titre),et je ne vois pas où! :smiley-mr-green:

Merci et bon dimanche.





SesechXP

Salut,

La taille du tableau "trame" n'est pas suffisante, dans le pire des cas la chaîne dépasse les 12 caractères. Il faut donc dimensionner correctement le tableau. Ensuite l'utilisation de sprintf ne prenant pas en compte la taille, la mémoire est corrompue. Pour plus de sécurité, il faut privilégier l'utilisation de snprintf.

Enfin comme l'écrit Skywodd, il est préférable d'utiliser des %ld pour formater les valeurs...

++
Julien - www.idreammicro.com

patsol

C'est ma faute,


À force de bidouiller j'avais accumulé les bugs.
Vous avez raison, c'est bien Long et %d qui étaient incompatibles.
Ce qui m'a surpris, c'est de ne pas m'être fait jeter par le compilateur.


Merci beaucoup,

SesechXP

Le compilateur lève juste un warning, mais comme l'IDE Arduino compile avec l'option -w tu ne l'as pas vu :
Quote
format '%d' expects type 'int', but argument 4 has type 'long int'


PS : n'oublie pas d'ajuster la taille de ton tableau...
Julien - www.idreammicro.com

patsol

Quote
La taille du tableau "trame" n'est pas suffisante, dans le pire des cas la chaîne dépasse les 12 caractères

cos(Theta)*1000 entier ne peut pas faire plus que 5 caractères (-1000) *3 =15 + 2';' = 17 caractères.
Dans ce cas, Trame[16] devrait suffire, ou je me trompe?

Quote
Le compilateur lève juste un warning, mais comme l'IDE Arduino compile avec l'option -w tu ne l'as pas vu :

On peut changer cette option, où bien il faut compiler avec gcc?

SesechXP


Quote
La taille du tableau "trame" n'est pas suffisante, dans le pire des cas la chaîne dépasse les 12 caractères

cos(Theta)*1000 entier ne peut pas faire plus que 5 caractères (-1000) *3 =15 + 2';' = 17 caractères.
Dans ce cas, Trame[16] devrait suffire, ou je me trompe?

Là tu n'accordes que 16 octets. Hors tu peux avoir au maximum 17 octets + le caractère de fin de chaîne '\0'. Donc il te faut Trame[18]...


Quote
Le compilateur lève juste un warning, mais comme l'IDE Arduino compile avec l'option -w tu ne l'as pas vu :

On peut changer cette option, où bien il faut compiler avec gcc?

Je ne sais pas si on peut changer les flags de compilation tout en conservant l'IDE Arduino, en tout cas je n'ai pas trouvé...
Julien - www.idreammicro.com

Go Up