[Résolu]Comment bien comprendre/utiliser les bytes, les doubles et les char

//void get_luminosity(char * luminosity)
void get_luminosity(uint8_t lum)
{
  /*
    LUMINOSITY
  */
#ifdef SENSOR_TSL2561
  if (millis() > scheduler_lux)
  {
    scheduler_lux = millis() + INTERVAL_LUX;

    sprintln(F("\nLuminosity Sensor"), 2);
    sprintln(F("******************************"), 2);


    // ms = 1000;
    // light.manualStart();
    // delay(ms);
    // light.manualStop();

    unsigned int data0, data1;

    if (light.getData(data0, data1))
    {
      
      double lux;    // Resulting lux value
      boolean good;  // True if neither sensor is saturated

      // Perform lux calculation:
      good = light.getLux(gain, ms, data0, data1, lux);

      // Print out the results:

      //Serial.print(" lux: ");
      sprint(lux, 2);
      if (good)
        sprintln(F(" (good)"), 2);
      else
        sprintln(F(" (BAD)"), 2);

      //Serial.print(F("\t"));

      lux = lux * 100;
      Serial.print(F("DEBUG: uint8_t ")); Serial.println(lux);
      dtostrf(lux, 4, 0, luminosity);
      Serial.print(F("DEBUG: uint8_t ")); Serial.println(luminosity);
      lum = (uint8_t)atoi(luminosity);
      Serial.print(F("DEBUG: uint8_t ")); Serial.println(lum);
      Serial.print(F("DEBUG: uint8_t ")); Serial.println(lum,HEX);
      
      
     // dtostrf(lux, 4, 0, luminosity);

    }
    else
    {
      // getData() returned false because of an I2C error, inform the user.

      byte error = light.getError();
      printError(error);
    }
  }
#else
  sprintln(F("\nSENSOR_TSL2561 (Luminosity) unactive"), 2);
#endif
}

Il faut décider où vous voulez faire les calculs

Un double c’est 4 octets sur un arduino « standard » donc similaire à ce que je fais pour chrono

Je perds patience :slight_smile:
Je vais lassiser mes fonctions comme elles sont. Elle fonctionne sauf "qu'elle returne les valeur en char" :slight_smile:

Je sais pas si vous avez encore le courage de me suivre :slight_smile: mais en tout cas merci

Je vais rapidement résumer ma situation en fonction des exemple que vous m'avez donner entre hier et aujourd'hui.

D'abord, je déclare de structure

const byte capteur_battery_id = 0;
const byte capteur_temperature_id = 1;
const byte capteur_pression_id = 2;
const byte capteur_alt_id = 3;
const byte capteur_humidity_id = 4;
const byte capteur_moisture_id = 5;
const byte capteur_luminosity_id = 6;
const byte capteur_uv_id = 7;
const byte capteur_latitude_id = 8;
const byte capteur_longitude_id = 9;
const byte capteur_datetime_id = 10;


// JE NE LES METS PAS TOUS; MAIS C EST LA MEME CHOSE POUR LES AUTRES CAPTEURS
#ifdef SENSOR_BATTERY
bool battery_active = true;
#else
bool battery_active = false;
#endif

#ifdef SENSOR_TSL2561
bool luminosity_active = true;
#else
bool luminosity_active = false;
#endif

struct capteur
{
  uint8_t idDuCapteur;
  boolean actif;
  char nomDuCapteur[2];
};
/*
J'ai changer les noms des capteurs, qui sont certe pas trop parlant, mais je voulais prendre des élment qui prend le moins de bit possible
Donc ceci est devenu
ba = a
te = b
pr = c
al = d
hu = e
mo = f
lu = g
uv = h
la = j
lo = k
da = l
*/




capteur mesCapteur[] = {
  {capteur_battery_id, battery_active, "a"},
  {capteur_temperature_id, temperature_active, "b"},
  {capteur_pression_id, pression_active, "c"},
  {capteur_alt_id, alt_active, "d"},
  {capteur_humidity_id, humidity_active, "e"},
  {capteur_moisture_id, moisture_active, "f"},
  {capteur_luminosity_id, luminosity_active, "g"},
  {capteur_uv_id, uv_active, 'h'},
  {capteur_latitude_id, latitude_active, "j"},
  {capteur_longitude_id, longitude_active, "k"},
  {capteur_datetime_id, datetime_active, "l"},
};



enum : byte {c_battery = 0, c_temperature, c_pression, c_alt, c_humidity, c_moisture, c_luminosity, c_uv, c_latitude, c_longitude, c_datetime}; // dans le même ordre que mesCapteurs
const byte nbMaxCapteurs = sizeof(mesCapteur) / sizeof(mesCapteur[0]);

struct mesure {
  uint16_t id_capteur;
  char when[20]; // moment de la mesure
  char valeur[20]; // valeur mesurée (adapter le type)
  // autre chose de pertinent à mémoriser lors d'une mesure ?
};

const byte tailleHistorique = 11; // Ce chiffre doit correspondre aux nombres de capteurs. Voir capteur mesCapteur[] = {
mesure mesMesures[nbMaxCapteurs][tailleHistorique];

Dans ma fonction do_send qui envoie les données au serveur,
je fais appelle à plusieurs fonction come

// La variable passées en paramètre sont de char
// char humidity[20];
get_luminosity(luminosity);
get_luminosity(humidity);

Et voicl le fameux passage qui me cause tant de cheveux blanc :slight_smile:

(je me suis basé sur votre exemple d'aujourd'hui)
Une fois que j'ai tout mes valaurs de capteur

void do_send(osjob_t* j)
{
/*
* [.. code ..] J'appelle mes fonctions "capteurs" comme ci-dessous
*/
#ifdef SENSOR_BMP180
    get_baro(mesMesures[c_temperature][capteur_temperature_id].valeur, mesMesures[c_pression][capteur_pression_id].valeur, mesMesures[c_alt][capteur_alt_id].valeur);
#endif
#ifdef SENSOR_DTH22
    get_humidity(mesMesures[c_humidity][capteur_humidity_id].valeur);
#endif
#ifdef SENSOR_TSL2561
    get_luminosity(mesMesures[c_luminosity][capteur_luminosity_id].valeur);
#endif


// PLUS HAUT, J AI MES FONCTION QUI VONT ME PERMETRE D AVOIR LES VALEUR DE MES CAPTEURS

// CODE BASE SUR L EXEMPLE D HIER
    // http://forum.arduino.cc/index.php?topic=500386.new#new
    // imprimer la liste des capteurs
    sprintln(F("\nListe des capteurs"), 2);
    sprintln(F("---------------------------------------"), 2);

    byte nbCapteurActif = 0;
    for (byte i = 0; i < nbMaxCapteurs; i++) {
      sprint(F("Capteur: ["), 2);
      sprint(mesCapteur[i].nomDuCapteur, 2);
      sprint(F("]\t"), 2);
      sprint(F("actif: "), 2); sprint(mesCapteur[i].actif ? F("VRAI") : F("FAUX"), 2);
      if (mesCapteur[i].actif)nbCapteurActif++;
      sprint(F("\tID: "), 2); sprintln(mesCapteur[i].idDuCapteur, 2);
    }
 

 // CI-DESSUS, CA FONCTIONNE TRES BIEN


 
    sprintln(F("\nValeurs des capteurs actifs"), 2);
    sprintln(F("---------------------------------------"), 2);
    sprint(F("Nombre de capteurs: "), 2);
    sprintln(nbMaxCapteurs, 2);
    sprint(F("Nombre de capteurs actifs: "), 2);
    sprintln(nbCapteurActif, 2);

    sprint(F("Valeurs:\t"), 2);

    // Loop la strcture des capteurs

    uint8_t * ptr = mydata; // expl d'ajourd'hui

    for (byte i = 0; i < nbMaxCapteurs; i++) {
      if (mesCapteur[i].actif) { // si le capteur n'est pas actif on n'imprime pas

        // PRINT LES MESURES MESUREES
        sprint(mesCapteur[i].nomDuCapteur, 2);
        sprint(F(":"), 2);
        sprint(mesMesures[i][mesCapteur[i].idDuCapteur].valeur, 2);
        if (i < nbCapteurActif + 1) sprint(F(","), 2);
 
// CI-DESSUS, CA FONCTIONNE TRES BIEN


        // --------------------------------------------------------
        // EMPILE LES VALERUS MESUREE DANS mydata POUR LES ENVOYER A TTN

// BASE SUR L EXEMPLE D HIER ET SURTOUT D AUJOURD'HUI
        /*
 * JE NE SUIS PAS SURE DE GARDER LE NOM DU CAPTEUR, SI TOUT NE DEVAIT PAS RENTRE DANS mydata[64]
 * JE CROIS QUE TTN NE PERMET D ENVOYER PLUS. DANS CE CAS J'AJOUTE DES VIRGULE POUR AVOIR UN TRUC DU GENRE
 * mydata = {3.7,234,56.66,,,,453,,34}
 * les vides entre les virgule sont des capteurs inactif. Ainsi, au niveau du serveur je saurai qu a la position
 * 1 ca sera toujours la batterie, positon 2 toujours temperature, pos 3 toujours pression, etc
 */
 
 /* MON PROBLEM */
 
 // J'ajoute le nom du capteur, mais mesCapteur[i].nomDuCapteur; est un char. Comment e convertir en hex
 // pour que mon terminal ne m'affiche pas une erreur. Dans votre exmple, vous utliser des hex comme valeur
 *ptr = mesCapteur[i].nomDuCapteur; // Le nome du capteur est une lettre comme a
        ptr += sizeof(char); // Je deplace mon pointeur

 // IDEM QUE PLUS HAUT, J AJOUTE la valeur, mais c'est un CHAR
        * ((uint16_t *) ptr) = mesMesures[i][mesCapteur[i].idDuCapteur].valeur;
        ptr += (uint16_t); // Je deplace mon pointeur

 // SI CE N EST PAS LE DERNIER CAPTEUR, J AJOUTE UNEVIRGULE
        if (i < nbCapteurActif+1)
        {
          *ptr = '2C'; // virgule
          ptr += (char); // JE DEPLACE MONPOINTEUR
        }
 
 printData();
 /*
 * PRINT DATA DEVRAIT M AFFICHER L'EQUIVAENCE DE 
 * a3.6,b24.44,c345.55,d424.33,h33.33
 * ou
 * 3.6,24.44,345.55,424.33,,,,33.33,,
 * Si je n'utilisait pas les noms des capteurs. Mais il faudra que mes capteurs s'inscrivent toujours dans le meme ordre
 * Je pesne que cette derniere option ne sera pas compliquée a traitée, cote serveur
 */
   
   
      }
  else
  {
 // SI INACTIE, AJOUTE UNE VIRGULE POUR LES CAPTEURS INACTIF
 
  }
    }
    sprintln(F("\n"), 2);

    // On met le buffer à zero partout
    // (pas nécessaire juste pour montrer, une variable globale sera à 0 la première fois)
    //memset(mydata, 0xFF, tailleMax);
    // DEBUG
    printData();

    //strcpy((char *) mydata, char_buffer);
    //printData();

// ENVOIE DES DONNEES. CECI FONCTIONNE TRES BIEN
    sprint(F("\nOpmode check: "), 2);
    LMIC_setTxData2(1, mydata, strlen((char *)mydata), 0);
}

