[Résolu] Conversion tableau de byte en Hexa

Bonjour,

Je débute quelque peu en programmation Arduino alors s'il vous plait, un peu d'indulgence, de patience et de compréhension.

Voila ma problématique.
Je reçois des données dans une trame d'un port série.
Ces données, j'ai réussi à les parser pour en extraire les octets qui m'intéresse.
J'ai stocké ces "bytes" dans un tableau de byte.
J'ai un tableau de 2 bytes d'un coté et un tableau de 10 bytes de l'autre chacun correspondant à un code particulier.

Maintenant que tout cela est bien rangé, il me faut faire une conversion que je ne sais pas faire !

Exemple, prenons l'un de ces 2 codes. J'ai dans mon tableau 2 bytes qui sont 0x46 et 0x41 (soit FA)
Si je prends la calculatrice de Windows, je peux facilement faire l'opération qui consiste à transformer "FA" en hexa en décimal soit 250.

Je voudrais faire la même chose avec mon arduino. Je précise que je ne veux pas simplement l'afficher par serial.print mais également stocker cette valeur calculée (ou convertie) pour ensuite la traiter.
C'est sans doute très simple pour la plupart d'entre vous.... mais là moi... newbie que je suis... je bloque depuis plusieurs soirées sans y arriver ni trouver une piste sur le net.

Pour la seconde donnée, je veux faire la même chose sauf qu'elle fait 10 byte au lieu de 2...

Quelqu'un pourrait il me mettre sur les rails s'il vous plait.
Merci
Pasque

precisez quelles sont les données que vous voulez extraire (parce que google traduction devient fou). s'agit il d'entiers . Sachez qu'arduino ne connaît "que" les bytes (8 bits: 2 cars hexadecimaux), les entiers (16 bits), les longs (32 bits) ou les chaines de caractères de longueur arbitraire. Si on ne sait pas ce que vous voulez en faire, vous allez casser toutes les boules de cristal.
Avez vous fait des bouts de code et pouvez vous les poster entre balises? Si on detecte une horreur, vous pourrez partir sur des bases plus confortables.... (et on n'a pas de tentacules assez longues pour lire ce que vous avez fait)

Merci pour cette première réponse.
Des bouts de code, malheureusement je n'en ai pas beaucoup car actuellement je ne sais pas comment faire.
Je travaille sur un code qui prend mon tableau de byte avec "FA" et je ne sais pas comment faire le calcul pour le obtenir les 250 en décimal que je cherche à calculer.

Je ne sais pas si je suis clair.

void setup() {
  // put your setup code here, to run once:
  Serial.begin(19200);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  } 
  Serial.println("Bonjour !");
 
  Serial.println("Hello, world?");
  // Pour commencer, je fais au plus simple avec 2 octets.... 
  byte someArray[] = {46, 41,0};  //F, A in ASCII plus null terminator
for(int i = 0; i < 2; i++)
{
  Serial.print(someArray[i]);
}
// Comment faire pour obtenir le calcul qui ferait que j'obiens 250 dans un int 
// Ce qui est en dessous qui est un essai ne marche bien evidemment pas. 
int val = atoi ((char*)someArray);
Serial.print(" VAL : ") ;   
Serial.println(val) ;   
  
}

void loop() {
  // put your main code here, to run repeatedly:

}

Bonjour,

Tu as une chaine de caractères en ascii qui représente un nombre hexa.
Pour le convertir en byte ou int tu peux utiliser la fonction strtol()

int val = strtol((char*)someArray,NULL,16);

Le problème, avec strtol, est qu'il faut rajouter un octet nul pour terminer le tableau de bytes (il en fera 3 au lieu de 2). La modif serait triviale si on voyait le bout de codes entre balises.....

Oui, \0 existe dans son exemple

 byte someArray[] = {46, 41,0};  //F, A in ASCII plus null terminator

Mais effectivement il faudra terminer la réception en mettant 0 dans le buffer et comme tu dis c'est trivial.

kamill:
Bonjour,

Tu as une chaine de caractères en ascii qui représente un nombre hexa.
Pour le convertir en byte ou int tu peux utiliser la fonction strtol()

int val = strtol((char*)someArray,NULL,16);

Bonjour,
Merci de cette suggestion.
Malheureusement elle retourne 0
Pasque

Oui, parce que le code ascii de F ce n'est pas 46 mais 0x46 et celui de A 0x41

  byte someArray[] = {0x46, 0x41, 0}; //F, A in ASCII plus null terminator

Re,

Effectivement je venais de faire la même constatation.

Super !
Sauf que, dans le cas du tableau de 10 bytes, le calcul est tronqué...
C'est du au fait que le résultat dépasse la valeur max de la variable long (2,147,483,647)

Comment pourrais je faire... Là je suis dépassé !

Voici le code :

void setup() {
  // put your setup code here, to run once:
  Serial.begin(19200);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  } 
  Serial.println("Bonjour !");
 
  Serial.println("Hello, world?");
  // Pour commencer, je fais au plus simple avec 2 octets.... 
 //byte someArray[] = {0x46, 0x41 ,0};  //F, A in ASCII plus null terminator
  byte someArray[] = {0x33, 0x45 , 0x43, 0x34, 0x44, 0x31, 0x32, 0x42, 0x37, 0x33 ,0};  //3EC4D12B73 in ASCII plus null terminator
for(int i = 0; i < 10; i++)
{
  Serial.print(someArray[i]);
}
// Comment faire pour obtenir le calcul qui ferait que j'obiens 250 dans un int 
// Ce qui est en dessous qui est un essai ne marche bien evidemment pas. 
long val = strtol(someArray,NULL,16);
Serial.print(" VAL : ") ;   // Val = 2147483647 au lieu de 269590014835
Serial.println(val) ;   
  
}

void loop() {
  // put your main code here, to run repeatedly:

}

Tu peux utiliser des 'long long' mais leur utilisation est délicate (peu de fonctions pour les manipuler directement).

La question qu'il faut te poser c'est qu'est ce que tu veux faire de cette valeur?

kamill:
Tu peux utiliser des 'long long' mais leur utilisation est délicate (peu de fonctions pour les manipuler directement).

La question qu'il faut te poser c'est qu'est ce que tu veux faire de cette valeur?

Encore une fois, je ne maitrise pas spécialement.
long long retourne une erreur à la compilation.

En fait les 10 bytes une fois convertis me donne un numéro décimal de 11 digits unique.
J'aimerai afficher cette valeur sur un afficheur car cette valeur parle dans l'application que je veux faire.
Je peux traiter mes données en me contentant de mon tableau de 10 bytes mais cela sera moins universel.

Je suis convaincu que par des décalages à droite ou a gauche que je ne maitrise pas du tout, on peut traiter les 10 bytes en 2 fois et reconstituer le chiffre final à l'affichage uniquement. Mais là je suis une buse !

Merci de votre aide.
Pasque

3ec4d12b73 sera forcément long long (64 bits)

Si j'ai bien compris le problème voilà ce que ça donne sur PC :

#include <stdio.h>

int main(int argc, char *argv[])
{
  char s[] = "3EC4D12B73";
  
  unsigned int x[5];
  unsigned long long val = 0;
  sscanf(s, "%02X%02X%02X%02X%02X", &x[0], &x[1], &x[2], &x[3], &x[4]);
  for (int i = 0 ; i < 5 ; i++) {
    printf("%x\n", x[i]);
    val |= (unsigned char)x[i];
    if (i < 4) {
      val <<= 8;
    }
  }
  printf("%llx\n", val);
  printf("%lld\n", val);
}

3e
c4
d1
2b
73
3ec4d12b73
269590014835

Sur ARDUINO on ne pourra pas afficher ce nombre.

Une librairie : GitHub - yoursunny/PriUint64: Print uint64_t in Arduino

#include "PriUint64.h"

// petite fonction simple :
void print_uint64_t(uint64_t num) {
  char rev[128];
  char *p = rev + 1;

  while (num > 0) {
    *p++ = '0' + ( num % 10);
    num /= 10;
  }
  p--;
  while (p > rev) {
    Serial.print(*p--);
  }
  Serial.println();
}

void setup() {
  Serial.begin(115200);
  char s[] = "3EC4D12B73";

  unsigned int x[5];
  unsigned long long val = 0;
  sscanf(s, "%02X%02X%02X%02X%02X", &x[0], &x[1], &x[2], &x[3], &x[4]);
  for (int i = 0 ; i < 5 ; i++) {
    Serial.print(x[i], HEX);
    Serial.println();
    val |= (unsigned char)x[i];
    if (i < 4) {
      val <<= 8;
    }
  }
  // avec la librairie PriUint64
  Serial.println(PriUint64<HEX>(val));
  Serial.println(PriUint64<DEC>(val));

  // avec print_uint64_t
  print_uint64_t(val);
}

void loop() {
}

Je suppose que le résultat est correct car PriUint64 et print_uint64_t affichent le même résultat.

voili voilou
@+

Bonjour hbachetti,
Ecoutes, c'est purement génial !! ;D

Je n'en attendais pas tant !

Du premier coup, cela fonctionne.
C'est super, tu viens de m'enlever une énorme épine du pied.

Merci beaucoup de ta contribution.

Ps : Je me suis fait une petite frayeur car quand j'ai copié la librairie j'ai copier du html au lieu du source... a la compilation cela ne le faisait pas du tout. Du coup, j'ai failli abandonner mais heureusement que je me suis rendu compte de cette erreur

Pasque

Les gens se mélangent pas mal les pinceaux quant il s'agit de conversion. Entre les représentations sous forme binaire ou ASCII, décimale ou hexa, etc :confused:

Bonne continuation.