Protocollo comunicazione. Serial.print VS Serial.write

Salve a tutti,

Sono nuovo del forum ma sono 15 giorni che provo a trovare una soluzione al mio problema senza risultato.
Sto creado un protocollo di trasmissione. Quando ricevo il valore "1a" da seriale USB accendo il LED quando "1b" lo spengo. e fin qui tutto ok. Ho creato una funzione di risposta che mi restituisce l'avvenuto comando.

const byte LED = 13;
const byte Address = 49; // Indirizzo fisico Leonardo

void Reply(int io){
Serial.print(Address);
Serial.print(io);
Serial.print(digitalRead(io));
}

Se non ho capito/letto male Serial.write è più performante di Serial.print. Come faccio a fare la stessa funzione utilizzando solo una chiamata a Serial.write?

Grazie,

Marco

Ti invitiamo a presentarti (dicci quali conoscenze hai di elettronica e di programmazione) qui: Presentazioni
e a leggere il regolamento: Regolamento

Ciao nid69ita,
Mi sono presentato nella sezione che mi hai suggerito.
Riporto il codice completo:

const byte LED = 13;
const byte Address = 49; // Indirizzo fisico Leonardo
int inByte[4];
int lastState;
int changeState;

void setup()
{
  pinMode(LED, OUTPUT);
  pinMode(2, INPUT);
  digitalWrite(LED, LOW);
  Serial.begin(115200);
  while (!Serial) {}
  lastState = false;
  changeState = false;
  Serial.flush();
}

void Reply(int io){
Serial.print(Address);
Serial.print(io);
Serial.print(digitalRead(io));
  }

boolean checkInput(){
if(lastState != digitalRead(2) && !changeState){ 
  lastState = digitalRead(2);
  changeState = true;
  }
}

void loop()
{
checkInput();
if (Serial.available() > 0) {
    for (int i=0; i<2; i++)   
{  
    inByte[i] = Serial.read();
}

if (inByte[0] == Address){

  if(inByte[1] == 97){

    digitalWrite(LED, HIGH);
    Reply(13);
    }
   if(inByte[1] == 98){
    digitalWrite(LED, LOW);
    Reply(13);
    }

   if(changeState){
      changeState= false;
      Serial.print(Address);
      Serial.print(2);
      Serial.print(lastState);
      }
    
Serial.flush();
}
else
{
  Serial.flush();
  }    
  }
}

La parte che voglio ottimizzare è la seguente:

void Reply(int io){
Serial.print(Address);
Serial.print(io);
Serial.print(digitalRead(io));
}

Come faccio a fare la stessa funzione utilizzando solo una chiamata a Serial.write?

maverikgoos:
Se non ho capito/letto male Serial.write è più performante di Serial.print. Come faccio a fare la stessa funzione utilizzando solo una chiamata a Serial.write?

La serial.write non è più performante della serial.print, la differenza è nel fatto che la serial.print invia sempre in formato ascii, la serial.write invia sempre in formato binario, va usata al posto della serial.print(dato, BYTE) che è deprecata dalla versione 1.0 del IDE.
In pratica serial.write(10) invia il valore 0x10 0x0A, esattamente la stessa cosa che faceva serial.print(10, BYTE), mentre se fai serial.print(10) viene inviato 0x31 e 0x30 che sono i valori ascii di 1 e 0.
Quale delle due usare dipende esclusivamente dal tipo di dati che devi inviare, se sono in formato ascii devi usare serial.print() se sono in formato binario serial.write().

ehm... Astro, serial.write(10) non invia il valore 0x10 ma 0x0A.

cyberhs:
ehm... Astro, serial.write(10) non invia il valore 0x10 ma 0x0A.

Vero, distrazione mia.

astrobeed:
La serial.write non è più performante della serial.print, la differenza è nel fatto che la serial.print invia sempre in formato ascii, la serial.write invia sempre in formato binario, va usata al posto della serial.print(dato, BYTE) che è deprecata dalla versione 1.0 del IDE.

Quindi a livello di peso computazionale write e print è lo stesso?
Se volessi usare una sola chiamata a print con 3 variabili come posso fare?

Serial.print(variabile1 + variabile2 + varibiale3);

In pratica voglio snellire al meglio la risposta rendendola la più rapida possibile, per evitare timeout o comunque un carico alto sulla CPU.

maverikgoos:
Quindi a livello di peso computazionale write e print è lo stesso?
In pratica voglio snellire al meglio la risposta rendendola la più rapida possibile, per evitare timeout o comunque un carico alto sulla CPU.