J'epère que je suis sur la bonne voie. Mais mon probleme est vraiment de convertir des char en hex/uint8_t/bits...

:o :slight_smile: :confused:

enum : byte {c_battery = 0, c_temperature, c_pression, c_alt, c_humidity, c_moisture, c_luminosity, c_uv, c_latitude, c_longitude, c_datetime}; // dans le même ordre que mesCapteurs
const byte nbMaxCapteurs = sizeof(mesCapteur) / sizeof(mesCapteur[0]);

struct mesure {
  uint16_t id_capteur;
  char when[20]; // moment de la mesure
  char valeur[20]; // valeur mesurée (adapter le type)
  // autre chose de pertinent à mémoriser lors d'une mesure ?
};

const byte tailleHistorique = 11; // Ce chiffre doit correspondre aux nombres de capteurs. Voir capteur mesCapteur[] = {
mesure mesMesures[nbMaxCapteurs][tailleHistorique];

Donc on a:
11 capteurs
une structure mémorisant une mesure d'une taille de 42 octets par capteurs
un historique de 11 mesures

Ce qui fait 11 x 11 x 42 = 5082 octets
D'où la question, pourquoi stocker les résultats des mesures sous forme d'une chaîne de caractères au lieu d'un long ou d'un float?
On arriverait alors à une taille de 11 x 11 x 10 = 1210 octets
Tu peux faire la conversion en chaîne de caractères au moment de l'envoi ce qui est beaucoup plus économique en matière de gestion de la mémoire.

Comme te l'a déjà expliqué J-M-L, byte, char et uint8_t sont la même chose ce sont des octets. C'est la manière de les interpréter qui change.

Vue le nombre de capteur et le contenu des mesures, les informations à envoyer consommeront toujours plus de 64 octets. Il suffit tout simplement de compter les octets que tu empiles dans mydata et de déclencher l'émission des données lorsque le compte arrive à 64 et de reprendre le remplissage du tampon après que l'envoi est terminé.

Vous faites

struct capteur
{
  uint8_t idDuCapteur;
  boolean actif;
  char nomDuCapteur[2];
};

--> le nom du capteur est donc un tableau de caractère, une c-string avec un char suivi d'un '\0'.... c'est un peu ballot.. autant déclarer le nom comme étant juste un char. (cf mon dernier exemple)

donc ça ne peut pas marcher (quand vous dites "mais mesCapteur[i].nomDuCapteur; est un char" ce n'est pas le cas, c'est un pointeur en mémoire sur un tableau de 2 caractères)

 // J'ajoute le nom du capteur, mais mesCapteur[i].nomDuCapteur; est un char. Comment e convertir en hex
 // pour que mon terminal ne m'affiche pas une erreur. Dans votre exmple, vous utliser des hex comme valeur
 *ptr = mesCapteur[i].nomDuCapteur; // Le nome du capteur est une lettre comme a
        ptr += sizeof(char); // Je deplace mon pointeur

@J-M-L
Oui, excuse moi, j'avais mal corrigé

struct capteur
{
  uint8_t idDuCapteur;
  boolean actif;
  const char * nomDuCapteur;
};

@fdufnews
Merci de te joindre :slight_smile:

Donc on a:
11 capteurs
une structure mémorisant une mesure d'une taille de 42 octets par capteurs
un historique de 11 mesures

Oui disons que je prévois des options. En fonction du besoin je pourrais en activer au pas, Mais évidemment, je fais en sorte que toutes les valeurs peuvent être envoyée..

//#define SENSOR_BATTERY      // Battery Voltage
//#define SENSOR_GPS        // latitude, longitude, datetime
//#define SENSOR_MEMORY     // Free memory
//#define SENSOR_BMP180       // Barometer (temperature/pression/alt)
#define SENSOR_TSL2561      // Luminoisty
//#define SENSOR_DTH22        // Humidity (Temrature)
//#define SENSOR_MOISTURE
//#define SENSOR_UV

#ifdef SENSOR_BATTERY
bool battery_active=true;
#else
bool battery_active=false;
#endif
//etc..

D'où la question, pourquoi stocker les résultats des mesures sous forme d'une chaîne de caractères au lieu d'un long ou d'un float?

Mais c'est une très bonne réflection et je me siuos penché la dessus hier...

Il faudrait alors que mes fonctions me retournent de long ou des float, au lieux de chaine de caractère. Je suis tout à fait d'accord d'aller ainsi. Surtout si On arriverait alors à une taille de 11 x 11 x 10 = 1210 octets.

Je vais donc modifier mes fonctions pour avoir des floats

Mais j'ai un problème que je n'arrive pas encore à cerner, et désolé si j'arrive pas encore à maitriser ceci.
Sachant que

To send data back and forth over The Things Network you’ll need to use bytes.
Technically, you can send 51 bytes. But, the more bytes you’ll send, the more airtime the package will cost you and the sooner you’ll hit your maximum allotted time. So, don’t ask yourself how many you can possibly send but rather ask how few could do the job.

je dois utiliser des bytes pour l'envoi des donnée

Comme te l'a déjà expliqué J-M-L, byte, char et uint8_t sont la même chose ce sont des octets. C'est la manière de les interpréter qui change.

D'accord.Mais que veux-tu dire par

C'est la manière de les interpréter qui change.

Je crois que ca, je n'ai encore pas compris :frowning: :frowning:

Tu peux faire la conversion en chaîne de caractères au moment de l'envoi ce qui est beaucoup plus économique en matière de gestion de la mémoire.

Mais oui. C'est un peu ce que j'avais fait ici

