Convertir byte en char et contenu d'un file.read

Bonjour,

J'essai d'utiliser un lecteur de carte SD avec un esp32, je bute sur deux trucs sûrement simple ...

1- j'essai de concaténer des *char avec des bytes.

char *chaine1  = "Il y a "
byte num = 5;
char * chaine2 ="singes dans le bananier n°:";
uint8_t etat= 1;

j'essai de fabriquer une chaîne pour l'écrire dans un fichier "Il y a 5 singes dans le bananier n°: 1". J'ai essayé la fonction char() pour convertir num et etat mais le résultat n'est pas cohérent car "num" varie de 1 à 56

Mon deuxième souci en lecture, avec le code ci dessous

while(file.available()){
      char c =file.read();
      Serial.write(c);
    }

Je vois le contenu de mon fichier dans la console mais comment fait t'on pour mettre chacune des lignes lues dans des variables *char?

Merci d'avance

j'essai de fabriquer une chaîne pour l'écrire dans un fichier "Il y a 5 singes dans le bananier n°: 1"

La bonne question à se poser c'est avez vous vraiment besoin de cette chaîne qui va manger de la mémoire pour rien.. il suffit d'écrire en 4 fois dans le fichier:

sdfile.print(chaine1);
sdfile.print(num);
sdfile.print(chaine2);
sdfile.print(etat);

sinon faut allouer un buffer avec assez d'espace et utiliser les fonction de base (celle des librairies (stdlib.h et string.h)

pour la seconde questions, lisez éventuellement mon tuto sur Ecouter le Port Série (ce n'est pas le port série mais un peu pareil, vous lisez des trucs caractères par caractères et voulez les stocker à un endroit en mémoire au fur et à mesure qu'ils arrivent - pour cela il faut un buffer mémoire)

Merci pour votre retour
Alors ce post est lié à mon post arduino et esp8266.
Le but est de stocker la structure

struct horaire_t {
  uint8_t h; // l'heure entre 0 et 23
  uint8_t m; // les minutes entre 0 et 59
};

const byte maxEtats = 32;
horaire_t Time[maxEtats]; // on stocke  heure et minute séparément
byte State[maxEtats];
[\code]
Sous la forme 
Ligne=i,horaire[i].etat,horaire[i].h,horaire[i].m
Avec une fin de ligne du type unix(\n)
Je vais essayer le sd.print en mode Append une fois le premier texte écris 
Faut il envoyer un sd.print(« \n »)en dernier?

Faut il envoyer un sd.print(« \n »)en dernier?

vous pouvez faire juste le dernier print en println

// ouvrir 'fichier' en écriture
....
// puis écrire dedans
for (int i = 0; i < nbEtats; i++) { // en supposant que nbEtats est le nombre d'états à copier
   fichier.print(F("Ligne="));   fichier.print(i);
   fichier.print(F(", Etat="));   fichier.print(horaire[i].etat);
   fichier.print(F(", Heure="));   fichier.print(horaire[i].h);
   fichier.print(F(", Minutes="));  fichier.println(horaire[i].h);
}
fichier.close(); // et penser à fermer le fichier

J’ai déjà fait le décodage sur une ligne Je veux essayer de le coder comme je le décrit Ligne=1,2,3,4 Ou 1 position 2 état 3 h 4 m

EricRecifal33480:
J’ai déjà fait le décodage sur une ligne
Je veux essayer de le coder comme je le décrit
Ligne=1,2,3,4
Ou
1 position
2 état
3 h
4 m

comprends pas… c’est donc juste une modification de ce que j’écris ci dessus

// ouvrir 'fichier' en écriture
....
// puis écrire dedans
for (int i = 0; i < nbEtats; i++) { // en supposant que nbEtats est le nombre d'états à copier
   fichier.print(F("Ligne="));   fichier.print(i);
   fichier.print(F(","));   fichier.print(horaire[i].etat);
   fichier.print(F(","));  fichier.print(horaire[i].h);
   fichier.print(F(","));  fichier.println(horaire[i].h);
}
fichier.close(); // et penser à fermer le fichier

ou est-ce que votre question est pour la relecture en mémoire?

Non désolé c’est ma connaissance limité Je n’aurais pas eu l’idée tester cela Veuillez m’excuser Merci à vous car vous me faites progresser

Pas de soucis - pas la peine de s’excuser.on apprend tous constamment et on a tous débuté sans connaissance particulière. Donc continuez

Merci

Alors je réussi à écrire comme je veux dans mon fichier. Avec le formatage que je voulais.

Je me heurte juste à un petit souci car j’aurais bien aimer faire appel à une void genre void(texte) mais comme les variables envoyées dans dans ne sont pas toutes les mêmes comment fait on pour ne pas déclarer le type de la variable texte ?

J’ai trouvé tout seul

Bravo :)

