Problema con Serial.readString();

Ciao a tutti , avrei bisogno di aiuto per un problema con Serial.readString.
Ho ripreso in mano un piccolo programma che aveo fatto per irrigare il giardino composto da arduino nano,rtc, e modulo bluetooth. Il funzionamento era semplice , i tempi ora, minuti ecc...era scritti fissi sulla dichiarazione delle variabili e con il modulo bluetooth attiva o disattivavo le zone inviando un messaggio.
Volevo implementare la possibilita di cambiare ora, minuti inviando una messaggio e con indexOf estrane il valore.
Il mio problema è che la lettura dalla seriale software della stinga è sempre senza il primo valore, per esempio se invio "abcdef"....leggo bcdef.
Potreste aiutarmi a capire dove sbaglio.
Questo è una parte di scketh.
Grazie

#include <SoftwareSerial.h>
#define  SS_RX 3            // RX PIN to receive  data
#define  SS_TX 4            // TX PIN to transmit data

////////////  filo rx del modulo bluetooth al pin 4 arduino
///////////   filo tx del modulo bluetooth al pin 3 arduino

SoftwareSerial ssSerial(SS_RX, SS_TX);

#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 RTC;

String message= "";                  
String messageValore = "";
String SerialssString = "";

const int Input6 = 6;
const int Input7 = 7;
const int Input8 = 8;

const int Output9 = 9;
const int Output10 = 10;
const int Output11 = 11;
const int Output12 = 12;


// variabili boolean

boolean irrattivaZ1t1 ;
boolean irrattivaZ1t2 ;
boolean irrattivaZ1t3 ;
boolean irrattivaZ2t1 ;
boolean irrattivaZ2t2 ;
boolean irrattivaZ2t3 ;

boolean solo1volta;
boolean z1onManuale;
boolean z2onManuale;
boolean timerz1attivo;
boolean timerz2attivo;

// variabili INT

int secondi;
int minuti;
int ora; 
int giorno; 
int mese; 
int anno; 
int giornosett;
int val=0;

////////////////////  timer zona 1

// z1 tempo 1
int z1t1ora;
int z1t1minuti;
int z1t1dur ;

// z1 tempo 2 
int z1t2ora;
int z1t2minuti;
int z1t2dur;

// z1 tempo 3 
int z1t3ora;
int z1t3minuti;
int z1t3dur;

////////////////////  timer zona 2

// z2 tempo1
int z2t1ora;
int z2t1minuti;
int z2t1dur;

// z2 tempo 2
int z2t2ora;
int z2t2minuti;
int z2t2dur;

// z2 tempo 3
int z2t3ora;
int z2t3minuti;
int z2t3dur;


void setup(){

pinMode(Input6, INPUT_PULLUP);
pinMode(Input7, INPUT_PULLUP);  
pinMode(Input8, INPUT_PULLUP);

pinMode(Output9, OUTPUT);
pinMode(Output10, OUTPUT);
pinMode(Output11, OUTPUT);
pinMode(Output12, OUTPUT);

digitalWrite(Output9, HIGH);
digitalWrite(Output10, HIGH);
digitalWrite(Output11, HIGH);
digitalWrite(Output12, HIGH);

Serial.begin(38400);        // Initialize USB Serial port
ssSerial.begin(38400);      // Initialize SoftwareSerial port


Wire.begin();
RTC.begin();
// la riga seguente imposta  rtc alla ora e data di compilazione
//RTC.adjust(DateTime(__DATE__, __TIME__)); 
}