Je pense que mon problème est surtout comment interpreter mes valeurs des capteurs et la conversion des types de variable

Vue le nombre de capteur et le contenu des mesures, les informations à envoyer consommeront toujours plus de 64 octets. Il suffit tout simplement de compter les octets que tu empiles dans mydata et de déclencher l'émission des données lorsque le compte arrive à 64 et de reprendre le remplissage du tampon après que l'envoi est terminé.

Oui en effet :slight_smile: Je sais qu'il y a moyen d'envoyer par séquence. Je vaus regarderceci après.

Dans tous les cas, je dois faire l'empilement des valeurs, la conersion des types et l'envoi, proprement :o)

Si je suis bien vos suggestions propositions et exemple, je vais

  • Revenir sur ce que j'avais commencer hier, modifier mes fonctions pour qu'elles me retorunent le valeurs de capteurs en float. Il va falloir que je trouve comment convertir des double en float, et surtout limiter les valeurs à deux décimal après la virgule
  • Péparer la chaine* à envoyer qui sera sur cette forme {3.75,24.00,345.66,424.50,,,,4.6,,,} en gardant toujours le même ordre
  • Traiter cette chaine pour que l'envoie se fasse en bits et vérifier qu'elle ne dépasse pas 64 (et encapsuler le reste dans mydata2)
  • Le problème est que ceci doit etre un char truc[22], non? On peut pas avoir plusieurs virgules dans une valeurs! Si je veux ne pas utiliser des char comme tu les dis ici

Ce qui fait 11 x 11 x 42 = 5082 octets
D'où la question, pourquoi stocker les résultats des mesures sous forme d'une chaîne de caractères au lieu d'un long ou d'un float?
On arriverait alors à une taille de 11 x 11 x 10 = 1210 octets
Tu peux faire la conversion en chaîne de caractères au moment de l'envoi ce qui est beaucoup plus économique en matière de gestion de la mémoire.

Il faudrait mieux suivre l'exemple de J-M-L ou il encapsule les valeurs dans la variable mydata dans la boucle.

Donc je me retrouve bloqué toujours ici (voir les *** dans le code ci-dessous).

Je suis au travail, et je peux pas tester ceci maintenant, mais je pensais donc faire un truc comme ceci. En espérant que je suis bien vos commentaires

uint8_t * ptr = mydata;

    for (byte i = 0; i < nbMaxCapteurs; i++) {

      if (mesCapteur[i].actif) { // si le capteur n'est pas actif on n'imprime pas

        // PRINT LES MESURES MESUREES
        sprint(mesCapteur[i].nomDuCapteur, 2);
        sprint(F(":"), 2);
        sprint(mesMesures[i][mesCapteur[i].idDuCapteur].valeur, 2);
        if (i < nbCapteurActif + 1) sprint(F(","), 2);


        // --------------------------------------------------------
        // EMPILE LES VALERUS MESUREE DANS mydata POUR LES ENVOYER A TTN

        //Je ne veux plus envoyer le nom du capteur
        //*ptr = mesCapteur[i].nomDuCapteur;
        //ptr += sizeof(char);

        //float test = 234.56;

       // *** En partant du principe que mesMesures[i][mesCapteur[i].idDuCapteur].valeur n'est plus une chaine de caractere mais un float. Est-ce que ceci va fonctionner pour avoir des bytes
       ((uint16_t *) ptr) = mesMesures[i][mesCapteur[i].idDuCapteur].valeur;
       // * ((uint16_t *) ptr) = test;
         ptr += sizeof(uint16_t); // deplace le capteur

        if (i < nbCapteurActif+1)
        {
          *ptr = '2C'; // virgule
          ptr += sizeof(char);
        }
      }
      else
      {
        *ptr = '2C'; // virgulepour les capteurs inactifs
        ptr += sizeof(char);
      }
    }
    *ptr = '00'; // Je ferme avec un \0
    ptr += sizeof(char);

printData();

printData() devrait m'afficher

33 2e 37 35 2c 32 34 2e 30 30 2c 33 34 35 2e 36 36 2c 34 32 34 2e 35 30 2c 2c 2c 2c 34 2e 36 2c 2c 2c

Si l'empilation des valeurs des capteurs est
3.75,24.00,345.66,424.50,,,,4.6,,,

J'aimerais beaucoup faire ceci proprement, après je regarderai comment spliter ceci si ca dépasse la limite de mydata. Ce soir je modifie mes fonctions pour qu'elle me retorune des float...

Milles mercis pour vos lumières et votre suivi :slight_smile: :slight_smile: :slight_smile: :slight_smile:

Est- ce que ca vous semble bien/correct ou je suis encore à côté de la plaque :slight_smile: :slight_smile:

Si vous envoyez en binaire et que vous connaissez le format du payload, pas besoin de virgule... ça aide que si vous envoyez en ascii car un double n’est pas représenté en nombre constant d’octes sous forme de caractères ascii (10 en a 2, 10.234 en a 6) mais ils seront tous représentés sous forme de 4 octets

En programmation si vous faites

double X = 21.1234;

Vous avez alloué 4 octets en mémoire (sous norme IEEE) qui est une représentation binaire de votre nombre. Donc si vous prenez les 4 octets en mémoire (ce que fais mon code plus haut) c’est ce dont vous avez besoin

Si vous voulez vous simplifier encore plus la vie, vu que vos capteurs actifs semble être définis à la complication avec vos #define, vous pourriez aussi avoir des #ifdef dans la structure et donc avoir une structure adaptéé au besoin ce qui fait que le payload deviendrait immédiatement votre tableau de mesures

Bonjour,

Merci pour votre retour.
Je ne m'en sors plus >:( . Je nage toujours au même point.
J'ose vous demander encore un petit moment?

J'espère n'être pas parti du mauvais côté

Je viens de modifier toutes mes fonctions qui me retorunent les valuers de mes capteurs.

