stockage SD (SPI) + HorlogeDs3234(SPI)

Bonjour,
Je me mets sur un nouveau topic, car je fais face à un problème de gestion de plusieurs modules SPI :

  • J’ai une horloge que je règle afin de prendre des mesures toutes les minutes (par interruptions sur la pin SQW)
  • J’ai un stockage sd effectué à chaque fois que je fais la moyenne de ma mesure.

Problème lorsque j’initialise la carte SD de mon module ethernet, et que je met ma partie enregistrement sur SD, le programme plante, les interruptions ne sont plus générées, et l’horloge perd l’heure…
Je met mon code en PJ car il est un peu long…
Si une âme charitable voulait bien m’aider un peu… ?

#include <AcceleroMMA7361.h>
#include <SD.h>

#include <SPI.h>
#include <DS3234.h>
#include "Enerlib.h"

#define BUFF_MAX 256
const int chipSelectSD = 4;
const int chipSelectHorl = 8;              // chip select pin
uint8_t sleep_period = 1;      // the sleep interval in minutes between 2 consecutive alarms
Energy energy;
int time_interrupt=0;

AcceleroMMA7361 accelero;
float comparaison;
int i = 0;

void set_next_alarm(void)
{
    struct ts t;
    unsigned char wakeup_min;
    DS3234_get(chipSelectHorl, &t);

    // calculate the minute when the next alarm will be triggered
    wakeup_min = (t.min / sleep_period + 1) * sleep_period;
    if (wakeup_min > 59) {
        wakeup_min -= 60;
    }
    
    // flags define what calendar component to be checked against the current time in order
    // to trigger the alarm
    // A2M2 (minutes) (0 to enable, 1 to disable)
    // A2M3 (hour)    (0 to enable, 1 to disable) 
    // A2M4 (day)     (0 to enable, 1 to disable)
    // DY/DT          (dayofweek == 1/dayofmonth == 0)
    boolean flags[4] = { 0, 1, 1, 1 };

    // set Alarm2. only the minute is set since we ignore the hour and day component
    DS3234_set_a2(chipSelectHorl, wakeup_min, 0, 0, flags);

    // activate Alarm2
    DS3234_set_creg(chipSelectHorl, DS3234_INTCN | DS3234_A2IE);
    
}

void INT0_ISR(void)
{
  //detach interrupt and set time_interrupt=1
  //interrupt must be attached again
  detachInterrupt(0);
  time_interrupt=1;

}

void setup()
{
  
  Serial.begin(9600);
  Serial.println("Entering setup");
    pinMode(2, INPUT);
    pinMode(10, OUTPUT); //broche SS de l'arduino, mise en sortie pour qu'il reste maitre
    digitalWrite(10, HIGH); //desactive le module ethernet W5100
    pinMode(chipSelectHorl, OUTPUT);
 //   pinMode(chipSelectSD, OUTPUT);
    delay(5000);
    DS3234_init(chipSelectHorl, DS3234_INTCN);
    DS3234_clear_a2f(chipSelectHorl);
    set_next_alarm();
    attachInterrupt(0, INT0_ISR, LOW);
    
 //====================================================== 
 /*    Serial.print("Initializing SD card...");
   // make sure that the default chip select pin is set to
   // output, even if you don't use it:
   
   // see if the card is present and can be initialized:
   if (!SD.begin(chipSelectSD)) {
     Serial.println("Card failed, or not present");
     // don't do anything more:
     return;
   }
   Serial.println("card initialized.");
   */
  //=========================================================== 
   accelero.begin(6, 3, 5, 9, A0, A1, A2);
 accelero.setARefVoltage(3.3); //sets the AREF voltage to 3.3V
 accelero.setSensitivity(HIGH); //sets the sensitivity to +/-6G 206mV/G
 accelero.calibrate();
}
//===================================================================

void loop()
{  
// open the file. note that only one file can be open at a time,
  /* // so you have to close this one before opening another.
   File dataFile = SD.open("datalog.txt", FILE_WRITE);

   // if the file is available, write to it:
   if (dataFile) {
     dataFile.println(analogRead(A0));
     dataFile.close();
  //   digitalWrite(chipSelectSD,HIGH);
   }  
   // if the file isn't open, pop up an error:
   else {
     Serial.println("error opening datalog.txt");
   } 
}
  
  if(time_interrupt==1){
    Serial.println(" time_interrupt==1");
    time_interrupt=0;
    
    // set next alarm
    set_next_alarm();
    // clear a2 alarm flag and let INT go into hi-z
    DS3234_clear_a2f(chipSelectHorl);
    //Attach interrupt again
    attachInterrupt(0, INT0_ISR, LOW);
    if (energy.WasSleeping())
      {
        Serial.println("  Interrupt and was sleeping");
      }
    else
      {
        /*
        The IRQ happened in awake state.
        This code is for the "normal" ISR.
        */
    Serial.println("  Interrupt and was NOT sleeping");
      }
  }
 Serial.println("Entering loop");
  delay(1000);
  
 /*
  //For debuf only
  char buff[BUFF_MAX];
  struct ts t;
    
  DS3234_get(chipSelectHorl, &t);
  // display current time
  snprintf(buff, BUFF_MAX, "%d.%02d.%02d %02d:%02d:%02d", t.year, t.mon, t.mday, t.hour, t.min, t.sec);
  Serial.println(buff);
  */
 delay(10); 
  Serial.println("Powering down");
  energy.PowerDown();


}

Dans ton code on ne voit aucun Serial.print() de débogage !

Commence par placer des serial.print() aux endroits stratégiques pour t'assurer

  • que le programme passe bien où tu veux
  • que les valeurs des variables stratégiques sont conformes à ce que tu t'attend.

Et tu verra que tu trouvera bien des erreurs par toi-même.

Tu voudrais que je mette ou des Serial.print(); !!?
Moi ce que je constate c'est que mon horloge se dérègle lorsque le programme tourne et que celui ci contient la partie carte SD, qui pourtant fonctionne très bien toute seule avec mon accéléromètre... et le programme de réveille toute les minutes fonctionne lui aussi très bien tout seul !!
Pourtant : - les chipSelects sont bien différenciés celui SD et celui Horloge

  • J'ai bien déclaré les entrés et sortie
  • Il n'y a normalement nul besoin de rajouter des digitalWrite(CS, LOW ou HIGH) car ils sont déjà gérés par les library

Le lorsque je décoche la partie SD le programme fait une première fois le loop et plante, car l’horloge est déréglée et il n’y a plus d’interruption, je ne vois pas en quoi des serial.print pourraient m’aider ici?! surtout qu’on ne peux pas en placer dans les fonctions d’interruptions…
Donc j’en suis tjrs au même point… =(
Mon horloge et perturbé par la SD…

ma question :
Est-ce qu'utiliser une autre librarie que celle de la SD, style SdFatLib pourrait résoudre le problème ??!

quelqu'un peut-il m'aider??!

Les gens bossent la journée tu sais ...

pouvais-vous m'expliquer la signification de :
The solder jumper marked "INT" can be connected to allow the Arduino board to receive interrupt-driven notification of events from the W5100, but this is not supported by the Ethernet library. The jumper connects the INT pin of the W5100 to digital pin 2 of the Arduino.

Si j'ai bien compris certaines librairies ne gèrent pas les interruptions ? ça pourrait expliquer mon problème ??!...

test effectué avec la librairie fatLib : Echec !

je ne vois pas en quoi des serial.print pourraient m'aider ici?! surtout qu'on ne peux pas en placer dans les fonctions d'interruptions..

Faut être souple dans les raisonnements.

Dans un programme terminé, fonctionnel, oui il faut faire le strict minimum dans une interruption, mais il faut comprendre pourquoi il faut être bref dans une interruption et ne pas le faire parce qu'on dit que.

Ton programme ne marche pas, il faut bien le mettre au point.

Ok tu va ralentir l'interruption et cela risque de mal fonctionner dans la suite du programme mais tu t'en fiche puisque qu'en mettant un seriel.print tu cherchais seulement à vérifier que tu passait dans l'interruption.
Immédiatement après que tu a vérifié que tu passait bien par l'interruption tu mets les serial.print en commentaire (on ne sait jamais dès fois qu'ils resservent)

La mise au point c'est la méthode des petits pas : on règle problème après problème.

Bonsoir,

68tjs:
La mise au point c'est la méthode des petits pas : on règle problème après problème.

+1
La meilleure façon d'avancer et encore de mettre un pied devant l'autre ou selon Conficius, la méthode des petits pas.
:grin:

Mon petit grain de sel ... Ne faut-il pas déclarer en volatile les variables utilisées dans les fonctions appelée lors des interruptions ?
int time_interrupt=0;

Et est-ce qu'il est vraiment nécessaire de passer par cette interruption pour déclencher une mesure toutes les minutes ?

Eh bien voila avec un Serial.print il passe dans le loop, puis une fois dans la fonction d'interruption, affiche ce que je lui ai demandé, puis se remet en veille dans le loop, et la plus moyen de le réveiller.
Et quand il bloque à cette étape il dérègle l’horloge.. que je suis obligé de remettre à l'heure ?!
As-tu une idée ? (il ne fait que la 1ère interruption et se bloque...)

c'est normal !

dans ta fonction void INT0_ISR(void) (code du premier post) tu désactives l'interruption ... et tu ne l'actives plus ...

Remet les lignes 111 à 130 hors commentaire
Declare aussi la variable time_interrupt en volatile int time_interrupt = 0;

Je suis en train de regarder, effectivement je n’avais pas déclaré en volatile ici…
mais sinon si je réactive l’interruption dans le if du loop…

sinon oui c'est vraiment nécessaire de passer par cette interruption, car j'aurais besoin de prendre une mesure toutes les 60 mins ...
Et il se crée le même problème lorsque je déclare en volatile..

//#include <AcceleroMMA7361.h>
#include <SD.h>

#include <SPI.h>
#include <DS3234.h>
#include "Enerlib.h"

