Arduino Forum

International => Français => Topic started by: fredo5962 on Mar 27, 2019, 02:29 pm

Title: les string me rendent fou ! :)
Post by: fredo5962 on Mar 27, 2019, 02:29 pm
bonjour j'ai besoin de vos lumieres car la.... je deviens dingue !

je vous explique, sur un arduino uno, j'ai branché un shield carte sd afin de lire, un petit fichier texte qui contient des numéros de telephone.

numero0 est un string

je recupere le numéro via ce code

myFile = SD.open("numero.txt");
 
     for (int i=0; i<13; i++ )
  {
           myFile.seek(i); // se positionne à la position i
           numero0=numero0+char(myFile.peek()); // affiche le caractère courant
         }

je fais le test, numero0 est donc +33781000000


je veux utliser ce numero pour envoyer un sms
j'utilise donc ce code


    sim808.print("AT+CMGS=\"");
    sim808.print(numero0);
    sim808.print("\"");
    sim808.println("");
    delay(300);
    sim808.print("petit coucou de l'arduino :)");
    delay(200);
    sim808.println((char)26); // End AT command with a ^Z, ASCII code 26
    delay(200);
    sim808.println();
    delay(20000);
    sim808.flush();



et bin... ca ne fonctionne pas ! ca ne s'envoie pas !

pire ! si je déclare un autre string message1

et que je l'appelle "+33700000000"  bah lui il fonctionne !?!
si compare message0 et message 1.. ils sont identiques ! l'un part pas l'autre !!!

je vous donne le programme complet si vous pourriez m'indiquer ou ca plante.... merciiiiiii

Code: [Select]

#include <SD.h>
#include <SoftwareSerial.h>
const int chipSelect = 10;  //pin de l'Arduino reliee au CS du module SD
SoftwareSerial sim808(5, 6); // RX,TX
Sd2Card card;
SdVolume volume;
SdFile root;
File myFile;
int val = 0;
String numero0;
String numero1;

void setup()
{
  sim808.begin(9600);
  Serial.begin(9600);
  lecture();
}


void loop() {
  demo();

}

void demo() {
  Serial.println("Envoie du message...");
  Serial.println(numero0);
  numero1 = "+33786000000";
  Serial.println(numero1);
// ICI j'affiche numero0 et numero1.... ils sont identiques ! à l'écran...

  sim808.print("AT+CMGS=\"");
  sim808.print(numero1);  // si j'envoie le numero0 ca passe pas,  le numero1..ca passe ?!?
  sim808.print("\"");
  sim808.println("");
  delay(300);
  sim808.print("petit coucou de l'arduino :)");
  delay(200);
  sim808.println((char)26); // End AT command with a ^Z, ASCII code 26
  delay(200);
  sim808.println();
  delay(20000);
  sim808.flush();
  Serial.println("Message envoyé");

}

void lecture() {

  Serial.print("\nRecherche de la carte SD...");
  pinMode(10, OUTPUT);
  if (!card.init(SPI_HALF_SPEED, chipSelect)) // Pas de carte ?
  {
    Serial.println("pas de carte?");
    return;
  }

  if (!volume.init(card)) // Carte formatée ?
  {
    Serial.println("La carte n'est pas formatee?");
    return;
  }
  if (!SD.begin(chipSelect)) // Défaut initialisation ?
  {
    Serial.println("Echec de l'initialisation");
    return;
  }
  Serial.println("Initialisation OK.");
  myFile = SD.open("numero.txt");
  if (myFile) {
    Serial.println("Contenu du fichier:");

    for (int i = 0; i < 13; i++ )
    {
      myFile.seek(i); // se positionne à la position i
      numero0 = numero0 + char(myFile.peek()); // affiche le caractère courant
    }
    for (int i = 13; i < 27; i++ )
    {
      myFile.seek(i); // se positionne à la position i
      numero1 = numero1 + char(myFile.peek()); // affiche le caractère courant
    }
   

    myFile.close(); // ON FERME
  }
  else {
    Serial.println("impossible d'ouvrir le fichier pour la lecture"); // Défaut de fichier

  }
}








   