void loop(){

///////////////////////////////////////////////////////////////////////////////////////////////
//                                  RTC DS1307                                                          
///////////////////////////////////////////////////////////////////////////////////////////////

DateTime now = RTC.now();
secondi = now.second();
minuti = now.minute();
ora = now.hour();
giorno = now.day();
mese = now.month();
anno = now.year();

/////////////// /////////////////////////////////////////////// LETTURA MESSAGGI BLUETOOTH///////////////////////////////////////////////////
  
  while(ssSerial.available()){
  message+=char(ssSerial.read()); 
  SerialssString = ssSerial.readString();    
  }
    
///////////////////////////////////////////////////////////// LETTURA E IMPOSTAZIONI VARIABILI /////////////////////////////////////////////     
////////////////////ZONA1

// Zona1 Timer1 ORA , MINUTI , DURATA
     if (SerialssString.indexOf("z1t1h") > 0) {     
         val = SerialssString.indexOf("z1t1h");
         messageValore = SerialssString.substring(val + 1, val + 5);
         z1t1ora = (messageValore.toInt());
         }     
     if (SerialssString.indexOf("z1t1m") > 0) {     
         val = SerialssString.indexOf("z1t1m");
         messageValore = SerialssString.substring(val + 1, val + 5);
         z1t1minuti = (messageValore.toInt());
         }     
      if (SerialssString.indexOf("z1t1d") > 0) {     
         val = SerialssString.indexOf("z1t1d");
         messageValore = SerialssString.substring(val + 1, val + 5);
         z1t1dur = (messageValore.toInt());
         }        
  
//////////////////////////////////////////////////////////////// ATTIVAZIONI ZONA 1///////////////////////////////////////////////////////

// ATTIVA IRRIGAZIONE ZONA 1 T1      
       if(message == "t1z1on"){
          irrattivaZ1t1 = true;
      } 
// DISATTIVA IRRIGAZIONE ZONA 1 T1       
       if(message == "t1z1off"){
          irrattivaZ1t1 = false;
      }    

// ATTIVA IRRIGAZIONE ZONA 1 T2     
       if(message == "t2z1on"){
          irrattivaZ1t2 = true;
      } 
// DISATTIVA IRRIGAZIONE ZONA 1 T2       
       if(message == "t2z1off"){
          irrattivaZ1t2= false;
      }    

// ATTIVA IRRIGAZIONE ZONA 1 T3      
       if(message == "t3z1on"){
          irrattivaZ1t3 = true;
      }
// DISATTIVA IRRIGAZIONE ZONA 1 T3       
       if(message == "t3z1off"){
          irrattivaZ1t3= false;
      }
while(ssSerial.available()){
  message+=char(ssSerial.read()); 
  SerialssString = ssSerial.readString();    
  }

con char(ssSerial.read()) leggi il primo carattere, poi ovvio che in SerialssString non lo trovi.
Inoltre tu metti la stringa elaborata in messageValore ma il confronto lo fai con messege. Perché?

Se la parte incriminata è questa

while(ssSerial.available()){
  message+=char(ssSerial.read());
  SerialssString = ssSerial.readString();   
  }

è normale che tu perda il primo carattere, lo leggi e lo metti nella variabile message, i successivi li metti in SerialsString.
Se puoi metti un po' di messaggi di debug sul serial monitor e vedi se ho ragione o se non il caso che ti ho indicato
P.S = in contemporanea con @PaoloP quindi a questo punto penso di averci azzeccato :slight_smile:

Lo leggevo in "message" perchè in principio facevo solo la comparazione con =.
Adesso l'ho modificato , eseguo solo "SerialssString = ssSerial.readString();" , ho fatto un debug in serial monitor e la lettura è corretta, infatti nella comparazione "if(SerialssString == "xxxxx") funziona, quello che continua a non funzionare è la parte con IndexOf per estrarre il valore.
Il valore in lettura SerialssString l'ho cancello ogni volta alla fine del loop , per eliminare codici non corretti,cosa sbaglio ancora?
Grazie

#include <SoftwareSerial.h>
#define  SS_RX 3            // RX PIN to receive  data
#define  SS_TX 4            // TX PIN to transmit data

////////////  filo rx del modulo bluetooth al pin 4 arduino
///////////   filo tx del modulo bluetooth al pin 3 arduino

SoftwareSerial ssSerial(SS_RX, SS_TX);

#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 RTC;

String message= "";                  
String messageValore = "";
String SerialssString = "";
String SerialssStringCopy = "";

const int Input6 = 6;
const int Input7 = 7;
const int Input8 = 8;

const int Output9 = 9;
const int Output10 = 10;
const int Output11 = 11;
const int Output12 = 12;


// variabili boolean

boolean irrattivaZ1t1 ;
boolean irrattivaZ1t2 ;
boolean irrattivaZ1t3 ;
boolean irrattivaZ2t1 ;
boolean irrattivaZ2t2 ;
boolean irrattivaZ2t3 ;

boolean solo1volta;
boolean z1onManuale;
boolean z2onManuale;
boolean timerz1attivo;
boolean timerz2attivo;

// variabili INT

int secondi;
int minuti;
int ora; 
int giorno; 
int mese; 
int anno; 
int giornosett;
int val=0;

////////////////////  timer zona 1

// z1 tempo 1
int z1t1ora;
int z1t1minuti;
int z1t1dur ;

// z1 tempo 2 
int z1t2ora;
int z1t2minuti;
int z1t2dur;

// z1 tempo 3 
int z1t3ora;
int z1t3minuti;
int z1t3dur;

////////////////////  timer zona 2

// z2 tempo1
int z2t1ora;
int z2t1minuti;
int z2t1dur;

// z2 tempo 2
int z2t2ora;
int z2t2minuti;
int z2t2dur;

// z2 tempo 3
int z2t3ora;
int z2t3minuti;
int z2t3dur;


void setup(){

pinMode(Input6, INPUT_PULLUP);
pinMode(Input7, INPUT_PULLUP);  
pinMode(Input8, INPUT_PULLUP);

pinMode(Output9, OUTPUT);
pinMode(Output10, OUTPUT);
pinMode(Output11, OUTPUT);
pinMode(Output12, OUTPUT);

digitalWrite(Output9, HIGH);
digitalWrite(Output10, HIGH);
digitalWrite(Output11, HIGH);
digitalWrite(Output12, HIGH);

Serial.begin(38400);        // Initialize USB Serial port
ssSerial.begin(38400);      // Initialize SoftwareSerial port


Wire.begin();
RTC.begin();
// la riga seguente imposta  rtc alla ora e data di compilazione
//RTC.adjust(DateTime(__DATE__, __TIME__)); 
}


void loop(){

///////////////////////////////////////////////////////////////////////////////////////////////
//                                  RTC DS1307                                                          
///////////////////////////////////////////////////////////////////////////////////////////////

DateTime now = RTC.now();
secondi = now.second();
minuti = now.minute();
ora = now.hour();
giorno = now.day();
mese = now.month();
anno = now.year();

/////////////// /////////////////////////////////////////////// LETTURA MESSAGGI BLUETOOTH///////////////////////////////////////////////////
  
  while(ssSerial.available()){
  SerialssString = ssSerial.readString(); 
  }
    
///////////////////////////////////////////////////////////// LETTURA E IMPOSTAZIONI VARIABILI /////////////////////////////////////////////     
////////////////////ZONA1

// Zona1 Timer1 ORA , MINUTI , DURATA
     if (SerialssString .indexOf("z1t1h") > 0) {     
         val = SerialssString .indexOf("z1t1h");
         messageValore = SerialssString .substring(val + 1, val + 5);
         z1t1ora = (messageValore.toInt())
         }     
     if (SerialssString.indexOf("z1t1m") > 0) {     
         val = SerialssString.indexOf("z1t1m");
         messageValore = SerialssString.substring(val + 1, val + 5);
         z1t1minuti = (messageValore.toInt());
         }     
      if (SerialssString.indexOf("z1t1d") > 0) {     
         val = SerialssString.indexOf("z1t1d");
         messageValore = SerialssString.substring(val + 1, val + 5);
         z1t1dur = (messageValore.toInt());
         }        
  

//////////////////////////////////////////////////////////////// ATTIVAZIONI ZONA 1///////////////////////////////////////////////////////

// ATTIVA IRRIGAZIONE ZONA 1 T1      
       if(SerialssString == "t1z1on"){
          irrattivaZ1t1 = true;
      } 
// DISATTIVA IRRIGAZIONE ZONA 1 T1       
       if(SerialssString == "t1z1off"){
          irrattivaZ1t1 = false;
      }    

// ATTIVA IRRIGAZIONE ZONA 1 T2     
       if(SerialssString == "t2z1on"){
          irrattivaZ1t2 = true;
      } 
// DISATTIVA IRRIGAZIONE ZONA 1 T2       
       if(SerialssString == "t2z1off"){
          irrattivaZ1t2= false;
      }    

      }    
//////////////////////////////////////////////////////////////// ATTIVAZIONI ZONA 2///////////////////////////////////////////////////////

// ATTIVA IRRIGAZIONE ZONA 2 T1    
       if(SerialssString == "t1z2on"){
          irrattivaZ2t1 = true;
      } 
// DISATTIVA IRRIGAZIONE ZONA 2 T1      
       if(SerialssString == "t1z2off"){
          irrattivaZ2t1 = false;
      }               


       }  

