Salvataggio in EEPROM e variazione progressiva dell'indirizzo di scrittura

SukkoPera: Credo che tu non abbia capito la mia osservazione. Supponiamo di cambiare cella ogni 10 scritture e di farne 30: - Usi la cella 9 10 volte: BENE! - Usi la cella 10 10 volte: BENE! - Usi la cella 11 10 volte: BENE! - Usi la cella 8 3 volte: OTTIMO! - Usi le celle 0-7 30 volte: AZZ! Tanto valeva scrivere direttamente il valore nella prima cella e basta.

No no! avevo capito benissimo di aver sbagliato, infatti ora sto lavorando sul materiale datomi da Guglielmo.

maubarzi: Scusami la domanda, ma perchè invece di un encoder non usi un potenziometro e mediante partitore resistivo ti leggi una tensione ad es. variabile da 0 a 2,5V così anche se salta il mondo, la resistenza impostata sul potenziometro non cambia e al riavvio rileggi esattamente la tensione pre catastrofe ... Cioè il controllo da digitale lo fai diventare analogico.

come detto in precedenza in realtà scrivere in un unica cella mi basta e avanza. Infatti gli O-Buffer non andrò ad implementarli, anche perché sono già tirato con lo spazio nella flash.

Ciò non toglie che sia incuriosito e che voglia imparare una cosa nuova, tempo permettendo... :roll_eyes:

Basta tenere il numero di utilizzo di un blocco all’interno del blocco stesso (assieme ai suoi dati), e nella prima cella indicare solo il blocco attivo. La prima cella viene riscritta solo al cambiamento del blocco, quindi un numero infimo di volte rispetto alla riscrittura dei blocchi stessi.

Se si usa un solo byte per identificare i blocchi, e un solo byte come contatore interno del blocco, la prima cella viene variata una volta ogni 256 riscritture di un blocco.

Se si usano 10 blocchi, ciascuno può essere usato 391 volte portando le scritture a un milione garantito, e la prima cella sarà stata riscritta meno di 4000 volte.

Al di la di questo io ho fatto uno stress test (a tensione regolare e temperatura ambiente) e le celle hanno iniziato a scantinare a 10 milioni di riscritture, cioè a cento volte il minimo garantito.

-4

Claudio_FF:
Se si usa un solo byte per identificare i blocchi, e un solo byte come contatore interno del blocco, la prima cella viene variata una volta ogni 256 riscritture di un blocco.

Al di la di questo io ho fatto uno stress test (a tensione regolare e temperatura ambiente) e le celle hanno iniziato a scantinare a 10 milioni di riscritture, cioè a cento volte il minimo garantito.

Si ma il contare interno viene scritto ogni qual volta vado a scrivere un dato… e senza di quel dato come farei a trovare l’ultima cella scritta all’interno del blocco dopo il riavvio ?

Dato molto interessante!! Terrò sicuramente a mente. Grazie :slight_smile:

Tornando al mio posto principale, sono riuscito a trovare un po di tempo ed ho finito questo “esperimento”,
dai pochi test che ho fatto sembra funzionare, continuo con la sperimentazione e vediamo:

/***********************************_EEPROM_********************************//*
   Salva l'ultimo valore dell'encoder nella eeprom interna:

      -Il valore deve essere essere diverso dal precedente
      -Se il valore è diverso dal precedente, deve essere stabile per almeno 60 secondi.

  ==========================================================================*/
void saveValue()
{
  if (encoderValue != previousEncoderValue)
  {
    tempo = millis();
    writeOnEeprom = false;
    previousEncoderValue = encoderValue;
    Serial.println(encoderValue);
  }

  if (millis() >= tempo + 5000 && encoderValue == previousEncoderValue && writeOnEeprom == false)
  {

    writeOnEepromBuffers();
    writeOnEeprom = true;

  }
}
/**********************************_WRITE ON EEBPROM BUFFERS_**********************************//*
-Scrivo nelle celle del buffer in maniera progressiva.
-Sposto i due indirizzi di scrittura di un unità all'interno dei buffer circolari.
-Implemento la variabile statusCounter di un unità, serve per individuare i puntatori dei due buffer.

===============================================================================================*/

