Pages: [1]   Go Down
Author Topic: Concaténation String + Float + String  (Read 2186 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 41
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonjour,

J'ai un petit souci qui commence a me prendre la tête.

Je voudrais envoyer a mon afficheur une ligne de type: Temp = 35,5 C

Ma variable 35.5 est un float. je l'envoie donc dans une methode:

Code:
String ConvertionFloatToString(float Val)
{  
  char bufFloat[5];
  String str;
  dtostrf(Val,5,2, bufFloat);
  str = String(bufFloat);
  return str;
}

Sa me renvoie bien ma variable sous forme d'un string.

Voici ce que je fais pour utilisé cette fonction et l'envoyer dans mon afficheur. (Afficheur I2C de ma boite)
          
Variables
String L2; // contenue de la ligne 2
Float Temp; Variable de température

  
Code:
         
           String st;
           Serial.print("Valeur de Mesure Temperature = ");
           Serial.println(Temp); //Temp étant ma variable float.
           Ligne = "temp = ";
           st = ConvertionFloatToString(Temp);
           L2 = Ligne + st;  //J'ai retiré le  + "C" pour voir mais c'est pareil
           Serial.print("Valeur de L2 = ");//Voila, parfois cela bloque ici, je n'arrive pas a voir le serial print.
           Serial.println(L2);
           LCD.Write_Line(L2,2);
           Serial.println("debug affichage 3");

Cela ne plante pas tout le temps, Seule la 1ere fois cela passe bien, mais la seconde fois cela plante. à la ligne L2. Plantage complet arrêt de l'arduino car du coup mon afficheur ne reçois rien et s'il n'a rien pendant quelque milliseconde il plante lui aussi.

Vous avez une idée, merci
« Last Edit: November 18, 2011, 09:28:02 am by megamario » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 35
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Salut. Peux tu poster ton code en entier ?
Quel type est L2 ?
Logged

0
Offline Offline
God Member
*****
Karma: 2
Posts: 802
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Yep!

J'utilise ceci pour envoyer des float à mon afficheur.

Code:
char inputbuffer[6] = { '\0' };                         // variable temperature
char outputbuffer[20] = { '\0' };                    // variable string (de taille suffisante pour acceuillir la phrase + 1 pour le caractère de fin de ligne.)

dtostrf(temperature1,5,2,inputbuffer);          // conversion float en string.

snprintf(outputbuffer,20, "Temperature= %s C", inputbuffer);    // on formate le texte dans le buffer de sortie

glcd.writeBitmapText(outputbuffer, 10, 100, LUCIDA_FONT);     // on affiche.

@+

Zoroastre.
« Last Edit: November 18, 2011, 11:28:26 am by zoroastre » Logged

Veuillez indiquer [RESOLU] dans l'entête du titre en éditant votre premier message smiley-wink

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

J'ai rencontré les mêmes difficultés que toi j'ai tourné en rond pendant des jours : plantages intempestifs lorsque je concaténais des chaines de caractères.
J'ai trouvé ceci qui semble résoudre pour le moment mon problème :
http://stackoverflow.com/questions/5782772/arduino-difficulty-with-string-concatenation

Dans mon cas j'initialise ma chaine avec qq chose par exemple String str="     "; avant de concaténer c'est bizare mais depuis plus de plantages et cela fait au moins trois jours.... avant je faisais String str="";
Pour convertir un float en string j'utilise cette fonction trouvé sur le forum cela fonctionne parfaitement dans mon cas :
Code:
String ftoa(float number, uint8_t precision, uint8_t size) {
  // Based on mem,  16.07.2008
  // http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num = 1207226548/6#6

  // prints val with number of decimal places determine by precision
  // precision is a number from 0 to 6 indicating the desired decimial places
  // example: printDouble(3.1415, 2); // prints 3.14 (two decimal places)

  // Added rounding, size and overflow #
  // ftoa(343.1453, 2, 10) -> "    343.15"
  // ftoa(343.1453, 4,  7) -> "#      "
  // avenue33, April 10th, 2010

  String s = "";

  // Negative
  if (number < 0.0)  {
    s = "-";
    number = -number;
  }

  double rounding = 0.5;
  for (uint8_t i = 0; i < precision; ++i)    rounding /= 10.0;

  number += rounding;
  s += String(uint16_t(number));  // prints the integer part

  if(precision > 0) {
    s += ".";                // prints the decimal point
    uint32_t frac;
    uint32_t mult = 1;
    uint8_t padding = precision -1;
    while(precision--)     mult *= 10;

    frac = (number - uint16_t(number)) * mult;

    uint32_t frac1 = frac;
    while(frac1 /= 10)    padding--;
    while(padding--)      s += "0";

    s += String(frac,DEC) ;  // prints the fractional part
  }

  if (size>0)                // checks size
    if (s.length()>size)        return("#");
    else while(s.length()<size) s = " "+s;

  return s;
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 41
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

L2 est un String aussi.

Je pense qu'il va falloir que je m'habitue à utiliser les Char*. Je l'ai fait pendant m'a formation BTS IRIS, mais depuis que je suis au boulot, ils utilisent encore VB6, j'ai réussi a imposé VB.net au moi j'ai aussi le C#, mais j'ai perdu l'habitude.

Le code complet commence à être imposant, pour l’éclaircir, ce qui marchais bien j'ai crée une autre classe qui gère l'affichage.

merci pour l'info pour l'initialisation, moi aussi j'ai essayé avec "" et non "   ". Je vais essayer demain, mais la avec 40 de fièvre c'est pas top pour réfléchir.

merci pour le code. je n'est pas besoin de chercher les negatif car la c'est pour un aquarium récifal donc je doit être toujours a 25 et avec des borne mini maxi de 22 a 28°C .
D'ailleurs pour le moment j'utilise un LM35 que j'envoie directement sur l'entrée analogique. La tension mesurer du LM est bonne mais l'ardinio oscille un peut trop à mon gout. Surtout que je vais me servir de la mesure pour commander des ventilateurs, alarme, et Calibrage de la sonde PH

Merci

PS: J'ai essayé de mettre mon code complet mais cela fait trop de caractère donc je vais voir sa demain pour le découper

Voici en attendant la méthode Loop ou il y a mon souci. je vais le sortir du loop après:

Code:
void loop()
{
  int top;
  unsigned char dt[16];
  unsigned char Button;
  boolean ScanOsci = true;
  String Ligne;
  String st;

  if (millis() >= ancien_millis) { // Vérifie que le temps millis() est bien supérieur à l'ancienne valeur mémorisée
   // >> risque à l'init et au retour à zéro de l'horloge interne.
    if (millis() - ancien_millis >= 100){ top = 1;  // création d'un top toutes les 100ms
      ancien_millis = millis();    // réinitialisation ancien_millis
      compteur_top = compteur_top + 1;     // Incrémente le compteur de tops
      compteur_Heure = compteur_Heure +1;
      compteur_I2C = compteur_I2C + 1;
      compteur_InCom = compteur_InCom + 1;
      compteur_Temperature = compteur_Temperature + 1;
      compteur_DigitEntree += 1;
      compteur_Nourissage += 1;
      compteur_PH1 += 1;
      for (int i = 0 ; i<= 3 ; i ++)
      {
        compteur_Osci[i] += 1;
        compteur_PauseOsci[i] += 1;
      }
    } 
  }
  //Recherche de l'heure DS1307
  if (compteur_Heure * 10 >= 1000){ //en milliseconde
    DateHeure();
    compteur_Heure = 0;
  }
 
 //Oscilateur
 
    GestionOscilateur();

    //Verification des entrées;
    if(compteur_DigitEntree >= 5){
      DetectEntree();
      compteur_DigitEntree = 0;
    }
 
    //Temperature
    if (compteur_Temperature >= 10)
    {
      Temperature();
      compteur_Temperature = 0;
    }
 
   //Gestion de l'I2C Vitesse
    if (compteur_I2C  >= 3){
        //Affichage de la 1ere ligne
       LCD.Write_Line("Aquarius  37",1);
       //Affichage de la 2eme lignes
       LCD.Write_Line(L2,2);
       // Serial.println("debug affichage 1");
       switch (affichageBas){
         case 0:
           L2 = "   ";
           L2 = AffichageHeure();
           affichageBas ++;
           LCD.Write_Line(L2,2);
            Serial.println("debug affichage 2");
           break;
         case 10:
           L2 = "   ";
           Serial.print("Valeur de Mesure Temperature = ");
           Serial.println(Temp);
           Ligne = "temp = ";
           st = ConvertionFloatToString(Temp);
           L2 = Ligne + st;
           Serial.print("Valeur de L2 = ");
           Serial.println(L2);
           LCD.Write_Line(L2,2);
           Serial.println("debug affichage 3");
           affichageBas ++;
           break;
         case 20:
           L2 = "   ";
           Serial.print("Valeur de Mesure PH1 = ");
           Serial.println(MesurePH1);
           st = ConvertionFloatToString(MesurePH1);
           Serial.print("Valeur de ST = ");
           Serial.println(st);
           Ligne = "PH Rac = ";
           L2 = Ligne + st;
           Serial.print("Valeur de L2 = ");
           Serial.println(L2);
           LCD.Write_Line(L2,2);
           Serial.println("debug affichage 5");
           Serial.println(MesurePH1);
           affichageBas ++;
           break;
         case 30:
     
           affichageBas = 0;
            Serial.println("debug affichage 5");
           break;
         default:
           affichageBas ++;
       }
       /*Serial.print("Nonbre de tour = ");
       Serial.println(affichageBas);*/
       if(affichageBas >= 30)affichageBas = 0;     
       //LCD.Write_Line(L2,2);
       //String L = AffichageHeure();
       //LCD.Write_Line(L,2);
       Button = LCD.I2CXD_ReadCommand(LCD_SLAVE_ADRR, I2C_CMD_BUTTON_STATUS_REGISTER ,1);
       compteur_I2C = 0;
    }
    //Compteur Input COM
     if (compteur_InCom >= 3){
       InputCOM();
        compteur_InCom = 0;
     }
     if (compteur_PH1 >= 10){
         MyPH1Mesure();
         compteur_PH1 = 0;
     }
« Last Edit: November 18, 2011, 02:40:03 pm by megamario » Logged

Offline Offline
Full Member
***
Karma: 0
Posts: 116
N00b but I treat myself.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,

Il y a une autre méthode, qui fait un peu enfler le binaire je crois, mais qui marche:

Code:
// Niveau global
char buffer[50]; // Doit être en mesure de contenir toute la chaine

// Dans le loop
sprintf(buffer, // Là ou va travailler sprintf
  "Ma temperature est: %.2f", // en prenant ce template (avec %.2f comme "placeholder" avec 2 digit de précision)
  Temp);
Serial.println(buffer);

Ce code n'est probablement pas exempt d'erreur mais dans l'idée, il doit être bon smiley


D.
Logged

I've lost my mind, but I've a backup tape ... somewhere

Offline Offline
Newbie
*
Karma: 0
Posts: 41
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bonsoir, alors la je comprend plus rien.
En me basant sur le code sprintf.
Voici ce que j'ai fait comme essaie:

Code:
#include <WProgram.h>
#include <stdio.h>
#include <stdlib.h>

char buffer[50];
float Mes;
void setup()
{
   Serial.begin(9600);
  Mes = 0;
}

void loop()
{
  String MaLigne = "  ";
  Mes += 0.02;
  MaLigne = LigneMesure(Mes);
  Serial.println(MaLigne);
  delay(200);
}

String LigneMesure(float Mesure)
{
 String Ligne;
 Serial.println(Mesure); //Pour controler ma mesure float
 sprintf(buffer,"Temperature = %0.2f", Mesure);
 Ligne = String(buffer);
  return Ligne;
}

J'ai essayé aussi avec %.2f mais même résultat:
Temperature = ?

Logged

0
Offline Offline
God Member
*****
Karma: 2
Posts: 802
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Yep!

As-tu essayé ma méthode ???

@+

Zoroastre.
Logged

Veuillez indiquer [RESOLU] dans l'entête du titre en éditant votre premier message smiley-wink

Offline Offline
Full Member
***
Karma: 0
Posts: 116
N00b but I treat myself.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Zut, j'ai souvent utilise sprintf avec des ints, c'est pratique pour formater rapidement pendant le debugage, mais jamais avec des floats.

Après quelques recherches, il s'avère que le sprintf de l'arduino ne gère pas les floats (problème de place [déjà ajouter sprintf fait salement enfler le binaire smiley]).
Source: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1164927646

Désolé pour la fausse piste :/

D.
Logged

I've lost my mind, but I've a backup tape ... somewhere

0
Offline Offline
God Member
*****
Karma: 2
Posts: 802
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Yep!

C'est pour cela que l'on passe par dtostrf pour la conversion, le resultat est un buffer qui sera réutiliser par snprintf. A savoir que snprintf est plus sur que sprintf et attend un caractère de fin d'instruction (0).


Code:
char inputbuffer[6] = { '\0' };                         // variable temperature (12.55 = 5 char)
char outputbuffer[20] = { '\0' };                    // variable string (de taille suffisante pour acceuillir la phrase + 1 pour le caractère de fin de ligne.)

dtostrf(temperature1,5,2,inputbuffer);          // conversion float en string.

snprintf(outputbuffer,20, "Temperature= %s C", inputbuffer);    // on formate le texte dans le buffer de sortie

glcd.writeBitmapText(outputbuffer, 10, 100, LUCIDA_FONT);     // on affiche.

@+

Zoroastre.

« Last Edit: November 20, 2011, 03:59:55 am by zoroastre » Logged

Veuillez indiquer [RESOLU] dans l'entête du titre en éditant votre premier message smiley-wink

Offline Offline
Newbie
*
Karma: 0
Posts: 41
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yep!

C'est pour cela que l'on passe par dtostrf pour la conversion, le resultat est un buffer qui sera réutiliser par snprintf. A savoir que snprintf est plus sur que sprintf et attend un caractère de fin d'instruction (0).


Code:
char inputbuffer[6] = { '\0' };                         // variable temperature (12.55 = 5 char)
char outputbuffer[20] = { '\0' };                    // variable string (de taille suffisante pour acceuillir la phrase + 1 pour le caractère de fin de ligne.)

dtostrf(temperature1,5,2,inputbuffer);          // conversion float en string.

snprintf(outputbuffer,20, "Temperature= %s C", inputbuffer);    // on formate le texte dans le buffer de sortie

glcd.writeBitmapText(outputbuffer, 10, 100, LUCIDA_FONT);     // on affiche.

@+

Zoroastre.



J'allais l'essayer ce matin, comme je l'ai annoncé je suis pas trop en forme en ce moment, la fièvre est tombée donc cela va aller un peut mieux ce matin, j'essaie sa, merci.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 41
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Merci cela marche, enfin à quelque chose près, car je n'est pas le C après la valeur de température.

Voici du coup ce que j'ai fait pour tester et pour me resservir de cette méthode plusieurs fois:

Code:
#include <WProgram.h>
#include <stdio.h>
#include <stdlib.h>


float Mes;
void setup()
{
   Serial.begin(9600);
  Mes = 0;
}

void loop()
{
 
  String MaLigne = "  ";
  Mes += 0.02;
 
  MaLigne = LigneMesure("Temperature = %s", Mes, "C");
  Serial.println(MaLigne);
  delay(200);
}

String LigneMesure(char * Type, float Mesure, String Unite)
{
 char Mes[6] = { '\0' };
 char buffer[20] = {'\0'};
 String Ligne;
 dtostrf(Mesure,5,2,Mes);
 snprintf(buffer,20, Type, Mes);
 Ligne = String(buffer);
 Ligne = Ligne + Unite;
  return Ligne;
}
Logged

0
Offline Offline
God Member
*****
Karma: 2
Posts: 802
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Yep!

Essayes ceci plutôt:

Code:
MaLigne = LigneMesure("Temperature = %s %s", Mes, "C");

"C" est à considerer comme une seconde variable string à inclure dans ta phrase.

Le buffer doit être augmenter à 22 pour passer.
  --> "temperature = 00.00 C" = 21 caractères (espaces compris).

Pour que le string soit valide, il faut considérer le caractère de fin de ligne attendu par snprintf, le buffer doit faire 21+1 = 22
Tu peux mettre le buffer à 25 pour voir large, il occupera l'espace jusqu'au '\0'.

Remarque : snprintf(outputbuffer,50, "%s %s %s %s", inputbuffer1, inputbuffer2, inputbuffer3,inputbuffer4);

Tu peux ainsi résumer ta fonction LigneMesure() à un simple "return buffer", en te passant des String.

The code :
Code:
#include <WProgram.h>
#include <stdio.h>
#include <stdlib.h>


float Mes;
void setup()
{
   Serial.begin(9600);
  Mes = 0;
}

void loop()
{
  
  Mes += 0.02;
  
  String MaLigne = LigneMesure("Temperature = %s %s", Mes, "C");
  Serial.println(MaLigne);
  delay(200);
}

String LigneMesure(char *Type, float Mesure, char *Unite)
{
 char Mes[6] = { '\0' };
 char buffer[25] = {'\0'};
 dtostrf(Mesure,5,2,Mes);
 snprintf(buffer,25, Type, Mes, Unite);
 return buffer;
}


@+

Zoroastre.

« Last Edit: November 20, 2011, 06:41:58 am by zoroastre » Logged

Veuillez indiquer [RESOLU] dans l'entête du titre en éditant votre premier message smiley-wink

Pages: [1]   Go Up
Jump to: