durée de vie de l'EEPROM

Salut,

Je cherche à connaître le temps de fonctionnement d'un circuit (le temps où il est alimenté) et je vais donc devoir stocker cette donnée quelque part. Je suppose que l'EEPROM est là pour ça. Cela dit, je crois avoir compris qu'elle a une durée de vie assez limitée et n'aimait pas les enregistrements à répétition.

Je pense donc mettre en place quelque chose qui incrémente un long non signé (donc 4 octets).

Quelle pourrait être la durée de vie de l'EEPROM si j'enregistre cette variable toutes les secondes, toutes les 10 secondes par exemple ?

Vaut-il mieux utiliser la minute ? ou alors un autre moyen de stockage ?

J'ai vu qu'il y avait un cycle de 100 000 écriture. Cela veut dire quoi ? qu'on peut réécrire sur la même adresse 100 000x ou dans toute la mémoire en général ?

Merci

Edit : que se passe t'il une fois le nombre de cycle max dépassé, est ce que ça fonctionne toujours sauf que ça n'enregistre plus dans l'EEPROM ? Est ce que l'arduino est totalement inutilisable ?

Ce sujet revient toutes les 3 semaines et il y a déjà été répondu un nombre incalculable de fois.

En haut à droite de la page il y a un rectangle pour écrire un sujet de recherche sur le forum. Tu y écris : ecriture eeprom et tu auras des centaines de réponses.

Après avoir parcouru quelques pages dans les résultats cette recherche que tu m'as cordialement invité à faire, je conclu que je dois être vraiment débile, car je ne trouve ni de réponse à :

J'ai vu qu'il y avait un cycle de 100 000 écriture. Cela veut dire quoi ? qu'on peut réécrire sur la même adresse 100 000x ou dans toute la mémoire en général ?

Ni à :

Edit : que se passe t'il une fois le nombre de cycle max dépassé, est ce que ça fonctionne toujours sauf que ça n'enregistre plus dans l'EEPROM ? Est ce que l'arduino est totalement inutilisable ?

Alors forcément, si je dois lire intégralement des 100ènes de topics sans rater la moindre intervention, quelque part sur internet, je devrais pouvoir trouver un jour mes réponses. Mais il me semblait que ce n'était pas forcément le but de ce genre de sites, qui n'aurai alors pas grand intérêt, car toutes les réponses sont déjà quelque part....

Mais j'ai bien compris le message...

Ce n'est pas toujours facile de trouver les réponses surtout lorsqu'il faut tout lire, par exemple ici c'est, me semble-t-il, la dernière fois que le sujet y a été abordé. La réponse à ta question est donnée très clairement. Mais il faut nous comprendre aussi, ca devient pas drôle de répondre aux mêmes questions tout le temps... ;)

Pour condenser:

•100 000 écritures pour chaque emplacement de la mémoire.

•une fois les 100 000 écriture passée, l'emplacement est mort, pas le reste mais ça devient problématique.

•L'arduino reste utilisable même si l'entièreté de l'EEprom est raide.

•une bonne gestion de la mémoire (comme pour les clés USB par ex) est d'écrire un peu partout pour user de manière homogène la mémoire. Forcément ça implique plus de code

•Pour finir, 100 000 est une valeur "minimum garantie constructeur " c'est pas du pile poil, l'eeprom n'arrête pas de fonctionner à la 100 001eme écriture, ça peut être plus (comme ca peut être moins). Il y a des vidéos à ce sujet, montrant ~180 000 écritures avant mort cérébrale de l'eeprom.

•les lectures simples n'affectent pas la durée de vie de la mémoire.

•Une autre bonne gestion de la mémoire: vérifier les valeurs contenue dans la mémoire et faire juste des mise à jour si les valeurs ont changés. Le traitement est un peu plus long et nécessité aussi plus de code mais la durée de vie est allongée.

Écris une fois par minute et la durée de vie sera de à peu près 70jrs, une fois par seconde et en 27heures c'est fini.

Merci Zorro_X (et oui je comprends très bien le problème) mais tu vois, par exemple, le post que tu m'as donné en lien, j'étais même pas tombé dessus.