void writeOnEepromBuffers ()
{

  parameterAddress ++;
  statusAddress = parameterAddress - bufferSize;

    if (statusAddress >= bufferSize)
      {
        statusAddress = 0;
        parameterAddress = statusAddress + bufferSize;
      }

  statusCounter++;

  EEPROM.write(statusAddress, statusCounter);
  EEPROM.write(parameterAddress, encoderValue);



    Serial.println("------->> WRITE ON EEPROM <<-------");
    Serial.print("STATUS ADDRESS       >>    ");
    Serial.println(statusAddress);
    Serial.print("PARAMETERS ADDRESS   >>    ");
    Serial.println(parameterAddress);
    Serial.println("------------------------------");
    Serial.print("STATUS COUNTER       >>    ");
    Serial.println(statusCounter);
    Serial.print("WRITE ON EEPROM      >>    ");
    Serial.println(encoderValue);
    Serial.println("-------->>   END   <<-------");
  
  

}
/**************************************_POINTER ADDRESS_***********************************//*
- Cerco i due indirizzi dei buffer dovo sono andato a scrivere l'ultima volta.
- Setto i due indirizzi per le future scritture.
=========================================================================================== */


void pointerAddress ()
{
  do
  {
    
    if (statusAddress >= bufferSize)
    {
      statusAddress = 0;
    }
    previousStatusCounter = EEPROM.read(statusAddress);
    
      Serial.print("PRIMO VALORE      >>    ");
      Serial.println(previousStatusCounter);
    statusCounter = EEPROM.read((statusAddress + 1));
      Serial.print("SECONDO VALORE    >>    ");
      Serial.println(statusCounter);
    statusAddress++;
  }

  while (statusCounter == previousStatusCounter + 1);

  statusAddress = statusAddress - 1;
  parameterAddress = statusAddress + bufferSize;
  encoderValue = EEPROM.read(parameterAddress);
  statusCounter = EEPROM.read(statusAddress);

    Serial.println("------>>  READING FINISH    <<------");
    Serial.print("STATUS_ADDRESS         >>  ");
    Serial.println(statusAddress);
    Serial.print("PARAMETER_ADDRESS      >>  ");
    Serial.println(parameterAddress);
    Serial.println("--------------------------------");
    Serial.print("STATUS_COUNTER         >>  ");
    Serial.println(statusCounter);
    Serial.print("SAVED PARAMETER        >>  ");
    Serial.println(encoderValue);
    Serial.println("---------->>  END   <<--------------");

}

Spero di non aver fatto errori :sweat_smile:

Il mio dubbio permane sulla dimensione del O-buffer per evitare casini in fase di ricerca dell’indirizzo.

Correggetemi se sbaglio ma ragionandoci un attimo le dimensioni degli O-Buffer devono essere per forza 2^N ?

Io intendo questa struttura, dove il valore di blocco attivo viene variato solo al cambio del blocco, e il cambio del blocco avviene solo quando il valore numero write fa il rollover. Qui abbiamo 3 blocchi da 3 byte. Si usa per 256 volte il primo. Poi 256 volte il secondo ecc. Poi si riparte dal primo, il tutto per 391 volte (ogni blocco viene riscritto per 100.096 volte per un totale di 300288 salvataggi e 1173 scritture sulla prima cella che identifica il blocco attivo).

  .---------------.
0 | bloccoAttivo  |
  '---------------'
  .---------------.------.------.
1 | numero write  | dati | dati | 
  '---------------'------'------'
  .---------------.------.------.
4 | numero write  | dati | dati | 
  '---------------'------'------'
  .---------------.------.------.
7 | numero write  | dati | dati | 
  '---------------'------'------'

addr = 1 + (3 * bloccoAttivo)
if (millis() >= tempo + 5000 && ....

Qui c'è l'errore dell'overflow di millis, il valore fornito da millis non è sempre crescente, ma ritorna a zero e la condizione non risulta vera, la forma corretta è:

if (millis() - tempo >= 5000 && ....

-1

Un Pic serie 16, ha come valore di scritture celle eeprom 1.000.000 di volte. Fatto un test, la cella in esame si è rotta dopo 29.000.000 di scritture e letture Quindi...