[Résolu] Affichage en notation scientifique

Bonjour,

Je cherche une fonction afin d'afficher de grand nombre sur un écran LCD en notation scientifique : 1.23E+10

Où est-ce que je pourrais trouver ça ?

En vous remerciant

Jetez un oeil à la fonction dtostre()

petit exemple

double valeur = (double) 123456789.123; // notez la perte de précision....
char notationScientifique[20];

const unsigned char precision = 4;

void setup() {
  Serial.begin(115200);
// http://www.atmel.com/webdoc/avrlibcreferencemanual/group__avr__stdlib_1ga6c140bdd3b9bd740a1490137317caa44.html
  dtostre(valeur, notationScientifique, precision, DTOSTR_ALWAYS_SIGN | DTOSTR_UPPERCASE); // place pour le signe toujours et grand 'E'
  Serial.print(valeur,5);
  Serial.print("\t-->\t [");
  Serial.print(notationScientifique);
  Serial.println("]");

  dtostre(valeur, notationScientifique, precision, DTOSTR_ALWAYS_SIGN); // place pour le signe toujours et petit 'e'
  Serial.print(valeur,5);
  Serial.print("\t-->\t [");
  Serial.print(notationScientifique);
  Serial.println("]");

  dtostre(valeur, notationScientifique, precision, 0); // pas de place pour le signe, un - sera mis bien sûr si la valeur est négative, petit 'e'
  Serial.print(valeur,5);
  Serial.print("\t-->\t [");
  Serial.print(notationScientifique);
  Serial.println("]");

}

void loop() {}

ça donne sur la console série à 115200 bauds

[color=blue]123456792.00000	-->	 [ 1.2346E+08]
123456792.00000	-->	 [ 1.2346e+08]
123456792.00000	-->	 [1.2346e+08]
[/color]

ATTENTION le buffer doit être assez grand pour stocker la représentation ASCII de votre nombre y compris le signe et un '\0' à la fin de la chaîne

Bonjour,

Merci pour la réponse !

J'ai voulu tester mais j'ai un message d'erreur me disant que la fonction et les constantes ne sont pas déclarées alors que j'ai inclue la bibliothèque stdlib.h.

Est-ce normal ?

Bonjour,

C'est bien une carte arduino que tu utilises?
Car pour d'autres cartes (comme par exemple la NodeMcu) certaines fonctions ne sont pas accessibles.

Oui j'utilise une carte Arduino M0. Après cette carte est à base d'un SAMD, est-ce que ça change quelque chose ?

Je viens d'essayer et effectivement dtostre n'est pas reconnu si on compile pour une arduino M0.

dotostre fait partie de la bibliotheque Atmel et j'avais déjà vu que ces fonctions n'étaient pas disponibles avec les cartes esp8266, mais c'est effectivement bizarre qu'elles ne soient pas disponibles pour les cartes avec processeur samd.

Merci pour la confirmation.

Mais du coup, quelle fonction est ce que je pourrais utiliser sur le M0 pour avoir une notation scientifique ?

Oui comme le lien le montre c'est une fonction AVR

Le code source est dispo, donc vous pouvez le rajouter (avec les fonctions utilisées comme [

__ftoa_engine()

](avr-libc-1.7.1/libc/stdlib/ftoa_engine.S - toolchain/avr-libc - Git at Google) mais vérifier sur un 32 bit le comportement, j'ai pas testé)

EDIT: je viens de regarder et le second code c'est de l'assembleur, c'est sans doute pour cela que ce n'est pas porté

Sur les autres plateformes je pense qu'il faut passer à sprintf() ou snprintf() (pour plus de sécurité) avec %e ou %E dans les flags (ça ajoute une grosse fonction à votre code qui va bien grossir...)

Les flags de format sont documentés dans la fonction printf()

Ok merci pour la réponse mais je t'avoue que je n'ai pas bien compris ce que tu voulais dire:

Le code source que tu donne en lien ne fonctionne pas sur un 32 bit ?

Et qu'est-ce qu'il faut que je passe en snprintf ?

nathanv0:
Ok merci pour la réponse mais je t'avoue que je n'ai pas bien compris ce que tu voulais dire:
Le code source que tu donne en lien ne fonctionne pas sur un 32 bit ?

Non car c'est de l'assembleur spécifique pour AVR, c'est pour cela que ce n'est pas porté.

--> oui il faut passer par [url=http://www.cplusplus.com/reference/cstdio/snprintf/]snprintf()[/url]donc

Ok, j'ai essayé mais rien ne s'affiche

ah oui c'est vrai que je crois que les flottants et double ne sont pas implémentés dans ces fonctions...

je regarde un peu plus tard, je crois qu'il faut rajouter des options de compilation pour dire au linker de prendre une version plus complète des fonctions ce qui fait qu'il faut sortir de l'IDE pour compiler...

ça ne va pas vous simplifier la vie... vous gérez des entiers ou de nombres flottants ?

une façon "simpliste" de régler le problème est de diviser votre nombre par 1000 ou 10000 ou 100000 en de gérer vous même l'affichage avec xxx.xxxe3 ou xxx.xxxe4 ou xxx.xxxe5 en fonction de votre diviseur... un peu un hack... (vous affichez juste en fait un nombre flottant et rajoutez manuellement le e3, e4 ou e5)

par exemple

void printScientifique(double v)
{
  if (v >= 100000l) {
    Serial.print(v / 100000l, 4); Serial.print(F("e5"));
  } else if (v >= 10000l) {
    Serial.print(v / 10000l, 4); Serial.print(F("e4"));
  } else if (v >= 1000l) {
    Serial.print(v / 1000l, 4); Serial.print(F("e3"));
  } else
    Serial.print(v, 4);
}


void setup() {
  double valeur;

  Serial.begin(115200);
  while (!Serial);
  Serial.println();
  Serial.println(F("\n------------------"));

  valeur = 123456789.123;
  Serial.print(valeur, 4);
  Serial.print("\t-->\t [");
  printScientifique(valeur);
  Serial.println("]");

  valeur = 12345.123;
  Serial.print(valeur, 4);
  Serial.print("\t-->\t [");
  printScientifique(valeur);
  Serial.println("]");

  valeur = 1234.123;
  Serial.print(valeur, 4);
  Serial.print("\t-->\t [");
  printScientifique(valeur);
  Serial.println("]");

  valeur = 123.123;
  Serial.print(valeur, 4);
  Serial.print("\t-->\t [");
  printScientifique(valeur);
  Serial.println("]");
}

void loop() {}

va donner sur la console

[color=blue]------------------
123456789.1230	-->	 [1234.5679e5]
12345.1230	-->	 [1.2345e4]
1234.1230	-->	 [1.2341e3]
123.1230	-->	 [123.1230]
[/color]

un peu un hack, mais bon...

Bonjour,
Il faut ajouter au linker l'option :

-Wl,-u,vfprintf -lprintf_flt -lm

ou selon

-Wl,-u,vfprintf -lprintf_min

Ok merci pour les infos mais vu que je me doutais que ça allait être super compliqué, j'ai fais ma propre fonction qui très bien :

String ConvertExpo(float Num){
  int longueur = 0;
  int index = 0;
  String str, str2, str3, str4;

  str = String(Num);
  index = str.indexOf(".");
  str2 = str.substring(0,index);
  longueur = str2.length();
  if(Num < 0){
    str3 = "E+" + String(longueur-2);
    str4 = str2.substring(0,2) + "." + str2.substring(2,4) + str3;
  }
  else{
    str3 = "E+" + String(longueur-1);
    str4 = str2.substring(0,1) + "." + str2.substring(1,3) + str3;
    }

  return str4;
}

Bonne continuation à vous

Re,

nathanv0:
Ok merci pour les infos mais vu que je me doutais que ça allait être super compliqué, j'ai fais ma propre fonction qui très bien :

Très bien mais attention aux objets String (plus d'inconvénients que d'avantages).

Oui vous pouvez écrire la même chose en utilisant dstrof() et un buffer static