lecture/ecriture ram ds1307

bonjour,

c'est mon premier post...

alors voilà, j'utilise une uno avec module ds1307 pour la gestion du temps.
il me faut aussi sauvegarder des données non volatiles.
j'utilise l'EEPROM pour cela. Mais étant donné qu'elle est limitée en nombre d'écriture, je souhaite utiliser les ressources ram du ds1307.
j'ai besoin de 48 octets, la ram en dispose 56.

je souhaite aussi écrire les 48 variables en une fois et les relire en une fois aussi. (utilisation de l'instruction read/writeBytesInRam)
j'ai la librairie RTClib qui prend en charge la ram du ds1307.

mais voilà, ça ne fonctionne pas. les 32 premiers octets sont bien stockés et relus, les 16 derniers sont relus à 255.

voilà le code d’illustration de mes propos qui a le seul mérite de reproduire mon problème

#include "Wire.h"
#include "RTClib.h"

RTC_DS1307 RTC;

int AnaBtnIn = 0;

byte data [48];

int LcdBouton()
{
  AnaBtnIn = analogRead(0);
  if (AnaBtnIn > 1000) return 0;
  if (AnaBtnIn < 80) return 1;
  if (AnaBtnIn < 280) return 2;
  if (AnaBtnIn < 470) return 3;
  if (AnaBtnIn < 670) return 4;
  if (AnaBtnIn < 870) return 5;
  return 0;
}

void setup() {
  
  Serial.begin(9600);
  Wire.begin();
  RTC.begin();
  
  }

void loop() {
  
       if (LcdBouton() == 3){
         for (int i = 0; i < 48; i++){
           data [i] = i;
           Serial.println (data [i]);
          }
       delay (1000);
       }
    
       if (LcdBouton() == 4){
         for (int i = 0; i < 48; i++){
         Serial.println (data[i]);
         }         
        RTC.writeBytesInRam (0x08, 48, data);
        delay (1000);        
       }
       
       if (LcdBouton() == 5){
      RTC.readBytesInRam(0x08, 48, data);
       delay (1000);
       
       for (int i = 0 ; i<48;i++){
       Serial.println (data [i]);
      }
   }
}

voilà, je ne sais pas si j'ai été suffisamment clair. j'attend vos remarques.

Salut

Pas de réponse évidente au vu du code.

NB : La ligne ci-dessous n'initialise que la première occurrence du tableau

byte data [48] = {0};

Quand tu dis que tu ne relis pas ce que tu as écrit en ram, on est bien d'accord que ta séquence de test est :

  1. j'affiche le contenu de data (bouton 3)
  2. j'écris data dans la ram (bouton 4)
  3. je recharge data depuis la ram (bouton 5)
  4. j'affiche le contenu de data (bouton 3)

et là les valeurs affichées aux étapes 1 et 4 sont différentes

bonsoir bricoleau et merci d'avoir pris un peu de temps.

en fait non, le bouton 3 n'est là que pour affecter 48 valeurs différentes

le bouton 4 est censé chargé ces 48 valeurs dans la ram
le bouton 5 lit la ram et affiche les valeurs lues

cela affiche les chiffres suivants :
0,1, 2, 3... 30, 31, 0, 255, 255, 255 ... 255.

il semblerait qu'au delà de 32 valeurs, seuls les 32 premières valeurs sont prises en compte.
quand je fais 2 envois de 24 valeurs par exemple, tout se passe bien.

Ton initialisation ne met que le premier élément à zéro. Si tu veux mettre tout à zéro, utilise memset()

amphioxus:
...
il semblerait qu'au delà de 32 valeurs, seuls les 32 premières valeurs sont prises en compte.
quand je fais 2 envois de 24 valeurs par exemple, tout se passe bien.

32 c'est une belle puissance de 2 :grin:
c'est quelle version de rtclib ? lien ?
si tu debute ton ecriture de ram apres 0 (par exemple à 5) tu relis toujours tes 32 bytes OK à partir de position 5 ?

bonsoir,

la version RTClib (dont je n'ai plus le lien) c'est :

// A library for handling real-time clocks, dates, etc.
// 2010-02-04 jc@wippler.nl http://opensource.org/licenses/mit-license.php
// 2012-11-08 RAM methods - idreammicro.com
// 2012-11-14 SQW/OUT methods - idreammicro.com
// 2012-01-12 DS1388 support
// 2013-08-29 ENERGIA MSP430 support

.

Artouste:
si tu debute ton ecriture de ram apres 0 (par exemple à 5) tu relis toujours tes 32 bytes OK à partir de position 5 ?

si je débute mon écriture en partant de l'adresse autre que 0x08 par exemple ?
ca ne change rien.
j'ai essayé de mémoriser à partir de l'adresse 0x0f de la ram par exemple, seules les 32 premières valeurs sont correctement mémorisées.
la 33 ème est toujours à 0 et les suivantes à 255.

j'ai essayé aussi 56 valeurs, même chose

amphioxus:
bonsoir,
...
la version RTClib (dont je n'ai plus le lien) c'est :
...

Alors mets celle que tu utilise en PJ :grin:

voilà

RTClib.h (4.89 KB)

RTClib.cpp (18 KB)

Juste une remarque concernant l'EEProm, certes le nombre d'écritures est limité mais selon l'usage du produit ça peut quand même représenter plusieurs dizaines d'années ou plusieurs siècles d'utilisation.
J'ai un de mes montages qui dans le pire des cas est allumé une fois par jour, causant une écriture dans l'EEProm, et ça me fait quand même 273 ans d'utilisation avant d'avoir un défaut d'écriture :slight_smile:

amphioxus:
il semblerait qu'au delà de 32 valeurs, seuls les 32 premières valeurs sont prises en compte.
quand je fais 2 envois de 24 valeurs par exemple, tout se passe bien.

As-tu essayé d'écrire en une seule fois les 48 valeurs et de les lire en 2x24 afin de déterminer si c'est l'écriture ou la lecture qui pose problème?
Juste une piste, parce que je ne vois rien dans ton code ou celui de la rtlib qui pourrait expliquer le problème.

bonsoir,

j'ai suivi ta piste

#include "Wire.h"
#include "RTClib.h"

RTC_DS1307 RTC;

int AnaBtnIn = 0;

byte Slot [48];
byte data1 [24];
byte data2 [24];

int LcdBouton()
{
  AnaBtnIn = analogRead(0);
  if (AnaBtnIn > 1000) return 0;
  if (AnaBtnIn < 80) return 1;
  if (AnaBtnIn < 280) return 2;
  if (AnaBtnIn < 470) return 3;
  if (AnaBtnIn < 670) return 4;
  if (AnaBtnIn < 870) return 5;
  return 0;
}

void setup() {
  
  Serial.begin(9600);
  Wire.begin();
  RTC.begin();
  }

void loop() {
  
       if (LcdBouton() == 3){
         for (int i = 0; i < 48; i++){
           Slot [i] = i;
                    
         Serial.println (Slot [i]);
 
       }
       delay (1000);
       }
    
       if (LcdBouton() == 4){
         
       //for (int i = 0; i < 24; i++){
         //data1 [i] = Slot [i];
         //data2 [i] = Slot [i + 24];
         
         //Serial.println (data[i]);
         //}
         //RTC.writeBytesInRam (0x08, 24, data1);
         //RTC.writeBytesInRam (0x20, 24, data2);
         RTC.writeBytesInRam (0x08, 48, Slot);
        delay (1000);
        
       }
       if (LcdBouton() == 5){
      
      RTC.readBytesInRam(0x08, 24, data1);
   RTC.readBytesInRam(0x20,24,data2);
   for (int i = 0 ; i<24;i++){
   Slot [i] = data1 [i];
   }
   for (int i = 24 ; i < 48 ; i++){
    Slot [i] = data2 [i-24];
   }
       delay (1000);
   for (int i = 0 ; i<48;i++){
   
   Serial.println (Slot [i]);   
   }  
 }
}

écriture en un paquet de 48 octets, et lecture en deux paquets de 24 octets

j'avais préalablement placé des valeurs typiques dans la ram.
résultat, les 32 premières valeurs ont bien été prise en compte, et les 16 dernières ont été celle que j'avais préalablement placé.

donc, le problème se situe bien à l'écriture.

effectivement patg_, l'EEPROM répond parfaitement à mes besoins mais voilà, j'essai toujours plus de trucs... je ne dois pas être le seul !

amphioxus:
j'avais préalablement placé des valeurs typiques dans la ram.
résultat, les 32 premières valeurs ont bien été prise en compte, et les 16 dernières ont été celle que j'avais préalablement placé.

donc, le problème se situe bien à l'écriture.

Bizarre. Rien n'indique ce genre de limitation dans la datasheet.

amphioxus:
effectivement patg_, l'EEPROM répond parfaitement à mes besoins mais voilà, j'essai toujours plus de trucs... je ne dois pas être le seul !

Non :slight_smile:
Je suis aussi dans ce cas.
Pour mon projet actuel j'avais envisagé d'utiliser la RAM de la DS3234 mais voilà, c'est pour mémoriser l'heure courante lors du changement de la pile alors je suis bien obligé d'utiliser l'EEProm :slight_smile:
J'utilise aussi l'EEProm pour mémoriser le fait que j'ai bien effectué le changement d'heure.
(Je remplace un DS1307+récepteur DCF77 par un DS3234 et j'implémente le changement d'heure d'été/hiver "manuellement").

amphioxus:
écriture en un paquet de 48 octets, et lecture en deux paquets de 24 octets

j'avais préalablement placé des valeurs typiques dans la ram.
résultat, les 32 premières valeurs ont bien été prise en compte, et les 16 dernières ont été celle que j'avais préalablement placé.

donc, le problème se situe bien à l'écriture.

bonsoir
A priori , je ne vois rien du suspect avec la librairie
je n'ai pas de ds1307 pour test sous la main avant lundi
ça donne quoi pour test si tu remplace
les instructions readBytesInRam , writeBytesInRam
par une boucle de 48 readByteInRam, writeByteInRam ?

bonjour,

j'ai d'abords écrit ça :

#include "Wire.h"
#include "RTClib.h"

RTC_DS1307 RTC;

int AnaBtnIn = 0;

byte Slot [48];
byte data1 [24];
byte data2 [24];

int LcdBouton()
{
  AnaBtnIn = analogRead(0);
  if (AnaBtnIn > 1000) return 0;
  if (AnaBtnIn < 80) return 1;
  if (AnaBtnIn < 280) return 2;
  if (AnaBtnIn < 470) return 3;
  if (AnaBtnIn < 670) return 4;
  if (AnaBtnIn < 870) return 5;
  return 0;
}

void setup() {
  
  Serial.begin(9600);
  Wire.begin();
  RTC.begin();
  
  
  
  }

void loop() {
  
       if (LcdBouton() == 3){
         for (int i = 0; i < 48; i++){
           Slot [i] = 132;
                    
         Serial.println (Slot [i]);
         
   
       }
       delay (1000);
       }
    
       if (LcdBouton() == 4){
       
         RTC.writeByteInRam (0x08, Slot [0]);
         RTC.writeByteInRam (0x09, Slot [1]);
         RTC.writeByteInRam (0x0a, Slot [2]);
         RTC.writeByteInRam (0x0b, Slot [3]);
         RTC.writeByteInRam (0x0c, Slot [4]);
         RTC.writeByteInRam (0x0d, Slot [5]);
         RTC.writeByteInRam (0x0e, Slot [6]);
         RTC.writeByteInRam (0x0f, Slot [7]);
         RTC.writeByteInRam (0x10, Slot [8]);
         RTC.writeByteInRam (0x11, Slot [9]);
         RTC.writeByteInRam (0x12, Slot [10]);
         RTC.writeByteInRam (0x13, Slot [11]);
         RTC.writeByteInRam (0x14, Slot [12]);
         RTC.writeByteInRam (0x15, Slot [13]);
         RTC.writeByteInRam (0x16, Slot [14]);
         RTC.writeByteInRam (0x17, Slot [15]);
         RTC.writeByteInRam (0x18, Slot [16]);
         RTC.writeByteInRam (0x19, Slot [17]);
         RTC.writeByteInRam (0x1a, Slot [18]);
         RTC.writeByteInRam (0x1b, Slot [19]);
         RTC.writeByteInRam (0x1c, Slot [20]);
         RTC.writeByteInRam (0x1d, Slot [21]);
         RTC.writeByteInRam (0x1e, Slot [22]);
         RTC.writeByteInRam (0x1f, Slot [23]);
         RTC.writeByteInRam (0x20, Slot [24]);
         RTC.writeByteInRam (0x21, Slot [25]);
         RTC.writeByteInRam (0x22, Slot [26]);
         RTC.writeByteInRam (0x23, Slot [27]);
         RTC.writeByteInRam (0x24, Slot [28]);
         RTC.writeByteInRam (0x25, Slot [29]);
         RTC.writeByteInRam (0x26, Slot [30]);
         RTC.writeByteInRam (0x27, Slot [31]);
         RTC.writeByteInRam (0x28, Slot [32]);
         RTC.writeByteInRam (0x29, Slot [33]);
         RTC.writeByteInRam (0x2a, Slot [34]);
         RTC.writeByteInRam (0x2b, Slot [35]);
         RTC.writeByteInRam (0x2c, Slot [36]);
         RTC.writeByteInRam (0x2d, Slot [37]);
         RTC.writeByteInRam (0x2e, Slot [38]);
         RTC.writeByteInRam (0x2f, Slot [39]);
         RTC.writeByteInRam (0x30, Slot [40]);
         RTC.writeByteInRam (0x31, Slot [41]);
         RTC.writeByteInRam (0x32, Slot [42]);
         RTC.writeByteInRam (0x33, Slot [43]);
         RTC.writeByteInRam (0x34, Slot [44]);
         RTC.writeByteInRam (0x35, Slot [45]);
         RTC.writeByteInRam (0x36, Slot [46]);
         RTC.writeByteInRam (0x37, Slot [47]);
        delay (1000);
        
       }
       if (LcdBouton() == 5){
      
         RTC.readBytesInRam (0x08, 48, Slot);
         
         delay (1000);
   for (int i = 0 ; i<48;i++){
   
   Serial.println (Slot [i]);
  
   
   }
    
}
}

écriture slot après slot et lecture en une fois.
les 16 dernière valeurs sont lues à 255.

puis j'ai écrit ça :

#include "Wire.h"
#include "RTClib.h"

RTC_DS1307 RTC;

int AnaBtnIn = 0;

word Slot [48];
byte data1 [24];
byte data2 [24];

int LcdBouton()
{
  AnaBtnIn = analogRead(0);
  if (AnaBtnIn > 1000) return 0;
  if (AnaBtnIn < 80) return 1;
  if (AnaBtnIn < 280) return 2;
  if (AnaBtnIn < 470) return 3;
  if (AnaBtnIn < 670) return 4;
  if (AnaBtnIn < 870) return 5;
  return 0;
}

void setup() {
  
  Serial.begin(9600);
  Wire.begin();
  RTC.begin();
  
  
  
  }

void loop() {
  
       if (LcdBouton() == 3){
         for (int i = 0; i < 48; i++){
           Slot [i] = 132;
                    
         Serial.println (Slot [i]);
         
   
       }
       delay (1000);
       }
    
       if (LcdBouton() == 4){
         RTC.writeByteInRam (0x08, Slot [0]);
         RTC.writeByteInRam (0x09, Slot [1]);
         RTC.writeByteInRam (0x0a, Slot [2]);
         RTC.writeByteInRam (0x0b, Slot [3]);
         RTC.writeByteInRam (0x0c, Slot [4]);
         RTC.writeByteInRam (0x0d, Slot [5]);
         RTC.writeByteInRam (0x0e, Slot [6]);
         RTC.writeByteInRam (0x0f, Slot [7]);
         RTC.writeByteInRam (0x10, Slot [8]);
         RTC.writeByteInRam (0x11, Slot [9]);
         RTC.writeByteInRam (0x12, Slot [10]);
         RTC.writeByteInRam (0x13, Slot [11]);
         RTC.writeByteInRam (0x14, Slot [12]);
         RTC.writeByteInRam (0x15, Slot [13]);
         RTC.writeByteInRam (0x16, Slot [14]);
         RTC.writeByteInRam (0x17, Slot [15]);
         RTC.writeByteInRam (0x18, Slot [16]);
         RTC.writeByteInRam (0x19, Slot [17]);
         RTC.writeByteInRam (0x1a, Slot [18]);
         RTC.writeByteInRam (0x1b, Slot [19]);
         RTC.writeByteInRam (0x1c, Slot [20]);
         RTC.writeByteInRam (0x1d, Slot [21]);
         RTC.writeByteInRam (0x1e, Slot [22]);
         RTC.writeByteInRam (0x1f, Slot [23]);
         RTC.writeByteInRam (0x20, Slot [24]);
         RTC.writeByteInRam (0x21, Slot [25]);
         RTC.writeByteInRam (0x22, Slot [26]);
         RTC.writeByteInRam (0x23, Slot [27]);
         RTC.writeByteInRam (0x24, Slot [28]);
         RTC.writeByteInRam (0x25, Slot [29]);
         RTC.writeByteInRam (0x26, Slot [30]);
         RTC.writeByteInRam (0x27, Slot [31]);
         RTC.writeByteInRam (0x28, Slot [32]);
         RTC.writeByteInRam (0x29, Slot [33]);
         RTC.writeByteInRam (0x2a, Slot [34]);
         RTC.writeByteInRam (0x2b, Slot [35]);
         RTC.writeByteInRam (0x2c, Slot [36]);
         RTC.writeByteInRam (0x2d, Slot [37]);
         RTC.writeByteInRam (0x2e, Slot [38]);
         RTC.writeByteInRam (0x2f, Slot [39]);
         RTC.writeByteInRam (0x30, Slot [40]);
         RTC.writeByteInRam (0x31, Slot [41]);
         RTC.writeByteInRam (0x32, Slot [42]);
         RTC.writeByteInRam (0x33, Slot [43]);
         RTC.writeByteInRam (0x34, Slot [44]);
         RTC.writeByteInRam (0x35, Slot [45]);
         RTC.writeByteInRam (0x36, Slot [46]);
         RTC.writeByteInRam (0x37, Slot [47]);
        delay (1000);
        
       }
       if (LcdBouton() == 5){
      
      RTC.readBytesInRam(0x08, 24, data1);
   RTC.readBytesInRam(0x20,24,data2);
   for (int i = 0 ; i<24;i++){
   Slot [i] = data1 [i];
   }
   for (int i = 24 ; i < 48 ; i++){
    Slot [i] = data2 [i-24];
   }
       delay (1000);
   for (int i = 0 ; i<48;i++){
   
   Serial.println (Slot [i]);
  
   
   }
    
}


}

écriture slot par slot et lecture en deux fois et là, les valeurs sont toutes lues correctement.

En gros si tu as une valeur qui est de l'ordre du million, tu décomposes le million en tronçon que tu notes en ram. Et pour la lecture tu recomposes les tronçons, j'ai bon ?

Parce que je ne comprends pas trop pourquoi il faut noter le résultat en plusieurs parties.

Désolé si je suis un peu boulet.

Donc si je dois noter 1 000 000 000 dans la ram du DS1307 je fais quoi ?

amphioxus:
...
écriture slot par slot et lecture en deux fois et là, les valeurs sont toutes lues correctement.

bonjour
au moins ça leve le doute sur l'integrité de la zone RAM
je regarderais en debut de semaine avec un D1307

Bonjour,

gunsman76:
En gros si tu as une valeur qui est de l'ordre du million, tu décomposes le million en tronçon que tu notes en ram. Et pour la lecture tu recomposes les tronçons, j'ai bon ?
Parce que je ne comprends pas trop pourquoi il faut noter le résultat en plusieurs parties.

Le "découpage en tronçons" est simple car ta RAM est composée d'emplacement de 8 bits, cad pouvant contenir les valeurs allant de 0 à 255.
Pour stocker une valeur supérieur à 255, il faudra utiliser une "astuce" pour stocker le nombre. Il existe de nombreuses méthodes de codage allant du stockage individuel de chaque chiffre ou en passant par une déclaration de variable capable de contenir le chiffre en question.

gunsman76:
Donc si je dois noter 1 000 000 000 dans la ram du DS1307 je fais quoi ?

Si tu veux stocker 1 milliards, il te faudra 10 emplacements de ta RAM pour stocker le chiffre 1 et les neuf 0 par contre si tu utilises une variable du type unsigned long, tu n'auras besoin que de 4 emplacements de 8 bits dans ta RAM.

Je te laisse un peu chercher pour voir comment tu dois procéder.
Regarde les liens ci-dessous cela devrait t'aider :wink:
http://arduino.cc/en/Reference/UnsignedLong#.Uy6_8Kh5OO8
http://arduino.cc/en/Reference/UnsignedChar#.Uy7DjKh5OO8

Merci, je vais éplucher tes liens !

:slight_smile: