[Risolto] Problema reset inaspettato compilando con Windows 10

Buongiorno a tutti.
Scrivo per sottoporvi una questione che mi sta facendo uscire pazzo…

Problema:

ho scritto uno sketch dove nel loop vado a leggere quale pulsante sto premendo in un array di 12 pulsanti, poi a seconda dello stato di alcune variabili vado a richiamare tre funzioni, ognuna con degli switch-case al suo interno i quali in base al pulsante letto in precedenza porteranno dei valori in una ulteriore funzione. Più sotto allego il codice.
Se compilo e carico lo sketch su Arduino(Mega2560) con un pc che ho al lavoro (win Otto) tutto va bene, al contrario se compilo e carico (senza ricevere errori da parte dell’IDE) con i due pc che ho a casa (win 10) quando nel loop vado a richiamare le funzioni si blocca l’esecuzione del programma e Arduino si resetta.

Ho notato che, invertendo l’ordine delle funzioni nel loop, si blocca sempre quando richiamo la seconda o la terza funzione e nel serial monitor mi restituisce un punto interrogativo ruotato e si resetta.
Qualsiasi cosa io scriva nella seconda funzione, anche un semplice int a=0; si blocca.
N.B. il punto interrogativo che mi restituisce il serial monitor è girato in senso orizzontale e non verticale, in pratica come se lo si guardasse in uno specchio.

Quello che ho fatto io finora:

  • ho reinstallato driver ed IDE in tutti nei pc ma il problema persiste;
  • ho infarcito il codice di serial.print per verificarne lo scorrimento ed il punto esatto del blocco;
  • ho ridigitato da zero il loop e le funzioni;
  • ho controllato e ricontrollato tutti cablaggi dei pulsanti connessi con la scheda, in effetti all’inizio
    pensavo potesse essere un problema di disturbi elettromagnetici, vista anche la quantità e la lunghezza
    di alcuni cavi (intorno ai 30 cm);

Utilizzo una scheda Mega 2560 originale
Cosa posso provare a fare secondo voi??? Io non credo sia un problema di scrittura dello sketch nell’IDE ma un qualche problema con Windows 10.

Questa la parte di codice nel loop relativa alla lettura dei pulsanti e l’indirizzamento verso le tre funzioni in base allo stato di alcune variabili:

for (int row = 0; row < numRows; row++)    
    if (digitalRead(rowPins[row]) == LOW)    
    {
      
      delay(debounceTime);                     
      while (digitalRead(rowPins[row]) == LOW); 
      key = row + 1;
    }
  }

  
  if (key != 0)
  {
     if (!stato_mode && !stato_memory && !stato_muteby )
      {
        sw_readpatch(key);
        key = 0;
      }

    if ((stato_mode) && (!stato_memory) && (!stato_muteby))
     {
       sw_manual(key);
       key = 0;
     }

    if (stato_memory && stato_dsp)
     {
       sw_memory(key);
       key = 0;
     }
  }
}

Se qui sopra scambio di posizione “sw_readpatch(key);” con “sw_manual(key);” mi funzionerà solo la funzione messa nella prima posizione.

Qui una delle tre funzioni con gli switch-case richiamate, ne metto una per comodità ma sono scritte tutte in ugual maniera, cambiano solo i nomi delle variabili o delle funzioni.

void sw_readpatch(int patch)
    {
      if (patch)
    {
      patch_att = patch;

        switch (patch)
      {
        case 1:
          readpatch(10, 0);
          break;
        case 2:
          readpatch(25, 1);
          break;
        case 3:
          readpatch(40, 2);
          break;
        case 4:
          readpatch(55, 3);
          break;
        case 5:
          readpatch(70, 4);
          break;
        case 6:
          readpatch(85, 5);
          break;
        case 7:
          readpatch(100, 6);
          break;
        case 8:
          readpatch(115, 7);
          break;
        case 9:
          readpatch(130, 8);
          break;
        case 10:
          readpatch(145, 9);
          break;
        case 11:
          readpatch(160, 10);
          break;
        case 12:
          readpatch(175, 11);
          break;
      }
    }
  }

Qui la funzione dopo lo “smistamento” da parte dei case.

void readpatch(int addr, int led)
{
  int incremento = 0;
  if (banco_prov > 0)
  {
    switch (banco_prov)
    {
      case 1:
        incremento = 0;
        break;

      case 2:
        incremento = 190;
        break;

      case 3:
        incremento = 390;
        break;
    }
  }

  for (int i; i < numberOfPedal; i++)
  {
    digitalWrite(LedRelePin[i], EEPROM.read(addr + i + incremento));
    digitalWrite(PatchledPin[i], LOW);
    digitalWrite(PatchledPin[led], HIGH);
  }

  latchn = EEPROM.read(addr + 12 + incremento);
  bancon = banco_prov;
  patchn = led + 1;
  stato_banco = 0;
  digitalWrite(latch_rele_pin, latchn);
  if (stato_dsp == 1)
  {
    lcd.clear();
    stato_dsp = 0;
  }
  gestione_lcd_main(patchn, bancon, moden, latchn);




}

Vi ringrazio in anticipo per l’attenzione e sopratutto per la pazienza.
Buona Giornata,
Gabriele.

Hai usato delle String?
Gli indici degli array rientrano nelle dimensioni degli stessi?

Ciao Datman, si ho dichiarato delle String qui prima del setup:

String modalita[3] =
{
  {"Preset"},
  {"Manual"},
  {"Memory"}
};
String latch_mode[2] =
{
  {"OFF"},
  {"ON "}
};
String pulse_mode[2] =
{
  {"  "},
  {"ON"}
};

e le ho usate in altre funzioni diverse da quelle citate prima, ovvero qui:

void gestione_lcd_main(int patch, int banco, int mode, int ctrl)
{
  lcd.setCursor(0, 0); lcd.print("Patch:");
  lcd.setCursor(12, 0); lcd.print("Banco:");
  lcd.setCursor(0, 1); lcd.print("Modalita':");
  lcd.setCursor(0, 2); lcd.print("Ctrl Pulse:");
  lcd.setCursor(0, 3); lcd.print("Ctrl Latch:");
  lcd.setCursor(7, 0); lcd.print("  "); lcd.setCursor(7, 0); lcd.print(patch);
  lcd.setCursor(19, 0); lcd.print(banco);
  lcd.setCursor(12, 1); lcd.print(modalita[mode]);
  //lcd.setCursor(6,2); lcd.print(latch_mode[pulsen]);
  lcd.setCursor(12, 3); lcd.print(latch_mode[ctrl]);
}

Adesso che hai nominato gli array, nelle dichiarazioni ho notato questo però:

int LedRelePin[14] = {33, 2, 35, 4, 37, 6, 39, 8, 41, 10, 43, 12}

un array di dimensione 14 ma con 12 valori al suo interno.
A parte la mega svista non capisco come ci sia finito quel 14 li dentro.... potrebbe essere questo che provoca il reset??

Grazie per l'attenzione!!
Gabriele.

Stavo guardando le versioni precedenti degli sketch che comunque erano funzionanti e quell'array è stato sempre di grandezza [14] ma con 12 valori..... aiuto....
A proposito altro particolare: altri tipi ci sketch riesco a caricarli e sono ben funzionanti, solo questo mi da problemi

Gabriele

Più volte si è detto che "è male" (cfr. "MAI INCROCIARE I FLUSSI!!!" :slight_smile: ) usare String. Qui, ad esempio, spiegano perché:
the evils of arduino strings

... avete già notato/letto QUESTO mio thread ? :slight_smile:

Guglielmo

Appunto: quella è una della volte. :slight_smile:

mmm interessante, no Guglielmo non avevo notato il tuo post effettivamente.... Stasera mi leggerò con calma quello che riguarda la SafeString e vedrò di capirci qualcosa.

Proverò anche a fare una cosa come prova: tolgo dallo sketch tutta la parte relativa alle String e vedo se funziona.

Però... perchè quello stesso identico sketch caricato su Mega2560 un paio di mesi fa funzionava alla perfezione ed ora no??

Grazie di tutte le dritte carissimi!!
Gabriele

Perché... E' MEGA! :slight_smile:

Comunque, per quello che devi fare, String non ti serve: metti un if/else o uno switch/case che, a seconda di un numero che indica il modo di funzionamento, visualizzi "preset" o "manual" o "memory".

lcd.setCursor(12, 1);
switch(modo)
{
case 1:
  lcd.print("preset");
  break;
case 2:
  lcd.print("manual");
  break;
case 3:
  lcd.print("memory");
  break;
}

:smiley:
Nel senso è uno sketch grande??? :grinning:

Questo mi dice dopo la compilazione:

Lo sketch usa 10752 byte (4%) dello spazio disponibile per i programmi. Il massimo è 253952 byte.
Le variabili globali usano 1060 byte (12%) di memoria dinamica, lasciando altri 7132 byte liberi per le variabili locali. Il massimo è 8192 byte.

O perchè è Mega la scheda???

Datman sicuramente con if/else o switch/case mi viene più semplice elaborare lo sketch, proverò anche questa strada.

Grazie mille!
Gabriele

Perché è "Mega" la scheda!
ATmega328 vs. ATmega2560

Afferrato!!!!! :smiley:

N.B.: "preset", "manual" e "memory" sono tutte di 6 caratteri. Se non fosse stato così, avrei dovuto lasciare degli spazi nelle scritte più corte per cancellare le lettere residue delle altre scritte più lunghe.

io vorrei vedere il programma completo, perché c’è qualcosa che non mi convince

comunque prendendo per buono (non se ne abbia a male lo OP) che in effetti compilando con due differenti installazioni si ottengono due differenti risultati io guarderei bene impostazioni e similia

oppure, non so se su windows è possibile, ma credo di si, farei una installazione “portable” e me la porterei in giro.
ovvero la copio su chiavetta e me la porto sul PC che mi serve, così sono sicuro che librerie, impostazioni e altri ammeniccoli sono tutti “uguali uguali”, anzi, non “uguali”: proprio gli stessi

invece per l’uso degli oggetti String:

per non dover cambiare il programma in ogni punto dove hai usato una String basta sostituire la dichiarazione dell’array di String con una dichiarazione e inizializzazione di array di puntatori a carattere

provare per credere

// di Nelson-StandardOil
// IDE 1.8.10
// Progetto:
// Scopo:
// Data inizio lavori:


char * stringhe[] = {"ma che bel ", "castello maccondiro", "dirondello"};
#define STRINGHE sizeof stringhe /sizeof stringhe[0]



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

   for (byte i = 0; i < STRINGHE; i++)
   {
      Serial.println(stringhe[i]);
   }
}

void loop(void)
{
   Serial.println("programma finito");

   while (1);
}

come si vede non c’é bisogno di cambiare molto nel programma originale

in effetti così facendo le stringhe non sarebbero modificabili secondo i sacri testi, io avevo provato e andava ma “non è cosa”

invece se li si vuole poter modificare serve dichiarare un array bidimensionale di caratteri, ma diventa più difficile inizializzarlo e gestire stringhe di lunghezza tra di loro differente

per solo sostituire le scritte invece che modificarle (notare la sottile differenza)
basta cambiare il puntatore, facendolo puntare alla scritta “nuova”

Ciao, Standardoil.
Sì, l'ho fatto per correggere alcune String in programmi che avevo scritto nei miei primi tempi. Funziona :slight_smile:
Forse, però, String permette certe operazioni che non possono essere fatte con char*?... Comunque ho già deciso di non usarlo mai più :slight_smile:

La classe String permette tante cose che con char * non sono possibili, ma se si tratta di stringhe statiche sono facilmente sostituibili, e con qualche sbattimento anche per scritte dinamiche (dove per statico e dinamico non intendo la classe di memoria, solo il contenuto)

invece devo vedere bene come sarebbe che la nuova safestring sia, appunto, safe

Si, però però però, c'è un però!
Eliminare String è cosa buona e giusta, nostro dovere e fonte di salvezza...
Però non dovrebbe centrare con il problema dello OP.
Ha memoria a stra.ottere e dice due cose, almeno la prima forse non la dice lui ma io, mi smentirà se ho sbagliato:

  1. il problema è sistematico e non dopo un po' di tempo.
  2. il problema si ha se si compila con una macchina e non con le altre.
    Ora, sebbene io sono dell'avviso che sia nostro dovere e fonte di salvezza debellare anche un'altra cosa oltre alla classe String, piccolo suggerimento... inizia con W... dubito che in questo immondo ammasso di strati di cipolla siano riusciti a inserire qualcosa che comprometta il compilato producendo un problema di questo tipo. E' più probabile che si sia corrotto il compilatore usato dall'IDE.

Quindi, va bene eliminare String perchè è scritto anche nell'undicesimo comandamento, ma mi piacerebbe capire e avere conferma del fatto che le varie installazioni sui PC siano uguali, es. stessa versione dell'IDE e che effettivamente, compilando con uno si ottenga il problema e compilando con gli altri no, in modo sistematico.

Per sistematico, intendo che compilando con una versione ci si possano scommettere sopra parecchi soldi sulla presenza o meno del problema, senza patemi perchè si è sicuri di vincere!

L'idea del mio socio, di provare un'installazione "portable" mi pare ottima, cercherei di percorrere questa strada.

L'array di 14 per contenere 12 non da problemi, oltre a sprecare spazio, altro non fa. Sarebbe stato catastrofico il contrario.
Poi, magari, vedendo il resto del codice si scopra un array da 10 che tiene 11 valori...

Maurizio

Buonasera a tutti!!
Per ora ho fatto questo:
ho "messo da parte", commentando con //, tutte le dichiarazioni di String e ogni riga dove viene usata tale stringa, corretto l'array con valore 14 portandolo a 12.
Risultato: si resetta e ricomincia da capo….

Rispondo a maubarzi:
credo che il problema sia sistematico nel senso che sistematicamente compilo e carico con il pc con Win 8 e tutto va bene, compilo e carico con i due pc con Win 10 e tutto va male…. e mi ci gioco la camicia :smiley:
Nei mesi scorsi ho compilato e caricato lo sketch finito con i due pc Win 10 e tutto funzionava, tant'è che l'ho messo da parte ed ho usato la scheda per altre cose.
Pochi giorni fa ho recuperato lo sketch e sono nati i problemi solo su i pc con Win 10 dove ho installato l'ultima versione dell'ide 1.8.12 scaricata di recente, che non è quella con cui ho compilato due mesi fa.
Nel pc con Win 8 non ricordo che versione ho, probabilmente è la precedente a quella più recente.

Per installazione portable si intende una chiavetta con sketch e versione di IDE installata da usare per ogni compilazione??

Di solito il mio sistema è di caricare lo sketch, magari da casa dove ci ho lavorato, su google drive per poi riscaricarlo al lavoro dove ci posso lavorare ulteriormente. E ovviamente viceversa.

Aggiornamento: poco fa mentre scrivevo qui ho cancellato tutto il contenuto della funzione (al suo interno: if/switch/case) scrivendoci un semplice serial.print, quindi da così:

void sw_manual(int val)
 { 
    if (val)
    {Serial.print("switch manual chiave ");Serial.println(val);delay(1000);
    /*switch (val)
    {//Serial.println("switch manual 3");//delay(1000);
        case 1:Serial.println("leggo manual 1");
          manual(0);  /* (Fra parentesi la variabile che verrà portata nella routine, ovvero il numero della patch + 1*/
          break;
        case 2: Serial.println("leggo manual 2");
          manual(1);
        break;        
        case 3:Serial.println("leggo manual 3");
          manual(2);         
        break;
        case 4:Serial.println("leggo manual 4");
          manual(3);         
        break;
        case 5:Serial.println("leggo manual 5");
          manual(4);         
        break;
        case 6:Serial.println("leggo manual 6");
          manual(5);        
        break;
        case 7:Serial.println("leggo manual 7");
          manual(6);         
        break;
        case 8:Serial.println("leggo manual 8");
          manual(7);
          break;
        case 9:Serial.println("leggo manual 9");
          manual(8);
          break;
        case 10:Serial.println("leggo manual 10");
          manual(9);
          break;
        case 11:Serial.println("leggo manual 11");
          manual(10);
          break;
        case 12:Serial.println("leggo manual 12");
          manual(11);
          break;
      }Serial.println("fine switch manual");
    }
    }

a così:

void sw_manual(int val)
 { 
    Serial.print("switch_manual"); Serial.print(val);
    }

e non si resetta, il flusso dello sketch continua.

Oggi qualcuno mi ha parlato di watchdog....può entrarci qualcosa con il mio problema??

Gabriele