Comunicazione seriale su Diplay

Buongiorno a tutti,
mi sto avvicinando al mondo di Arduino (per adesso nella versione UNO) e sto facendo un po' di esercizi in preparazione di lavori più complessi.
Premetto, come ho evidenziato nella mia presentazione, che ho una discreta padronanza dell'eelettronica, ma difficoltà nella programmazione.
Penso che la mia domanda sia semplice:
ho lanciato l'esempio SerialDisplay per visualizzare su un Display (16x2) le parole scritte in via seriale, ma ho visto che il Display utilizza con questo esempio solo la prima riga e termina la visualizzazione quando si superano i 16 caratteri, VOrrei che lo sketch facesse andare a capo nel disply nella seconda riga quando si superano i 16 caratteri. Ho provato con alcuni cicli for con una variabile di posizione e spostando successivamente il cursore, forse la strada è giusta ma non funziona. Potreste, se è possibile, indicarmi come fare partendo dall'esempio SerialDisplay.
Grazie a tutti

La strada del posizionamento del cursore è quella giusta. Posta il tuo codice così è possibile indicarti eventuali errori che ne pregiudicano il funzionamento.
In linea generale ti basta una varibile che conti i caratteri già stampati, se superiore a 16 posizioni nella seconda riga. Poi c'è da vedere cosa deve succedere se ti arrivano più di 32 caratteri ma quello lo si affronta poi

void loop()
{
  int i =0;
// when characters arrive over the serial port...
  if (Serial.available()){ 
  }
    // wait a bit for the entire message to arrive
    delay(100);
    // clear the screen
    lcd.clear();
    // read all the available characters
    while (Serial.available() > 0) {
	i = Serial.available();
      // display each character to the LCD
      for (i = 0; i < 16; i++) {
      lcd.setCursor(0, 0); 
      lcd.write(Serial.read(i));
    }
    for ( i = 17; i < 32; i++){
     lcd.setCursor(0, 1); 
     lcd.write(Serial.read(i)); 
    }
  }
}

In conformità al REGOLAMENTO , punto 7, cortesemente edita il tuo post qui sopra (quindi NON scrivendo un nuovo post, ma utilizzando il bottone a forma di piccola matita :pencil2: che si trova in basso del tuo post), seleziona la parte di codice e premi l’icona </> nella barra degli strumenti per contrassegnarla come codice. Grazie.

Hai frainteso il funzionamento della seriale. Il metodo Available ti dice se c'è qualcosa nel buffer, il metodo read legge il primo byte del buffer, non accetta parametri per richiedere l'Nesimo carattere del buffer.
Quindi non puoi usare i for in quel modo ma potresti usare una variabile per sapere quanti caratteri hai già letto incrementandola ad ogni carattere letto, se questa arriva a 16 la azzeri e riposizioni il cursore nella riga numero uno.
Una volta che sei riuscito a gestire la cosa in modo corretto puoi pensare di memorizzare anche in che riga sei in modo da spostarti dalla riga zero alla uno e poi di nuovo alla zero (se i caratteri sono più di 32) e così via per tutti i multipli di 16 caratteri.
Altra cosa che poi potresti fare è eliminare le informazioni precedenti nella riga in cui ti stai posizionando in modo da non avere "sporcizia" derivante dalle trasmissioni precedenti di caratteri.
Non ti serviranno for, ti basta il while della serial.available

void loop()
{
  int ncar = 0;                           // conta quanti caratteri ho letto

  
  // when characters arrive over the serial port...
  if (Serial.available()){ 
    // wait a bit for the entire message to arrive
    delay(100);
    // clear the screen
    lcd.clear();
    // read all the available characters
    while (Serial.available() > 0) {
      
       ncar++;                          // incremento il n di caratteri

// display each character to the LCD
       
      lcd.write(Serial.read());
    
      if (ncar == 16) {
      lcd.setCursor(0,1);               // mi posiziono sulla seconda riga

            
      // display each character to the LCD
              
      lcd.write(Serial.read());
         ncar = 0;
        delay(1000);
        lcd.clear();  
      
     
     }
     
    }

     }

Prova con questa semplice funzione, che ovviamente devi usare al posto di lcd.print() quando hai delle stringhe molto lunghe.
Se il tuo display è un 16x2 puoi semplicemente riadattare, eliminando i due case inutili.

#define COLS 20
#define ROWS 4

void printLongText(const char* text){
  for(uint8_t i=0; i< strlen(text); i++){
    lcd.print(text[i]);
    switch (i) {
      case COLS-1:
        lcd.setCursor(0, 1);
        break;
      case (2*COLS)-1:
        lcd.setCursor(0, 2);
        break;
      case (3*COLS)-1:
        lcd.setCursor(0, 3);
        break;
      default: break;
    }
  }  
}

grazie, però io non devo scrivere stringhe predefinite e quindi usare lcd.print, ma voglio scrivere sul LCD quello che edito in via seriale

Dovresti sistemare tutti i tuoi post sopra perché il codice non è correttamente incluso dentro gli appositi tag.
Fallo quanto prima perché corri il serio rischio che se arriva un moderatore elimina tutte le risposte finché non si hanno i post correttamente formattati.

E che cambia? E' una funzione, gli passi quello che vuoi oppure replichi il funzionamento direttamente sulla ricezione dalla seriale.

ho provato il tuo metodo, ho passato alla funzione l'argomento Serial.read(), ma non funziona, scrive qualche carattere sulla prima colonna ma poi non fa niente, devo passargli un altro argomento?

Cosi è normale che non funzioni, Serial.read() legge un carattere per volta ed ogni volta che richiami la funzione il ciclo for riparte da zero.
Una possibile variante che comporta poche modifiche è rendere la variabile di conteggio statica in modo che non viene re-inizializzata ogni volta. A quel punto non serve più il ciclo for perché stampi un carattere alla volta direttamente da Serial.read()

Comunque non è necessario implementare una funzione, puoi anche semplicemente mettere tutto nel blocco di codice dove leggi la seriale come stavi già facendo, anche se la funzione aiuta a mantenere il codice più pulito e leggibile.

/*
 Potrebbe essere utile conoscere l'ultima posizione del cursore dopo la scrittura
 che quindi facciamo ritornare dalla funzione. Un'altra possibile miglioria,
 potrebbe essere la possibilità di aggiungere un parametro opzionale che consente
 di impostare da dove la funzione inizia a scrivere sul display
*/
uint8_t printLongText (char ch) {
  static uint8_t pos = 0;
  lcd.print(ch);
  switch (pos++) {
    case COLS-1:
      lcd.setCursor(0, 1);
      break;
    case (2*COLS)-1:
      lcd.setCursor(0, 2);
      break;
    case (3*COLS)-1:
      lcd.setCursor(0, 3);
      break;
    case (4*COLS)-1:
      lcd.setCursor(0, 0);
      pos = 0;
      break;
    default: break;
  }
return pos;
}
....................
....................
 while (Serial.available()) {
    uint8_t actualPos = printLongText(Serial.read());
  }
....................

La memoria degli LCD è sempre strutturata per la larghezza massima di 40 caratteri, perciò su un LCD 16x2 con:
lcd.setCursor (0...15, 0)
scriverà sulla prima riga, mentre con:
lcd.setCursor (40...55, 0)
scriverà sulla seconda.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.