#define BUFF_MAX 256
const int chipSelectSD = 4;
const int chipSelectHorl = 8;              // chip select pin
uint8_t sleep_period = 1;      // the sleep interval in minutes between 2 consecutive alarms
Energy energy;
volatile int time_interrupt=0;

//AcceleroMMA7361 accelero;
float comparaison;
int i = 0;

void set_next_alarm(void)
{
    struct ts t;
    unsigned char wakeup_min;
    DS3234_get(chipSelectHorl, &t);

    // calculate the minute when the next alarm will be triggered
    wakeup_min = (t.min / sleep_period + 1) * sleep_period;
    if (wakeup_min > 59) {
        wakeup_min -= 60;
    }
    
    // flags define what calendar component to be checked against the current time in order
    // to trigger the alarm
    // A2M2 (minutes) (0 to enable, 1 to disable)
    // A2M3 (hour)    (0 to enable, 1 to disable) 
    // A2M4 (day)     (0 to enable, 1 to disable)
    // DY/DT          (dayofweek == 1/dayofmonth == 0)
    boolean flags[4] = { 0, 1, 1, 1 };

    // set Alarm2. only the minute is set since we ignore the hour and day component
    DS3234_set_a2(chipSelectHorl, wakeup_min, 0, 0, flags);

    // activate Alarm2
    DS3234_set_creg(chipSelectHorl, DS3234_INTCN | DS3234_A2IE);
    
}

void INT0_ISR(void)
{
  //detach interrupt and set time_interrupt=1
  //interrupt must be attached again
  detachInterrupt(0);
  time_interrupt=1;

}

void setup()
{
  
  Serial.begin(9600);
  Serial.println("Entering setup");
    pinMode(2, INPUT);
    pinMode(10, OUTPUT); //broche SS de l'arduino, mise en sortie pour qu'il reste maitre
    digitalWrite(10, HIGH); //desactive le module ethernet W5100
    pinMode(chipSelectHorl, OUTPUT);
    pinMode(chipSelectSD, OUTPUT);
    delay(5000);
    DS3234_init(chipSelectHorl, DS3234_INTCN);
    DS3234_clear_a2f(chipSelectHorl);
    set_next_alarm();
    attachInterrupt(0, INT0_ISR, LOW);
    
 //====================================================== 
     Serial.print("Initializing SD card...");
   // make sure that the default chip select pin is set to
   // output, even if you don't use it:
   
   // see if the card is present and can be initialized:
   if (!SD.begin(chipSelectSD)) {
     Serial.println("Card failed, or not present");
     // don't do anything more:
     return;
   }
   Serial.println("card initialized.");
   
  //=========================================================== 
//   accelero.begin(6, 3, 5, 9, A0, A1, A2);
// accelero.setARefVoltage(3.3); //sets the AREF voltage to 3.3V
// accelero.setSensitivity(HIGH); //sets the sensitivity to +/-6G 206mV/G
// accelero.calibrate();
}
//===================================================================

void loop()
{  
  /*
// open the file. note that only one file can be open at a time,
   // so you have to close this one before opening another.
   File dataFile = SD.open("datalog.txt", FILE_WRITE);

   // if the file is available, write to it:
   if (dataFile) {
     dataFile.println(analogRead(A0));
     dataFile.close();
  //   digitalWrite(chipSelectSD,HIGH);
   }  
   // if the file isn't open, pop up an error:
   else {
     Serial.println("error opening datalog.txt");
   } 
   */

  
  if(time_interrupt==1){
    
    Serial.println(" time_interrupt==1");
    time_interrupt=0;
    attachInterrupt(0, INT0_ISR, LOW);
    
    // set next alarm
    set_next_alarm();
    // clear a2 alarm flag and let INT go into hi-z
    DS3234_clear_a2f(chipSelectHorl);
    //Attach interrupt again
    
    if (energy.WasSleeping())
      {
        Serial.println("  Interrupt and was sleeping");
      }
    else
      {
        /*
        The IRQ happened in awake state.
        This code is for the "normal" ISR.
        */
    Serial.println("  Interrupt and was NOT sleeping");
      }
  }
 Serial.println("Entering loop");
  delay(1000);
  
 /*
  //For debuf only
  char buff[BUFF_MAX];
  struct ts t;
    
  DS3234_get(chipSelectHorl, &t);
  // display current time
  snprintf(buff, BUFF_MAX, "%d.%02d.%02d %02d:%02d:%02d", t.year, t.mon, t.mday, t.hour, t.min, t.sec);
  Serial.println(buff);
  */
 delay(10); 
  Serial.println("Powering down");
  energy.PowerDown();

}

je désespère...

il plante direct dès l'ajout de ça dans le setup..

 Serial.print("Initializing SD card...");
   // make sure that the default chip select pin is set to
   // output, even if you don't use it:
   
   // see if the card is present and can be initialized:
 
   if (!SD.begin(chipSelectSD)) {
     Serial.println("Card failed, or not present");
     // don't do anything more:
     return;
   }
   Serial.println("card initialized.");

Bonjour,
Pourquoi un return dans le setup ?