Problema Seriale Arduino

Buongiorno a tutti!

Vorrei sottoporvi un problema che ho riscontrato ultimamente mentre sto facendo un nuovo programma con una scheda che mai avevo utilizzato prima, con l'ATMega 32u4 che non ha il controller FTDI esterno per la comunicazione su USB.

Io ho alcuni Arduino UNO rev.3 e un Arduino Micro per fare le prove.

Sto facendo un piccolo voltmetro con quest'ultima scheda e per fare un debug delle varie funzioni voglio stampare sulla seriale USB, tramite il monitor seriale, alcune variabili da visualizzare.

Richiamo la funzione nella maniera corretta ma non visualizzo nulla.

Ho passato lo stesso codice anche in Arduino UNO ed ottengo lo stesso risultato.

Nello stesso sketch carico anche la libreria SPI.h per la gestione di due display, ma anche eliminata l'inclusione della libreria il problema persiste.

Ho provato a caricare anche altri firmware precedenti, che funzionavano sulla seriale, per esempio il firmware dell'orologio / sveglia radiocontrollato, ma anche in questo caso la comunicazione seriale rimane muta, anche con Arduino UNO

Ho controllato in gestione dispositivi il dispositivo Arduino seriale, la velocità di comunicazione che utilizza ed entrambi (sia l'UNO sia Micro) sono a 9600. Naturalmente ho inizializzato la seriale a quella velocità là e dal monitor seriale ho selezionato la medesima velocità.

L'unica cosa che ho fatto è stata l'aggiornamento dell'IDE di Arduino, passando dalla versione 1.8. ? all'ultima versione 1.8.5.

Come sistema operativo ho Windows 10.

Il problema è che non funziona con la UNO la seriale, anche per semplici cose.

Pensavo che, avendo l'ATMega 32u4 il collegamento diretto con l'USB, magari quando inizializzo la seriale in realtà inizializzo lo scambio dati sui pin RXI e TXO e non sull'USB.

Ma avendo lo stesso problema anche sulla UNO credo di poter escludere una cosa di questo genere.

Che cosa potrebbe essere? Che controlli posso fare?

Grazie per le risposte

Riccardo

Metti il codice che stai usando (… mi raccomando, in conformità al regolamento, punto 7, racchiuso tra i tag CODE che, in fase di edit, ti inserisce il bottone </> … primo a sinistra) … così vediamo cosa fai … ::slight_smile:

Guglielmo

Il codice è un po’ lungo e lo ometto nelle parti non essenziali per questo problema:

#define sclk 13                                       /* clock della comunicazione SPI, in comune tra i due display. il pin è il 15 per Arduino Pro Micro. */
#define mosi 11                                       /* comunicazione unidirezionale master -> slave, in comune tra i due display. il pin è il 16 per Arduino Pro Micro. */
#define cs1 2                                         /* selezione dello slave 1, primo display. */
#define rs1 3                                         /* pin rs dello slave 1, primo display. */
#define rst1 4                                        /* reset dello slave 1, primo display. */
#define cs2 5                                         /* selezione dello slave 2, secondo display */
#define rs2 6                                         /* pin rs dello slave 2, secondo display */
#define rst2 7                                        /* reset dello slave 2, secondo display */


//#include <SPI.h>                                      /* libreria per comunicazione SPI */
#include <Adafruit_GFX.h>                             /* libreria grafica di Adafruit */
#include <Adafruit_ST7735.h>                          /* libreria per il chip ST7735 di gestione del display */

Adafruit_ST7735 display1 = Adafruit_ST7735(cs1, rs1, rst1);   /* creazione oggetto display1 per la libreria Adafruit di gestione del chip del display */
Adafruit_ST7735 display2 = Adafruit_ST7735(cs2, rs2, rst2);   /* creazione oggetto display2 per la libreria Adafruit di gestione del chip del display */

...

#define KeyboardPin A4                                /* pin lettura tastiera */
byte varKeyboard = 0;                                 /* variabile byte che contiene il valore della lettura del pin anallogico della tastiera */
bool select = false;                                  /* variabile booleana per il pulsante select */
bool reset = false;                                   /* variabile booleana per il pulsante reset */

void keyboard(){
  varKeyboard = analogRead(KeyboardPin);              /* lettura del pin analogico della tastiera */
  if (varKeyboard > 767){select = true;}              /* se la lettura è maggiore del valore, allora il pulsante select è premuto e la variabile booleana è true */
  else {select = false;}                              /* in caso contrario la variabile booleana è false */
  if(varKeyboard < 767 && varKeyboard > 255){reset = true;}   /* se la lettura è minore del valore e allo stesso tempo maggiore di 255, allora il pulsante reset è premuto e la variabile mooleana è true */
  else {reset = false;}                               /* in caso contrario la variabile booleane è false */
}

byte varMAX = 0;                                      /* variabile che contine il numero del canale in base a quante volte schiaccio il tasto select */

void resetMAX(){
  if (select){varMAX++;}                              /* se select è true, aggiungi un valore alla variabile varMAX */
  for (varMAX; varMAX <= (Channel - 1);){             /* ciclo for, finché la variabile è minore o uguale del numero dei canali */
    if (reset){VdigitalMAX[varMAX] = 0;}              /* se reset è true, azzera l'elemento dell'array della tensione digitale corrispondente al canale selezionato */
  }
  varMAX = 0;                                         /* azzera la variabile */
}

...

void printCH0(){ 
  display1.setTextColor(ST7735_GREEN,ST7735_BLACK);   /*  */
  display1.setTextSize(2);                            /*  */
  display1.setCursor(40, 15);                         /*  */
  display1.print("VERDE ");                           /*  */
  display1.setCursor(40, 33);                         /*  */
  display1.print(Vanalog[0], 1);                      /*  */
  display1.print("V ");                               /*  */

  display1.setTextColor(ST7735_WHITE,ST7735_BLACK);   /*  */
  display1.setTextSize(1);                            /*  */
  display1.setCursor(30, 53);                         /*  */
  display1.print("Vmax ");                            /*  */
  display1.print(VanalogMAX[0], 1);                   /*  */
  display1.print("V ");                               /*  */
}

...

...

void setup() {

  Serial.begin(9600);
    
  pinMode(sclk, OUTPUT);
  pinMode(mosi, OUTPUT);
  pinMode(cs1, OUTPUT);
  pinMode(rs1, OUTPUT);
  pinMode(rst1, OUTPUT);
  pinMode(cs2, OUTPUT);
  pinMode(rs2, OUTPUT);
  pinMode(rst2, OUTPUT);
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);
  pinMode(A3, INPUT);
  pinMode(A4, INPUT);
  
...

}