// ATTIVA IRRIGAZIONE ZONA 2  T3     
       if(SerialssString == "t3z2on"){
          irrattivaZ2t3 = true;
      } 
// DISATTIVA IRRIGAZIONE ZONA 2  T3     
       if(SerialssString == "t3z2off"){
          irrattivaZ2t3 = false;
      }  
       
//// APRI CANCELLO PICCOLO        
       if(SerialssString == "apri"){
          digitalWrite(Output9, LOW);
          delay(800);
           digitalWrite(Output9, HIGH);
           SerialssString=""; //clear the data
      } 
   
//// ZONA 1 MANUALE APERTA
 if(SerialssString == "11"){
          digitalWrite(Output10, LOW);
          z1onManuale = true;
      } 


//// ZONA 1 2 3 MANUALE CHIUSA "STOP"
 if(SerialssString == "stop"){
          digitalWrite(Output10, HIGH);
          z1onManuale = false;

          digitalWrite(Output11, HIGH);
          z2onManuale = false;  
       
      } 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 




 
////////////////////////////////////////////////////////////////////////////////////////////////////////
//// STAMPA IN SERIALE PC E ssSERIALE BLUETOOTH PER VISUALIZZARE LE IMPOSTAZIONI OGNI 10 Sec   
/////////////////////////////////////////////////////////////////////////////////////////////////////////

if (((secondi == 0)&&(solo1volta == false)) || ((secondi == 10)&&(solo1volta == false)) || ((secondi == 20)&&(solo1volta == false)) ||
   ((secondi == 30)&&(solo1volta == false)) || ((secondi == 40)&&(solo1volta == false)) || ((secondi == 50)&&(solo1volta == false))){



////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//// STAMPA IN ssSERIALE BLUETOOTH (ANDROID APP BLUETOOTH HC05)PER VISUALIZZARE LE IMPOSTAZIONI OGNI 10 Sec
////////////////////////////////////////////////////////////////////////////////////////////////////////////////

ssSerial.println("*************************************************************************");  
ssSerial.println ("Versione: IrrNano 1.9");
ssSerial.println("-------------------------------"); 
 
ssSerial.print("Ora: ");
ssSerial.print(ora);
ssSerial.print(':');
ssSerial.print(minuti);
ssSerial.print(':');
ssSerial.print(secondi);
ssSerial.println();

ssSerial.println("-------------------------------");





 //////////////////////////////////////////////////// A OGNI CICLO CANCELLO IL MESSAGGIO RICEVUTO ////////////////////////////////

 SerialssString="";
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


}   // fine loop

Ho qualche consiglio in via generale che facilita:
In primo luogo mi sembra di capire che devi comandare tante cose simili (almeno 3) e che quindi richiedono 3 gruppi di variabili simili. Io farei almeno array di quelle variabili, senza usare variabili singole.
Inoltre l'uso di String su Arduino può comportare problemindi memoria, sarebbe oreferibile sostituire le String con stringhe (array di char), modificando un po la logica di funzionamento. Comunque, specie se usi String, conviene ridimensionare le variabili il più piccole possibili: #define per variabili contenenti informazioni statiche (pin) e byte per variabili il cui massimo sia minore di 255 e che siano sempre positive.

