Invio e ricezione dati in seriale

Ciao a tutti. Chi mi può indicare dov’è l’errore ? non ricevo il terzo valore. e il primo viene visualizzato ma a valore 0. Ho una mega e un NODEMCU. Invio tre valori al nodemcu in Seriale ma al nodemcu arrivano solo 2.
questa è la parte NODE che riceve

const int NUMBER_OF_FIELDS = 3;
int fieldIndex = 0;
valori int [NUMBER_OF_FIELDS];
 
void setup () {
Serial.begin (9600);
}
void loop () {
se (Serial.available ())
  {
    char ch = Serial.read ();
    if (ch> = '0' && ch <= '9')
    {
      if (fieldIndex <NUMBER_OF_FIELDS)
      {
        valori [fieldIndex] = (valori [fieldIndex] * 10) + (ch - '0');
      }
  }
  altrimenti se (ch == ',') {
    FieldIndex ++;
  }
  altro{
    for (int i = 0; i <min (NUMBER_OF_FIELDS, fieldIndex + 1); i ++) {
      Serial.println (valori [i]);
      valori [i] = 0;
    }
    fieldIndex = 0;
  }
  }
}

Questa è la parte MEGA che trasmette

if (millis () - splitdatiMills> intervalSplit) {
  splitdatiMills = millis ();
  Serial.print ( 'H');
  Serial.print ( "");
  Serial.print (val1, DEC);
  Serial.print ( "");
  Serial.print (val2, DEC);
  Serial.print ( "");
  Serial.print (val3, DEC);
  Serial.print ( "");
  Serial.println ();
}

nella foto quello che vedo nei due seriali. seriale DX Mega seriale SX NODE.
in più Vorrei separare i tre valori che ricevo in come Val1 , Val2, Val3.
Grazie mille

const int NUMBER_OF_FIELDS = 3;
int fieldIndex = 0;
int values[NUMBER_OF_FIELDS];
 
void setup() {
Serial.begin(9600);
}
void loop(){
if (Serial.available())
  {
    char ch = Serial.read();
    if(ch >= '0' && ch <= '9')
    {
      if(fieldIndex < NUMBER_OF_FIELDS)
      {
        values[fieldIndex] = (values[fieldIndex] * 10) + (ch - '0');
      }
  }
  else if (ch ==','){
    fieldIndex++;
  }
  else{
    for(int i=0; i < min(NUMBER_OF_FIELDS, fieldIndex+1); i++){
      Serial.println(values[i]);
      values[i] =0;
    }
    fieldIndex = 0;
  }
  }
}

scusate era sotto traduzione il computer

E tu, dopo 385 post, ancora non hai imparato che nella sezione in lingua Inglese si può scrivere SOLO in Inglese ? ? ? :o

Per favore, la prossima volta presta più attenzione in quale sezione metti i tuoi post ... Grazie.

Guglielmo

P.S.: Il tuo post è già stato spostato nell'opportuna sezione del forum "Italiano"

da quello che vedo
se ricevi da 0 a 9 oppure “,” va tutto bene
se ricevi qualche cosa diverso stampi e azzeri il valore

il primo valore che trasmetti è “H”

quindi il primo valore è 0
poi invii val1 e questo chedo che te lo legga
poi invii val2 e anche questo dovrebbe leggertelo
poi invii val3 ma questo è il 4 invio e tu controlli
if (fieldIndex < NUMBER_OF_FIELDS) che vale 3 quindi…

mmmm no, non è vero … ci studio :slight_smile:

edit:
presumo comunque che nell’invio della mega ci siano anche le virgole…

Sto provando a capire dov'è l'errore ma non riesco. lo sketch è ok. mi sfugge qualcosa

allora:

int values[NUMBER_OF_FIELDS];

questo è un array di 4 elementi (0,1,2,3)
tu ne popoli 3

 if (fieldIndex < NUMBER_OF_FIELDS) {

quindi tu trasmetti ad esempoi h,1,2,3
e l’ultimo carattere che è come minimo CR
quindi quando trova il CR che non è un numero e nemmeno virgola
cosa fa?
comincia a stampare (in effetti comincia appena riceve H perchè non è numero e non è virgola)
e stampa

for (int i = 0; i < min(NUMBER_OF_FIELDS, fieldIndex + 1); i++)

con i da 0 a i minore di in questo caso fieldIndex che vale 0 + 1 (quindi un totale di 1 volta)

Serial.println(values[i]);

quindi stampa 0
poi trova la virgola (dopo h prima del numero c’è la virgola)
e quindi incrementi fieldindex ad 1

poi riceve i 3 numeri
per cui finisce che fieldIndex vale 3 (1,2,3 sono i 3 numeri)
quando riceve il famoso cr
stampa

for (int i = 0; i < min(NUMBER_OF_FIELDS, fieldIndex + 1); i++)

NUMBER_OF_FIELDS vale 3
fieldIndex + 1 vale 4

da i =0 a i < 3 (quindi 2)

value [0] che vale 0 perchè era la H
value [1] prima cifra
value [2] seconda cifra

quindi a video avrai:
0 (che aveva stampato prima)
0
1
2

e il terzo te lo sei fumato :slight_smile:

ciao Gian70Luca,

nel tuo codice discrimini:
se lettera resetto l’array ed l’index
se virgola incremento l’index
se char tra ‘0’ e ‘9’ faccio quel calcolo per unità, decine, centinaia etc.

quindi dertto questo il tuo messaggio dovrebbe essere:

a123,321,456a

Patrick_M, Ti ringrazio mille per la spiegazione del programma, MA mi credi che non sono arrivato alla soluzione per poter leggere i valori sul NODE ? ho modificato

const int NUMBER_OF_FIELDS = 3;

Ma nel seriale del NODE io vedo sempre
la sequenza di valori :
0
657
0
657
ecc.

Se è possibile, ma soprattutto se si può fare, Avere una correzione o la soluzione al mio problema. Cosi da capire come funziona il programma. Grazie mille.

A parte che nessuno, da regolamento, scrive programmi completi per altri, provo a darti una tra le molte possibili soluzioni.
Questa soluzione ti consente di ridurre l'uso di seriale (cosa che certamente limita il riempimento del buffer) con un leggero aumento dei caratteri trasmessi. Si tratta di riconoscere i singoli numeri, e di spedirli separatamente.
La trasmissione diventa: in inizio differente per ogni numero, chiaramente un carattere diverso da una cifra (io userei le lettere in ordine,inizio 'a' per il primo, 'b' per il secondo ecc). Il numero scritto in cifre (un massimo di 4 per gli int) e un terminatore comune (io userei '.'). Sconsiglio l'introduzione di un controllo all'inizio (prima di aver provato questa parte), perché fino a questo punto sono tutti caatteri scrivibili da tastiera. A prova finita credo che un crc sia utile, ma dico fin da ora che non lo so calcolare.
In trasmissione...trasmetti,semplice semplice. Puoi complicarlo leggermente trasmettendo solo i numero che sono cambiati (tieni traccia dei numeri trasmessi in precedenza)
In ricezione:
#define seriale "qualsiasi metodo di collegamento usato"//capiscila

  1. fai le tue fino a che non senti seriale
  2. quando senti seriale ti ricordi il primo carattere. Verifichi se é un inizio valido, e se non lo fosse ignori tutto e continui a fare le tue
  3. se lo fosse ti segneresti in variabile a che numero corrisponde quell'inizio. E poi da li hai molte scelte. Io ti dico la mia: crei e svuoti un array di char (stringa classica di C) grande 4/5 caratteri (circa il numero massimo di cifre per singolo numero), inoltre ti scrivi una funzione che ti riempie l'array secondo queste regole
    A) se sente qualcosa che non é una cifra (terminatre escluso) si ferma e ritorna 0.
    B) se sente più di 5 cifre si ferma e ritorna 0.
    C) se sente una cifra la mette al posto giusto nell'array
    D) se tra due ricezioni passa più di un dato tempo (pochi ms) si ferma e ritorna 0
    E) se sente il terminatore non lo aggiunge, e ritorna 1
    Sembra difficile, ma si può fare, ed in piche righe.
    Al che se la funzione ritorna 0 qualcosa é andato storto, e io ignoro e torno alle mie occupazioni.
  4. se la funzione restituisce 1 allora so che nell'array ci sono tutte le cifre del numero segnato dal ricordo dell'inizio. Non ho che da passare array, sua lunghezza e numero ad una funzione (esistenre o creata) che mi aggiorni il numero.
    Ho spiegato bene?

ok. grazie, si forse rileggendo con calma riesco a "forse" a risolvere. Ti ringrazio. ti farò sapere.

prova usando Serial.parseInt

/*
 *  analisi stringa inviata
 *  l'invio deve avere il seguente formato
 *  H,num1,num2,num3+/n (ritorno a capo)
 *
 */


const int NUMBER_OF_FIELDS = 3;
int fieldIndex = 0;
int values[NUMBER_OF_FIELDS];

void setup() {
   Serial.begin(9600);
}
void loop() {
   while (Serial.available() > 0) {
      if (Serial.read() == 'H') {
         for (int x = 0; x < NUMBER_OF_FIELDS; x++) {
            values[fieldIndex] = Serial.parseInt();
            fieldIndex++;
         }
         if (Serial.read() == '\n') {
            for (int i = 0; i < 3; i++) {
               Serial.println(values[i]);
            }
            fieldIndex = 0;
            break;
         }
      } else {
         Serial.println("non capisco");
      }
   }
}

anzi, i separatori tra i numeri possono essere quello che vuoi spazi, lettere, virgole… l’importante è che il primo carattere sia H (maiuscola) e tra questo e il primo numero puoi metterci uno spaziatore oppure no

Ciao Patrick, grazie per aver provato. Ma non funziona. Da quel che ho capito con tutte le varie modifiche che ho fatto sembra che qualcosa vada in conflitto nella ricezione dei dati.

bah, io l'ho provato e funziona.... apri la seriale e scrivi H12,34,65 e lui ti scrive 12 34 65 :slight_smile:
quindi forse devi controllare l'invio... o appunto la ricevente