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;
}
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é?
è 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
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.
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
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());
}