Potrei provare, ma l'app del telefono manda solo ascii, per quello volevo usare un testo... o mi sbaglio

Ritornando al problema IndexOf, vorrei riuscire a capire perchè non riesco a farlo funzionare,ho visto che "message" facendo un debug in serial monitor è uguale a quello che invio da Bluetooth, infatti nella comparazione == funziona , qualche idea?

in questa comparazione "if (message.indexOf("z1t1h") > 0)" il risultato del Val è sempre 0 ù

Grazie

/////////////// /LETTURA MESSAGGI BLUETOOTH//////////////////////////////
  
  while(ssSerial.available()){
   message = ssSerial.readString();    
  }
     
//////////////LETTURA E IMPOSTAZIONI VARIABILI /////////////////////   
////////////////////ZONA1

// Zona1 Timer1 ORA , MINUTI , DURATA

     if (message.indexOf("z1t1h") > 0) {     
         val = message.indexOf("z1t1h");
         messageValore = message.substring(val + 1, val + 5);
         z1t1ora = (messageValore.toInt());
         }     
     if (message.indexOf("z1t1m") > 0) {     
         val = message.indexOf("z1t1m");
         messageValore = message.substring(val + 1, val + 5);
         z1t1minuti = (message.toInt());
         }     
      if (message.indexOf("z1t1d") > 0) {     
         val = message.indexOf("z1t1d");
         messageValore = message.substring(val + 1, val + 5);
         z1t1dur = (messageValore.toInt());
         }        
         


// ATTIVA IRRIGAZIONE ZONA 1 T1      
       if(message == "t1z1on"){
          irrattivaZ1t1 = true;
      } 
// DISATTIVA IRRIGAZIONE ZONA 1 T1       
       if(message == "t1z1off"){
          irrattivaZ1t1 = false;
      }

da questo pezzo non si capisce... magari più sopra c'è qualche condizione che non fa entrare il programma in questa serie di if
oppure + semplicemente la comparazione che funziona .... se sono le 2 ultime if è perchè vengono fatte con on e off e non con h, m e d

Ho provato a fare la comparazione == in questo modo:

// ATTIVA IRRIGAZIONE ZONA 1 T1      
       if(message == "z1t1h1"){
          irrattivaZ1t1 = true;
      } 
