[RISOLTO]SD_Card leggere un determinato file .txt - .wav.

Ciao a tutti, mi servirebbe un aiuto per fare una ricerca du una riga nella SD_card

P0D1,Epic,Cartone,0,98,0,S,N,1,
P0D2,Baby Boss,Cartone,0,97,0,S,N,2,
P0D3,Ralph spaccatutto,Cartone,0,58,0,S,N,3,
P0D4,I corti Pixar 1,Cartone,0,51,0,S,N,4,

Questo è il file DATADVD.txt dove sono elencati i vari film in DVD. come si può notare all’inizio c’è un codice dove identifica il film. questo codice mi arriva via seriale da un ESP8266.
Attualmenti il programma sta funzionando effettuando un controllo con if, ma facendo cosi mi comporta molte righe di codice. Ho fatto una ricerca nel Forum ma non trovo esempi che mi aiutato in merito.

void loop() {
  readString = "";
  char c[9];
  while (Serial3.available()) {
    delay(3);
    Serial3.readBytes(c, 9);
    Serial3.write("/n");
    readString += c;
    Serial.println(readString);
  }
  if (readString.length() > 0) {

    if (readString.indexOf("P0D1") > -1) {
      myFile = SD.open("P0D1.txt");

      if (myFile) {
        // legge il file fino a quando non c'è nient'altro :
        String  myString;
        while (myFile.available()) {
          myString += (char) myFile.read();

        }
        //delay(5);
        tmrpcm.play("P0D1.wav");
        // Ora il contenuto del file test_4.txt
        // è stato salvato nella variabile String myString

        if (myString.length() > 0) {
          int m = 0;
          int n = myString.indexOf(",");
          int indice = 0;
          while (n > 0) {
            String token = myString.substring(n, m);
            //Serial.println(token);
            m = n + 1;
            n = myString.indexOf(",", n + 1);

            //elaboro il token:
            processToken(indice, token);
            indice++;
          }
          //applico i risultati
          Stringdata();
        }

        // chiude il file
        myFile.close();
        myString = "";
      } else {
        // se non apre il file da errore
        Serial.println("Errore apertura file dati");
      }

    }

questo è la parte del codice dove prende il codice per poi cercarlo.
Chi mi può fare un esempio ? grazie mille

innanzitutto buona Pasqua

purtroppo il tuo programma mi sembra confuso
e fa uso di oggetti String
solo per questo fatto non andrà mai (MAI) in modo affidabile
devi ripensarlo in termini di stringhe di 'C' e una più "ferrea" logica di input
prendi ispirazione dai tanti miei post sull'argomento, comincia da "aiutateci ad aiutarvi", che è solo di argomento generale, ma li richiama tutti
in particolare "la pappa è fatta" "grep non vuol dire greppia" "salva che ti passa"
dove trovi tutti gli esempi che ti servono

Grazie mille. quindi nel mio caso non ho nessuna possibilità di Farlo ? devo rifare tutto il programma ? Va bhee grazie comunque.

Non sei andato a vedere, vero?

Io vedo due possibili scelte:

  1. esattamente come tu chiedi, crei una stringa (intesa array di char, dimentica il concetto di String, Aruino non ha una gestione della memoria adeguata) lungo come la riga di massima lunghezza possibile +1 carattere (il terminatore di stringa), successivamente crei una funzione che, se chiamata, ti riempie suddetta stringa con il contenuto della ennesima riga del file. Fatto questo hai in mano la riga, e ne fai quello che serve.
  2. tratti i singoli caratteri del file separatamente (immagino tu debba trovare, e stampare, una riga indicata attraverso il codice di 4 caratteri, quindi ti basterà verificare che i primi 4 caratteri trovati dopo un '\n' siano uguali a quelli cercati, se si allora stampi la riga, altrimenti vai avanti fi no al prossimo '\n').

In entrambi i casi devi modificare il codice in maniera radicale (ripeto, non puoi usare String su Arduino, pena: crash del programma per memoria variabili piena in momenti imprevedibili), e secondo me se tocchi quel codice ti conviene, per la tua sanità mentale nella ricerca di errori, scarpare via tutto e ricominciare. Noi ovviamente siamo qui per aiutare in caso di bisogno.

Grazie. sicuramente come dite voi il programma non va bene. Attualmente come l’ho scritto funziona bene su 100 ricerche. il fatto e che mi ritrovo con ben 400+ DVD non vorrei rifare tutto. Quindi vorrei tanto trovare una soluzione con il mio sketch. Allego una foto delle due seriali, quella di sinistra è la seriale ESP8266 che riceve il dato dal mio assistente cioè il titolo del film, che poi trasforma in codice quella di destra è la mega dove riceve il titolo o “CODICE”. Non mi cambia nulla modificare la modalità di arrivo. Al momento dell’arrivo del dato la mega lato destro della foto, effettua la ricerca e mi dice dove si trova il film nella libreria. Ora sarei veramente grato se mi fate un esempio sul mio sketch o se mi dite dove trovare qualcosa di funzionante. Perchè vedendo in giro nei forum sono tutti vaghi e non funzionanti. Grazie mille. Se poi proprio non si riesce pace lascio tutto cosi. Se alla fine non funzionerà metto nel cassetto il progetto.

Devi usare le stringhe classiche del C, ovvero crei un array di char invece di uno String (il quale dentro nasconde un array di char dinamico)

Sulle stringhe classiche del C esistono molte funzioni già fatte per fare ricerche, strstr(), strtok() e molte altre
https://www.nongnu.org/avr-libc/user-manual/group__avr__string.html

ok grazie mille.

ma ti sei reso conto che col tuo programma carici in RAM l'intero contenuto del file dati?
inoltre usndo oggetti String?
quel programma fa pena, lo devi comunque rivedere completamente
fai a vedere "la mia seconda volta in C++" e "ti metto ti trovo ma non riesco..."
fanno esattamente quello che ti serve, abbastanza commentati
poi, se non hai voglia, non farlo

Ho parlato

Ciao, scusate ancora per la richiesta. Mi serve un piccolo aiuto per completare lo sketch, che attualmente sta funzionando alla perfezione senza fare nessuna modifica, ma solo un cambio di ricerca. Ho un punto da capire perchè non mi funziona la chiamata di un file .wav.
Sulla SD ho dei file audio .wav, che si chiamano come il file .txt, quindi se il file si chiama P0D001.txt anche il file audio si chiama P0D001.wav. Volevo fare in modo che il nome P0D001.wav mi entrasse nella voce tmrpcm.play(nome_file); . Con il file .txt mi funziona perchè con il file .wav no ?
Cosa cambia ?
Grazie mille!!!

Gian70Luca, io sinceramente non ho capito nulla della tua domanda.

Ho un codice comando che non mi funziona, la ricerca su SD.car di un file .wav tmrpcm.play(nome_file);
Per un normale funzionamento il codice comando viene compilato cosi tmrpcm.play(P0D001.wav); è mi chiama il file sulla SD card
Io vorrei che, invece di mettere direttamente il nome del file da sentire, inserire una stringa che mi arriva dalla seriale. tmrpcm.play(nome_file);
Dove il nome_file è la stringa che mi arriva dalla seriale "readString";
scusa spero che cosi mi sono spiegato meglio.

Sai perchè ti dicono che il programma non va bene?
Perchè usi l'oggetto String che su Arduino, tende a frammentare la memoria fino a quando sarà talmente frammentata da non essere più utilizzabile e questo produrrà il crash del programma.
La quantità di memoria disponibile e l'intensità con cui la usi, determina il tempo medio di vita della tua applicazione.
Fino allo schianto funzionerà normalmente e poi andrà riavviata.

Invece di usare la classe String dovresti usare array di char.
Puoi fare le stesse cose ma senza gli stessi problemi, devi solo pensarle in un modo leggermente diverso, magari senza crearty un array che memorizzi l'intero file contenente tutti i titoli, ma solo una riga alla volta, tanto a te serve solo trovare quella che ti interessa all'interno del file per cui puoi leggere una riga per volta scartando quelle già lette.
Questo (cioè eliminare la classe String usando array di char) potrebbe anche risolvere il tuo problema.
Non ho capito a cosa si riferiscono certe variabili del tuo programma, ma magari passare come variabile "pippo" non equivale a passare x con x definita come String x ="pippo"; che parrebbe essere l'ultimo dei tuoi problemi...

Visto che è un po' che bazzichi il forum, potresti pensare seriamente di iniziare a studiare un po' di basi di programmazione, tanto la fatica da fare è inizialmente uguale a quella di interpretare 10 programmi che pare facciano quello che ti serve ma invece vanno pesantemente modificati.... e dopo che hai preso un po' di confidenza, stai sicuro che la strada diventa tutta in discesa e ti si allontana sempre di più lo spettro di dover rimettere nel cassetto un progetto solo perchè non trovi qualcosa di già pronto da copiare e modificare solo in minima parte e con modifiche basilari.

Maurizio

maubarzy,
sicuramente lo sketch non funziona bene e non funzionerà mai, ma se possibile volevo solo capire se c’è un modo per far funzionare il comando per ascoltare un file audio .wav.

Al comando tmrpcm.play(“P0D001”);

vorrei togliere il “P0D001.wav” e inserire tmrpcm.play(nome_file);

dove “nome_file” mi arriva dalla Seriale.

Chiedo solo questo, un esempio o qualcosa per capire come fare.

Grazie ancora a tutti voi.

Ma da qualche parte hai scritto cos'è esattamente tmrpcm?
Perchè essendo una variabile il cui nome può essere qualunque cosa, è difficile aiutarti senza sapere di cosa si tratti.

Fammi capire se ho capito, tu vuoi una cosa già bella e pronta da copiaincollare e che funzioni e non ti stai nemmeno prendendo la briga di leggere e quantomeno cercare di capire tutti i suggerimenti che ti sono arrivati fino ad ora?
Hai almeno capito o vagamente intuito la differenza tra String e gli array di char?
Perchè la soluzione è tutta qui, se non provi nemmeno un po' a capire di cosa si stia parlando... la vedo molto dura.

Maurizio

Ok, questo è un esempio completo,

#include <SD.h>                     
#define SD_ChipSelectPin 53         
#include <TMRpcm.h>                 
#include <SPI.h>
TMRpcm tmrpcm; // LIBRERIA PER ASCOLTARE FILE AUDIO SU SD
void setup(){
  tmrpcm.speakerPin = 5; 
  Serial.begin(9600);
  if (!SD.begin(SD_ChipSelectPin)) {  
    Serial.println("SD fail");  
    return;  
  }
  }
void loop(){  
  if(Serial.available()){    
    if(Serial.read() == 'p'){ 
      tmrpcm.play("music"); // ASCOLTO IL FILE MUSIC
}}}

come puoi vedere nella funzione void loop () c’è il comando che vorrei modificare
cioè tmrpcm.play(“music”);
La modifica che vorrei capire come fare, togliere “music” e inserire il Serial.read letto. In questo caso se io digito P lui mi fa ascoltare la musica “P”, se inserisco “domani” voglio ascoltare la musica domani.
E’ una cosa fattibile ?
Altrimenti chiudo con il mio progetto.
Ancora grazie mille

Si. Comincia (e fallo TU, oppure di chiaramente che vuoi solo un codice funzionante), e creare un array di char, tra le variabili globali, contenente 6 elementi. Semore mentre lo crei rendilo uguale alla parola music. Infine cancella tutto quello che é scritto tra le tonde della funzione voluta, e sostituiscilo con il nome dell'array creato in precedenza.
Fine, e cosí DEVE funzionare esattamente come funziona quel codice.

Nella libreria TMRpcm
la definizione è

void play(char* filename);

non

void play(String filename);

per questo in ogni post precedente ti è stato suggerito di sostituire String con un array di char, che poi devi passare alla funzione come puntatore.
Ora, se passi la stringa fissa “pippo” questa viene automaticamente convertita in un array di char e quindi ti funziona.

Maurizio

Grazie mille, sinceramente la definizione

void play(char* nome del file)

non l'avevo mai messo in considerazione, il char* come l'hai messo te si, avevo già provato più volte ma non mi funzionava.

void loop() {
  char c[6];
  while (Serial3.available()) {   
    delay(3);
    Serial3.readBytes(c, 6);     
    Serial3.write("/n");   
    readString += c;              
    ricercatxt = readString;       
    ricercawav = readString;
   
// UNISCO IL .WAV PERCHE SENZA NON FUNZIONA  
    ricercawav += ".wav";
    Serial.print("Stampo ricercawav + .wav  : "); Serial.println(ricercawav); 
// alla stampa ricercawav il risulato è giusto "P0D001.wav"
    void play(char* ricercawav);
// inserendolo nel play come mi hai detto (spero di averlo fatto bene), lo sketch funziona
// ma non sento il file audio
  }
 
// CON LA PARTE RICERCA FILE test MI FUNZIONA BENE
 if (readString.length() > 0) {
    readString = "";                  
    ricercatxt += ".txt";         
    myFile = SD.open(ricercatxt);

Sto cercando di capire su vari Forum e modifico in base alla mia esigenza ma non funziona mai.
Il fatto e che mi spiace se non riesco a finirlo, perchè sono 4 settimane di COVID19 impegnative, solo per questo cavillo sul file Audio devo buttare un bel progetto.

No, é ancora sbagliato. Quello che fai adesso è creare una nuova stringa da passare alla funzione. Devi trattare il testo come una stringa, NON USARE NESSUNA STRING!!! Se il nome del file contiene 6+4=10 caratteri la stringa di 6 non sará più sufficiente, deve essere di 11 caratteri, e contenere il nome completo del file (11=10 caratteri che é lunga la stringa +1 carattere terminatore)