Je récupère maintenant mes valuers en float (pas en double, mais s'il le faut, je corrige.

(J'ai activé 5 capteurs)
La boucle for

    sprintln(F("\nValeurs des capteurs actifs"), 2);
    sprintln(F("---------------------------------------"), 2);
    sprint(F("Nombre de capteurs: "), 2);
    sprintln(nbMaxCapteurs, 2);
    sprint(F("Nombre de capteurs actifs: "), 2);
    sprintln(nbCapteurActif, 2);

    sprintln(F("Valeurs:"), 2);

    // Clean char_buffer

    // Loop la strcture des capteurs
    //sprint(F("["),2);
    for (byte i = 0; i < nbMaxCapteurs; i++) {
      if (mesCapteur[i].actif) { // si le capteur n'est pas actif on n'imprime pas

        // PRINT LES MESURES MESUREES
        sprint(mesCapteur[i].nomDuCapteur, 0);
        sprint(F(":"), 0);
        sprintln(mesMesures[i][mesCapteur[i].idDuCapteur].valeur, 0);
        //if (i < nbCapteurActif) sprint(F("\n"), 0);
      }
      else
      {
        sprint(mesCapteur[i].nomDuCapteur, 0);
        sprintln(F(":"), 0);
        //if (i < nbCapteurActif) sprint(F("\n"), 0);
      }
     }

m'affiche ceci

Valeurs des capteurs actifs

Nombre de capteurs: 11
Nombre de capteurs actifs: 5
Valeurs:
a:4.32
b:24.08
c:971.73
d:424.00
e:25.00
f:
g:
h:
j:
k:
l:

Si on oublie les lettres et les :

J'essayyyyeee :slight_smile: d'empiler dans mon uint8_t mydata en essayant vos echemples (masi je dois manquer quelque chose

sprintln(F("\nEmpilatios des valeurs capteurs"), 2);
     sprintln(F("---------------------------------------"), 2);

     memset(mydata, 0xFF, tailleMax);
     uint8_t * ptr = mydata;
     
     for (byte i = 0; i < nbMaxCapteurs; i++) {
      
      if (mesCapteur[i].actif) { // si le capteur n'est pas actif on n'imprime pas
        // --------------------------------------------------------
        // EMPILE LES VALERUS MESUREE DANS mydata POUR LES ENVOYER A TTN
  
        //Je ne veux plus envoyer le nom du capteur
        //*ptr = mesCapteur[i].nomDuCapteur;
        //ptr += sizeof(char);

        *ptr = mesMesures[i][mesCapteur[i].idDuCapteur].valeur; // C EST UN FLOAT
        ptr += 15; // COMMENT CALCULER LE DEPLACEMENT DU POINTEUR EN FONCTION DE LA DERNIER VALEUR float
       

        if (i < nbCapteurActif + 1)
        {
          *ptr = 0x2C; // virgule
          ptr += sizeof(char);
          
        }
      }
      else
      {
        *ptr = 0x2C; // virgulepour les capteurs inactifs
        ptr += sizeof(char);
        
      }
    }
    
    *ptr = '00'; // Je ferme avec un \0
    ptr += sizeof(char);


    printData();

printData() m'affiche ceci

Empilatios des valeurs capteurs

mydata = { 04 FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2C 18 FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2C CB FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2C A8 FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2C }

Donc on voit que c'est totalement rappé...

Cette partie ne fonctionne vraiment pas

// [mesMesures[i][mesCapteur[i].idDuCapteur].valeur] est de type float
*ptr = mesMesures[i][mesCapteur[i].idDuCapteur].valeur;

(J'aimerais bien aussi supprimer ce qu'il y après les points (décimal))

Je me sens mal à l'aise car vous m'avez donner tellement d'exemple, mais je nage toujours....

Pourquoi ptr += 15; // deplace le capteur?

ça explique le résultat 04 FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2C 18 ...
Vous écrivez 15 octets plus loin

Voyez la mémoire comme une grande commode pleine de tiroirs. Il faut ranger dans les tiroirs successifs vos données mais un tiroir ne contient que 1 octet, donc si vous avez une donnée sur 4 octets il faut les mettre dans 4 tiroirs successifs

Pourquoi ptr += 15; // deplace le capteur?

ça explique le résultat 04 FF FF FF FF FF FF FF FF FF FF FF FF FF FF 2C 18 ...
Vous écrivez 15 octets plus loin

Oui je suis tout à fait d'accord.
mais au lieu de

04 FF FF FF FF...

on devrait voir

34 2e 33 32 FF FF FF FF FF FF FF FF FF FF FF 2C 18

car

34 2e 33 32

vaut 4.32 !!!

Alors pourquoi j'ai que 04???

ptr est un pointeur typé et quand vous dites *ptr = ... vous n’écrivez que le nombre d’octest Dépendant de ce type car ça dépend du type de stockage pour la variable destination - et ici *ptr est de type 1 seul octet de mémoire (uint8_t)

Donc *ptr = 0xAABB; par exemple ne récupérerait que le BB à l’endroit du pointeur le compilateur comprend que vous ne voulez que l’octet de poids faible car il n’y a qu’une case dans la destination alors que

* ([color=red](uint16_t *)[/color] ptr) = 0xAABB;

va bien mettre BB au niveau du pointeur et AA dans l’octet suivant (little endian, on range en mémoire d’abord le poids faible)

C’est pour cela que dans mon exemple ci dessus quand j’écris 16 bits, je cast le pointeur en 16 bits (transformé temporairement pour cette ligne)

* ([color=red](uint16_t *)[/color] ptr) = [nobbc]allMesures[s][m].mesure;[/nobbc]

Parce que mesure est sur 2 octets dans mon exemple

Bien sûr il faut avancer ensuite le pointeur du bon nombre de case d’où ptr += sizeof(uint16_t);

De la même manière quand je veux mettre chrono dans le buffer je dis au compilateur par un cast (changement de type) que ptr pointe vers une zone 32 bits et ensuite j’avance de 4 cases le pointeur

Bonjour J-M-L.

J'aimerais savoir si vous pouviez encore me filer un coup de pouce. Je n'arrive pas à résoudre mon problème malgré tous les exemples.

En soit, ces exemples mon beaucoup aidé car ils font toujours partie de mon code.

Ceci je bloque toujours sur le même point.

J'ai surfé sur le net et sur le site de TTN et ils fournissent un exemple pour envoyer plusieurs variables.
Avec ceci j'ai réussi à faire ce que je veux SAUF que je n'arrive toujours pas à empiler des int dans un byte!!!!

GRRR. :slight_smile:

Voic donc mon cas.

J'ai ces variables

byte payloadAltitude[] = {0x34};
    byte payloadHumidity[] = {0x35};
    byte payloadMoisture[] = {0x36};
    byte payloadLuminosity[] = {0x37};
    byte payloadUv[] = {0x38};
    byte payloadLatitude[] = {0x39};
    byte payloadLongitude[] = {0x31, 0x30};
    byte payloadDate[] = {0x31, 0x31};

Puis ensuite je calcule la taille

int sizeofPayloadBattery = sizeof(payloadBattery);
    int sizeofPayloadTemperature = sizeof(payloadTemperature);
    int sizeofPayloadPression = sizeof(payloadPression);
    int sizeofPayloadAltitude = sizeof(payloadAltitude);
    int sizeofPayloadHumidity = sizeof(payloadHumidity);
    int sizeofPayloadMoisture = sizeof(payloadMoisture);
    int sizeofPayloadLuminosity = sizeof(payloadLuminosity);
    int sizeofPayloadUv = sizeof(payloadUv);
    int sizeofPayloadLatitude = sizeof(payloadLatitude);
    int sizeofPayloadLongitude = sizeof(payloadLongitude);
    int sizeofPayloadDate = sizeof(payloadDate)

int playloadSize = sizeofPayloadBattery + sizeofPayloadTemperature + sizeofPayloadPression + sizeofPayloadAltitude + sizeofPayloadHumidity + sizeofPayloadMoisture + sizeofPayloadLuminosity + sizeofPayloadUv + sizeofPayloadLatitude +sizeofPayloadLongitude + sizeofPayloadDate;
    
    sprint(F("Payload size: "),1); sprintln(playloadSize,2);
    
    byte payload[playloadSize];

et j'empile

memcpy(payload, payloadBattery, sizeofPayloadBattery);
memcpy(payload + sizeofPayloadBattery, payloadTemperature, sizeofPayloadTemperature);
memcpy(payload + sizeofPayloadBattery + sizeofPayloadTemperature, payloadPression, sizeofPayloadPression);
memcpy(payload + sizeofPayloadBattery + sizeofPayloadTemperature + sizeofPayloadPression, payloadAltitude, sizeofPayloadAltitude);
memcpy(payload + sizeofPayloadBattery + sizeofPayloadTemperature + sizeofPayloadPression + sizeofPayloadAltitude, payloadHumidity, sizeofPayloadHumidity);
memcpy(payload + sizeofPayloadBattery + sizeofPayloadTemperature + sizeofPayloadPression + sizeofPayloadAltitude + sizeofPayloadHumidity, payloadMoisture, sizeofPayloadMoisture);
memcpy(payload + sizeofPayloadBattery + sizeofPayloadTemperature + sizeofPayloadPression + sizeofPayloadAltitude + sizeofPayloadHumidity + sizeofPayloadMoisture, payloadLuminosity, sizeofPayloadLuminosity);
memcpy(payload + sizeofPayloadBattery + sizeofPayloadTemperature + sizeofPayloadPression + sizeofPayloadAltitude + sizeofPayloadHumidity + sizeofPayloadMoisture + sizeofPayloadLuminosity, payloadUv, sizeofPayloadUv);
memcpy(payload + sizeofPayloadBattery + sizeofPayloadTemperature + sizeofPayloadPression + sizeofPayloadAltitude + sizeofPayloadHumidity + sizeofPayloadMoisture + sizeofPayloadLuminosity + sizeofPayloadUv, payloadLatitude, sizeofPayloadLatitude);
memcpy(payload + sizeofPayloadBattery + sizeofPayloadTemperature + sizeofPayloadPression + sizeofPayloadAltitude + sizeofPayloadHumidity + sizeofPayloadMoisture + sizeofPayloadLuminosity + sizeofPayloadUv + sizeofPayloadLatitude, payloadLongitude, sizeofPayloadLongitude);
memcpy(payload + sizeofPayloadBattery + sizeofPayloadTemperature + sizeofPayloadPression + sizeofPayloadAltitude + sizeofPayloadHumidity + sizeofPayloadMoisture + sizeofPayloadLuminosity + sizeofPayloadUv + sizeofPayloadLatitude + sizeofPayloadLongitude, payloadDate, sizeofPayloadDate);

//if((sizeofPayloadBattery + sizeofPayloadTemperature + sizeofPayloadPression + sizeofPayloadAltitude + sizeofPayloadHumidity + sizeofPayloadMoisture + sizeofPayloadLuminosity + sizeofPayloadUv + sizeofPayloadLatitude + sizeofPayloadLongitude + sizeofPayloadDate) > 51) Serial.println(F("playload is over (10)"));


// PRINT
Serial.print("mydata = { ");
  for (byte i = 0; i < playloadSize; i++) {
    //Serial.print("0x");
    if (payload[i] <= 0xF) Serial.print("-");
    Serial.print(payload[i], HEX);
    Serial.print(" ");
  }
Serial.println("}");

Ca marche!!!!!

Sauf que mon problème est encore ici

byte payloadBattery[] = {0x34};
    byte payloadTemperature[] = {0x35};
    byte payloadPression[] = {0x36};
    byte payloadAltitude[] = {0x37};

Et je précise.

sij'ai

int ibatt = 345
int itemp = -3
int ipres = 1
int ialti = 123456 // je fait expres de mettre un gros chiffre

Je n'arrive pas à les passer dans

byte payloadBattery[] = {0x33 0x34 0x35};
    byte payloadTemperature[] = {0x2d 0x33};
    byte payloadPression[] = {0x31};
    byte payloadAlttiude[] = {0x31 0x32 0x33 0x34 0x35 0x36 0x20};

J'ai essayé plein de truc comme paremple

byte payloadBattery[2];
playloadBattery[0] = ibatt / 256;
playloadBattery[1] = ibatt % 256;
    byte payloadTemperature[2];
playloadTemperature[0] = itemp / 256;
playloadTemperature[1] = itemp % 256;
    byte payloadPression[2];
playloadPression[0] = ipres / 256;
playloadPression[1] = ipres % 256;
    byte payloadAltitude[2];
playloadAltitude[0] = ialti / 256;
playloadAltitude[1] = ialti % 256;

Ci-dessus, affichera des valerus fausses sous // PRINT

J'ai encore essayé

byte tBattery[2];
tBattery[0] = ibatt / 256;
tBattery[1] = ibatt % 256;
    byte tTemperature[2];
tTemperature[0] = itemp / 256;
tTemperature[1] = itemp % 256;
    byte tPression[2];
tPression[0] = ipress / 256;
tPression[1] = ipres % 256;
    byte tAltitude[2];
tAltitude[0] = ialti / 256;
tAltitude[1] = ialti % 256;


byte payloadBattery[] = tBattery;
    byte payloadTemperature[] = tTemperature;
    byte payloadPression[] = tPression;
    byte payloadAlttiude[] = tAltitude;

Ceci m'affichera une erreur dans mon terminal. Je ne sais plus ce que j'ai essayé...

Comment travailler ibatt (et les nombre négatif ou grand nombre)

ibatt = 345

pour arriver à ce même résultat

byte payloadTemperature[] ={0x33, 0x34, 0x35};

Il est encore important que je puisse sauver dans notre comme
1 (1 digit)
345 (3 digit)
-4 (négative)
123456 (6 digit pour les longitude et latitude)

Des que j'arrive à comprendre et à la faire, je suis débloqué :o :o

Milles mercis

vous comprenez que quand vous écrivezbyte payloadBattery[] = {0x34};vous déclarez un tableau de 1 byte de long (car vous ne passez qu'une valeur) ? donc la variable payloadBattery est de type pointeur en mémoire sur un tableau de byte.

donc votre exemple avec

byte payloadAltitude[] = {0x34};
byte payloadHumidity[] = {0x35};
byte payloadMoisture[] = {0x36};
// ... etc

est tout à fait fonctionnel car la fonction memcpy() a besoin d'un pointeur en mémoire pour travailler.

A ce sujet, pour simplifier la lecture et l'écriture au lieu de faire

memcpy(payload, payloadBattery, sizeofPayloadBattery);
memcpy(payload + sizeofPayloadBattery, payloadTemperature, sizeofPayloadTemperature);
memcpy(payload + sizeofPayloadBattery + sizeofPayloadTemperature, payloadPression, sizeofPayloadPression);

qui devient vite pénible à lire, il est plus simple de déclarer un pointeur et de le bouger.

byte * ptr = payload; // on initialise ptr au début du payload
memcpy(ptr, payloadBattery, sizeofPayloadBattery);
ptr+= sizeofPayloadBattery; // on décale le pointeur

memcpy(ptr, payloadTemperature, sizeofPayloadTemperature);
ptr+= sizeofPayloadTemperature; // on décale le pointeur

memcpy(ptr, payloadPression, sizeofPayloadPression);
ptr+= sizeofPayloadPression; // on décale le pointeur

// etc

Pour votre question maintenant concernantint ibatt = 345;
il faut comprendre ici que ibatt est une variable de type entier. Comme ce n'est pas un tableau, lorsque dans du code vous faites référence à ibatt, vous manipulez le contenu de la mémoire et pas le pointeur sur la mémoire associée. En C le pointeur (l'adresse de la case mémoire du début du stockage) se représente par &ibatt. à cet endroit en mémoire va se trouver le codage sur plusieurs octets de votre nombre. Le nombre d'octets de codage dépend du type de la variable. Un int sur arduino standard c'est 2 octets, un float ou un long c'est 4 par exemple. Le nombre d'octets affectés au stockage d'un entier va influencer les valeurs représentables: sur un Arduino typique (genre UNO), un int est sur 2 octets donc 16 bits. un int est signé donc il y a un bit qui va être utilisé pour dire si le nombre est positif ou négatif et il reste 15 bits pour représenter la valeur, ce qui permet par convention (puisqu'on est en base 2) d'avoir une valeur minimum à -215 = -32,768 et maximale à +215-1 = 32,767.
Si vos valeurs sont toutes positives vous pouvez utiliser un unsigned int qui va alors vous donner les 16 bits pour représenter vos nombres entre 0 et 216-1=65535. On voit bien que la représentation sous forme de 1 et de 0 de votre nombre n'est qu'affaire de convention (qui suit une norme internationale), cette convention vous la définissez avec le type de la variable et le compilateur se charge du reste.

Pour ibatt qui est un int donc sur 2 octets, vous aurez à partir de l'adresse mémoire &ibatt la représentation de 345(décimal) qui est en héxadécimal 0x159(hex).

Le compilateur sur Arduino étant little endian et la mémoire étant organisée en octets (une adresse pointe vers 8 bits de mémoire) il va mettre dans la mémoire d'abord l'octet de poids faible puis celui de poids fort et donc on aura à partir de l'adresse mémoire &ibatt 0x59 puis dans l'octet qui suit en mémoire la valeur 0x01.

Mais vous me dites vouloir avoir dans le payload 0x33 0x34 0x35 ce qui correspond à la représentation en ASCII de votre nombre en base 10 (le caractère '3' est effectivement codé en 0x33, le caractère '4' est 0x34 et le caractère '5' est 0x35).

Cette approche comme on vous l'a déjà mentionné n'est pas super car l'entier 15228 par exemple va nécessiter 5 octets pour être représenté alors que l'entier 3 ne va en nécessité qu'un seul. Pour calculer la taille de votre payload a priori, c'est pénible... et côté décodage ça va être un peu galère aussi, il faudra marquer la fin de la chaîne de caractères puisque sa longueur n'est pas fixe. et donc rajouter un octet (généralement on met '\0' dans ce caractère). Il est bcp plus efficace d'envoyer la représentation binaire, les fameux 2 octets à partir de l'adresse mémoire &ibatt 0x59 puis 0x01.

en continuant l'approche mentionnée ci dessus cela se ferait par

int ibatt = 345;

byte * ptr = payload; // on initialise ptr au début du payload
memcpy(ptr, (byte *) (& ibatt), sizeof(ibatt));
ptr+= sizeof(ibatt); // on décale le pointeur du bon nombre d'octets

Cependant si vous tenez à représenterez en mémoire la chaîne de caractères ASCII, il faut d'abord la convertir.

Pour cela il y a des fonctions dans les librairies standard (stdlib.h ou string.h par exemple) et celle qui permet de convertir un entier (type int) en chaîne ASCII est itoa()

Pour convertir un entier stocké dans

valeur

, et mettre la chaîne correspondante à la représentation ASCII dans une certaine

base

à l'adresse pointée par

adresseMémoire

, l'appel de fonction est le suivant

itoa([color=red]valeur[/color], [color=blue]adresseMémoire[/color], [color=purple]base[/color] );

ça rajoute tout seul aussi un caractère nul de fin de chaîne '\0' à la fin de l'encodage.

Donc puisque vous voulez représenter en base 10 et stocker ça dans le payload (en supposant qu'il y ait toute la place nécessaire dans le payload)

int ibatt = 345;

byte * ptr = payload; // on initialise ptr au début du payload
itoa ( ibatt, (char *) ptr, 10 ); // on écrit à partir de ptr la représentation ASCII en base 10 de la valeur de ibatt
ptr+= strlen(ptr) + 1; // on décale le pointeur du bon nombre d'octets, besoin du +1 pour conserver le '\0'

La fonction standard [url=http://www.cplusplus.com/reference/cstring/strlen/]strlen()[/url] donne le nombre de caractères utilisés. cette fonction ne compte pas le caractère nul de fin et donc je fais +1 pour déplacer le pointeur vers la prochaine case vide du payload.

Si on met tout cela dans un exemple de code:

uint8_t payload[10]; // uint8_t c'est comme byte mais plus standard
const byte nbBytesDansPayload = sizeof(payload);

void afficherPayload()
{
  for (byte i = 0; i < nbBytesDansPayload; i++) {
    Serial.print(F("payload["));
    Serial.print(i);
    Serial.print(F("]=0x"));
    Serial.print(payload[i], HEX);
    Serial.print(F("\tsoit le caractère ASCII '"));
    Serial.print((char) payload[i]);
    Serial.println(F("'"));
  }
}

void setup() {
  int ibatt = 345; // 0x159 en hexa

  Serial.begin(115200);
  // on met tout le buffer à '#'histoire de voir quelque chose lors de l'impression
  memset(payload, '#', nbBytesDansPayload);

  // on copie la représentation binaire (2 octets sur UNO)
  uint8_t * ptr = payload; // on initialise ptr au début du payload
  memcpy(ptr, (uint8_t *) (& ibatt), sizeof(ibatt));
  ptr += sizeof(ibatt); // on décale le pointeur du bon nombre d'octets

  // on copie la représentation base 10 en ASCII
  itoa(ibatt, (char *) ptr, 10); // on écrit à partir de ptr la représentation ASCII en base 10 de la valeur de ibatt
  ptr += strlen((char *) ptr) + 1; // on décale le pointeur du bon nombre d'octets, besoin du +1 pour conserver le '\0'

  afficherPayload();
}

void loop() {}

si vous exécutez, vous verrez dans la console

[nobbc]
payload[0]=0x59	soit le caractère ASCII 'Y'
payload[1]=0x1	soit le caractère ASCII ''
payload[2]=0x33	soit le caractère ASCII '3'
payload[3]=0x34	soit le caractère ASCII '4'
payload[4]=0x35	soit le caractère ASCII '5'
payload[5]=0x0	soit le caractère ASCII ''
payload[6]=0x23	soit le caractère ASCII '#'
payload[7]=0x23	soit le caractère ASCII '#'
payload[8]=0x23	soit le caractère ASCII '#'
payload[9]=0x23	soit le caractère ASCII '#'
[/nobbc]

on retrouve bien en cases 0 et 1 la représentation de 0x159 (avec le 0x59 d'abord) puis la représentation ASCII correcte de 345 en base 10, suivi du zéro de fin de chaîne et ensuite rien n'a été touché, on trouve tous les '#' que j'avais mis au départ.

Pour des nombre négatifs ou des grands nombres c'est la même chose, si vous voulez de l'ASCII il faut prendre la fonction de conversion ASCII adaptée... mais ma recommendation c'est de ne pas envoyer l'ASCII et d'envoyer la représentation mémoire et faire ensuite le traitement côté serveur....

ça aide ?

Bonjour J-M-L
Je vous réponds juste pour vous dire que j'ai reçu votre super mega réponse. Vous être extraordinaire.
Je ne pourrai pas me pencher la dessus ce week-end, car je suis avec ma fille, mais je lirai ligne par ligne votre réponse lundi. Milles mercis et tout bon week-end à vous

Bonjour J-M-L,

Je crois que j'y suis arrivéééééeeeee!!!!!!!!!!!!!!!!!
Je crois, je crois, je crois.

Je me suis basé sur votre dernière réponse sans avoir de résultat concluant, mais très proche.

Avant de continuer:

A ce sujet, pour simplifier la lecture et l'écriture au lieu de faire

Oui en effet, je l'ai corrigé de la sorte. C'est en effet bien bien mieux :slight_smile:
Ce code fonctionne exactement comme je le veux, sauf que je n'arrive toujours pas à ce que
payloadBattery prenne la valeur de ibatt, comme ci-dessous

byte payloadBattery[] = {0x33, 0x34, 0x35};     //345
    byte payloadTemperature[] = {0x2D, 0x31, 0x30}; // -10
    byte payloadPression[] = {0x31};                //1
    byte payloadAltitude[] = {0x34, 0x32, 0x34};    // 424
    byte payloadHumidity[] = {0x35};                // 5
    byte payloadMoisture[] = {0x36};                // 6
    byte payloadLuminosity[] = {0x37};              // 7
    byte payloadUv[] = {0x38};                      // 8
    byte payloadLatitude[] = {0x39};                // 9
    byte payloadLongitude[] = {0x31, 0x30};         // 10
    byte payloadDate[] = {0x31, 0x31};              // 11

    int sizeofPayloadBattery = sizeof(payloadBattery);
    int sizeofPayloadTemperature = sizeof(payloadTemperature);
    int sizeofPayloadPression = sizeof(payloadPression);
    int sizeofPayloadAltitude = sizeof(payloadAltitude);
    int sizeofPayloadHumidity = sizeof(payloadHumidity);
    int sizeofPayloadMoisture = sizeof(payloadMoisture);
    int sizeofPayloadLuminosity = sizeof(payloadLuminosity);
    int sizeofPayloadUv = sizeof(payloadUv);
    int sizeofPayloadLatitude = sizeof(payloadLatitude);
    int sizeofPayloadLongitude = sizeof(payloadLongitude);
    int sizeofPayloadDate = sizeof(payloadDate); 
    
    //int playloadSize = sizeofPayloadBattery + sizeofPayloadTemperature + sizeofPayloadPression + sizeofPayloadAltitude + sizeofPayloadHumidity + sizeofPayloadMoisture + sizeofPayloadLuminosity + sizeofPayloadUv + sizeofPayloadLatitude +sizeofPayloadLongitude + sizeofPayloadDate;
    int playloadSize = 64;
    sprint(F("Payload size: "),1); sprintln(playloadSize,2);
    
    uint8_t payload[playloadSize];
    // on met tout le buffer à '#'histoire de voir quelque chose lors de l'impression
    memset(payload, '#', playloadSize);

    uint8_t * ptr = payload;

    //Arranegment proposée par J-M-L
     
    memcpy(ptr, payloadBattery, sizeofPayloadBattery);
    ptr+= sizeofPayloadBattery+1;   // On deplace le pointeur. J'ajoute volontaire un espace suppl. pour ieux lire le réultat

    memcpy(ptr, payloadTemperature, sizeofPayloadTemperature);
    ptr+= sizeofPayloadTemperature+1;   // On deplace le pointeur
    
    memcpy(ptr, payloadPression, sizeofPayloadPression);
    ptr+= sizeofPayloadPression+1;   // On deplace le pointeur

    memcpy(ptr, payloadAltitude, sizeofPayloadAltitude);
    ptr+= sizeofPayloadAltitude+1;   // On deplace le pointeur

    memcpy(ptr, payloadHumidity, sizeofPayloadHumidity);
    ptr+= sizeofPayloadHumidity+1;   // On deplace le pointeur

    memcpy(ptr, payloadMoisture, sizeofPayloadMoisture);
    ptr+= sizeofPayloadMoisture+1;   // On deplace le pointeur

    memcpy(ptr, payloadLuminosity, sizeofPayloadLuminosity);
    ptr+= sizeofPayloadLuminosity+1;   // On deplace le pointeur

    memcpy(ptr, payloadUv, sizeofPayloadUv);
    ptr+= sizeofPayloadUv+1;   // On deplace le pointeur

    memcpy(ptr, payloadLatitude, sizeofPayloadLatitude);
    ptr+= sizeofPayloadLatitude+1;   // On deplace le pointeur

    memcpy(ptr, payloadLongitude, sizeofPayloadLongitude);
    ptr+= sizeofPayloadLongitude+1;   // On deplace le pointeur

    memcpy(ptr, payloadDate, sizeofPayloadDate);

Ce qui donne

33 34 35 23 2D 31 30 23 31 23 34 32 34 23 35 23 36 23 37 23 38 39 23 31 30 23 31 31 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23 23

ou

345#-10#1#424#5#6#7#89#10#11####################################

C'est exactement le résultat que je veux avoir!!!( Avec des # des, c'est egal..)

Après avoir rendu cette partie plus lisible, je me suis penché sur vos propositions, sans pour autant réussir.

Finalement, je me suis basé sur votre tout dernier code

Cette partie m'affichait des caracteres ilisible

  // on copie la représentation binaire (2 octets sur UNO)
  uint8_t * ptr = payload; // on initialise ptr au début du payload
  memcpy(ptr, (uint8_t *) (& ibatt), sizeof(ibatt));
  ptr += sizeof(ibatt); // on décale le pointeur du bon nombre d'octets

Finalement, je l'ai supprimé pour gardé que ceci et là il semble que ca s'affiche bien

Si

ibatt=345
itemp=-10
ipres=1
ialti=424
ihumi=-34654// Je mets volontairement un chiffre à 6 difigt
imois=6
ilumi=7
iuv=8
ilati=4686789 // 5 deimal
lati=412436 //5decimal
idate=170925
itime=1747

Ceci

 int payloadSize = 64;
    uint8_t payload[payloadSize];
    memset(payload,'#',payloadSize);
    uint8_t * ptr = payload;

    ibatt = 345;
    itemp = -10;
    ipres = 1;
    ialti = 424;
    ihumi = -34654; // Je mets volontairement un chiffre à 6 difigt
    imois = 6;
    ilumi = 7;
    iuv = 8;
    ilati = 4686789; // 5 deimal
    ilong = 412436; //5decimal
    idate = 170925;
    itime = 1731;

    // on copie la représentation binaire (2 octets sur UNO)
    // memcpy(ptr, (uint8_t *) (& ibatt), sizeof(ibatt));
    // ptr += sizeof(ibatt); // on décale le pointeur du bon nombre d'octets

    // on copie la représentation base 10 en ASCII
    itoa(ibatt, (char *) ptr, 10); // on écrit à partir de ptr la représentation ASCII en base 10 de la valeur de ibatt
    ptr += strlen((char *) ptr) + 1; // on décale le pointeur du bon nombre d'octets, besoin du +1 pour conserver le '\0'

    // memcpy(ptr, (uint8_t *) (& itemp), sizeof(itemp));
    // ptr += sizeof(itemp); 
    itoa(itemp, (char *) ptr, 10);
    ptr += strlen((char *) ptr) + 1;
   
    // memcpy(ptr, (uint8_t *) (& ipres), sizeof(ipres));
    // ptr += sizeof(ipres); 
    itoa(ipres, (char *) ptr, 10);
    ptr += strlen((char *) ptr) + 1;

    // memcpy(ptr, (uint8_t *) (& ialti), sizeof(ialti));
    // ptr += sizeof(ialti); 
    itoa(ialti, (char *) ptr, 10);
    ptr += strlen((char *) ptr) + 1;

    itoa(ihumi, (char *) ptr, 10);
    ptr += strlen((char *) ptr) + 1;

    itoa(imois, (char *) ptr, 10);
    ptr += strlen((char *) ptr) + 1;

    itoa(ilumi, (char *) ptr, 10);
    ptr += strlen((char *) ptr) + 1;

    itoa(iuv, (char *) ptr, 10);
    ptr += strlen((char *) ptr) + 1;

    itoa(ilati, (char *) ptr, 10);
    ptr += strlen((char *) ptr) + 1;

    itoa(ilong, (char *) ptr, 10);
    ptr += strlen((char *) ptr) + 1;

    itoa(idate, (char *) ptr, 10);
    ptr += strlen((char *) ptr) + 1;

    itoa(itime, (char *) ptr, 10);
    ptr += strlen((char *) ptr) + 1;
    
    for (byte i = 0; i < 64; i++) {
      Serial.print(F("payload3["));
      Serial.print(i);
      Serial.print(F("]=0x"));
      Serial.print(payload[i], HEX);
      Serial.print(F("\tsoit le caractere ASCII '"));
      Serial.print((char) payload[i]);
      Serial.println(F("'"));
    }

m'affiche bien

payload3[0]=0x33 soit le caractere ASCII '3'
payload3[1]=0x34 soit le caractere ASCII '4'
payload3[2]=0x35 soit le caractere ASCII '5'
payload3[3]=0x0 soit le caractere ASCII ''
payload3[4]=0x2D soit le caractere ASCII '-'
payload3[5]=0x31 soit le caractere ASCII '1'
payload3[6]=0x30 soit le caractere ASCII '0'
payload3[7]=0x0 soit le caractere ASCII ''
payload3[8]=0x31 soit le caractere ASCII '1'
payload3[9]=0x0 soit le caractere ASCII ''
payload3[10]=0x34 soit le caractere ASCII '4'
payload3[11]=0x32 soit le caractere ASCII '2'
payload3[12]=0x34 soit le caractere ASCII '4'
payload3[13]=0x0 soit le caractere ASCII ''
payload3[14]=0x2D soit le caractere ASCII '-'
payload3[15]=0x33 soit le caractere ASCII '3'
payload3[16]=0x34 soit le caractere ASCII '4'
payload3[17]=0x36 soit le caractere ASCII '6'
payload3[18]=0x35 soit le caractere ASCII '5'
payload3[19]=0x34 soit le caractere ASCII '4
payload3[20]=0x0 soit le caractere ASCII ''
payload3[21]=0x36 soit le caractere ASCII '6'
payload3[22]=0x0 soit le caractere ASCII ''
payload3[23]=0x37 soit le caractere ASCII '7'
payload3[24]=0x0 soit le caractere ASCII ''
payload3[25]=0x38 soit le caractere ASCII '8'
payload3[26]=0x0 soit le caractere ASCII ''
payload3[27]=0x34 soit le caractere ASCII '4'
payload3[28]=0x36 soit le caractere ASCII '6'
payload3[29]=0x38 soit le caractere ASCII '8'
payload3[30]=0x36 soit le caractere ASCII '6'
payload3[31]=0x37 soit le caractere ASCII '7'
payload3[32]=0x38 soit le caractere ASCII '8'
payload3[33]=0x39 soit le caractere ASCII '9'
payload3[34]=0x0 soit le caractere ASCII ''
payload3[35]=0x34 soit le caractere ASCII '4'
payload3[36]=0x31 soit le caractere ASCII '1'
payload3[37]=0x32 soit le caractere ASCII '2'
payload3[38]=0x34 soit le caractere ASCII '4'
payload3[39]=0x33 soit le caractere ASCII '3'
payload3[40]=0x36 soit le caractere ASCII '6'
payload3[41]=0x0 soit le caractere ASCII ''
payload3[42]=0x31 soit le caractere ASCII '1'
payload3[43]=0x37 soit le caractere ASCII '7'
payload3[44]=0x30 soit le caractere ASCII '0'
payload3[45]=0x39 soit le caractere ASCII '9'
payload3[46]=0x32 soit le caractere ASCII '2'
payload3[47]=0x35 soit le caractere ASCII '5'
payload3[48]=0x0 soit le caractere ASCII ''
payload3[49]=0x31 soit le caractere ASCII '1'
payload3[50]=0x37 soit le caractere ASCII '7'
payload3[51]=0x33 soit le caractere ASCII '3'
payload3[52]=0x31 soit le caractere ASCII '1'
payload3[51]=0x0 soit le caractere ASCII ''
payload3[54]=0x23 soit le caractere ASCII '#'
payload3[55]=0x23 soit le caractere ASCII '#'
payload3[56]=0x23 soit le caractere ASCII '#'
payload3[57]=0x23 soit le caractere ASCII '#'
payload3[58]=0x23 soit le caractere ASCII '#'
payload3[59]=0x23 soit le caractere ASCII '#'
payload3[60]=0x23 soit le caractere ASCII '#'
payload3[61]=0x23 soit le caractere ASCII '#'
payload3[62]=0x23 soit le caractere ASCII '#'
payload3[63]=0x23 soit le caractere ASCII '#'

Et je vois même qu'il me reste un peu de place :slight_smile:

C'est génial. Il me reste plus qu'a voir si mes données seront bien envoyées. J'essayerai aussi arrivé à la maison.

En attendant, je vais simplifer l'affichage d ela sorte

payload3 {33 34 35 0 2D 31 30 0 31 0 34 32 34 0 2D 33 34 36 35 34 0 36 0 37 0 38 0 34 36 38 36 37 38 39 0 34 31 32 34 33 36 0 31 37 30 39 32 35 0 31 37 33 31 0 23 23 23 23 23 23 23 23 23 23 }

et que je remplace les 0 par 2C (la virgule)

Je me réjouis d'essayé tut ceci.

Qu'en pensez-vous?

je vous tiens au courant et tout cas, milles milles milles mercis pour tout ce que vous avez fait, pour tout vos exemples, votre temps. C'est vraiment super sympa et je vous en suis très reconnaissant.

Vous êtes quel côté géographique?

Bonjour J-M-L

Je voulais encore vraiment vous remercier pour toute l'énergie et la patience que vous avez pris pour moi.

Ca fonctionne!!!!!!

J'ai envoyé des données que je retrouve sur le serveur. Je suis super content et sans vous j'aurais jamais réussi.

Aussi, l'air de rien, j'ai beaucoup, beaucoup appris surtout e ce qui concerne le pointer. Je ne sais pas ou vous etes localisé, mais c'est avec grand plaisir que je vous offrirais un bon verre.

Cette discussion, elle est vraiment été énorme et je vais prendre un moment pour mettre tout mon code. Je vais avant faire un peu de nettoyage mais je le mets plus tard

Super boulot - vous avez tout compris !

(bon si c'était moi vous savez bien que je n'enverrai pas de l'ASCII puisque le serveur sera bcp plus puissant pour décoder vos octets directement mais pas grave)

Bonne continuation

Voilà, j'espère qu'il n'y aura rien à redire :slight_smile:

(J'espère ne rien oublier)

//---------------------------------------------------------
// Sensor activation
//---------------------------------------------------------

#define SENSOR_BATTERY      // Battery Voltage
//#define SENSOR_GPS        // latitude, longitude, datetime
#define SENSOR_BMP180       // Barometer (temperature/pression/alt)
#define SENSOR_DTH22        // Humidity (Temrature)
//#define SENSOR_MOISTURE
#define SENSOR_TSL2561      // Luminoisty
//#define SENSOR_UV
//#define SENSOR_MEMORY     // Free memory

const byte capteur_battery_id = 0;
const byte capteur_temperature_id = 1;
const byte capteur_pression_id = 2;
const byte capteur_alt_id = 3;
const byte capteur_humidity_id = 4;
const byte capteur_moisture_id = 5;
const byte capteur_luminosity_id = 6;
const byte capteur_uv_id = 7;
const byte capteur_latitude_id = 8;
const byte capteur_longitude_id = 9;
const byte capteur_datetime_id = 10;

// JE NE LES METS PAS TOUS...
#ifdef SENSOR_BATTERY
bool battery_active = true;
#else
bool battery_active = false;
#endif

struct capteur
{
  uint8_t idDuCapteur;
  boolean actif;
  const char * nomDuCapteur;
};
capteur mesCapteur[] = {
  {capteur_battery_id, battery_active, "ba"},
  {capteur_temperature_id, temperature_active, "te"},
  {capteur_pression_id, pression_active, "pr"},
  {capteur_alt_id, alt_active, "al"},
  {capteur_humidity_id, humidity_active, "hu"},
  {capteur_moisture_id, moisture_active, "mo"},
  {capteur_luminosity_id, luminosity_active, "lu"},
  {capteur_uv_id, uv_active, "uv"},
  {capteur_latitude_id, latitude_active, "la"},
  {capteur_longitude_id, longitude_active, "lo"},
  {capteur_datetime_id, datetime_active, "da"},
};



enum : byte {c_battery = 0, c_temperature, c_pression, c_alt, c_humidity, c_moisture, c_luminosity, c_uv, c_latitude, c_longitude, c_datetime}; // dans le même ordre que mesCapteurs
const byte nbMaxCapteurs = sizeof(mesCapteur) / sizeof(mesCapteur[0]);

struct mesure {
  uint16_t id_capteur;
  int valeur; // valeur mesurée (adapter le type)
  // autre chose de pertinent à mémoriser lors d'une mesure ?
};

const byte tailleHistorique = 11; // Ce chiffre doit correspondre aux nombres de capteurs. Voir capteur mesCapteur[] = {
mesure mesMesures[nbMaxCapteurs][tailleHistorique];

Je ne peux pas mettre tout mon code dans un post, je le split

(Suite)
J'ai maintenant une fonction do_send(). Elle est appelée tous les 120sec. A caque fois qu'elle est applée, les fonctions "capteurs" sont applés..

void do_send(osjob_t* j)
{
  uint8_t payload[payloadSize];
  memset(payload,'#',payloadSize);

// Ici la partie du code qui prépare LoRa a l'envoi

/*
* Je fais appelle à mes fonctions qui me retorune tous des float.
* J'ai décidé ne pas garder les décimal, sauf pour la batterie et poue les latitude et longitude
* Je dois encore étudier la date. Ce que j'ai fais c'est du brouillon.
* Pour la batterie je garde 2 décimal
* pour lat et lon, je garde 4 décimal
* pour les autres, je garde rien
* Si le moduel est inactif, je garde la valeur de -99. Cette valeur ne sera jamais envoyée. Elle ne s'affiche que si il ya un problème...
*/

   /*
    * Getting battery value
    */
    float fbatt;
    int ibatt;
    if(battery_active)
    {
      fbatt = get_battery(battery);
      fbatt = fbatt*100;
      ibatt = fbatt;
    }
    else
    {
      ibatt = -99;
    }
    mesMesures[c_battery][capteur_battery_id].valeur = ibatt;

/*
     * Get temperature, pression, altitude value
     */
    float ftemp, fpres, falti;
    int itemp, ipres, ialti;
    
    if(temperature_active)
    {
      ftemp = get_temperature(temperature);
      itemp = ftemp;
    }
    else
    {
      itemp = -99;
    }
    mesMesures[c_temperature][capteur_temperature_id].valeur = itemp;

    if(pression_active)
    {
      fpres = get_pression(pression);
      ipres = fpres;
    }
    else
    {
      ipres = -99;
    }
    mesMesures[c_pression][capteur_pression_id].valeur = ipres;

    if(alt_active)
    {
      ialti = ALTITUDE;
    }
    else
    {
      ialti = -99;
    }
    mesMesures[c_alt][capteur_alt_id].valeur = ialti;

 /*
     * Get humidity value
     */
    float fhumi;
    int ihumi;
    if(humidity_active)
    { 
      fhumi = get_humidity(humidity);
      ihumi = fhumi;
    }
    else
    {
      ihumi = -99;
    }
    mesMesures[c_humidity][capteur_humidity_id].valeur = ihumi;

    /*
     * Get moisture value 
    */
    float fmois;
    int imois;
    if(moisture_active)
    {
      fmois = get_moisture(moisture);
      imois = fmois;
    }else{
      imois = -99;
    }
    mesMesures[c_moisture][capteur_moisture_id].valeur = imois;


    /*
     * Get luminosity value
     */
    int ilumi;
    float flumi;
    if(luminosity_active)
    {
      flumi = get_luminosity(luminosity);
      ilumi = flumi;
    }
    else
    {
      ilumi = -99;
    }
    mesMesures[c_luminosity][capteur_luminosity_id].valeur = ilumi;


    /*
     * Get UV value
     */
    float fuv;
    int iuv;
    if(uv_active)
    {
      fuv = get_uv(uv);
      iuv = fuv;
    }else{
      iuv = -99;
    }
    mesMesures[c_uv][capteur_uv_id].valeur = iuv;
    
  /*
     * Getting GPS value
     */
    float flati, flong, fdate;
    int ilati, ilong, idate, itime;    
    if(latitude_active)
    {
      flati = get_latitude(latitude);
      flati = flati*10000;
      ilati = flati;
    }
    else
    {
      ilati = -99;
    }
    mesMesures[c_latitude][capteur_latitude_id].valeur = ilati;

    if(longitude_active)
    {
      flong = get_longitude(longitude);
      flong = flong*10000;
      ilong = flong;
    }
    else
    {
      ilong = -99;
    }
    mesMesures[c_longitude][capteur_longitude_id].valeur = ilong;

    if(datetime_active)
    {
      fdate = get_time(datetime); // 170927.2356
      idate = fdate;   // 170927
     
      uint16_t item, item2;

      fdate = fdate*10000;  // 1709272356.00
      item = fdate;         // 1709272356
      item2 = idate*10000;  // 1709270000
      
      itime = item-item2;   // 2356
      
    }else{
      idate = -99;
      itime = -99;
    }
    mesMesures[c_datetime][capteur_datetime_id].valeur = idate;