void loop() {
  
...
  
  detectMAX();
  keyboard();
  resetMAX();
  
...

  Serial.print("varKeyboard: "); Serial.print(varKeyboard); Serial.print(" select: "); Serial.print(select); Serial.print(" reset: "); Serial.print(reset); Serial.print(" varMAX: "); Serial.println(varMAX);
}

Questo è il codice usato su Arduino UNO, per Arduino Micro semplicemente alcuni pin cambiano ma nulla d’altro.

Questo codice non stampa nulla sul monitor seriale.

Ma stai usando una SPI software ? Perché altrimenti NON capisco la dicharazione dei pin MOSI e SCK ... ::slight_smile:

Detto questo ... elimina tutte le librerie e prova a scrivere sulla seriale, dopo di che, includi una libreria alla volta e verfichi dove nasce il problema.

Secondo me NON è che non stampa, secondo me è che si pianta in un punto (qualche errore che non controlli) e resta fermo li ... ::slight_smile:

Guglielmo

Per usare le librerie Adafruit per la gestione dei display ho visto che bisogna richiamare quella libreria.
I pin che richiamo sono quelli che ho visto essere sul pinout corrispondenti a quelli che mi servono.

Ora ho provato questo codice dove ho eliminato le parti e le funzioni che fanno riferimento ad altre librerie:

#define sclk 13                                       /* clock della comunicazione SPI, in comune tra i due display. il pin è il 15 per Arduino Pro Micro. */
#define mosi 11                                       /* comunicazione unidirezionale master -> slave, in comune tra i due display. il pin è il 16 per Arduino Pro Micro. */
#define cs1 2                                         /* selezione dello slave 1, primo display. */
#define rs1 3                                         /* pin rs dello slave 1, primo display. */
#define rst1 4                                        /* reset dello slave 1, primo display. */
#define cs2 5                                         /* selezione dello slave 2, secondo display */
#define rs2 6                                         /* pin rs dello slave 2, secondo display */
#define rst2 7                                        /* reset dello slave 2, secondo display */