Pour info void est un mot clé (pas très loin d’un type comme int ou long) qui veut dire que quelque chose ne retourne rien ou n’attend rien; donc on ne parle pas d’un ‘void’ comme raccourci pour dire ‘une fonction’.

On écrira

void maFonction(const char * message)
{
   ...
}

pour dire que maFonction ne retourne rien à l’appelant

Concernant cette réponse, ma question portait sur le *char message car cela oblige à envoyer un char. Si l'on veux envoyer des variables int et char dans message comment fait on pour ne pas déclarer le type de variable pour message

void maFonction(????  message)
{
   ...
}

Me voila de nouveau bloqué avec la ligne suivante :

value = &buffer[i];

car quand je fais

Ini_Param[0]=value;

dès que je lis la seconde ligne la variable Ini_Param[0] "bouge", alors que le but est dans la première boucle d'assigner définitivement à Ini_Param[0] la valeur value. J'ai essayé de faire un strcpy() mais l'esp32 n'aime pas du tout mon idée et reboot en boucle

Pouvez vous m'expliquer comment effectuer ce stockage?

ci dessous le code

#include "SD.h"
#include "SPI.h"

// Lecteur  SD     ---->     ESP32
//*************************************
//          CS    >>>>>>>>>>  D5
//          SCK   >>>>>>>>>>  D18
//          MOSI  >>>>>>>>>>  D23
//          MISO  >>>>>>>>>>  D19
//          VCC   >>>>>>>>>>  +5V
//          GND   >>>>>>>>>>  GND

const char * path_Config ="/Rampe/Sauvegarde/Config" ;
const char * Path_WIFI="/Rampe/Wifi/WIFI";
const char * path_Config_old="/Rampe/Sauvegarde/Config.old" ;
const byte maxIniState=9;
char *Ini_Param[maxIniState];



char * valeur1;
char * valeur2;
char * valeur3;
int  valeur5;
struct horaire_t {
  uint8_t h; // les heures
  uint8_t m; // les minutes
  uint8_t etat; // HIGH ou LOW
};
const byte maxEtats = 56;
horaire_t horaires[maxEtats]; // on stocke 60 x heure + minute


void Lecture_Fichier(fs::FS &fs, const char * path){
/* Déclare l'itérateur et le compteur de lignes */
byte i, buffer_lenght, line_counter = 0;
/* Déclare le buffer qui stockera une ligne du fichier, ainsi que les deux pointeurs key et value */
const byte BUFFER_SIZE = 50;
char buffer[BUFFER_SIZE], *key, *value;
    Serial.printf("Reading file: %s\n", path);
    File file = fs.open(path);
    if(!file){
    Serial.println("Failed to open file for reading");
     return;
    }
    Serial.print("Read from file: ");
  while(file.available() > 0 ){
    /* Récupère une ligne entière dans le buffer */
    i = 0;
    while((buffer[i++] = file.read()) != '\n') {
      /* Si la ligne dépasse la taille du buffer */
      if(i == BUFFER_SIZE) {
        /* On finit de lire la ligne mais sans stocker les données */
        while(file.read() != '\n');
        break; // Et on arrête la lecture de cette ligne
      }
    }
    /* On garde de côté le nombre de char stocké dans le buffer */
    buffer_lenght = i;
    /* Gestion des lignes trop grande */
    if(i == BUFFER_SIZE) {
      Serial.print("Ligne trop longue à la ligne ");
      Serial.println(line_counter, DEC);
    } 
    /* Finalise la chaine de caractéres ASCII en supprimant le \n au passage */
    buffer[--i] = '\0';
    /* Incrémente le compteur de lignes */
    ++line_counter;
    /* Ignore les lignes vides ou les lignes de commentaires */
    if(buffer[0] == '\0' || buffer[0] == '#') continue;
    /* Cherche l'emplacement de la clef en ignorant les espaces et les tabulations en début de ligne */
    i = 0;
    while(buffer[i] == ' ' || buffer[i] == '\t') {
      if(++i == buffer_lenght) break; // Ignore les lignes contenant uniquement des espaces et/ou des tabulations
    }
    if(i == buffer_lenght) continue; // Gère les lignes contenant uniquement des espaces et/ou des tabulations
    key = &buffer[i];
    /* Cherche l'emplacement du séparateur = en ignorant les espaces et les tabulations âpres la clef */
    while(buffer[i] != '=') {
      /* Ignore les espaces et les tabulations */
      if(buffer[i] == ' ' || buffer[i] == '\t') buffer[i] = '\0';
      if(++i == buffer_lenght) {
        Serial.print("Ligne mal forme a la ligne ");
        Serial.println(line_counter, DEC);
        break; // Ignore les lignes mal formé
      }
    }
    if(i == buffer_lenght) continue; // Gère les lignes mal formé
    /* Transforme le séparateur = en \0 et continue */
    buffer[i++] = '\0';
    /* Cherche l'emplacement de la valeur en ignorant les espaces et les tabulations âpres le séparateur */
    while(buffer[i] == ' ' || buffer[i] == '\t') {
      if(++i == buffer_lenght) {
        Serial.print("Ligne mal forme a la ligne ");
        Serial.println(line_counter, DEC);
        break; // Ignore les lignes mal formé
      }
    }
    if(i == buffer_lenght) continue; // Gère les lignes mal formé
    value = &buffer[i];
    
    Serial.println(key);
    Serial.println(value);
      
    if(strcmp(key, "IPAddress_local_IP") ==0){
                                  //strcpy(Ini_Param[0]=val_ini); //ne fonctionne pas fait rebooter esp32
                                  Ini_Param[0]=value;
                                  Serial.print("Ini_Param1=");
                                  Serial.println(Ini_Param[0]);
                                }//SSID
    if(strcmp(key, "IPAddress_gateway") ==0){
                                Ini_Param[1]=value;
                                Serial.print("Ini_Param1=");
                                Serial.println(Ini_Param[0]);
                                }//Mdp
        }
        Serial.print("Ini_Param11=");
        Serial.println(Ini_Param[0]);
      } 