Je cherche une solution à ça depuis quelques heures maintenant, et vu qu'on trouve de l'information et autant de désinformation, oui c'est pas évident.

M'enfin, pour en revenir donc à ma question :

La solution serait donc de créer une espèce d'algo qui permet de ne pas écrire toujours au même endroit, et donc de décaler chaque écriture de 4 octets.

Donc, ayant 1Kb de dispo et une incrémentation sur un long chaque minutes :

J'ai donc 1024o / 4o = 256 minutes pour écrire 1x toute la mémoire (soit 1 cycle) 256 minutes * 100000 cycles max (théorique, merci Jambe) = 25 600 000 minutes soit 46 ans.

Je vais donc pouvoir écrire quelques fonctions qui gère cette écrite et lecture de façon transparente. La position du dernier enregistrement est donc à l'adresse du long le plus grand.

--- petit mémo dans le cas ou on incrémenterai pas la valeur à mémoriser ---

Il faudrait alors effacer les 4 octets suivants (avec 0x0 ou 0xFFFFFFFF, lors d'une écriture) pour marquer le dernier enregistrement. Cela divise par 2 la durée de vie et interdit aussi de stocker la valeur d'effacement qui permet de retrouver le dernier enregistrement)

Merci pour votre aide

Où ne pas utiliser l’eeprom du micro-contrôleur qui est plutôt prévue pour recevoir des configurations.
A la place utiliser une eeprom externe I2C que tu peux changer préventivement au rythme que tu veux.
Il existe aussi des cartes SD.
En cherchant un peu on devrait pouvoir trouver de la RAM. Je n’en connais pas à part les 56 octets de ram du circuit DS1307 (I2C) mais ce n’est pas pour autant que cela n’existe pas.

Plus on cherche, plus on comprend les astuces des moteurs de recherche et plus cela devient facile.

Edit : recherche Ebay
PCF8570
Ram 256 octets
Tension entre 2,5V et 6V
Courant :
en fonctionnement 15µA
en mode sauvegarde 400 nA
Lien Ebay (je vais me faire gronder mais tant pis) http://www.ebay.fr/itm/1PCS-PCF8570P-256-x-8-bit-static-low-voltage-RAM-with-I2C-bus-interface-DIP-8-/221422443477?hash=item338dce5bd5:m:mfKz00ZLgNQMp76Fhj5NpqA
Coût <2€
Eh voilà vite fait et (peut être) bien fait.

Edit sur l’édit :
on peut en gérer 8 ce qui fait 2048 octets.
c’est disponible en boîtier à piquer (Dual in Line)

@vohu : sur mes montages j'ai fait un algo qui ressemble un peu à ce que t'ennonçes, en effet il faut écrire deux fois plus mais t'utilises toute l'EEPROM. Personnellement je considère qu'il vaut mieux écrire (((taille totale de l'EEPROM) / (taille de ta zone de données)) x 100'000) / 2 que seulement sur une toute petite zone à bouziller... Chacun ses choix, et il est vrai que tout le monde n'a pas forcément les connaissances pour écrire un algo de ce genre où on joue beaucoup avec les pointeurs ! ;)

Je pense qu’on bien mieux faire, mais voilà un 1er jet de code vite fait qui permet d’indenter une variable 32 bits de façon à préserver l’eeprom.

Pour l’instant j’ai pas pu tester sur un arduino, d’où la manipulation d’un tableau qui simule l’eeprom. Mais normalement il suffira de dé-commenter quelques lignes.

#include <stdio.h>
#include <stdint.h>

#define EEPROM_SIZE 1024
#define MAX 0xFFFFFFFF

typedef unsigned char byte;

const int nb_octets = 4;

byte EEPROM[EEPROM_SIZE] = { 0 };

void eeprom_write ( int address, uint32_t value )
{
    byte b4 = ( value & 0xFF );
    byte b3 = ( ( value >> 8 ) & 0xFF );
    byte b2 = ( ( value >> 16 ) & 0xFF );
    byte b1 = ( ( value >> 24 ) & 0xFF );

    //EEPROM.update(address, b4);
    //EEPROM.update(address + 1, b3);
    //EEPROM.update(address + 2, b2);
    //EEPROM.update(address + 3, b1);

    EEPROM[address] = b4;
    EEPROM[address + 1] = b3;
    EEPROM[address + 2] = b2;
    EEPROM[address + 3] = b1;

}

uint32_t eeprom_read ( uint32_t address )
{
    //uint32_t b4 = EEPROM.read(address);
    //uint32_t b3 = EEPROM.read(address + 1);
    //uint32_t b2 = EEPROM.read(address + 2);
    //uint32_t b1 = EEPROM.read(address + 3);

    uint32_t b4 = EEPROM[address];
    uint32_t b3 = EEPROM[address + 1];
    uint32_t b2 = EEPROM[address + 2];
    uint32_t b1 = EEPROM[address + 3];

    return ( ( b4 << 0 ) & 0xFF ) + ( ( b3 << 8 ) & 0xFFFF ) +
        ( ( b2 << 16 ) & 0xFFFFFF ) + ( ( b1 << 24 ) & 0xFFFFFFFF );
}

int return_addr_plus_grand (  )
{
    uint32_t vh = 0;            //valeur la plus élevée
    int addr_vh = 0;
    int i = 0;

    for ( i = 0; i < EEPROM_SIZE; i += nb_octets )
    {
        //printf("\n%lu (%d)", eeprom_read(i), i);
        uint32_t v = eeprom_read ( i );
        if ( v > vh )
        {
            vh = v;
            addr_vh = i;
        }
    }
    //printf("%d", addr_vh);
    return addr_vh;
}

uint32_t eeprom_compteur (  )
{
    return eeprom_read ( return_addr_plus_grand (  ) );
}

int eeprom_increment (  )
{
    int addr = return_addr_plus_grand (  ); 
    uint32_t val = eeprom_read ( addr ); 
    addr += nb_octets;
    if ( addr >= EEPROM_SIZE )
        addr = 0;

    if ( val != MAX )
    {
        eeprom_write ( addr, ++val );
        return 1;
    }
    else
        return 0;
}

int nb_cycles (  )
{
    uint32_t val = eeprom_read ( return_addr_plus_grand (  ) );

    return val / ( EEPROM_SIZE / nb_octets );
}

void eeprom_dump ( int arret )
{
    int i = 0;
    int max = ( arret ) ? arret : EEPROM_SIZE;

    printf ( "\n\n------------ début du dump -----------" );
    for ( i = 0; i < max; i += nb_octets )
        printf ( "\n%d (%lu)", i, eeprom_read ( i ) );

    printf ( "\n------------ fin du dump -----------\n\n" );

}

int main ( void )
{
    //eeprom_write(1020, MAX - 10);

    int i = 0;
    for ( i = 0; i < 300; ++i )
    {
        if ( !eeprom_increment (  ) )
            printf ( "\nerror" );
    }

    printf ( "nb de cycles terminés : %d / 256\nCompteur à %lu \n",
             nb_cycles (  ), eeprom_compteur (  ) );
    return 0;
}

68tjs, merci pour ces composants, ça pourra toujours servir. Là je cherchais une solution ne nécessitant pas des broches supplémentaires.

Une astuce consisterait à avoir une "réserve" suffisante d'énergie (gold caps ou pile puis deep sleep) pour avoir le temps d'écrire la durée de fonctionnement en cas d'extinction de la source principale d'alimentation - comme ça pas besoin d'écrire toutes les minutes....

@vohu : si je comprends bien ton code tu n'écris qu'un int_32, pour ma part je fais un peu la même chose mais avec une struct à taille variable. Je pourrais en faire une classe template pour rendre mon code réutilisable et "montrable", mais le principe est le même : l'EEPROM a une valeur constante tant qu'il n'y a pas du contenu utile.

@J-M-L : c'est ce que je suis parvenu à faire dans mon child's timer, mais ma solution semble très "usine à gaz" pour les connaisseurs...