#define Vref  5.0                                     /* calibrazione della tensione di riferimento delle misure */

/*
siccome Arduino legge in entrata al massimo 5 v, devo dividere con un partitore di tensione la Vin.
Per fare ciò utilizzo una Ra = 681 k Ohm 1% e una Rb = potenziometro multigiro 200 k Ohm.
*/

/* 
Vin(max) viene calcolata con Vout(max) / (Rb / (Ra + Rb)). Quindi coef = (Ra + Rb) / Rb.
Ma siccome Ra è fisso, basta inserire il valore di Rb.
*/

#define Ra1 680000                                    /* valore in Ohm di Ra1. 681 k Ohm 1% */
#define Rb1 200000                                    /* valore in Ohm di Rb1. potenziometro multigiro 200 k Ohm */
#define Ra2 680000                                    /* valore in Ohm di Ra2. 681 k Ohm 1% */
#define Rb2 200000                                    /* valore in Ohm di Rb2. potenziometro multigiro 200 k Ohm */
#define Ra3 680000                                    /* valore in Ohm di Ra3. 681 k Ohm 1% */
#define Rb3 200000                                    /* valore in Ohm di Rb3. potenziometro multigiro 200 k Ohm */
#define Ra4 680000                                    /* valore in Ohm di Ra4. 681 k Ohm 1% */
#define Rb4 200000                                    /* valore in Ohm di Rb4. potenziometro multigiro 200 k Ohm */

float coef[4] = {((Ra1 + Rb1) / Rb1), ((Ra2 + Rb2) / Rb2), ((Ra3 + Rb3) / Rb3), ((Ra4 + Rb4) / Rb4)};   /* array di valori fissi dati dalle resistenze di ogni canale. */

float Vanalog[4] = {0.00, 0.00, 0.00, 0.00};          /* array di valori di tensione, convertiti in analogico tra 0 e 5 v. i valori sono a 2 cifre decimali. */
float VanalogMAX[4] = {0.00, 0.00, 0.00, 0.00};       /* array di valori di tensione massimi, convertiti in analogico tra 0 e 5 v. i valori sono a 2 cifre decimali. */

#define Sample 32                                     /* numero dei campionamenti */
#define Channel 4                                     /* numero dei canali */

int CH[4] = {A0, A1, A2, A3};                         /* array che per elementi ha i numeri dei pin per richiamare i pin analogici su Arduino Pro Micro. */
int Vdigital[4] = {0, 0, 0, 0};                       /* array di valori di tensione, convertiti in digitale tra 0 e 1023. i valori sono interi. */
int VdigitalMAX[4] = {0, 0, 0, 0};                    /* array di valori di tensione massimi, convertiti in digitale tra 0 e 1023. i valori sono interi. */ 

void readCH(byte n){
  unsigned int Somma;                                 /* variabile che contiene la somma di tutti i campionamenti (1023 * 32 = 32736 al massimo) */
  byte varSample;                                     /* variabile del campionamento */
  for (varSample <= (Sample - 1); varSample++;){      /* ciclo for per i campionamenti, da 0 a 31, quindi 32 campionamenti */
    Somma += analogRead(CH[n]);                       /* ad ogni ciclo aggiungi una lettura */
  }
  Vdigital[n] = Somma / Sample;                       /* salva nell'array la media dei campionamenti  */
  Somma = 0;                                          /* uscito dal ciclo for azzera la sommatoria per il prossimo richiamo della funzione */
  varSample = 0;                                      /* uscito dal ciclo for azzera la variabile da 0 a 31 per il prossimo richiamo della funzione */
}

void detectMAX(){
  for (byte varCH = 0; varCH < (Channel - 1); varCH++){   /* ciclo for per i canali */
    if(Vdigital[varCH] > VdigitalMAX[varCH]){         /* if per trovare il valore più alto */
      VdigitalMAX[varCH] = Vdigital[varCH];           /* se trovo un valore più alto del precedente lo salvo al posto del precedente */
    }
  }
}

#define KeyboardPin A4                                /* pin lettura tastiera */
byte varKeyboard = 0;                                 /* variabile byte che contiene il valore della lettura del pin anallogico della tastiera */
bool select = false;                                  /* variabile booleana per il pulsante select */
bool reset = false;                                   /* variabile booleana per il pulsante reset */