void setup() {  
    Serial.begin(115200);
    if(!SD.begin()){
        Serial.println("Card Mount Failed");
        return;
    }
    uint8_t cardType = SD.cardType();
    if(cardType == CARD_NONE){
        Serial.println("No SD card attached");
        return;
    }
  Lecture_Fichier (SD, Path_WIFI);
}
void loop() {
}

Merci

le plus simple c'est de faire 2 fonctions, une pour un int, une pour un char *

pour pouvoir faire un strcpy() il ne faut pas qu'un simple pointeur il faut réserver de la mémoire pour copier dedans les octets.

char * pointeurMessage; // pointeurMessage c'est juste assez de place pour conserver l'adresse d'une case en mémoire (on appelle cela un pointeur, ça pointe sur une adresse)
char message[30]; // On reserve 30 octets et le premier octet est pointé par message, qui est un pointeur sur des caractères

j’ai suivi votre remarque j’ai modifié mon programme

j’ai crée les variables :

const byte maxIniState=60;
char Ini_Param[maxIniState];
char *Ini_SSID;
value = &buffer[i];
strcpy(Ini_Param,value);

et

Ini_SSID=Ini_Param;

mais mon Ini_SSID continu de bouger et de prendre les différentes valeurs de value, je ne comprend pas pourquoi?

est-ce que ça c'est dans une boucle for ?

value = &buffer[i];
strcpy(Ini_Param,value);

si oui vous copiez à chaque fois ce qui a dans

[tt]buffer[i][/tt][nobbc] au même endroit mémoire

si vous voulez tous les conserver il vous faut aussi plusieurs buffer mémoire destination

[code]const byte maxIniState=60;
char Ini_Param[4][maxIniState]; // 4 buffers mémoire[/code]

et comme ça vous pouvez faire des 
[code] strcpy(Ini_Param[i],&buffer[i]); // pour i de 0 à 3[/code]
 pour les conserver mais faut avoir conscience que vous allouer alors pour chaque buffer 60 caractères.. la mémoire est limitée donc faut essayer de faire au plus juste et ne conserver sous forme de chaine que ce qui nécessite d'être sous forme textuelle. par exemple les nombres, autant les représenter avec un int ou un long

Si je comprends bien Je crée un buffer par paramètres mais j’ai 63 paramètres à récupérer en tout,sa va être énorme On ne peux pas sauvegarder le contenu du buffer dans un char ?

un char c'est un octet... comment voulez vous stocker plus qu'un caractère dedans ? si vous voulez conservez par exemple le message "HELLO" il vous faut un char par lettre, plus un pour le caractère que vous ne voyez pas et qui marque la fin de chaîne (un '\0') --> donc 6 char.

pouvez vous re-préciser ce que vous essayez de faire? relire le fichier et initialiser la structure en mémoire?

J’ai un fichier ou j’ai stocker Ssid et Mdp wifi ect.... La fonction de lecture ouvre le fichier et recherche les clés exemple SSID= Et « stock » la valeur ce trouvant derrière le = dans value

Je voudrais stocker les valeurs contenues dans value dans des variables pour initialiser le programme les valeurs de mon programme Par exemple char* ssid = Ini_SSID;

oui dans ce cas il faut des buffers mémoire séparés pour chacun des champs

char SSID[10]; // prévoir assez de caractères + 1 pour le '\0'
char motDePasse[15];
...

et vous faites directement la lecture dans ces buffers

Bonjour nouvelle galère

J'ai bine mes buffers avec les valeurs dedans mais quand je compile j'ai une erreur sur la ligne

IPAddress local_IP(Ini_IPAddress_local_IP);

Le message dit : "no matching function for call to 'IPAddress(char [35])"

j'imagine qu'il faut convertir mon char[] en ????

Pouvez vous m'aider ?