Salve a tutti,
come ho detto al mio primo post, sto cercando di realizzare un controllo di temperature in fase di preparazione della birra.
Il tutto funziona bene grazie ai vostri consigli ma adesso vorrei passare i valori delle variabili di temperatura e tempo tramite la porta seriale in modo da poterli leggere da excel
ecco il mio codice completo
//controllo temperature in fase di mash
//definisco tempi e temperature
int prt = 60; //tempo di protein rest
int prc = 0; //temperatura protein rest
int m1t = 5; //primo step tempo di mash
int m1c = 63; //primo step temperatura di mash
int m2t = 5; //secondo step tempo di mash
int m2c = 68; //secondo step temperatura di mash
int mot = 6; //tempo di mash out
int moc = 78; //temperatura di mash out
int ciclo=1;//conto i cicli
int Temp=0;//temperatura del ciclo
int Tempo=0;//tempo del ciclo
int R=0; //controllo se ho già scaldato
char cifre[3]; //imposto il vettore che contiene le letture da seriale
#define ITP A1 //temperatura Mosto
#define ITM A2 //temperatura Piastra
#define P 1
#define F1 13
#define F2 12
#define F3 11
#define F4 10
#define FR 9
#define FINE 8
void setup()
{
Serial.begin(9600);//inizializzo porta seriale
pinMode (P, OUTPUT);//piastra
pinMode (F1, OUTPUT); //fase1
pinMode (F2, OUTPUT); //fase2
pinMode (F3, OUTPUT); //fase3
pinMode (F4, OUTPUT); //fase4
pinMode (FR, OUTPUT); //riscaldamento
pinMode (FINE, OUTPUT);//fine cottura
}
void loop(){
switch (ciclo){//eseguo il primo ciclo di riscaldamento e cottura
case 1:
leggoseriale();//richiamo la funzione per leggere la seriale
prc= atoi(cifre);//scrivo il valore letto nella temperatura
Tempo=prt*60;
R=0;
do{
riscaldamento (prc);//riscaldo il mosto
R++;
}while (R<1);
digitalWrite (F1,HIGH);//indico che sono in fase 1
mantenimento(Tempo,prc);//cottura mosto
case 2:
Tempo=m1t*60;
R=0;
do{
riscaldamento (m1c);
R++;
}while (R<1);
digitalWrite (F2,HIGH);
mantenimento(Tempo,m1c);
case 3:
Tempo=m2t*60;
R=0;
do{
riscaldamento (m2c);
R++;
}while (R<1);
digitalWrite (F3,HIGH);
mantenimento(Tempo,m2c);
case 4:
Tempo=mot*60;
R=0;
do{
riscaldamento (moc);
}while (R<1);
digitalWrite (F4,HIGH);
mantenimento(Tempo,moc);
case 5:
digitalWrite(FINE,LOW);
finecottura();
}
}
void riscaldamento(int Temp){ //inizio a riscaldare il mosto per la fase successiva
while (R<1){
if (analogRead(ITM)<Temp)
{
digitalWrite(P, HIGH);
}
if (analogRead(ITM)>=Temp)
{
digitalWrite (P,LOW);
R=1;
return ;
}
}
}
int mantenimento (int Tempo, int Temp){ //mantengo la temperatura impostata
int TC=290;
while (TC<Tempo){
if (analogRead(ITP)<Temp&&Tempo>TC){//accendo la piastra se la temperatura è bassa
digitalWrite(P,HIGH);
digitalWrite(FR,HIGH);
}
if (analogRead(ITP)>Temp&&Tempo>TC){//spengo la piastra se la temperatura è alta
digitalWrite(P,LOW);
digitalWrite(FR,LOW);
}
if (TC==Tempo){ //interrompo il ciclo allo scadere del tempo di fase
ciclo++;
return ciclo;
}
delay(1000);
TC++;
}
}
int finecottura(){
digitalWrite(P,LOW);
digitalWrite(FINE,HIGH);
delay(1000);
ciclo=5;
}
String leggoseriale(){
while (Serial.available()>0){
for (int i=0;i<3;i++){
cifre[i]=Serial.read();
}
return cifre;
}
}
in questo punto:
leggoseriale();//richiamo la funzione per leggere la seriale
prc= atoi(cifre);//scrivo il valore letto nella temperatura
richiamo la funzione per leggere le cifre da seriale e cerco di convertire il tutto in un intero da poter usare dopo
il problema è che il valore di quell'intero è sempre 0
ho provato ad inizializzare il valore di prc ad un valore diverso da 0 ma al passaggio in atoi mi ritorna 0.
cosa sbaglio???
grazie a tutti
A prima vista direi che atoi non chiede quanti caratteri formano la stringa (anzi il vettore di caratteri)
Perciò la funzione ha un solo modo di sapere quando finiscono i caratteri, cercare il finestringa ovvero il carattere \0 (zero)
La tua leggoseriale prende il vettore cifre e lo ripassa indietro come una String. La macchina dovrà convertire da vettore di char a String (che è un oggetto, non un insieme di caratteri) il tutto senza mai un finestringa.
Prova ad aggiungere:
for (int i=0;i<3;i++){
cifre[i]=Serial.read();
}
cifre[i]='\0'; // oppure semplicemente cifre[i]=0;
Almeno a me non sembra chiaro cosa stai facendo e come lo stai facendo.
Hai un qualcosa che funziona, presumo uno sketch Arduino che funziona.
Aggiungi l'invio tramite seriale, ma verso chi? Se spedisci i dati su seriale perchè il programma che hai postato legge da seriale?
Se vuoi leggerli da excel li spedisci verso un pc, presumo, perchè c'è la lettura nell'Arduino invece della scrittura?
uwefed:
Ma sei sicuro che il siulatore simuli al 100% l'arduino?
Prima di dire che hai problemi prova per favore lo sketch su un Arduino.
Ciao Uwe
Giusto, era solo per fare qualche esperimento prima dell'arrivo dei sensori che mi mancano.
Comunque hai ragione.
nid69ita:
Almeno a me non sembra chiaro cosa stai facendo e come lo stai facendo.
Hai un qualcosa che funziona, presumo uno sketch Arduino che funziona.
Aggiungi l'invio tramite seriale, ma verso chi? Se spedisci i dati su seriale perchè il programma che hai postato legge da seriale?
Se vuoi leggerli da excel li spedisci verso un pc, presumo, perchè c'è la lettura nell'Arduino invece della scrittura?
sto cercando di fare il contrario:
Ho uno sketch che imposta e controlla le temperature durante le fasi di cottura.
Adesso vorrei passare ad arduino le temperature e i tempi tramite excel.
Per ogni fase dovrò inserire la chiamata alla funzione che legge la seriale per leggere questi due valori e usarli all'interno dello sketch.
Spero di essere stato più chiaro
Grazie
La logica mi dice, dopo quello che dichiari, che allora hai 2 programmi, uno in Arduino che riceve ma l'altro spedisce dati da Excel.
Prima di tutto bisogna stabilire che chi spedisce sia corretto. Siccome hai 2 soggetti, escludiamo che il problema sia chi spedisce.
Sei sicuro che il programma che spedisce invii i dati correttamente?
void loop(){
switch (ciclo){//eseguo il primo ciclo di riscaldamento e cottura
case 1:
leggoseriale();//richiamo la funzione per leggere la seriale
prc= atoi(cifre);//scrivo il valore letto nella temperatura
...
String leggoseriale(){
while (Serial.available()>0){
for (int i=0;i<3;i++){
cifre[i]=Serial.read();
}
return cifre;
}
}
Di base ci sono alcune cose che fai che non hanno senso.
ripeto che tu nel vettore cifre non metti mai un fine stringa '\0' e le funzioni base del C si aspettano di trovarlo se no non sanno dove termina la stringa.
se inizializzi prc a che serve visto che prendi cifre e le sbatti dentro a prc?
la funzione leggiseriale è un pò un casino.
Ovvero, lavori con una variabile globale cifre che poi metti in return
Ma allora dovresti fare
String x=leggoseriale();//richiamo la funzione per leggere la seriale
prc= atoi(x);//scrivo il valore letto nella temperatura
ovvero sfrutti il ritorno della String e perciò cifre dovrebbe essere una variabile privata della funzione
quindi:
String x=leggoseriale();//richiamo la funzione per leggere la seriale
prc= atoi(x);//scrivo il valore letto nella temperatura
...
String leggoseriale()
{ char cifre[3]; // metto qui cifre, variabile privata
while (Serial.available()>0)
{ for (int i=0;i<3;i++)
{ cifre[i]=Serial.read();
}
}
return cifre;
}
Sai che forse hai anche errato il numero di graffe della leggiseriale? la return deve essere fuori dal while
Metti le graffe come faccio io. Non sono un fastidio le graffe, evidenziale per fare meno errori. Lascia stare gli esempi in giro che la graffa quasi la "nascondono".
edit: per favore includere il codice usando gli appositi tag
Ho corretto l'errore del return nel while grazie.
Per il resto se faccio come mi hai detto tu durante la compilazione ricevo una serie di errori:
controllo_temperature2_0.ino: In function 'void loop()':
controllo_temperature2_0:43: error: cannot convert 'String' to 'const char*' for argument '1' to 'int atoi(const char*)'
controllo_temperature2_0:54: error: jump to case label
controllo_temperature2_0:42: error: crosses initialization of 'String x'
controllo_temperature2_0:64: error: jump to case label
controllo_temperature2_0:42: error: crosses initialization of 'String x'
controllo_temperature2_0:74: error: jump to case label
controllo_temperature2_0:42: error: crosses initialization of 'String x'
controllo_temperature2_0:83: error: jump to case label
controllo_temperature2_0:42: error: crosses initialization of 'String x'
Per la funzione e il ritorno non era una soluzione ma solo una spiegazione che se usi una funzione che ritorna qualcosa, allora dovresti usarlo, altrimenti lavori con variabili globali e fai a meno del return.
Immaginavo poi che la atoi() si aspetta di lavorare con vettori di caratteri e non con oggetti String. Perciò non userei l'oggetto String tanto per fare.
leggoseriale(); //richiamo la funzione per leggere la seriale
prc= atoi(cifre); //scrivo il valore letto nella temperatura
...
void leggoseriale() // non ritorno nulla, lavoro con cifre, variabile globale
{ while (Serial.available()>0)
{ for (int i=0;i<3;i++)
{ cifre[i]=Serial.read();
}
}
}
Prova poi ad aumentare di 1 la dimensione di cifre ma lascia il resto invariato.
Nella leggoseriale aggiungi solo:
void leggoseriale() // non ritorno nulla, lavoro con cifre, variabile globale
{ while (Serial.available()>0)
{ for (int i=0;i<3;i++)
{ cifre[i]=Serial.read();
}
}
cifre[i]='\0';
}
ho capito,
grazie per le spiegazioni mi sa che faccio ancora confusione con la visibilità delle variabili :~
faccio qualche prova e ti faccio sapere
grazie mille per la disponibilità
Ho ricontrollato la cosa e in effetti i commenti vengono eliminati prima di passare il codice al pre-processore.
Comunque in caso di bug il testo potrebbe essere accodato al define. Vedi ad esempio il bug dell'IDe quando, in alcuni casi si usa il /* */ su più righe.
Quindi diciamo che non è un obbligo ma una buona prassi.
Anch'io ero della convinzione che i commenti cozzassero in fase di compilazione. Tant'è che non più di un paio di giorni fa un utente aveva un problema simile e togliendo i commenti dal #define aveva risolto i suoi guai.
Ad esempio, GNU C, seguendo dette specifiche, converte i commenti in uno spazio prima di processare il codice (The C Preprocessor: 1. The C Preprocessor al punto 1.1) ...
... in ogni caso buono a sapere che, con l'IDE di Arduino, questo potrebbe a volte creare problemi.
Però c'è da dire anche che noi stiamo usando avr-gcc, non gcc. E non è detto che tutto quello che è supportato da gcc lo sia anche su avr-gcc e nello stesso modo.