void keyboard(){
  varKeyboard = analogRead(KeyboardPin);              /* lettura del pin analogico della tastiera */
  if (varKeyboard > 767){select = true;}              /* se la lettura è maggiore del valore, allora il pulsante select è premuto e la variabile booleana è true */
  else {select = false;}                              /* in caso contrario la variabile booleana è false */
  if(varKeyboard < 767 && varKeyboard > 255){reset = true;}   /* se la lettura è minore del valore e allo stesso tempo maggiore di 255, allora il pulsante reset è premuto e la variabile mooleana è true */
  else {reset = false;}                               /* in caso contrario la variabile booleane è false */
}

byte varMAX = 0;                                      /* variabile che contine il numero del canale in base a quante volte schiaccio il tasto select */

void resetMAX(){
  if (select){varMAX++;}                              /* se select è true, aggiungi un valore alla variabile varMAX */
  for (varMAX; varMAX <= (Channel - 1);){             /* ciclo for, finché la variabile è minore o uguale del numero dei canali */
    if (reset){VdigitalMAX[varMAX] = 0;}              /* se reset è true, azzera l'elemento dell'array della tensione digitale corrispondente al canale selezionato */
  }
  varMAX = 0;                                         /* azzera la variabile */
}

void conversionDA(byte n){
  Vanalog[n] = ((Vref * Vdigital[n]) / 1023) * coef[n];      /* conversione tensione da digitale intero ad analogico decimale, da 0 a 22 Volt */
  VanalogMAX[n] = ((Vref * Vdigital[n]) / 1023) * coef[n];   /* conversione tensione MAX da digitale intero ad analogico decimale, da 0 a 22 Volt */
}


unsigned long refreshDisplayTime = micros();          /* salva i microsecondi una sola volta all'accensione del processore per il loop del refresh dei due display */
#define refreshDisplayLoop 2000                       /* tempo di clock per il loop del refresh dei due display */

void setup() {

  Serial.begin(9600);
    
  pinMode(sclk, OUTPUT);
  pinMode(mosi, OUTPUT);
  pinMode(cs1, OUTPUT);
  pinMode(rs1, OUTPUT);
  pinMode(rst1, OUTPUT);
  pinMode(cs2, OUTPUT);
  pinMode(rs2, OUTPUT);
  pinMode(rst2, OUTPUT);
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);
  pinMode(A3, INPUT);
  pinMode(A4, INPUT);

}

void loop() {
  
  readCH(0);
  readCH(1);
  readCH(2);
  readCH(3);
  
  detectMAX();
  keyboard();
  resetMAX();
  
  conversionDA(0);
  conversionDA(1);
  conversionDA(2);
  conversionDA(3);
  
  if(micros() - refreshDisplayTime > refreshDisplayLoop){
  refreshDisplayTime += refreshDisplayLoop;
  
  
  }

  Serial.print("varKeyboard: "); Serial.print(varKeyboard); Serial.print(" select: "); Serial.print(select); Serial.print(" reset: "); Serial.print(reset); Serial.print(" varMAX: "); Serial.println(varMAX);
}

Il problema è che anche utilizzando un altro sketch (che non allego perché molto lungo ma che trovate comunque nel topic “Orologio / Sveglia Radiocontrollato” nella sezione “Generale”) ho lo stesso problema con Arduino UNO, cioè che non leggo nulla sulla seriale.

Non vorrei fosse un problema software sul pc più che sulla programmazione della scheda.

Scusa è, ma scrivi un programmino in croce che manda un messaggio sulla seriale e hai bello che verificato !

Comunque, ripeto la mia opinione ...
... AdaFruit, spesso, nei suoi codici, in caso di errore grave (sensore NON rilevato, ecc. ecc.) fa un bel while(1) {}; ... ovvero blocca TOTALMENTE il programma che tanto NON potrebbe proseguire. Ho idea che tu sia incappato in uno di questi ...

Guglielmo

Ho provato quindi questo codice:

void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.println("Ciao");
}

E funziona, ma come mai il codice precedente non funziona? Ho levato tutte le librerie.

Inoltre il codice che ha sempre funzionato su Arduino UNO per la radio sveglia, non comunicava via seriale e non ne capisco il motivo poiché non ha nessuna libreria a parte la wire.h per la comunicazione i2c.

Ho caricato questo codice, del voltmetro, senza la parte di librerie e pin riconducibili a tali.

#define Vref  5.0                                     /* calibrazione della tensione di riferimento delle misure */