Title: Re: les string me rendent fou ! :)
Post by: fredo5962 on Mar 27, 2019, 02:42 pm
l'horreur .... incomprenhensible....

je rajoute un petit test .

if (numero0!=numero1){
Serial.println("numero différent...");}

if (numero0==numero1){
Serial.println("numero identique...");}


et il m'affiche sans la moindre honte...


+33786000000

+33786000000
numero différent...
Title: Re: les string me rendent fou ! :)
Post by: CelticLord on Mar 27, 2019, 02:52 pm
Bonjour, déjà evite d utiliser des String, utilise plutôt des tableaux de char numero0 char[13]
Title: Re: les string me rendent fou ! :)
Post by: fdufnews on Mar 27, 2019, 02:57 pm
Le problème de print c'est qu'il n'affiche que les caractères imprimable. S'il y a des caractères de contrôle ils ne sont pas visibles.Il vaut mieux faire
Code: [Select]
Serial.print("**");
[Serial.print(numero0);
Serial.print("**");
comme ça tu verras s'il y a des caractères cachés.
Ou bien faire imprimer la chaîne caractère par caractère en hexa pour voir s'il n'y aurais pas un code non imprimable
Title: Re: les string me rendent fou ! :)
Post by: dbrion06 on Mar 27, 2019, 03:08 pm
Code: [Select]
    for (int i = 0; i < 13; i++ )
    {
      myFile.seek(i); // se positionne à la position i
      numero0 = numero0 + char(myFile.peek()); // affiche le caractère courant
    }


deviendrait, pour censurer les caractères non imprimables

Code: [Select]
    for (int i = 0; i < 13; i++ )
    {
      myFile.seek(i); // se positionne à la position i
      char c = myFile.peek();
      if (((c <= '9') && (c>= '0') ) || (c == '+')) {
      numero0 = numero0 + c; // affiche le caractère courant
    } else {
     Serial.print("<"); Serial.print(c);Serial.println(">"); // pour voir si le test est suffisant
    }
Title: Re: les string me rendent fou ! :)
Post by: fredo5962 on Mar 27, 2019, 03:31 pm
hey hey hey... ouiiiiiiii vous avez raison !

j'ai rajouté
 Serial.println(numero0.length());

Serial.println(numero1.length());


+33786000000

longueur de numéro 0... : 13
+33786000000
longueur de numéro 1... : 12

on dirait qu'il y a un 'enter' .. invisible !
je vois pour virer ce truc...
Title: Re: les string me rendent fou ! :)
Post by: dbrion06 on Mar 27, 2019, 03:34 pm
"je vois pour virer ce truc..."
ne concaténez que des caractères lisibles, ou mieux, faisant partie des caractères admissibles pour les téléphones : '0' à '9' et '+', manifestement...
Title: Re: les string me rendent fou ! :)
Post by: fredo5962 on Mar 27, 2019, 03:57 pm
Franchement.. BRAVO !
vous êtes genial ...
j'ai utilisé votre filtre de caracteres lors du chargement du fichier... et ca fonctionne parfaitement !

genial genial genial !!!!

merciiiiiiii

Title: Re: les string me rendent fou ! :)
Post by: CelticLord on Mar 27, 2019, 04:15 pm
C est tjs le problème avec la déclaration String elle n est pas fiable.
C est la notion de pointeurs en langage C qu il faut bien intégrer et utiliser les char array a la place de String.
Ta différente dans la longueur de ta chaine vient du fait que numero0 contient certainement la caractère \0 au 13eme byte et pas l autre.
De plus ta comparaison de chaine avec un = ne donnera pas de bon résultat car tu compare des pointeurs pas des chaines, approfondi tout ca pour tes futurs codes.
Title: Re: les string me rendent fou ! :)
Post by: fredo5962 on Mar 27, 2019, 04:22 pm
oh que oui tu as raison, je reve de m'en passer !!

mais la concretement dans ce programme, comment je peux les remplacer ?
Title: Re: les string me rendent fou ! :)
Post by: -Standby on Mar 27, 2019, 04:59 pm
Quote
les string me rendent fou ! :)
Quote
l'horreur .... incomprenhensible....
Quote
Bonjour, déjà evite d utiliser des String
Quote
"je vois pour virer ce truc..."
Quote
Franchement.. BRAVO !
Quote
oh que oui tu as raison, je reve de m'en passer !!
Je sors ---> []
Title: Re: les string me rendent fou ! :)
Post by: dbrion06 on Mar 27, 2019, 05:10 pm
Quote
mais la concretement dans ce programme, comment je peux les remplacer
Une saine et sensée critique des strings et des solutions pour les remplacer (lire char aptès char un fichier ou une ligne série est équivalent) est dans https://forum.arduino.cc/index.php?topic=500683.0 (https://forum.arduino.cc/index.php?topic=500683.0)
les charactères arrivent l'un après l'autre, sont mis dans un tableau de caractères s'ils sont valides, et à la fin (matérialisée par une fin de ligne dans un fichier ou sur une ligne série), on les exploite. La théorie sous jacente est exposée avec talent et des liens judicieux.

la réponse courte est donc : un tableau de 13 ou 14 charactères, terminés par \0 ;
Title: Re: les string me rendent fou ! :)
Post by: fredo5962 on Mar 27, 2019, 06:47 pm
 :o après une lecture reposée... j'ai RIEN compris du tout... sauf que char prend la moitié de place que string... mais ca... au final je m'en doutais déjà!

bref, j'ai essayé de modifier les strings en char
comme ceci .

string numero0; est devenu char numero0[12];
12 caracteres pour +33786000000
jusque la ... ca va ;)

ensuite, j'ai modifié logiquement la facon de recupérer les données.

j'ai donc fait ceci :

for (int i=0; i<13; i++ )
  {
           myFile.seek(i); // se positionne à la position i
           char c = myFile.peek();
      if (((c <= '9') && (c>= '0') ) || (c == '+')) {
     
      numero0 [ i ] = c;
     
      }
         }

si ca fonctionne comme un tableau..
numero0[0] = premier caractère
numero0[1] = deuxième caractère

je dirai que jusque la... ca va !

confiant, je fais la mm chose pour la suite !


en rajoutant juste une variable pour toujours remplir à partir de 0;

voici ce que ca donne .

count=0;
 for (int i=13; i<27; i++ )
  {
           myFile.seek(i); // se positionne à la position i
           char c = myFile.peek();
      if (((c <= '9') && (c>= '0') ) || (c == '+')) {
      count=i-13;
      numero1[count] = c;
     
      }
         }

et je vous laisse deviner le résultat...
numero1.... grave à l'ouest !!

résultat affiché :


dans la boucle de lecture, numero 0 : +33700000000
dans la boucle de lecture, numero 1 :


bref.... char ou string.... c'est une galère !


Title: Re: les string me rendent fou ! :)
Post by: dbrion06 on Mar 27, 2019, 06:59 pm
Déjà, vous devriez donner un peu plus de place que 12 à vos tableaux de caractères, qui doivent avoir, tout à la fin, le caractère \0 ou 0;

Code: [Select]

char numero0[14], numero1[14];// très légèerment surdimensionnés
int indicenum = 0;
for (int i = 0; i<13; i++ ) {
      myFile.seek(i); // se positionne à la position i
      char c = myFile.peek();
// filtrage et remplissage  si possible
      if (((c <= '9') && (c>= '0') ) || (c == '+')) {
             numero0[indicenum] = c;
             indicenum ++; // prêt à écrire dans le suivant
      }
   }
 numero0[indicenum]  = 0; // est terminé effectivement
indicenum = 0;
 for (int i=13; i<27; i++ )  {
    myFile.seek(i); // se positionne à la position i
    char c = myFile.peek();
     if (((c <= '9') && (c>= '0') ) || (c == '+')) {
      numero1[indicenum ] = c;
      indicenum ++;
      }
    }
 numero1[indicenum]  = 0;

(non testé) devrait marcher -en tous cas, serait plus voisin de la gestion des caractères classique
Title: Re: les string me rendent fou ! :)
Post by: hbachetti on Mar 27, 2019, 07:21 pm
1ère remarque : seek ne sert à rien

Quand tu ouvres un fichier, l'index vaut zéro.
Ensuite tu utilises read(), à chaque caractère lu, l'index s'incrémente, donc au prochain read() tu liras le caractère suivant, automatiquement.

Exemple ici : https://github.com/greiman/SdFat/blob/master/examples/ReadWrite/ReadWrite.ino (https://github.com/greiman/SdFat/blob/master/examples/ReadWrite/ReadWrite.ino)

Ligne 61 : ouverture d'un fichier, lecture et affichage.

Un petit myFile.available() avant de lire ne fait pas de mal non plus, pour savoir si le fichier contient encore des données.

2ème remarque : on termine toujours une chaîne de caractères par un caractère NULL (zéro binaire), ce que tu ne fais pas.

3ème remarque : tu lis deux numéros
- index 0 à 12
- index 13 à 26

Si les numéros sont sur deux lignes distinctes dans le fichier, il y a forcément un séparateur entre les deux ('\n' ou "\r\n")

Si tu commençais par poster le contenu du fichier, tu ne crois pas que ce serait une bonne idée ?

Title: Re: les string me rendent fou ! :)
Post by: fredo5962 on Mar 28, 2019, 06:37 am
Hello

pour répondre à dbrion06.

merci beaucoup de ton aide et de m'éclairer ! j'avais utilisé 12 car lorsque j'utilisais la fonction length sur le string qui contenait le numéro de telephone, il me retournait 12.. donc j'ai pas cherché plus loin :)

effectivement je ne rajoute pas un 0 à la fin... mais pourquoi le faire ?? mon numéro de telephone aura un 0 en plus à la fin et quand j'appelle numero0 ou numero1, je vais me retrouver avec un 0 a la fin qui sert à rien ??
ou alors je dois utiliser à la fin un string du genre ...
numerofinal = numero0[1]+numero0[2]....jusque + numero0[12]

ou alors il y a une solution pour lorsque j'appelle numero0 il me donne tout sauf le 0 de la fin ? concact ?

pour répondre à hbachetti,

merci de ton aide également, en fait le seek me sert à positionner le début de la chaîne que je veux lire, car je ne cherche pas à l'afficher, je cherche à le lire et à le stocker pour l'utiliser ensuite comme numéro de téléphone.

le fichier lu est un fichier on ne peut plus basique créé avec note de Windows ou les numéros sont les uns en dessous des autres....

cela dit... maintenant que tu le dis... s'ils sont les un en dessous des autres.... il y aurait bien un caractère caché qui le dit quelque part... sinon ils seraient les uns a la suite des autres....

numero.txt


+33796000000
+33900000000
etc...


vraiment désolé de vous embêter avec ca.. mais je débute et comme j'apprends tout seul... bref... heureusement que vous êtes la à m'aider !
Title: Re: les string me rendent fou ! :)
Post by: dbrion06 on Mar 28, 2019, 08:17 am
"effectivement je ne rajoute pas un 0 à la fin... mais pourquoi le faire ??"
Parce que que les tableaux de caractères c DOIVENT se terminer par le charactère de valeur entière 0 (\0), sinon, les fonctions de manipulation -calcul de la longueur, affichage, conversion en string- donnent des résultats bizarres... Comme, à l'initialisation, un tableau de chars peut être rempli de caractères nuls, cette nécessité peut être cachée, donnant l'illusion qu'un bout de code marche... mais il vaut mieux le faire explicitement.
En passant, il ne faut pas confondre un caractère et son équivalent entier; exemple, le caractère 'a' a pour valeur, en entier 97 -en decimal- ou 0x61 -en hexa-; le caractère '9' a pour representation entière 57, 0x39 et le carctère '0' est codé en 48 -0x30-
Code: [Select]

