probleme avec un String

bonjour,

je sèche sur un problème simple en apparence, voila:

je fais un "Serial.readString" et j'aimerai retransmettre ce String via "RCSwitch" sous la forme :" mySwitch.switchOn("11111", "00010") " (ce qui serai donc le retour d'une lecture serie de "1111100010")

scinder un string, ça, ça va.

le probleme est que lorsqu'un ensemble commence avec un ou des zéro il ne les prend pas en compte.

si on prend l'exemple suivant de lecture serie "0011110000" je n'arrive a afficher que "111" en premiere partie et "10000" en seconde.

l'un d'entre vous aurai une solution ou au moins un piste ??

par avance merci.

Postez un bout de code pour montrer ce que vous faites

Vous recevez vraiment des 1 et des 0 en ASCII ou c’est la représentation binaire et en fait vous avez lu un nombre ?

bonjour, merci de l'interet mais depuis j'ai contourné le probleme en utilisant un autre codage pour rcswitch qui n'utilise pas de 0 dans ses commandes.

pour répondre néanmoins, cette suite de 0 et de 1 sont (etaient) tapés au clavier dans le moniteur serie (en vue d'etre pas la suite connecté a un raspberry pi avec node-red).

toutefois, si vous avez une piste pour mon problème de 0 et de 1 je suis toujours partant pour apprendre (enfin mon niveau étant assez faible il me faut des choses simples).

bien a vous.

Perso je n’utiliserais pas la classe String.... jetez un œil éventuellement à mon tuto
Ecouter le Port Série ou un keypad

Une fois la ligne dans le buffer d’entrée utiliser les fonctions de manipulations de cStrings (stdlib.h et string.h) pour extraire les sous chaînes

J-M-L:
Perso je n’utiliserais pas la classe String...

Je confirme : un bon vieux slip c'est plus confortable...

(ok, je sors)

:slight_smile:

lesept:
Je confirme : un bon vieux slip c'est plus confortable...

(ok, je sors)

:smiley: :smiley:

je serai plutot caleçon...

J-M-L:
Perso je n’utiliserais pas la classe String.... jetez un œil éventuellement à mon tuto
Ecouter le Port Série ou un keypad

Une fois la ligne dans le buffer d’entrée utiliser les fonctions de manipulations de cStrings (stdlib.h et string.h) pour extraire les sous chaînes

merci pour ce tuto, je vais m'y pencher et voir si j'arrive a l'appliquer a mon projet (mais pas tout de suite, les 2 jours a venir sont chargés) et aussi voir si j'aarive sans trop de difficultés a integrer votre solution a mon code qui est, avec le peu de connaissances et de compréhension du C, deja assez complexe (entre la communication bi-directionnelle rs485 et serie (avec node-red sur raspberry) et le rf433).

au passage voici la solution que j'ai mis en oeuvre, elle n'est peut-etre pas élégante mais elle a le merite de fonctionner et de venir a 100% de ma reflexion perso (et donc pas d'un simple copier/coller) :

if(Serial.available())
  {
    comFull = Serial.readString();

comA=comFull.substring(0,2);
comB=comFull.substring(2,4);
comC=comFull.substring(4,5);
comD=comFull.substring(5,6);
comE=comFull.substring(6,7);
comF=comFull.substring(7,8);
comG=comFull.substring(8,9);
comH=comFull.substring(9,10);
comI=comFull.substring(10,11);
comJ=comFull.substring(11,12);
comK=comFull.substring(12,13);
comL=comFull.substring(13,14);

if (comA == "00")
{
  if (comE == "0")
  E = 0;
  else if (comE == "1")
  E = 1;
  else if (comE == "2")
  E = 2;
  else if (comE == "3")
  E = 3;
  else if (comE == "4")
  E = 4;
  else if (comE == "5")
  E = 5;
  else if (comE == "6")
  E = 6;
  else if (comE == "7")
  E = 7;
  else if (comE == "8")
  E = 8;
  else if (comE == "9")
  E = 9;
  else E = 0;

  if (comF == "0")
  F = 0;
  else if (comF == "1")
  F = 1;
  else if (comF == "2")
  F = 2;
  else if (comF == "3")
  F = 3;
  else if (comF == "4")
  F = 4;
  else if (comF == "5")
  F = 5;
  else if (comF == "6")
  F = 6;
  else if (comF == "7")
  F = 7;
  else if (comF == "8")
  F = 8;
  else if (comF == "9")
  F = 9;
  else F = 0;

  if (comG == "0")
  G = 0;
  else if (comG == "1")
  G = 1;
  else if (comG == "2")
  G = 2;
  else if (comG == "3")
  G = 3;
  else if (comG == "4")
  G = 4;
  else if (comG == "5")
  G = 5;
  else if (comG == "6")
  G = 6;
  else if (comG == "7")
  G = 7;
  else if (comG == "8")
  G = 8;
  else if (comG == "9")
  G = 9;
  else G = 0;

  if (comH == "0")
  H = 0;
  else if (comH == "1")
  H = 1;
  else if (comH == "2")
  H = 2;
  else if (comH == "3")
  H = 3;
  else if (comH == "4")
  H = 4;
  else if (comH == "5")
  H = 5;
  else if (comH == "6")
  H = 6;
  else if (comH == "7")
  H = 7;
  else if (comH == "8")
  H = 8;
  else if (comH == "9")
  H = 9;
  else H = 0;

  if (comI == "0")
  I = 0;
  else if (comI == "1")
  I = 1;
  else if (comI == "2")
  I = 2;
  else if (comI == "3")
  I = 3;
  else if (comI == "4")
  I = 4;
  else if (comI == "5")
  I = 5;
  else if (comI == "6")
  I = 6;
  else if (comI == "7")
  I = 7;
  else if (comI == "8")
  I = 8;
  else if (comI == "9")
  I = 9;
  else I = 0;

  if (comJ == "0")
  J = 0;
  else if (comJ == "1")
  J = 1;
  else if (comJ == "2")
  J = 2;
  else if (comJ == "3")
  J = 3;
  else if (comJ == "4")
  J = 4;
  else if (comJ == "5")
  J = 5;
  else if (comJ == "6")
  J = 6;
  else if (comJ == "7")
  J = 7;
  else if (comJ == "8")
  J = 8;
  else if (comJ == "9")
  J = 9;
  else J = 0;

  if (comK == "0")
  K = 0;
  else if (comK == "1")
  K = 1;
  else if (comK == "2")
  K = 2;
  else if (comK == "3")
  K = 3;
  else if (comK == "4")
  K = 4;
  else if (comK == "5")
  K = 5;
  else if (comK == "6")
  K = 6;
  else if (comK == "7")
  K = 7;
  else if (comK == "8")
  K = 8;
  else if (comK == "9")
  K = 9;
  else K = 0;

  if (comL == "0")
  L = 0;
  else if (comL == "1")
  L = 1;
  else if (comL == "2")
  L = 2;
  else if (comL == "3")
  L = 3;
  else if (comL == "4")
  L = 4;
  else if (comL == "5")
  L = 5;
  else if (comL == "6")
  L = 6;
  else if (comL == "7")
  L = 7;
  else if (comL == "8")
  L = 8;
  else if (comL == "9")
  L = 9;
  else L = 0;

  RRF=(1000000*F);
  RRG=(100000*G);
  RRH=(5000*H);
  RRH=RRH*2;
  RRI=(1000*I);
  RRJ=(100*J);
  RRK=(10*K);
  RRL=L;
  RRZ = RRF+RRG+RRH+RRI+RRJ+RRK+RRL;

  {
    if (E == 1)
    {
     mySwitch.send((RRZ),24);
     
     }
    
  }
}

je précise aussi que mon prog n'est pas finalisé ni épuré (genre les parenthèses dans les calculs).

tant que j'y pense, une curiosité est apparue, dons mon code, si je fais directement "RRH=H*10000" j'obtient un résultat négatif alors même que "H" est un entier positif (4 par exemple).
j'ai donc encore une fois contourné en scindant le calcul en deux et la ça fonctionne nickel.

merci de votre aide.

Vous pourrez simplifier énormément tout cela sans les Strings

Par exemple si vous avez un char c = ‘5’; alors pas besoin de faire plein de if pour trouver sa valeur numérique 5

char c = ‘5’;
byte v =0;
if (c >= ‘0’ && c <= ‘9’) v = c - ‘0’; // v vaudra 5

suffit...

Pour les Strings avec une majuscule il y a la fonction [url=https://www.arduino.cc/reference/en/language/variables/data-types/string/functions/toint/]toInt()[/url] que vous pouvez appeler et au lieu de faire

  if (comE == "0")
  E = 0;
  else if (comE == "1")
  E = 1;
  else if (comE == "2")
  E = 2;
  else if (comE == "3")
  E = 3;
  else if (comE == "4")
  E = 4;
  else if (comE == "5")
  E = 5;
  else if (comE == "6")
  E = 6;
  else if (comE == "7")
  E = 7;
  else if (comE == "8")
  E = 8;
  else if (comE == "9")
  E = 9;
  else E = 0;

vous pouvez faire E = comE.toInt();c’est plus court non? :wink:

Sinon comme on ne voit pas le type de vos variables genre RRF difficile de dire si vous n’aurez pas un bug

Oui, le problème de signe doit venir du type de variable choisi pour RRH, tu peux le déclarer 'unsigned long' pour éviter tout problème ou 'float'

lesept:
Oui, le problème de signe doit venir du type de variable choisi pour RRH, tu peux le déclarer 'unsigned long' pour éviter tout problème ou 'float'

Pas que changer le type.... Faudrait aussi écrire RRF=(1000000[color=red]UL[/color]*F); (idem pour les autres) pour forcer le calcul en unsigned long et éviter le rollover

tenez voici un exemple effectué à partir du code de mon tuto mentionné plus haut

const byte tailleMessageMax = 15;
char message[tailleMessageMax + 1]; // +1 car on doit avoir un caractère de fin de chaîne en C, le '\0'

const char marqueurDeFin = '\n';

boolean ecouter()
{
  static byte indexMessage = 0; // static pour se souvenir de cette variable entre 2 appels consécutifs. initialisée qu'une seule fois.
  boolean messageEnCours = true;

  while (Serial.available() && messageEnCours) {
    int c = Serial.read();
    if (c != -1) {
      switch (c) {
        case marqueurDeFin:
          message[indexMessage] = '\0'; // on termine la c-string
          indexMessage = 0; // on se remet au début pour la prochaine fois
          messageEnCours = false;
          break;
        case '\r': // on ignore le \r
          break;
        default:
          if (indexMessage <= tailleMessageMax - 1) message[indexMessage++] = (char) c; // on stocke le caractère et on passe à la case suivante
          else Serial.println(F("j'ignore!"));
          break;
      }
    }
  }
  return messageEnCours;
}

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

void loop() {
  if (! ecouter()) {
    // on a reçu le marqueur de fin
    Serial.print(F("Phrase: [")); Serial.print(message); Serial.println(F("]"));
    if (strlen(message) >= 10) { // on attend un code du genre 1111100010
      char buf1[6], buf2[6];
      memcpy(buf1, message, 5); // on copie les 5 premiers octets dans buf1
      buf1[5] = '\0'; // on termine buf1 par un caractère nul pour faire une cString
      memcpy(buf2, message + 5, 5); // on copie les 5  octets suivants dans buf2
      buf2[5] = '\0'; // on termine buf2 par un caractère nul pour faire une cString

      // ICI buf1 et buf2 sont utilsables pour faire
      // mySwitch.switchOn(buf1, buf2);

      // ici j'imprime juste pour montrer ce que ça donne
      Serial.print(F("mySwitch.switchOn(\""));
      Serial.print(buf1);
      Serial.print(F("\",\""));
      Serial.print(buf2);
      Serial.println(F("\");"));
    } else Serial.println(F("MESSAGE TROP COURT"));
  }

  // ici on peut faire autre chose

}

si je charge ce code et que j'ouvre la console série (configurée à 115200 bauds et envoyant \n ou \r\n quand on valide une entrée) et que je tape 01234ABCDE et que je valide, la console série me dit

[sub][color=purple]Phrase: [01234ABCDE]
mySwitch.switchOn("01234","ABCDE");
[/color][/sub]

On voit donc bien qu'on a correctement découpé les blocs de 5 caractères (octets)

et si je tape COUCOU, la console me dit

[sub][color=purple]Phrase: [COUCOU]
MESSAGE TROP COURT[/color][/sub]

parce que le code test si on a reçu au moins 10 caractères par le testif (strlen(message) >= 10) { (le buffer peut en comprendre 15 - défini par tailleMessageMax)

bonjour,

merci pour votre aide.

@J-M-L, nickel ce "toInt", ça me simplifie la vie (et économise des lignes)

pour ce qui est de mes différents types de variables, j'ai :

"string" pour les "comX"
"int" pour les "X"
"double" pour les "RX"
et "long" pour les "RRX"

je vais essayer de passer les "RRX" en "unsigned long".

un grand merci a vous deux.