Scrivere su LCD 16x2 con seriale e andare a capo una volta raggiunto il massimo dei caratteri su una riga

Salve a tutti. Ho realizzato un piccolo schizzo che prevede la scrittura su un LCD 16x2 di ciò che inserisco nel serial monitor. Sono riuscito a fare in modo che superati i 16 caratteri su una riga (ovvero la prima riga), l'altra parte del testo mi sbucasse di nuovo dall'inizio.
Però ciò che vorrei è che una volta superati i 16 caratteri, quelli che superano il massimo di spazio della riga anzichè sbucare da capo sempre sulla stessa riga, andassero a capo nella seconda riga.
Come potrei fare? Grazie in anticipo

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2);

char message[32];

void setup() {
  Serial.begin(9600);
  lcd.init();
  lcd.backlight();
}

void loop() {
  int charsLettura;
  if (Serial.available() > 0) {
    charsLettura = Serial.readBytesUntil('\n', message, 16);   
    message[charsLettura] = '\0';      
    lcd.clear();
    lcd.print(message);
   }
}

Raggiunti i primi 16 caratteri ti posizioni sulla seconda riga.
lcd.setCursor(0, 1);

Grazie per la risposta, ho provato già prima di aprire l'argomento a fare qualcosa con setCursor, del tipo

if(charsLettura >= 16){
    lcd.setCursor(0,1);}
    

ma con nessun risultato

Qui il tuo problema e che fai la lettura di tutto quello che trovi, costruisci la stringa e poi la stampi. Devi invece leggere e stampare passo a passo e man mano contare i caratteri stampati, solo arrivato a 16 cambiare riga e ripartire col conto

Grazie, più o meno avevo intuito fosse quello il problema, vedrò cosa fare anche perchè non ho idea come fare un conteggio dei caratteri stampati singolarmente

Alle istruzioni

    lcd.clear();
    lcd.print(message);

sostituisci questa

    PrintMessage();

e scrivi questa funzione

void PrintMessage() {
  lcd.clear();
  for (int i=0; i<16; i++) {
    if (message[i] == '\0') return;
    lcd.print(message[i]);
  }
  lcd.setCursor(0,1);
  for (int i=16; i<32; i++) {
    if (message[i] == '\0') return;
    lcd.print(message[i]);
  }
}

DOVREBBE funzionare. S.E.& O.

Ciao,
P.

Grazie mille per la risposta, funziona perfettamente.
Avevo trovato una soluzione analoga, sempre con il for suggeritami da una persona, ossia così:

char message [32];
char part1[16];
char part2[16];

for (int i = 0; i < 16; i++) {
part1[i] = message[i];
part2[i] = message[i+16];
}

lcd.clear();
lcd.print(part1);
lcd.setCursor(0,1);
lcd.print(part2);

che alla fine è piu o meno la stessa cosa.

Attenzione però che i caratteri rimangono salvati nella stringa message e quindi il clear non funziona; quindi per svuotare basta inserire dopo PrintMessage(); questo ciclo for:

for (int i = 0; i < 32; i++) {
message[i] = 0;
}

Grazie mille ancora.

Visto che hai trovato la soluzione, ti propongo anche un altro metodo giusto per farti affrontare la problematica anche da un altro punto di vista (si tratta più o meno quanto suggerito da @C1P8 )

LCD_wordwrap.ino - Wokwi Arduino Simulator

Sì questo è fantastico come esempio!
Come potrei svuotare la stringa in modo tale che ad ogni nuovo messaggio avvenga un lcd.clear() e l'azzeramento dell'array di char?

Non ho ben capito la domanda...
Se vuoi ripulire il display ad ogni nuovo messaggio basta che inserisci l'istruzione lcd.clear() prima di stampare. Forse tu intendi appena ricevuto il messaggio dalla seriale?

In tal caso è necessario intervenire sulla porzione di codice che legge i caratteri dalla seriale e attendere il terminatore di riga prima di stampare

Edit:
E' necessario anche modificare la funzione che stampa carrattere per carattere per fare in modo che non tenga memoria costantemente della posizione raggiunta.

LCD_wordwrap2.ino - Wokwi Arduino Simulator

Scusami, cerco di essere più chiaro.
Questo tuo codice permette di stampare su più righe appena ricevuto un messaggio dalla seriale. Nel momento in cui però ne invio un secondo, anzichè cancellare tutto il contenuto printato sul display e scrivere da capo questo nuovo messaggio, continua a scrivere dopo l'ultima parola del primo messaggio. Cioè, ad esempio, all'inizio abbiamo "Hello world", nel momento in cui scrivo qualcosa nel seriale, questo viene printato sul display subito dopo "Hello world", io vorrei che venga cancellato tutto e che il messaggio inviato parta da capo. In tal senso mi chiedevo quindi come svuotare l'array di char e dove posizionare l'istruzione lcd.clear();
Ho provato a mettere lcd.clear() prima di lcd.print(ch); nella funzione void printChar, ma non funziona. Inoltre, penso che bisogna portare a zero anche l'array di char nel quale viene contenuto il messaggio inviato tramite seriale.

Ok, allora avevo intuito bene.
Ho modifcato il messaggio precedente inserendo il link ad una seconda versione.

Azzerare l'array non lo ritengo necessario, ad ogni modo se lo vuoi fare basta che metti il primo elemento == '\0' oppure usi l'istruzione memset()

rxBuffer[0] = '\0';  // '\0' è equivalente a 0

//oppure
memset(rxBuffer, 0, sizeof(rxBuffer));

Perfetto, @cotestatnt
Sei sempre gentile e disponibile oltre che molto competente, grazie mille!!

1 Like

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