sh-4.1$ python
ordPython 2.7.3 (default, Dec 18 2012, 13:50:09)
[GCC 4.5.3] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
(>>> ord('a')
97
>>> ord('9')
57
>>> ord('0')
48
>>> chr(0x39)
'9'
>>> chr(0x30)
'0'



HBachetti vous indique une piste bien plus prometteuse que le fait de  sauter des caractères cachés (et on ne sait pas comment faire, sans bricoler, pour lire , disons, les 3 derniers numéros de téléphone; avec une lecture plus standard de votre fichier, c'est plus facile.
A noter que si votre fichier a été créé sous windows, il y a 2 caractères cachés pour le changement de ligne : \n -10 - et \r -13  (on les montre généralement comme ça...). Sous linux, il n'y en a qu'un (donc, les fichiers texte crées sous GNUlinux peuvent parfois sembler bizarres à des applications d'un autre système).
Il est vraisemblable (mais encore une fois, sans le fichier, on doit faire des paris) que l'on saute les fins de ligne -qui sont des caractères cachés-. A noter enfin que le filtrage que j'utilise fait un pari sur la liste des caractères valides pour les numéros de téléphone (la démarche de HBachetti est plus rationnelle, même si elle "marche" peut être un peu moins vite au début)
Title: Re: les string me rendent fou ! :)
Post by: J-M-L on Mar 28, 2019, 08:42 am
Si les Nos sont sur 2 lignes, Idéalement on devrait lire (avec read) jusqu'au '\n' en ignorant un éventuel '\r' et en filtrant peut-être les caractères non voulus, et ne pas faire d'hypothese Sur la longueur exacte du numéro, juste sur sa taille Max. S'ils sont sur la même ligne il doit y avoir un séparateur et faut lire jusqu'à tomber sur ce séparateur
Title: Re: les string me rendent fou ! :)
Post by: hbachetti on Mar 28, 2019, 11:30 am
Quote
merci de ton aide également, en fait le seek me sert à positionner le début de la chaîne que je veux lire, car je ne cherche pas à l'afficher, je cherche à le lire et à le stocker pour l'utiliser ensuite comme numéro de téléphone.
1ère chose avant d'apprendre à coder : apprendre à lire

Quote
Quand tu ouvres un fichier, l'index vaut zéro.
Ensuite tu utilises read(), à chaque caractère lu, l'index s'incrémente, donc au prochain read() tu liras le caractère suivant, automatiquement.
Quote
il y aurait bien un caractère caché qui le dit quelque part... sinon ils seraient les uns a la suite des autres....
Oui, ces caractères sont des retours à la ligne et des retours chariot comme dans un traitement de texte.
Lire exactement 12 caractères dans le fichier, 2 fois de suite, n'est pas la bonne méthode.

Pourquoi ?
Parce que le caractère que tu vas lire en 13è position est un retour à la ligne '\n'.
En 14è position tu auras probablement un retour chariot '\r'.

Il faut lire le fichier jusqu'à la fin :
   si tu rencontres '\n' tu mets un '\0' en bout de chaîne
   si tu rencontres '\r' tu ignores

Quand on lit dans un fichier on vérifie en permanence que l'on n'a pas atteint la fin :

Code: [Select]

    while (myFile.available()) {
      char c = myFile.read();


Title: Re: les string me rendent fou ! :)
Post by: fredo5962 on Mar 28, 2019, 03:22 pm
Re,
J'ai beau chercher.. J'ai même fait afficher caractère par caractère... Y a jamais un / suivi d'un N ??!?....

Ensuite j'ai bien compris le read qui avance pas à pas... Donc au pire étant donné que je connais le format des numéros.... Des que je tombe sur un +c'est le début de mon numéro et il est suivi de 11 chiffres.. Et ça ne sera toujours que 11 chiffres ! Ils vont quand mm pas me rajouter des fintes dans mes numéros... Après le reste je l'ignore... Je fais des read dans le vide et j'attends de tomber sur le prochain +...

Je rajouterai un / et un O pour voir... (Mais j'ai bien peur de galèrer à les retirer) avec ça à la fin de mes numéros.. Mais j'avance.. C'est bien ça le principal.. Et ça c'est grâce à vous !. Merciiiiiiii
Title: Re: les string me rendent fou ! :)
Post by: fdufnews on Mar 28, 2019, 04:34 pm
J'ai beau chercher.. J'ai même fait afficher caractère par caractère... Y a jamais un / suivi d'un N ??!?....
un print n'affiche pas \n. Le \n c'est une manière d'insérer dans une chaîne de caractère le fait que l'on veut faire passer la suite du texte à la ligne suivante. Lorsque le compilateur rencontre \n dans une chaîne de caractères il lui substitue le code ASCII 10. Le code ASCII 10 lorsqu'il est envoyé à une console est interprété comme un saut de ligne.
De même \r, correspond à "return" et il est remplacé par le code ASCII 13 par le compilateur.

Je rajouterai un / et un O pour voir... (Mais j'ai bien peur de galèrer à les retirer) avec ça à la fin de mes numéros.. Mais j'avance.. C'est bien ça le principal.. Et ça c'est grâce à vous !. Merciiiiiiii
\0 (zéro pas O) permet d'encoder dans une chaîne de caractère le code ASCII 0. Ce n'est pas une fantaisie de notre part c'est obligatoire pour que les fonctions de traitement de chaînes de caractères puissent fonctionner correctement. Le code ASCII 0 marque la fin d'une chaîne, c'est ce qui permet par exemple à la méthode length() de connaitre la longueur d'une chaîne de caractères.
Title: Re: les string me rendent fou ! :)
Post by: hbachetti on Mar 28, 2019, 05:12 pm
Avec un bout de code tu comprendras peut-être mieux :

Code: [Select]

#include <SPI.h>
#if defined ESP32
#include <FS.h>
#endif
#include <SD.h>

#define FILENAME "/numero.txt"

char *str = "+33796000000\n+33900000000\n+33989780000\n+33900333300\n+33900678900\n+33912340000\n";

void setup() {
  Serial.begin(115200);

  Serial.print("Initializing SD card...");

  if (!SD.begin(5)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  if (!SD.exists(FILENAME)) {
    Serial.println("numero.txt missing");
    File myFile = SD.open(FILENAME, FILE_WRITE);
    if (myFile) {
      Serial.print("Writing to numero.txt...");
      myFile.println(str);
      myFile.close();
      Serial.println("done.");
    } else {
      Serial.println("error opening numero.txt");
    }
  }

#define NUMEROS   10
#define LENGTH    13

  if (!SD.exists(FILENAME)) {
    Serial.println("numero.txt missing");
  }
  else {
    Serial.println("Reading numero.txt...");
    char numero[NUMEROS][LENGTH];
    File myFile = SD.open(FILENAME);
    if (myFile) {
      int n = 0, i = 0;
      while (myFile.available()) {
        char c = myFile.read();
        if (c == '\n') {
          if (n < NUMEROS && i < LENGTH) {
            numero[n][i] = '\0';
            Serial.print("numero ");
            Serial.print(n);
            Serial.print(": ");
            Serial.println(numero[n]);
            i = 0;
            n++;
          }
        }
        else if (c != '\r') {
          if (n < NUMEROS && i < LENGTH - 1) {
            numero[n][i++] = c;
          }
        }
      }
      myFile.close();
    } else {
      Serial.println("error opening numero.txt");
    }
  }
}

void loop() {
}


C'est un exemple que j'avais écrit pour un ESP32, mais il se compile sur un ARDUINO.

Le chipSelect est 5. Remplace par 10 pour ton cas.

Il lit 10 lignes dans un fichier. Je l'ai légèrement adapté en remplaçant les noms de variables et le nom du fichier.

Title: Re: les string me rendent fou ! :)
Post by: fredo5962 on Mar 28, 2019, 09:04 pm
re,

oui la c'est bon j'ai compris... franchement superbe ce bout de code..c'est vraiment agreable à lire et facile à comprendre ! j'ai compris la logique et maintenant c'est clair dans ma tete..
merci encore pour vous explication.

bonne soirée
Title: Re: les string me rendent fou ! :)
Post by: hbachetti on Mar 28, 2019, 11:00 pm
Je t'en prie.
On n'est pas toujours aussi généreux.
Ça traînait dans un fond de tiroir.

Ça marche au moins ?

Je n'ai pas essayé sur un ARDUINO, mais seulement sur un ESP32 il y a quelque temps déjà.