(RISOLTO) Leggere variabile da sd card

Salve a tutti!
Sto cercando di costruire uno sketch in cui leggo due valori (input1 e input2) da un potenziometro per poi eleborarli tramite operazioni matematiche per ricavarmi valoreatt e valoreacc. Sto provando a memorizzare sulla memory card il valoreacc e sembra che funziona. Tuttavia nel caso in cui ad arduino venga tolta la corrente vorrei far si che quando si riaccende legge l’ultimo valoreacc dalla sdcard per reinserirlo nel loop e continuare il calcolo in modo da non perdere il dato. Dal momento che ho imposto che valoreacc<1 dovrei inserire al termine del void setup una parte di sketch che mi permette di leggere l’ultimo valore di valoreacc nel caso in cui esiste il file nella sdcard, altrimenti gli assegno il valore 0.
Vorrei precisare che ho utilizzato la libreria bignumber in modo da avere molte cifre dopo la virgola che vorrei poter salvare (già fatto) e recuperare. Qualcuno saprebbe consigliarmi i comandi giusti per poterlo fare? Ho trovato un po di sketch sul forum, ma non essendo commentati non capisco bene il significato dei comandi e di conseguenza non so come adattarli al mio caso.
L’esempio che più si avvicina al mio caso è questo http://forum.arduino.cc/index.php?topic=162863.0 .
Ecco il mio sketch:

#include "BigNumber.h"
#include <SD.h>
#include <SPI.h>

File myfile;
BigNumber pot=A3, input1, input2, d1, d2, valoreatt, valoreacc=0;


void printBignum (BigNumber n){
  char * s = n.toString ();
  Serial.println (s);
  free (s);
}  // end of printBignum


void setup() {
    
    Serial.begin(9600);
    pinMode(10, OUTPUT);
    //verifico l'esistenza di una memory card
    if (!SD.begin(10)) {
    Serial.println("Card failed");
    return;
    }
    Serial.println("card inizialized");
    BigNumber::begin (20);  // initialize library
    input1 = analogRead(pot);
}

void loop() {

    if (valoreacc<1){
    input2 = analogRead(pot);
    
    d1 = BigNumber (input2) / BigNumber (1023);
    d2 = BigNumber (d1) * BigNumber (d1) * BigNumber (d1);
    valoreatt = BigNumber (d2) / BigNumber (125) / BigNumber (1000); 
    valoreacc = BigNumber (valoreatt) + BigNumber (valoreacc);

    Serial.print ( "input: " );    
    printBignum (input2);
    Serial.print ( " valoreatt: " );
    printBignum (valoreatt);
    Serial.print ( " valoreacc: " );  
    printBignum (valoreacc);  
    
    // memorizzo il danno sulla sd card
    myfile = SD.open("valori.csv", FILE_WRITE); 
    if (myfile) { 
    myfile.println( valoreacc );
    myfile.close();   
    }
    input1=input2;
    delay(1500);
    }
    else { 
    Serial.print( "stop" );    
    }
}

Sto provando a memorizzare sulla memory card il valoreacc e sembra che funziona. Tuttavia nel caso in cui ad arduino venga tolta la corrente vorrei far si che quando si riaccende legge l'ultimo valoreacc dalla sdcard per reinserirlo nel loop e continuare il calcolo in modo da non perdere il dato

Dipende da quante volte salvi il dato nella SD al secondo, al minuto .... considera che la sd ha mediamente 100.000 scritture (dipende dalla tecnologia di costruzione) e ogni volta che scrivi cancella il dato precedente e riscrive il nuovo, quindi sarebbero 50.000 volte effettive poi quella/quelle posizioni ti salutano, non essendoci un software per arduino in grado di gestire le posizioni guaste di una sd, va tutto a farsi friggere.

pablos:
Dipende da quante volte salvi il dato nella SD al secondo, al minuto … considera che la sd ha mediamente 100.000 scritture (dipende dalla tecnologia di costruzione) e ogni volta che scrivi cancella il dato precedente e riscrive il nuovo, quindi sarebbero 50.000 volte effettive .

Nessun costruttore di SD dichiara il reale valore di riscritture ammesse, tutti dichiarano solo l’endurance in tempo d’uso sulla base di un dato statistico e nell’ipotesi di un utilizzo “intelligente” della SD.
Sulle SD economiche difficilmente si va oltre le 2000-3000 riscritture dello stesso blocco, quelle buone arrivano a oltre 10.000, 100.000 è un valore utopico per una flash.
Quando l’endurance è specificata come cicli di cancellazione/scrittura non vuol dire che ogni volta che si effettua una scrittura vengono utilizzati due cicli, è sempre solo uno in quanto l’operazione è monociclo, al contrario la sola cancellazione si porta via un ciclo, in realtà è proprio la cancellazione, e non la scrittura, ad accorciare la vita della flash perché la sottopone a stress, viene usato l’effetto tunnel per cancellarla.

Il problema di cui parlate l ho già affrontato acquistando una industrial sd che mi permette di salvare ogni volta in una posizione differente. Qualcuno sa come costruire lo sketch x prendere ogni volta l ultimo valore?

Qualcuno sa come costruire lo sketch x prendere ogni volta l ultimo valore?

Si, ma se non fai nemmeno vedere come è fatta una linea di questo file ..... :astonished:

Il file memorizza i valori in questo modo:

0.00000069004655222191
0.00000138009310444382
0.00000207013965666573
0.00000276018620888764
0.00000345023276110955
0.00000414027931333146
0.00000483032586555337
0.00000552037241777528
0.00000621041896999719
0.00000690046552221910
0.00000759051207444101
0.00000828055862666292
0.00000897060517888483
0.00000966065173110674

Matteo90: Il problema di cui parlate l ho già affrontato acquistando una industrial sd che mi permette di salvare ogni volta in una posizione differente. Qualcuno sa come costruire lo sketch x prendere ogni volta l ultimo valore?

Ti serve un indice per sapere qual'è l'ultimo record registrato.

p.s. Tutte le SD scrivono utilizzando tutti i blocchi di flash a rotazione, fa parte della loro logica di funzionamento, quello che cambia tra le varie marche, soprattutto su quelle cineseria, è l'efficacia del algoritmo che gestisce la rotazione dei blocchi. Le SD industrial grade sono caratterizzate da una maggiore affidabilità sul trasferimento dati (da e verso il device), un range termico maggiore (tipicamente -40° +85° invece di 0° +70°), a volte anche una maggiore resistenza meccanica, non cambia nulla per quanto riguarda la rotazione dei blocchi della flash e la relativa endurance rispetto allo stesso modello standard grade.

astrobeed:

Matteo90: Il problema di cui parlate l ho già affrontato acquistando una industrial sd che mi permette di salvare ogni volta in una posizione differente. Qualcuno sa come costruire lo sketch x prendere ogni volta l ultimo valore?

Ti serve un indice per sapere qual'è l'ultimo record registrato.

p.s. Tutte le SD scrivono utilizzando tutti i blocchi di flash a rotazione, fa parte della loro logica di funzionamento, quello che cambia tra le varie marche, soprattutto su quelle cineseria, è l'efficacia del algoritmo che gestisce la rotazione dei blocchi. Le SD industrial grade sono caratterizzate da una maggiore affidabilità sul trasferimento dati (da e verso il device), un range termico maggiore (tipicamente -40° +85° invece di 0° +70°), a volte anche una maggiore resistenza meccanica, non cambia nulla per quanto riguarda la rotazione dei blocchi della flash e la relativa endurance rispetto allo stesso modello standard grade.

Al momento vorrei risolvere il problema relativo al recupero dell'ultimo valore memorizzato, poi per quanto riguarda la sd card vedrò come risolvere. Ti ringrazio per la precisazione! ;)

myFile.available() restituisce 0 quando il file è finito, corrisponde a un EOF (end of file)
perciò modificando leggermente l’esempio dell’ide
if(!myFile.available()) break; blocca la lettura prima che venga svuotata la stringa “inString” lasciandoti l’ultimo valore dentro

#include <SPI.h>
#include <SD.h>
File myFile;

void setup(){
  delay(1500);
  Serial.begin(19200);
  Serial.println("Initializing SD card...");
  pinMode(4, OUTPUT);
  digitalWrite(4, 1);
  pinMode(10, OUTPUT);
  digitalWrite(10, 1);
  
  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
  }

  char c; 
  String inString = String();  
  
  myFile = SD.open("file.txt");
  if (myFile) {
    while (myFile.available()) {
                  
       while(c != -1) {
          c = myFile.read();
       
          if(!myFile.available()) break;                   
          if (c == '\n') inString = "";          
          inString += c;   
      }           
    }
    myFile.close();
  } 
  
  // -----------questa è la tua ultima riga ----------
  Serial.println(inString); //debug
  //-------------------------------------------------- 
}

void loop(){  
}

però penso che il prossimo problema che avrai sarà quello di convertire la stringa in float con molte cifre dopo la virgola, io qui mi fermo non ci chiappo molto con i decimali … li odio :slight_smile:

grazie

Ti ringrazio Pablos! Sembra che funziona! Ho dovuto fare due correzioni, ossia mettere Serial.begin(9600); altrimenti mi dava caratteri strani e porre il pin 10 come collegamento con la sd card.
Ora devo cercare di assegnare il valore trovato a valoreacc utilizzando la libreria BigNumber. Speriamo bene.
Grazie ancora! :slight_smile: