Trouver les valeurs ASCII des nombres HEX à l'intérieur d'une string ?

Bonjour, je travaille avec un module GSM qui m'envoie des caractères sous formax HEXADECIMAL

Voici un exemple d'une ligne de code que j'ai reçu de mon module (j'ai masqué mon numero de tel avec des *):

+CMT: "2B31343530333431********","","15/03/24,11:45:20-16" 426F6E6A6F7572

La dernière partie est le message SMS que j'ai reçu: "426F6E6A6F7572" si on converti en ASCII cela donne: "Bonjour"

Ce que j'ai de besoin c'est une fonction qui peut convertir une string contenant des nombre HEX en leur valeur ASCII

Exemple:

String HEXString ="426F6E6A6F7572";
String ASCIIValeur ="";
ASCIIValeur = ConvertiVersASCII(HEXString);
// ASCIIValeur contient maintenant "Bonjour"

Pouvez-vous m'aider à créer cette fonction "ConvertiVersASCII" qui converti les nombres se trouvant dans un STRING à leur valeur ASCII?

Merci d'avance!

Tu as cherché un peu avant de poster ?

Oui! depuis hier soire que je suis la dessus!

J'ai beaucoup cherché!

Mais je suis pas très bon, et j'ai beau essayer de pleins de façon, je n'y arrive pas..

Bien sur je peut faire 256 comparaisons du genre:

if (donnée = "54"){ return "T";}
if (donnée = "55"){ return "U";}
.. etc...

Mais j'imagine qu'il y a des façons plus "intelligente" de faire ce que je veut!

Ben donne nous ce que tu as fait déjà. Je vois pas pourquoi on devrait tout faire à partir de rien (même si je suis en train 'o')

désolé, mais j'ai RIEN de fait, tout ce que j'ai fait ne fonctionne pas... j'ai trouvé comment convertir à partir de CHAR mais pas à partir de STRING

Ben ça tombe bien c’est char et String sont utilisables de la même façon en C

Et même si ça marche pas on préfère voir. Ca donne moins de boulot de corriger que de tout faire

Ok, tel que demandé, voici un code qui converti une chaine de nombre CHAR en leur valeur ASCII

Je n’arrive pas à la convertir pour utiliser une source en string plutôt qu’une source char…

void setup() {
  char input[] = "48454C4C4F";    // Should translate to HELLO
  char temp[3];
  char c;
  int index;
  int i;
  int val;
  Serial.begin(19200);

  for (i = 0; i < sizeof(input) - 1; i += 2) {
    temp[0] = input[i];
    temp[1] = input[i + 1];
    val = ASCIIHexToInt(temp[0]) * 16;      // First Hex digit
    val += ASCIIHexToInt(temp[1]);          // Second hex digit
    c = toascii(val);
    Serial.print(c);
  }
}
int ASCIIHexToInt(char c)
{
  int ret = 0;

  if ((c >= '0') && (c <= '9'))
    ret = (ret << 4) + c - '0';
  else
    ret = (ret << 4) + toupper(c) - 'A' + 10;

  return ret;
}

void loop() {

}

Merci de ton aide! :slight_smile:

Je te propose aussi une solution en C (sans la class string)

Comme toi, j’ai mis une fonction hexStr2AsciiStr et exemple d’utilisation dans le setup().
J’ai évité l’utilisation des opérateurs bitwise (<< >> ~ ^ | &) qui sont pas évident à utiliser au début mais qui n’ont rien à voir avec && ou ||.

Attention avec l’utilisation de sizeof (il ne faut surtout pas le mettre dans la fonction, car on aurait la taille du pointeur et pas de la chaine.

void setup( ) {

    Serial.begin( 19200 );

    char texteHex[] = "48656C6C6F20576F726C6421";

    // le nombre de caractère de la chaine  de destination égal sa taille / 2 + 1 
    // (toujours ajouter 1 pour le caractère NULL qui défini la fin de la chaine
    const int nb_car = sizeof( texteHex ) / 2 +1;
    char texteAscii[nb_car] = "";
    //conversion
    hexStr2AsciiStr ( texteHex, sizeof(texteHex), texteAscii );
    Serial.println( texteAscii );

}

void hexStr2AsciiStr ( const char *s, size_t size, char *d )
{
    int t = 0;                  
    char hex[3] = { '\0'};
    for ( t = 0; t < size; t += 2 )
    {
        hex[0] = s[t] ;
        hex[1] = s[t+1] ;
        sscanf( hex, "%X", &d[t/2] ) ;
    }
}

void loop() {

}

Merci pour ton code, je l’ai essayé et j’ai pus lire “hello world”

Par contre, le texte d’entré est en CHAR et la sortie est aussi en CHAR… Comme décrit dans le premier message, j’ai besoin d’une routine qui converti du texte String

donc au lieu d débuter comme ceci:
char texteHex = “48656C6C6F20576F726C6421”;

Il faudrait débuter comme cela:
String texteHex = “48656C6C6F20576F726C6421”;

Et la sortie dois aussi être du String…

Comme décrit dans le premier message, j’aurai besoin d’une fonction (ConvertiVersASCII dans l’exemple) qui pourrais fonctionner comme cela:

String HEXString =“426F6E6A6F7572”;
String ASCIIValeur ="";
ASCIIValeur = ConvertiVersASCII(HEXString);
// ASCIIValeur contient maintenant “Bonjour”

Merci de m’aider…

donc au lieu d débuter comme ceci:
char texteHex = "48656C6C6F20576F726C6421";

Il faudrait débuter comme cela:
String texteHex = "48656C6C6F20576F726C6421";

Et la sortie dois aussi être du String....

POURQUOI ?

Ce n'est absolument pas une obligation et en comptant ton autre sujet, ça doit faire 10 fois qu'on te conseille d'éviter d'utiliser la classe String, mais tu t'obstine :frowning:

Très peu de monde utilise cette classe, pour les divers problèmes qu'elle peut causer sur un petit microcontrôleur avec peu de mémoire, tel ton arduino. Les seuls qui utilisent cette librairie, ce sont les newbies... et c'est vraiment une plaie de les convaincre de ne pas l'utiliser... Tu en es la preuve :smiley:

Ton GSM envoi des OCTETS sur ton arduino. A toi ensuite d'en faire ce que tu veux, rien ne t'oblige à utiliser la classe String...

Si tu veut savoir pourquoi tu n'a qu'a lire l'autre sujet :slight_smile: j'ai expliqué le Pourquoi en long et en large...

Je sais que les String c'est pour les débutants, mais ça adonne bien: Je suis un Débutant!

Mais ce que je ne comprend pas: Pourquoi "String" existe s'il n'est pas possible de l'utiliser sans que le programme soit stable? Les concepteurs de l'arduino ont créer quelque chose en sachant que c'étai pour être instable??

Il est vrais que je suis débutant avec l'arduino, mais je programme en d'autre language depuis quelques années déjà et j'ai pas de problème à utiliser le "string" sur un pc ou autre.. Si ça existe, c'est que ça fonctionne! Pourquoi sur arduino on peut faire du travaille avec des "String" mais que cela peut planter??

Je n'y comprend rien...

Dernière chose, cela fait 24h que je demande à pleins de gens une fonction pour faire ce que je veut, et la seul chose que tout le monde fait c'est me demander "Pourquoi????" au lieu de m'expliquer comment faire cette fonction.. Personne jusqu'a maintenant ne m'as donné ce que je voulais!

Je comprend que les gens ont raison, mais je peut tu quand même savoir comment faire cette fonction?

Je crois que la plupart des gens ne savent pas comment faire, alors il ne font que me dire de pas faire ça plutot que de m'expliquer comment faire le code...

La seule raison pour laquelle cette classe existe, c’est parce qu’elle simplifie un peu la vie…

Par exemple on peut faire if ( String == "blabla" ) alors qu’avec un tableau de char on doit utiliser if ( !strcmp( string, "blabla" ) ) et… c’est à peu près le seul avantage. Le problème c’est que cette classe fragmente la mémoire de ton arduino, en allouant dynamiquement de la mémoire, et si tu ne fais pas attention, avec le temps tu risque ceci:

Et ne surtout pas considérer l’arduino comme un PC, ça n’a quasiment rien à voir…Sur PC, les librairies du genre “String” sont sûrement bien plus robustes, et posent nettement moins de problème vu la quantité de la mémoire disponible…

Sur Arduino, utiliser des tableaux de char oblige à allouer statiquement suffisamment de mémoire. Il n’y a donc pas de risques de créer une collision comme dans l’image ci dessus.

Et ce n’est pas que les gens ne savent pas faire, c’est juste que ce n’est pas recommandé… et j’ai beau lire ton autre sujet je ne comprend toujours pas pourquoi tu juge nécessaire d’utiliser un String. Enfin bref, si tu y tiens vraiment… j’ai essayé et ceci à l’air de fonctionner.

String hexToAscii( String hex )
{
  uint16_t len = hex.length();
  String ascii = "";

  for ( uint16_t i = 0; i < len; i += 2 )
    ascii += (char)strtol( hex.substring( i, i+2 ).c_str(), NULL, 16 );
    
  return ascii;
}

Mais ne viens pas chouiner si ton arduino se comporte étrangement. Peut-être que ça n’arrivera jamais, il y a beaucoup de paramètres qui entrent en compte… :wink:

Merci pour vos réponses...

En suivant les conseils de tout le monde, j'ai commencé à ré-écrire tout mon programme pour utiliser des CHAR... Mais j’avoue que j'ai beaucoup de difficulté, car c'est nouveau pour moi.. les String sont beaucoup plus simple...

Vous m'avez demander ce que je veut en faire?

Voila exactement le problème:


J'utilise un module GSM (qui permet de recevoir des messages SMS envoyé via un telephone cellulaire)

Je veut faire un programme qui reçoit les messages textes de quelqu'un et qui renvois à cette personne son message

Exemple: L'arduino recoit "bonjour toi" et elle répond à la personne en lui disant: "Tu m'as envoyé: bonjour toi"

Pour ce faire, je dois lire le message SMS reçu (Dans ce format:"426F6E6A6F7572" et le retourner dasn ce format: "Bonjour" Parce que mon module GSM fonctionne de cette façon.

Voici à quoi ressemble un message SMS reçu (j'ai mis des * pour masquer mon num de telephone):
+CMT: "2B31343530333431********","","15/03/24,11:45:20-16" 426F6E6A6F7572

cette ligne reçu contient au début le numero de cell de la personne qui à envoyé le SMS (en hex)
par la suite, la date et l'heure ou le message ont été reçu (en ascii)
Et pour terminé, le message en HEX

Comme vous voyez, le module GSM nous affiches CERTAINES informations reçus en HEX, mais quand on lui donne des informations on doit toutes les lui donner en format ASCII

Voici un exemple de code que j'utilise

char inchar; 
String ContenuDuSMS = "";     

// Exemple of string que je reçois:
// 
// +CMT: "2B31343530333431********","","15/03/24,11:45:20-16" 426F6E6A6F7572

void loop()
{
 if (Serial1.available())   
 {
   while(Serial1.available() > 0)         
   {
     inchar = Serial1.read();
     ContenuDuSMS += inchar;  
     
        // When new line is detected...
        if (inchar == '\n')
        {                   
              if (ContenuDuSMS.substring(0,5) == "+CMT:"){                  //If line start with "+CMT:" this is because a SMS is received	
              EnvoiSMS( ContenuDuSMS.substring(8,31) , "You have sent: "+ContenuDuSMS.substring(60,ContenuDuSMS.length()) ); // Extract the phone number + SMS message and send it to "EnvoiSMS" routine 
                                                                                                                              // envoiSMS is a routine to send a SMS              
              }           
              ContenuDuSMS = ""; // reset my string
        }
    }  
  }   
}


void EnvoiSMS(String message,String telephone)
{  
  Serial1.print("AT+CMGF=1\r");                 // AT command to send an SMS
  delay(2000);
  Serial1.println("AT+CMGS=\""+telephone+"\"");// AT command to give the destination phone number
  delay(2000);
  Serial1.println(message);                // The message that i want to send
  delay(2000);
  Serial1.println((char)26);                    // Finalize with  ^Z, (ASCII code 26)
  delay(2000);    
}

Quand j'utilise la routine "EnvoiSMS" de cette façon:
EnvoiSMS("+12223334444","Bonjour")
Le module GSM envoie un message texte au numéro "12223334444" et ce SMS contient le mot "Bonjour" (Je l'ai testé et cette routine fonctionne bien)

Mais si je l'utilise avec les données reçu, comme par exemple:
EnvoiSMS("2B3132323233333334343434","426F6E6A6F7572")
cela ne fonctionne pas, je reçois un message d'érreur du module qui s'attend à recevoir un numéro de tel en ASCII, et même si je lui donne un bon num de telephone mon cell va recevoir "426F6E6A6F7572" au lieu de "Bonjour"

Donc je dois convertir le numéro de tel reçu: (2B3132323233333334343434) et le message reçu (426F6E6A6F7572) en ascii avant de les renvoyer à mon module GSM...

Je ne sais pas si j'ai été assez claire?

Tk comme je dit j’essaie présentement de réécrire ce code en n'utilisant pas de String...

Merci de votre aide

Donc, avec des String et la fonction que je t'ai donnée dans mon précédent post:

EnvoiSMS( hexToAscii( ContenuDuSMS.substring(8,31) ), "You have sent: "+ hexToAscii( ContenuDuSMS.substring(60,ContenuDuSMS.length()) ) );

Maintenant si tu veux utiliser des tableaux de char, d'accord c'est un peu plus compliqué, mais c'est bien plus puissant. Regarde par exemple les fonctions strtok, sscanf, sprintf, tu en aura sûrement besoin.

KingRamses >
QUoi ??? Personne ne t’a donné ce que tu voulais ??? Tu te fiches de moi ??? je t’ai donné une fonction toute faite, et comment l’utiliser !! En plus, tu fais absolument pas attention à ce qu’on te dit. Je t’ai dit hier que utiliser les String en C c’était la même chose que char*. Donc pour que mon code fonctionne avec String suffit de changer les ‘char *’ par String dans la déclaration de la fonction.

Il faudrait te sortir les doigts du ***…

Donc, puisque tu es si assisté, et même si c’est inutile de faire ça, il suffit de changer UNE SEULE LIGNE et la déclaration de la fonction devient void hexStr2AsciiStr ( const String s, size_t size, String d )

Hmmm, c’est peut être pas assez mâché. tiens tout en entier

void setup( ) {

    Serial.begin( 19200 );

    String texteHex = "48656C6C6F20576F726C6421";

    // le nombre de caractère de la chaine  de destination égal sa taille / 2 + 1 
    // (toujours ajouter 1 pour le caractère NULL qui défini la fin de la chaine
    const int nb_car = sizeof( texteHex ) / 2 +1;
    char texteAscii[nb_car] = "";
    //conversion
    hexStr2AsciiStr ( texteHex, sizeof(texteHex), texteAscii );
    Serial.println( texteAscii );

}

void hexStr2AsciiStr ( const String s, size_t size, String d )
{
    int t = 0;                  
    char hex[3] = { '\0'};
    for ( t = 0; t < size; t += 2 )
    {
        hex[0] = s[t] ;
        hex[1] = s[t+1] ;
        sscanf( hex, "%X", &d[t/2] ) ;
    }
}

void loop() {

}

Bonjour,
Il est arrivé à ses fins. Tu l'as fait pour lui :wink:

Oui mais au moins il nous casse plus les pieds (ni nous, ni les mecs du forum anglais)

Il va utiliser un code auquel il ne capte pas une seule ligne. C'est lui qui se retrouve un peu idiot après...
Moi j'ai appris, car le temps que j'ai passé à sortir cette fonction est bien bénéfique !

Par contre, je vais m'habituer à regarder les derniers posts de chaque personne qui poste avant de répondre maintenant.

C'est dommage, ça va pourrir l'ambiance du forum à force.