Problemi con programmino semplice

no, LCD NON sa cosa farsene dei tuoi a capo. Lui è fatto per essere usato come a battaglia navale, dando le coordinate X e Y, non sa niente di righe o menate varie, il massimo della sua intelligenza è andare di seguito se gli passi più valori (ma nnon penso nemmeno che sia l'LCD, mi sa che è la libreria). Quindi in pratica se ricevi un \r\n (in windows) un \n (in linux) o un \n\r (in mac) devi dire all'lcd di posizionarsi alla riga successiva usando il gioco della battaglia navale col cursore.

Perfetto, ho risolto grazie!
Questo è lo sketch finale:

#include <LiquidCrystal.h>

LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

void setup() {
  lcd.begin(20,4);
  Serial.begin(1200);
}

void loop() {
  
  if (Serial.available()) {
    char inByte = Serial.read(); 
    switch (inByte) {
    case '\n':
      lcd.setCursor(0,0);
      break;
    case 'L':
      lcd.setCursor(0,1);
      lcd.write("L");
      break;
    case 'H':
      lcd.setCursor(0,2);
      lcd.write("H");
      break;
    case '\r':
      break;
    default: 
      Serial.write(inByte);
      lcd.write(inByte);
      }
  }
}

Cosi facendo ho eliminato anche il problema della stringa che eccedeva la lunghezza dell'LCD quindi quando mi da la temperatura max (Hi) e min (Lo) vado su una nuova riga.
Ora devo trovare il modo di stampare tutto questo su carta... il problema è, non so perchè, che quando inserisco un comando di tipo printer.write(); non legge più la stringa ASCII ma mi da tutta una serie di 00X30 05X30 ecc ecc che in teoria dovrebbe essere un'altra forma di lettura del carettere ASCII giusto?

Problemino divertente: nel case ho distinto varie operazioni nel caso in cui entrino i caratteri 'L' 'H' '\n' e'\r'... la cosa divertente è che lui compie quelle operazioni anche se li vede come 72 74 10 o 13 ovvero i loro corrispettivi decimali! Come faccio per evitare questa cosa?
Per capirci voglio che vada a capo solo quando legge \r e non 13 perchè la mia stringa ASCII è alfanumerica e quindi sarebbe un disastro.
Grazie

\n è un carattere ESCAPE e quindi è equivalente al byte 13.

Ho notato che al posto dello 0 (zero) mi mette degli spazi e spesso va a capo senza che effettivamente il dato fosse \r... com'è possibile???

00X30 e 05X30 sembrano valori esadecimali, ma quel 05 indica che prende 2 byte, quindi che probabilmente si tratta di UNICODE

Secondo me dovrei leggere prima tutta la stringa di 32 caratteri e poi elaborarla (mandarla a LCD, stamparla o salvarla su SD).
Sapendo che la mia stringa ASCII inizia con 'k' e finisce con '\n' come potrei fare? Che ciclo potrei usare?

bhe anzichè mettere le cose nell'LCD potresti metterle in una array di 32 elementi di char, che ne dici? e se sostituisci il \n con \0 diventa una stringa vera e propria (\0 è il carattere di fine stringa), e quindi potrai giocarci con le funzioni strlen, etc.. oppure dare l'array in pasto alla classe String e usarlo con la classe String (te lo sconsiglio se vuoi capire bene questo concetto)

come posso sostituire \n con \0? Dallo strumento mi arriva sempre una stringa fissa che finisce con \n :~
Parli di questo array? http://arduino.cc/en/Reference/String
un char array giusto?

esatto, parlo di quel link.

come posso sostituire \n con \0?

if leggo \n allora salva nell'array \0 altrimenti salvaci il carattere letto :grin:

Dunque... ho realizzato questo sketch:

void setup() {
  Serial.begin(1200);
  
}
String line = "";    
void loop() {
  if (Serial.available()) {
    char inByte = Serial.read(); 
    switch (inByte) {
    case '\n':
      Serial.println(line);     
      line = "";        
      break;
    default: 
      line += inByte;                         
    }
  }
}

E fin qui tutto ok, a serial monitor ho la stringa precisa! I problemi iniziano quando provo a loggare la stringa su SD con questo sketch:

#include <SD.h>

const int chipSelect = 10;

void setup() {
  Serial.begin(1200);
  Serial.print("Initializing SD card...");
  pinMode(10, OUTPUT);
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");
}  

String line = "";

void loop() {
  if (Serial.available()) {
    File dataFile = SD.open("datalog.txt", FILE_WRITE);
    char inByte = Serial.read(); 
    switch (inByte) {
    case '\n':
      if (dataFile) {
        dataFile.println(line);
        dataFile.close();
        Serial.println(line);     
        line = "";       
      } else {
          Serial.println("error opening datalog.txt");
        }
      break;
    default: 
      line += inByte;                         
      }
  }
}

Appena inizializzata la sd si pianta e sul file txt non c'è nulla. Oppure a volte scrive qualcosa, un pò confuso ma pertinente, ma sul file trovo la stessa confusione. Cosa sbaglio?
La riga File dataFile = SD.open("datalog.txt", FILE_WRITE); ho provato a metterla altrove, magari nel setup ma non me lo compila, mi dice che dataFile non è dichiarato per quello scopo.

l'errore è dato dal fatto che ad ogni open DEVE corrispondere una CLOSE. aggiusta il tuo codice di conseguenza.

mi dice che dataFile non è dichiarato per quello scopo.

si chiama visibilità delle variabili. una variabile nasce e muore all'interno del suo blocco, ovvero delle {}, e non può essere vista da cose al di fuori del suo blocco (salvo particolari casi) anche se "viva", però può essere vista dai "sottoblocchi". cerca visibilità delle variabili su wikipedia o google per magiori info.

Grazie, mi son studiato questo e credo di aver capio: Variabile (informatica) - Wikipedia
Ora però, nell'attesa di rimettermi sotto con la memorizzazione di questa stringa benedetta, sto provando a stamparla su stampante e la cosa si presenta assai problematica. Come consigliato ho creato un programma che prima di eseguire le operazioni di stampa mi crei la stringa. Il problema però, sebbene migliori, rimane.
Questo è lo sketch:

#include <SoftwareSerial.h>

#include <Adafruit_Thermal.h>

//#include <LiquidCrystal.h>

//LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

int printer_RX_Pin = 8;  // this is the green wire
int printer_TX_Pin = 9;  // this is the yellow wire

Adafruit_Thermal printer(printer_RX_Pin, printer_TX_Pin);

void setup() {
  Serial.begin(1200);
  //lcd.begin(20,4);
  printer.begin();
}

String line = "";    

void loop() {
  if (Serial.available()) {
    char inByte = Serial.read(); 
    switch (inByte) {
    case '\n':
      Serial.println(line);     //print complete line
      //lcd.setCursor(0,0);
      //lcd.print(line);
      printer.println(line);
      line = "";        //reset to empty string
      break;
    default: 
      line += inByte;                         //append inByte to the line String
    }
  }
}

Se io non uso la stampa tutto ok (anche se inizializzo la stampante). Nel momento in cui faccio partire la stampante mi omette parte della stringa (solitamente gli ultimi 2 o 3 caratteri) dopodichè inizia a sballare completamente il puntamento della stampa, sia su carta che su LCD. La stringa poi me la scrive anche correttamente, ma sballa tutti i puntamenti, come puoi vedere nella foto allegata.
Secondo te a cosa può essere dovuto?

#include <SoftwareSerial.h>

Lo puoi rimuovere perché viene richiamato direttamente dal Adafruit_Thermal.h

#ifndef Thermal_h
#define Thermal_h

#if ARDUINO >= 100
 #include "Arduino.h"
 #include "SoftwareSerial.h"
#else
 #include "WProgram.h"
 #include "WConstants.h"
 #include "NewSoftSerial.h"
#endif

non credo, tutti gli include nelle librerie vanno ripetuti anche nel file .pde o .ino... è una piccola controidicazine del sistema che arduino IDE usa per "reincollare" i sorgenti.

feci delle prove in merito, ed a volte potevano essere omesse, altre volte no, rinunciai a capire :slight_smile:

uhmm andiamo off-topi ma se ricordo bene il tutto dipende dell'estensione

Secondo me, possono essere esclusi gli include dove le funzioni non vengono utilizzate direttamente nello sketch ma solo tramite altre librerie.
In quel caso essendo la libreria che usa le funzioni dei una seconda libreria, questa deve essere richiamata all'interno della prima. Non nello sketch.
Se invece la libreria oltre ad essere usata in un altra libreria è utilizzata all'interno dello sketch allora dovrà essere inclusa.

Vi tolgo il dubbio, provato... non compila

In file included from log_sd_ok.cpp:2:
C:\Programmi\arduino-1.0\libraries\Adafruit_Thermal/Adafruit_Thermal.h:20:29: error: SoftwareSerial.h: No such file or directory
In file included from log_sd_ok.cpp:2:
C:\Programmi\arduino-1.0\libraries\Adafruit_Thermal/Adafruit_Thermal.h:105: error: ISO C++ forbids declaration of 'SoftwareSerial' with no type
C:\Programmi\arduino-1.0\libraries\Adafruit_Thermal/Adafruit_Thermal.h:105: error: expected ';' before '*' token