/*
siccome Arduino legge in entrata al massimo 5 v, devo dividere con un partitore di tensione la Vin.
Per fare ciò utilizzo una Ra = 681 k Ohm 1% e una Rb = potenziometro multigiro 200 k Ohm.
*/

/* 
Vin(max) viene calcolata con Vout(max) / (Rb / (Ra + Rb)). Quindi coef = (Ra + Rb) / Rb.
Ma siccome Ra è fisso, basta inserire il valore di Rb.
*/

#define Ra1 680000                                    /* valore in Ohm di Ra1. 681 k Ohm 1% */
#define Rb1 200000                                    /* valore in Ohm di Rb1. potenziometro multigiro 200 k Ohm */
#define Ra2 680000                                    /* valore in Ohm di Ra2. 681 k Ohm 1% */
#define Rb2 200000                                    /* valore in Ohm di Rb2. potenziometro multigiro 200 k Ohm */
#define Ra3 680000                                    /* valore in Ohm di Ra3. 681 k Ohm 1% */
#define Rb3 200000                                    /* valore in Ohm di Rb3. potenziometro multigiro 200 k Ohm */
#define Ra4 680000                                    /* valore in Ohm di Ra4. 681 k Ohm 1% */
#define Rb4 200000                                    /* valore in Ohm di Rb4. potenziometro multigiro 200 k Ohm */

float coef[4] = {((Ra1 + Rb1) / Rb1), ((Ra2 + Rb2) / Rb2), ((Ra3 + Rb3) / Rb3), ((Ra4 + Rb4) / Rb4)};   /* array di valori fissi dati dalle resistenze di ogni canale. */

float Vanalog[4] = {0.00, 0.00, 0.00, 0.00};          /* array di valori di tensione, convertiti in analogico tra 0 e 5 v. i valori sono a 2 cifre decimali. */
float VanalogMAX[4] = {0.00, 0.00, 0.00, 0.00};       /* array di valori di tensione massimi, convertiti in analogico tra 0 e 5 v. i valori sono a 2 cifre decimali. */

#define Sample 32                                     /* numero dei campionamenti */
#define Channel 4                                     /* numero dei canali */

int CH[4] = {18, 19, 20, 21};                         /* array che per elementi ha i numeri dei pin per richiamare i pin analogici su Arduino Pro Micro. */
int Vdigital[4] = {0, 0, 0, 0};                       /* array di valori di tensione, convertiti in digitale tra 0 e 1023. i valori sono interi. */
int VdigitalMAX[4] = {0, 0, 0, 0};                    /* array di valori di tensione massimi, convertiti in digitale tra 0 e 1023. i valori sono interi. */ 

void readCH(byte n){
  unsigned int Somma;                                 /* variabile che contiene la somma di tutti i campionamenti (1023 * 32 = 32736 al massimo) */
  byte varSample;                                     /* variabile del campionamento */
  for (varSample <= (Sample - 1); varSample++;){      /* ciclo for per i campionamenti, da 0 a 31, quindi 32 campionamenti */
    Somma += analogRead(CH[n]);                       /* ad ogni ciclo aggiungi una lettura */
  }
  Vdigital[n] = Somma / Sample;                       /* salva nell'array la media dei campionamenti  */
  Somma = 0;                                          /* uscito dal ciclo for azzera la sommatoria per il prossimo richiamo della funzione */
  varSample = 0;                                      /* uscito dal ciclo for azzera la variabile da 0 a 31 per il prossimo richiamo della funzione */
}

void detectMAX(){
  for (byte varCH = 0; varCH < (Channel - 1); varCH++){   /* ciclo for per i canali */
    if(Vdigital[varCH] > VdigitalMAX[varCH]){         /* if per trovare il valore più alto */
      VdigitalMAX[varCH] = Vdigital[varCH];           /* se trovo un valore più alto del precedente lo salvo al posto del precedente */
    }
  }
}

#define KeyboardPin A10                               /* pin lettura tastiera */
byte varKeyboard = 0;                                 /* variabile byte che contiene il valore della lettura del pin anallogico della tastiera */
bool select = false;                                  /* variabile booleana per il pulsante select */
bool reset = false;                                   /* variabile booleana per il pulsante reset */

void keyboard(){
  varKeyboard = analogRead(KeyboardPin);              /* lettura del pin analogico della tastiera */
  if (varKeyboard > 767){select = true;}              /* se la lettura è maggiore del valore, allora il pulsante select è premuto e la variabile booleana è true */
  else {select = false;}                              /* in caso contrario la variabile booleana è false */
  if(varKeyboard < 767 && varKeyboard > 255){reset = true;}   /* se la lettura è minore del valore e allo stesso tempo maggiore di 255, allora il pulsante reset è premuto e la variabile mooleana è true */
  else {reset = false;}                               /* in caso contrario la variabile booleane è false */
}

byte varMAX = 0;                                      /* variabile che contine il numero del canale in base a quante volte schiaccio il tasto select */

void resetMAX(){
  if (select){varMAX++;}                              /* se select è true, aggiungi un valore alla variabile varMAX */
  for (varMAX; varMAX <= (Channel - 1);){             /* ciclo for, finché la variabile è minore o uguale del numero dei canali */
    if (reset){VdigitalMAX[varMAX] = 0;}              /* se reset è true, azzera l'elemento dell'array della tensione digitale corrispondente al canale selezionato */
  }
  varMAX = 0;                                         /* azzera la variabile */
}

void conversionDA(byte n){
  Vanalog[n] = ((Vref * Vdigital[n]) / 1023) * coef[n];      /* conversione tensione da digitale intero ad analogico decimale, da 0 a 22 Volt */
  VanalogMAX[n] = ((Vref * Vdigital[n]) / 1023) * coef[n];   /* conversione tensione MAX da digitale intero ad analogico decimale, da 0 a 22 Volt */
}

void setup() {

  Serial.begin(9600);
  
  pinMode(18, INPUT);
  pinMode(19, INPUT);
  pinMode(20, INPUT);
  pinMode(21, INPUT);
  pinMode(A10, INPUT);

}

void loop() {
  
  readCH(0);
  readCH(1);
  readCH(2);
  readCH(3);
  
  detectMAX();
  keyboard();
  resetMAX();
  
  conversionDA(0);
  conversionDA(1);
  conversionDA(2);
  conversionDA(3);

  Serial.print("varKeyboard: "); Serial.print(varKeyboard); Serial.print(" select: "); Serial.print(select); Serial.print(" reset: "); Serial.print(reset); Serial.print(" varMAX: "); Serial.println(varMAX);
}

Non funziona.

Ma se nella sezione loop scrivo soltanto:

void loop() {

  Serial.print("varKeyboard: "); Serial.print(varKeyboard); Serial.print(" select: "); Serial.print(select); Serial.print(" reset: "); Serial.print(reset); Serial.print(" varMAX: "); Serial.println(varMAX);
}

Mantenendo inalterato il resto del codice, la comunicazione avviene correttamente.

Ho poi eliminato le 3 funzioni principali ed ho scoperto che la funzione resetMAX(); è quella che crea problemi:

byte varMAX = 0;                                      /* variabile che contine il numero del canale in base a quante volte schiaccio il tasto select */

void resetMAX(){
  if (select){varMAX++;}                              /* se select è true, aggiungi un valore alla variabile varMAX */
  for (varMAX; varMAX <= (Channel - 1);){             /* ciclo for, finché la variabile è minore o uguale del numero dei canali */
    if (reset){VdigitalMAX[varMAX] = 0;}              /* se reset è true, azzera l'elemento dell'array della tensione digitale corrispondente al canale selezionato */
  }
  varMAX = 0;                                         /* azzera la variabile */
}

Comunque adesso ho scoperto che non è un problema di software, driver o altro ma è il problema di quella specifica funzione che, non so il motivo, blocca tutto. Ho provato a ricaricare tutto il firmware comprese le librerie, cancellando il richiamo nel loop di quella specifica funzione e la seriale c'è.

Quella specifica funzione l'ho scritta senza pensarci su troppo e dubito che funzioni per come l'ho pensata io, ma appunto attraverso il debug avrei voluto capire. La cosa che però non mi è chiara è come mai quella funzione blocca la comunicazione seriale.

Io praticamente volevo fare una funzione dove quando premo il tasto "select" (select è una variabile booleana che va su true nel momento in cui ho 5 volt su un'entrata analogica) la variabile varMAX mi varia da 0 a 3, per scegliere l'elemento di un array di 4 elementi. Arrivato a 3 la pressione successiva mi porta a zero la variabile varMAX. Selezionato l'elemento che mi interessa, se premo il pulsante "reset" (reset è una variabile booleana che va su true nel momento in cui ho 2.5 volt sulla stessa entrata analogica di prima) mi si azzera l'elemento dell'array selezionato.

Inoltre mi interessa avere un numero da 0 a 3 per varMAX siccome mi piacerebbe inserire un asterisco vicino ai volt massimi stampati sui due display come se fosse un puntatore per capire quale canale sto selezionando.

Questo dovrebbe essere il codice necessario per fare quello che voglio fare:

byte varMAX = 0;                                      /* variabile che contine il numero del canale in base a quante volte schiaccio il tasto select */

void resetMAX(){
  
  if (select) {if (varMAX <= (Channel - 1)) varMAX++; else varMAX = 0;}   /* se select è true, se la variabile è minore o uguale del numero dei canali aggiungi uno, sennò è uguale a 0 */
  if (reset) {VdigitalMAX[varMAX] = 0;}               /* se reset è true, azzera l'elemento dell'array della tensione digitale corrispondente al canale selezionato */

}

Sembra funzionare, perlomeno non mi blocca il codice.

Beh non essendo un ciclo ora sicuramente non blocca nulla.
Quel for() che avevi messo prima era deleterio perché dato che nulla sembrava cambiare varMAX non usciva mai.

Ok capito.
Utilizzo il ciclo for anche in queste altre due funzioni:

void readCH(byte n){
  unsigned int Somma;                                 /* variabile che contiene la somma di tutti i campionamenti (1023 * 32 = 32736 al massimo) */
  byte varSample;                                     /* variabile del campionamento */
  for (varSample <= (Sample - 1); varSample++;){      /* ciclo for per i campionamenti, da 0 a 31, quindi 32 campionamenti */
    Somma += analogRead(CH[n]);                       /* ad ogni ciclo aggiungi una lettura */
  }
  Vdigital[n] = Somma / Sample;                       /* salva nell'array la media dei campionamenti  */
  Somma = 0;                                          /* uscito dal ciclo for azzera la sommatoria per il prossimo richiamo della funzione */
  varSample = 0;                                      /* uscito dal ciclo for azzera la variabile da 0 a 31 per il prossimo richiamo della funzione */
}

void detectMAX(){
  for (byte varCH = 0; varCH < (Channel - 1); varCH++){   /* ciclo for per i canali */
    if(Vdigital[varCH] > VdigitalMAX[varCH]){         /* if per trovare il valore più alto */
      VdigitalMAX[varCH] = Vdigital[varCH];           /* se trovo un valore più alto del precedente lo salvo al posto del precedente */
    }
  }
}

Sono penalizzato in qualche modo? Queste comunque ciclano e quindi escono dal ciclo for, ma mi bloccano il resto del codice?

Questo perché adesso ho provato a caricare il codice completo, ho dato una temporizzazione per la lettura dei tasti di 100 millisecondi così non mi varia all’impazzata il tasto select, ho dato una temporizzazione di 20 millisecondi alle funzioni che mi stampano sui display così da avere un aggiornamento veloce, ma chiamando la seriale al di fuori di queste due temporizzazioni, comunque mi si aggiorna lentamente.
Togliendo le funzioni che mi stampano sui display la seriale mi si aggiorna molto velocemente.
Quindi ne deduco che il collo di bottiglia per la velocità sia il print sui display.

Mi chiedevo se la stessa cosa potesse succedere con i cicli for chiamati in quelle due funzioni di prima.

… ti è stato segnalato il problema nella FOR perché:

for (varMAX; varMAX <= (Channel - 1);){             /* ciclo for, finché la variabile è minore o uguale del numero dei canali */

… la FOR ha tre elementi, valore iniziale, valore finale e incremento … tu vedi l’incremento ? ? ? E come pensi dal valore inziale possa raggiungere il valore finale ? ? ?

Così NON lo raggiunge mai e resta fisso in quella FOR !

Guglielmo

Eh? Qualcosa non mi torna in quest’altra for():

byte varSample;
for (varSample <= (Sample - 1); varSample++;){

Il primo parametro è l’inizializzazione (“varSample <= (Sample - 1)” ?), il secondo la condizione per il ciclo (“varSample++” ??), il terzo la reinizializzazione (vuoto!).

Questa quindi equivale di fatto a:

varSample <= (Sample - 1); 
while (varSample++) {
 ...
}

Mi sa che hai messo un punto e virgola sbagliato, e poi non inizializzi il valore iniziale di varSample.
Forse se “Sample” è il numero di campionamenti, volevi forse fare:

for (byte varSample=0;varSample < Sample; varSample++) {

che equivale a:

byte varSample = 0;
while (varSample < Sample) ) {
 ...
 varSample++
}

Era questo che volevi fare?

Insomma di fatto leggi “Sample” campioni dalla porta anlogica passata a parametro e questo è ok, ma leggerli così tutti di seguito a che serve? Devi metterci un minimo di delay tra una e l’altra. Inoltre azzerare le variabili Somma e varSample non serve a nulla, sono locali alla funzione e si distruggono all’uscita dalla stessa.
Io farei così:

void readCH(byte n){
  unsigned int Somma;
  for (byte i=0; i < Sample; i++;){
    Somma += analogRead(CH[n]);
    delay(5);
  }
  Vdigital[n] = Somma / Sample;
}

docdoc ... racchiudi TUTTI i pezzi di codice nei tag CODE ... altrimenti il forum fa un gran casino ...

Guglielmo

docdoc:
Eh? Qualcosa non mi torna in quest’altra for():

byte varSample;
for (varSample <= (Sample - 1); varSample++;){

Il primo parametro è l’inizializzazione (“varSample <= (Sample - 1)” ?), il secondo la condizione per il ciclo (“varSample++” ??), il terzo la reinizializzazione (vuoto!).

Questa quindi equivale di fatto a:

varSample <= (Sample - 1);
while (varSample++) {

}

Mi sa che hai messo un punto e virgola sbagliato, e poi non inizializzi il valore iniziale di varSample.
Forse se “Sample” è il numero di campionamenti, volevi forse fare:

for (byte varSample=0;varSample < Sample; varSample++) {

che equivale a:

byte varSample = 0;
while (varSample < Sample) ) {

varSample++
}

Era questo che volevi fare?

Insomma di fatto leggi “Sample” campioni dalla porta anlogica passata a parametro e questo è ok, ma leggerli così tutti di seguito a che serve? Devi metterci un minimo di delay tra una e l’altra. Inoltre azzerare le variabili Somma e varSample non serve a nulla, sono locali alla funzione e si distruggono all’uscita dalla stessa.
Io farei così:

void readCH(byte n){

unsigned int Somma;
  for (byte i=0; i < Sample; i++;){
    Somma += analogRead(CH[n]);
    delay(5);
  }
  Vdigital[n] = Somma / Sample;
}

Si esattamente, l’idea è quella di leggere 32 volte un canale “n” e poi fare la media.

Perché inserire un delay bloccando poi tutto quanto? Non posso invece aumentare il numero dei campioni?

Per quanto riguarda l’azzeramento di Somma era perché avevo letto in una discussione precedente che era sempre meglio farlo ma mi rendo conto ora che effettivamente in quel topic non veniva fatta una funzione ad hoc con variabile interna, ma veniva usata una variabile globale.

Comunque la tua funzione risponde con un errore expected “)” before “;” sulla riga del for.

gpb01:

docdoc ... racchiudi TUTTI i pezzi di codice nei tag CODE ... altrimenti il forum fa un gran casino ...

Ho fatto una prova, ed effettivamente viene bene anche per piccoli pezzi di codice, è che in "Anteprima" i blocchi code non li renderizza come nel forum, ma li faceva vedere sempre grandi quasi mezza pagina l'uno anche se contenevano una sola riga.
Scusa, farò come dici.

docdoc:
Ho fatto una prova, ed effettivamente viene bene anche per piccoli pezzi di codice, è che in "Anteprima" i blocchi code non li renderizza come nel forum, ma li faceva vedere sempre grandi quasi mezza pagina l'uno ...

Si, li fa vedere male (non so se solo con Chrome o anche con altri browser), ma poi se li pubblichi e guardi la pagina, sono apposto :wink:

Guglielmo

ricki158:
Comunque la tua funzione risponde con un errore expected “)” before “;” sulla riga del for.

  for (byte i=0; i < Sample; i++;){

//                              ^

c’è sempre l’ultimo ; di troppo :wink:

gpb01:
Si, li fa vedere male (non so se solo con Chrome o anche con altri browser), ma poi se li pubblichi e guardi la pagina, sono apposto :wink:

Guglielmo

anche con firefox, ma non sempre