Il collo di bottiglia è la seriale stessa, infinitamente più lenta rispetto alla cpu, non crearti problemi dove non esistono, inoltre la trasmissione seriale è gestita tramite un buffer, interrupt driven, in modo totalmente trasparente al tuo sketch.

Grazie mille astrobeed!
Mi hai chiarito dei quesiti da cui non riuscivo ad uscirne. Ho provato e riprovato a cerca senza che nessuno mi togliesse questo dubbio.

Per quanto riguarda l'unica chiamata a Serial.print() è meglio usare 3 chiamate piuttosto che gestire un unica varibile per poi stamparla?

maverikgoos:
Per quanto riguarda l'unica chiamata a Serial.print() è meglio usare 3 chiamate piuttosto che gestire un unica varibile per poi stamparla?

Puoi raggruppare preventivamente tutti i dati in un buffer tramite struttura più unione, leggi qui, per poi inviarlo con una singola serial.print.

Ecco il perchè della mia domanda su print vs write.

Codice Python:

import serial, time
import random
ser = serial.Serial("/dev/ttyACM0", 115200, bytesize=8, parity='N', stopbits=1, writeTimeout=1, timeout=1)
time.sleep(1)
ser.flushInput()
ser.flushOutput()
a = 1
k = 0
e = 0

while 1:

        if a == 1:
                    ser.write(b'1a')
                    a = 0
                    e = e + 1
                    x = ser.read(5)
                    if x != b'49131':
					    
		                            k = k + 1
		                            print(k)
		                            print(x)
		                            ser.flushInput()
		                            ser.flushOutput()
					   
        else:
                    ser.write(b'1b')
                    a = 1
                    e = e + 1
                    x = ser.read(5)
                    if x != b'49130':
					   
		                            k = k + 1
		                            print(k)
		                            print(x) 
		                            ser.flushInput()
		                            ser.flushOutput()

Arduino:

const byte LED = 13;
const byte Address = 49; // Indirizzo fisico Leonardo
int inByte[4];
int lastState;
int changeState;

void setup()
{
  pinMode(LED, OUTPUT);
  pinMode(2, INPUT);
  digitalWrite(LED, LOW);
  Serial.begin(115200);
  while (!Serial) {}
  lastState = false;
  changeState = false;
  Serial.flush();
}

void Reply(int io){
Serial.print(Address);
Serial.print(io);
Serial.print(digitalRead(io));
  }

boolean checkInput(){
if(lastState != digitalRead(2) && !changeState){ 
  lastState = digitalRead(2);
  changeState = true;
  }
}

void loop()
{
checkInput();
if (Serial.available() > 0) {
    for (int i=0; i<2; i++)   
{  
    inByte[i] = Serial.read();
}

if (inByte[0] == Address){

  if(inByte[1] == 97){

    digitalWrite(LED, HIGH);
    Reply(13);
    }
   if(inByte[1] == 98){
    digitalWrite(LED, LOW);
    Reply(13);
    }

   if(changeState){
      changeState= false;
      Serial.print(Address);
      Serial.print(2);
      Serial.print(lastState);
      }
    
Serial.flush();
}
else
{
  Serial.flush();
  }    
  }
}

Il codice Python eseguito su linux riceve dopo alcune ore di lavoro l'errore di risposta da Arduino. Secondo voi da cosa può dipendere?

maverikgoos:
l codice Python eseguito su linux riceve dopo alcune ore di lavoro l'errore di risposta da Arduino.

Che vuol dire "riceve errore di risposta da Arduino" ?

Lo script Python invia in loop una stringa ascii "1a" nel primo blocco if e "1b" nel blocco else.
Cosi facendo, Arduino accende 1a il led e lo spegne con 1b.

Lo Sketch quando riceve la stringa oltre ad accendere il Led, risponde inviando a sua volta una stringa di conferma. Lo script Python verifica se la risposta è corretta, se non è corretta restituisce un errore.

Durante il ciclo che dura ore si verificano alcuni errori. La stringa di risposta è sbagliata. Es. 4913 quando dovrebbe essere 49131.

Secondo te cosa potrebbe causare questo errore?

maverikgoos:
Secondo te cosa potrebbe causare questo errore?

Rientrano in quelli che sono i normali errori su un bus seriale, i protocolli di trasmissione, con varie modalità di verifica integrità dei dati, mica li hanno sviluppati perché quel giorno non avevano niente di meglio da fare :slight_smile:

Sono le piccole lacune ch devo colmare. Fortunatamente ci sono persone come te che riescono a colmare.