Go Down

Topic: [Résolu] Affichage en notation scientifique (Read 889 times) previous topic - next topic

nathanv0

Aug 22, 2017, 03:43 pm Last Edit: Aug 23, 2017, 03:56 pm by nathanv0
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

J-M-L

#1
Aug 22, 2017, 08:53 pm Last Edit: Aug 22, 2017, 08:57 pm by J-M-L
Jetez un oeil à la fonction dtostre()

petit exemple

Code: [Select]
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

123456792.00000   -->    [ 1.2346E+08]
123456792.00000   -->    [ 1.2346e+08]
123456792.00000   -->    [1.2346e+08]



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

Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

nathanv0

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 ?

kamill

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.

nathanv0

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

kamill

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.

nathanv0

Merci pour la confirmation.

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

J-M-L

#7
Aug 23, 2017, 09:32 am Last Edit: Aug 23, 2017, 09:41 am by J-M-L
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() 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()
Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

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 ?

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

J-M-L

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 snprintf()donc

Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

nathanv0

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

J-M-L

#11
Aug 23, 2017, 11:21 am Last Edit: Aug 23, 2017, 11:50 am by J-M-L
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

Code: [Select]
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

------------------
123456789.1230   -->    [1234.5679e5]
12345.1230   -->    [1.2345e4]
1234.1230   -->    [1.2341e3]
123.1230   -->    [123.1230]


un peu un hack, mais bon...

Hello - Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums.
Bonjour Pas de messages privés SVP, postez dans le forum directement pour que ça profite à tous

icare

Bonjour,
Il faut ajouter au linker l'option :
Code: [Select]
-Wl,-u,vfprintf -lprintf_flt -lm
ou selon
Code: [Select]
-Wl,-u,vfprintf -lprintf_min
2B OR NOT(2B) = FF
Arduino 1.0.5 à 1.8.5 + gEdit + Ubuntu 18.04 LTS

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 :

Code: [Select]
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

icare

Re,
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).
2B OR NOT(2B) = FF
Arduino 1.0.5 à 1.8.5 + gEdit + Ubuntu 18.04 LTS

Go Up