étourderie

Bonjour,
Je butte sur un problème ridicule:

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? :relaxed:
Le résultat sur la console me sidère un peu:

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

:astonished:
Comprends pas!

en écrivant

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

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

#define pi 3.1416
#define inc 0.1
float Theta;

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

euh... non.

il vaut peut être mieux ne pas utiliser sfprintf?

  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?

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 :

      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);

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

Non, trame me sert ensuite:

  n = FileLogger::append("data.csv",(byte*) trame,n);

(je récupère ensuite le csv avec un tableur, par exemple...)

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)

Bonjour,

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

Pour cette ligne :

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 :

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

Bonjour Skywodd,

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 :fearful:

Avant d'écrire

  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 ? :roll_eyes:
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ù! :grin:

Merci et bon dimanche.

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...

++

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,

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

format '%d' expects type 'int', but argument 4 has type 'long int'

PS : n'oublie pas d'ajuster la taille de ton tableau...

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?

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?

patsol:

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]...

patsol:

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é...