// DISATTIVA IRRIGAZIONE ZONA 1 T1       
       if(message == "z1t1h2){
          irrattivaZ1t1 = false;

e funziona comunque.

Questo è il loop , non mi sembra ci siano condizoni che non fanno entrare il programma

void loop(){
///////////////////////////////////////////////////////////////////////////////////////////////
//                                  RTC DS1307                                                          
///////////////////////////////////////////////////////////////////////////////////////////////

DateTime now = RTC.now();
secondi = now.second();
minuti = now.minute();
ora = now.hour();
giorno = now.day();
mese = now.month();
anno = now.year();

/////////////// /////////////////////////////////////////////// LETTURA MESSAGGI BLUETOOTH///////////////////////////////////////////////////
  
  while(ssSerial.available()){
   message = ssSerial.readString();    

  }
     
//////////// LETTURA E IMPOSTAZIONI VARIABILI /////////////////////////////////////////////     
////////////////////ZONA1

// Zona1 Timer1 ORA , MINUTI , DURATA

      if (message.indexOf("z1t1h") > 0) {     
         val = message.indexOf("z1t1h");
         messageValore = message.substring(val + 1, val + 5);
         z1t1ora = (messageValore.toInt());
         }     
      if (message.indexOf("z1t1m") > 0) {     
         val = message.indexOf("z1t1m");
         messageValore = message.substring(val + 1, val + 5);
         z1t1minuti = (message.toInt());
         }     
      if (message.indexOf("z1t1d=") > 0) {     
         val = message.indexOf("z1t1d");
         messageValore = message.substring(val + 1, val + 5);
         z1t1dur = (messageValore.toInt());
         }        
    
//////////////////////////////////////////////////////////////// ATTIVAZIONI ZONA 1///////////////////////////////////////////////////////

// ATTIVA IRRIGAZIONE ZONA 1 T1      
       if(message == "t1z1on"){
          irrattivaZ1t1 = true;
      } 
// DISATTIVA IRRIGAZIONE ZONA 1 T1       
       if(message == "t1z1off"){
          irrattivaZ1t1 = false;
      }    

// ATTIVA IRRIGAZIONE ZONA 1 T2     
       if(message == "t2z1on"){
          irrattivaZ1t2 = true;
      } 
// DISATTIVA IRRIGAZIONE ZONA 1 T2       
       if(message == "t2z1off"){
          irrattivaZ1t2= false;
      }    

// ATTIVA IRRIGAZIONE ZONA 1 T3      
       if(message == "t3z1on"){
          irrattivaZ1t3 = true;
      }
// DISATTIVA IRRIGAZIONE ZONA 1 T3       
       if(message == "t3z1off"){
          irrattivaZ1t3= false;
      }    




ssSerial.print("Zona1 Timer1 Ora accensione: ");
ssSerial.print (z1t1ora);
ssSerial.print(':');
ssSerial.print (z1t1minuti);
ssSerial.print(" Durata:");
ssSerial.println(z1t1dur);

ssSerial.print("Zona1 Timer2 Ora accensione: ");
ssSerial.print (z1t2ora);
ssSerial.print(':');
ssSerial.print (z1t2minuti);
ssSerial.print(" Durata:");
ssSerial.println(z1t2dur);

ssSerial.print("Zona1 Timer3 Ora accensione: ");
ssSerial.print (z1t3ora);
ssSerial.print(':');
ssSerial.print (z1t3minuti);
ssSerial.print(" Durata:");
ssSerial.println(z1t3dur);

ssSerial.print("Zona2 Timer1 Ora accensione: ");
ssSerial.print (z2t1ora);
ssSerial.print(':');
ssSerial.print (z2t1minuti);
ssSerial.print(" Durata:");
ssSerial.println(z2t1dur);

ssSerial.print("Zona2 Timer2 Ora accensione: ");
ssSerial.print (z2t2ora);
ssSerial.print(':');
ssSerial.print (z2t2minuti);
ssSerial.print(" Durata:");
ssSerial.println(z2t2dur);

ssSerial.print("Zona2 Timer3 Ora accensione: ");
ssSerial.print (z2t3ora);
ssSerial.print(':');
ssSerial.print (z2t3minuti);
ssSerial.print(" Durata:");
ssSerial.println(z2t3dur);

ssSerial.println("-------------------------------");

                           


 //// A OGNI CICLO CANCELLO IL MESSAGGIO RICEVUTO ////////////////////////////////
  message="";
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

}   // fine loop

ancora una cosa....

Definition and Usage

The indexOf() method returns the position of the first occurrence of a specified value in a string.

This method returns -1 if the value to search for never occurs.

se la tua stringa comincia dal primo carattere indexOf restituisce 0 (zero)

ma se tu controlli solo se è > 0 allora non lo trovi

qui puoi anche testare i valori :slight_smile:

Non so come ringraziarti Patrick_M, come dicevi tu inserendo un carattere prima del testo da cercare ,IndexOf funziona correttamente.
Invio " v z1t1h6" e la variabile int z1t1ora prende valore corretto.

  if (message.indexOf("z1t1h") > 0) {     
   val = message.indexOf("z1t1h");
   messageValore = message.substring(val + 5, val + 9);
   z1t1ora = (messageValore.toInt());
   }

Grazie!!!

scusa ma...
se al posto di aggiungere un carattere, il controllo lo facevi:

if (message.indexOf("z1t1h") >= 0)

funzionava comunque :smiley: