Leggere serie di dati da SDcard e processarli uno ad uno

Salve a tutti,
in precedenza avevo chiesto aiuto per scrivere un programma che leggesse una riga di dati da un array a seconda della posizione dell'encoder e inviasse un set di frequenze ad un modulo DDS, grazie al vostro aiuto il programma (allegato) funziona perfettamente. Ora siccome sono limitato dal numero dei possibili menù (e dalla memoria di arduino), vorrei scrivere una singola riga dell'array del programma tipo:

60,1330,5270,10890,90000,379930,425000,571000,829000,932000 (sono dati long)

in un file txt nella scheda SD separati da una virgola o punto e virgola leggerli ad uno ad uno e processarli come ho fatto per la riga dell'array nel programma.
Ora per quanto abbia cercato su internet non sono riuscito a trovare un esempio che mi facesse quello di cui ho bisogno.
Al di là dell'inizializzazione della scheda sd che ho compreso, qualcuno potrebbe indicarmi la via da seguire?
P.S. non riesco a postare il codice perchè eccede i 9000 caratteri, lo riduco e lo posto fra poco

ho ridotto l’array da 38 righe a 5 per poterlo postare:

/*questo programma usa un encoder rotativo per selezionare una voce di menù, e alla pressione del pulsante
   invia ad un modulo DDS un set di frequenze a seconda del programma scelto, alla fine del programma memorizza 
   la voce di menù usata nella EEPROM*/

#include <EEPROM.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <LiquidCrystal.h>
#include <DDS.h>           /* descrizione: http://m0xpd.blogspot.com/2014/03/dds-and-duedds-libraries.html
                              download:    https://github.com/m0xpd/DDS */

const int Stop = 3;                                              // Pin Pulsante di stop

const int Buzzer = 2;                                            // Pin Buzzer                                            

const int rs = 7, e = 8, d4 = 9, d5 = 10, d6 = 11, d7 = 12;      // costanti pin per display LCD

const int W_CLK = A3, FQ_UD = A2, DATA = A1, RESET = A0;         // costanti pin per modulo DDS

LiquidCrystal lcd(rs, e, d4, d5, d6, d7);                        // assegno i pin al display LCD

DDS dds(W_CLK, FQ_UD, DATA, RESET);                    // assegno i pin al modulo DDS

//prima riga del menù sul display

char* Menu[] = {"",  "Menu1           ", "Menu2           ", "Menu3           ", 
                     "Menu4           ", "Menu5           "
               };

//Array contenente i valori di frequenza caricati nella memoria Flash usando PROGMEM

const uint32_t  Frequenze[38][10] PROGMEM = {
{555, 827, 919, 1009, 1407, 7767, 16628, 18670, 19566,  28729},
{700, 5690, 7250, 30000, 55540, 93500,  322060, 515700, 689930, 970500},
{152, 442, 751,  797, 1011, 1146, 8146,  20313, 571000, 2596255},
{60, 1330, 5270, 10890, 90000, 379930, 425000,  571000, 829000, 932000},
{727, 1000, 2128, 25000, 30000, 35000, 45000, 50000, 60000, 75000}
};

int freq;
int encoder = EEPROM.read (0);         // posizione di start dell'encoder memorizzato nella EEPROM
bool letturaPrec = HIGH;               // Variabile lettura encoder
unsigned long startTime;               // Variabile inizio conteggio
unsigned long contTempo;               // Variabile di conteggio tempo
unsigned long WorkTime = 180000;       // Variabile di preset del tempo
unsigned long stampa;                  // variabile che contiene i valori di frequenza da stampare su lcd


void setup() {
  pinMode (W_CLK, OUTPUT);
  pinMode (FQ_UD, OUTPUT);
  pinMode (DATA, OUTPUT);
  pinMode (RESET, OUTPUT);
  
  pinMode (2, OUTPUT);
  pinMode (3, INPUT);
  pinMode (4, INPUT_PULLUP);     // pin DT encoder
  pinMode (5, INPUT_PULLUP);     // pin CLK encoder
  pinMode (6, INPUT_PULLUP);     // pin pulsante encoder
  lcd.begin(16, 2);              // inizializza LCD

  dds.init();                    // inizializza modulo DDS
  dds.trim(125000000);           /*opzionale per la taratura fine della frequenza dell'oscillatore
                                   rispetto alla reale frequenza del quarzo. Esempio: (125000017)*/

  }

void loop() {
  if (digitalRead(4) == LOW || digitalRead(5) == LOW) {    // Se l'encoder viene ruotato
        
        lcd.setCursor(0, 1);
        lcd.print("                ");                    // Cancella la seconda riga del display
     }
  
  if (digitalRead(6) == HIGH) {
    byte n = digitalRead(5);                  // assegna alla variabile "n" il livello letto dal pin CLK dell'encoder
    if ((letturaPrec == HIGH) && (n == LOW))  // rileva rotazione dell'encoder (fronte discesa CLK)
    {
      if (digitalRead(4) == HIGH) {           // se il pin DT è alto direzione decremento
        encoder--;                            // decrementa il valore di encoder
        if (encoder == 0) encoder = 38;       // decrementa circolarmente da 38 a 1

      } else {

        encoder = (encoder % 38) + 1;         // incrementa circolarmente da 1 a 38
      }

    }
    letturaPrec = n;

    if (digitalRead(6) == HIGH)               // se il pulsante non è premuto

      lcd.setCursor(0, 0);
      lcd.print(Menu[encoder]);               /* Stampo  nella  prima  riga la voce di menù
                                                 corrispondente alla posizione dell'encoder */


    if (digitalRead(6) == LOW)                // se il pulsante viene premuto
      for (freq = 0; freq < 10;) {            // ciclo di lettura della riga
        lcd.setCursor(0, 1);
        lcd.print("RUN           Hz");        // Stampa Prefisso e suffisso sulla seconda riga lcd

        stampa = (pgm_read_dword(& Frequenze[encoder - 1][freq]));   /* Legge il valore di frequenza dalla matrice
                                                                            e lo assegna alla variabile "stampa"*/

        lcd.setCursor(4, 1);                  // Posiziona il cursore dopo il prefisso
        lcd.print(stampa);                    // Stampa la frequenza in uso
        dds.setFrequency(stampa);             // Invia la frequenza al modulo DDS
        startTime = millis();                 // Resetta il tempo di inizio conteggio
        contTempo = startTime + WorkTime;     // Assegna il tempo di lavoro

        while (millis() < contTempo && digitalRead(Stop) == LOW); /* fino a che non raggiunge il tempo impostato o
                                                                  non viene premuto il pulsante di stop */
        
        int fineriga = freq + 1;              // Crea una variabile per l'if di "FINE PROGRAMMA"        
        freq++;                               // Incrementa la variabile del ciclo "for"
        lcd.setCursor(0, 1);
        lcd.print("                ");        // Cancella la seconda riga
     
     if (fineriga == 10) {                    // Se "fineriga" raggiunge il valore 10               
          lcd.setCursor(0, 1);
          lcd.print(" FINE PROGRAMMA ");      // Stampa su lcd che il ciclo è finito
          digitalWrite(Buzzer, HIGH);
          delay(3000);                        // Fa suonare il Buzzer
          digitalWrite(Buzzer, LOW);
          EEPROM.update(0, encoder);          // Memorizza la voce di menù nella EEPROM solo se è cambiata
          dds.init();                         // Resetta il modulo DDS
        }
      }
    }
  }

Visto che sei all'inizio nell'imparare la programmazione e che nell'attuale programma non c'è traccia di operazioni nella SD ti consiglio di scrivere un nuovo programma che si occupa solamente di leggere i dati dalla sd e scriverli sul monitor seriale.
Tra gli esempi dell'IDE trovi già alcuni concetti base per aprire il file e leggerlo, solo ti consiglio sin da subito di evitare l'uso della classe String (esse maiuscola) ma di leggere i dati mediante le stringhe classiche del C (se fai una ricerca sul forum troverai un infinità di messaggi e discussioni a tal proposito).
Come traccia di base di suggerisco di definire una lunghezza massima per la singola riga del file che memorizzi sull'SD in modo da poter dimensionare correttamente l'array di lettura.
Quando sarai riuscito a leggere l'intera riga dal file e a stamparla sul monitor seriale potrai passare ad elaborarla spezzandola in più parti usando il carattere separatore che preferisci(virgola, punto e virgola, ecc.) tramite le funzioni standard del C applicate alle stringhe quali:
strtok
atol
A quel punto avrai stampati sul monitor seriale i vari valori letti, da li a piazzarli nell'array (o matrice che sia) sarà facile.
Altra cosa se decidi di leggere i valori dalla SD non puoi mettere la matrice nell'area programmi (PROGMEM) perché hai necessità di variarla inserendo i dati letti dalla SD.
Ultima cosa, in caso di programmi lunghi al posto di inserirli nel post puoi allegare il file come si fa per un immagine, a quel punto non hai praticamente limiti di spazio
P.S. = Prima che tu lo chieda :slight_smile: no, non faccio un programma d'esempio per fare quello che ho descritto a parole

Come metodo alternativo, per fare le stesse cose che ti hanno appena suggerito, e per le stesse ragioni e con gli stessi commenti (che concorquoto in pieno)

Potresti leggere il file byte a byte (anzi, carattere a carattere, che per arduino byte e carattere non sono sinonimi)

Se trovi una cifra aggiorni la variabile che stai 'leggendo' in questo momento
Se trovi una virgola 'avanzi di uno' nella lista delle variabili
(Questa è una cosa che viene benissimo con array)
Se trovi un fine riga hai finito la riga di variabili da leggere

So per certo che non ti farò esempi in questo senso

una facile ricerca ti farà trovare molti esempi simili, anche in italiano, anche già scritti da me (che sono solo l'ultimo di una lunga schiera, molti più bravi di me)

Grazie a entrambi, devo dirvi che quello che ho postato è il secondo programma che abbia mai scritto con arduino, quindi pur avendo l'idea della programmazione (basic 30 anni fa con il commodore 64), ho molta difficoltà a comprendere il funzionamento di alcuni comandi, e interpretare le criptiche descrizioni dei vari comandi nel wiki mi lascia ancora più confuso. Comprendo che non vogliate postarmi degli esempi e non lo pretendo, ma visto che mi avete detto che ci sono molti esempi già trattati, potreste almeno puntarmi verso essi? Perché ho cercato molto e non ho ancora trovato qualcosa che mi potesse essere utile a comprendere. Riesco a leggere il file dalla sd, ma da lì in avanti su come dividerlo e processarlo è nebbia assoluta.

Ok, se riesci a leggere il fil dalla SD intanto posta il codice che stai usando, in base a quello arriveranno suggerimenti per migliorarlo (se serve) o per cercare di andare avanti, chiaro che servirà approfondire l'uso di alcuni comandi ma quello è indispensabile

Qui trovi un esempio di lettura e parsing di un file con Arduino, non fa esattamente quello che ti serve, ma potrebbe esserti utile a capire come funziona il meccanismo.

Ciao, Ale.