Go Down

Topic: Storage from Eeprom to SD (Read 542 times) previous topic - next topic

bors

Hi,
I want to log data from an Eeprom to a SD-Card using an Uno with an Adafruit SD-Card shield. To save power, I have a watch dog implemented, that is sniffing every 8 seconds for data.
Unfortunately, the code will not even create a file on my SD-Card, also I've been troubleshooting for days now. Is one of you able to help?
Thanks
Christoph

Code: [Select]

 
  #include <avr/sleep.h>
  #include <avr/power.h>
  #include <avr/wdt.h>
  #include <SD.h>


  #define LED_PIN (13)
 
  volatile int f_wdt=1;
  int counter = 1;    //initialize to 1
  int X = 1;       //# of watchdog interrupt cycles between data downloading sequence.  Each cycle is ~8 seconds, so 2700 cycles = 6 hours
 
File myFile;         
int byteNumber = 1;   
char a[9];           
int placeHolder = 1; 
int dummyVar = 1;     
int tempTimeStart;   
int tempTimeEnd;     
int variable = 3;

  void enterSleep(void)
  {
    set_sleep_mode(SLEEP_MODE_PWR_SAVE);   /* EDIT: could also use SLEEP_MODE_PWR_DOWN for lowest power consumption. */
    sleep_enable();
   
    /* Now enter sleep mode. */
    sleep_mode();
   
    /* The program will continue from here after the WDT timeout*/
    sleep_disable(); /* First thing to do is disable sleep. */
   
    /* Re-enable the peripherals. */
    power_all_enable();
  }
 
 
 

  void setup()
  {
   
    pinMode(13, OUTPUT);
 
    /*** Setup the WDT ***/
   
    /* Clear the reset flag. */
    MCUSR &= ~(1<<WDRF);
   
    /* In order to change WDE or the prescaler, we need to
     * set WDCE (This will allow updates for 4 clock cycles).
     */
    WDTCSR |= (1<<WDCE) | (1<<WDE);
 
    /* set new watchdog timeout prescaler value */
    WDTCSR = 1<<WDP0 | 1<<WDP3; /* 8.0 seconds */
   
    /* Enable the WD interrupt (note no reset). */
    WDTCSR |= _BV(WDIE);
 
 
    pinMode(10, OUTPUT);             
    a[8] = 0;                       
    Serial.setTimeout(5000);         
       
     delay(7000);                    //delay 7 seconds every time battery is restarted so the bottom arduino has time to initialize.  It can't be more than 8 seconds or the watchdog timer runs over.
     SD.begin();                   
   


}
 
 
  void loop()
  {
    if(f_wdt == 1)    //Every 8 seconds the Arduino will wake.  Every X wakeups it will toggle the LED
    {
     
       
      if(counter == X){  //If the Arduino has woken up X number of times, run through data-gathering sequence
       
                     downloadData();
                               counter = 1;      //reset the counter variable to 1 for sleep cycle code   
                               
                              }
                                       
       
       
         
         
      else{
        counter = counter + 1;   //update counter variable
     
       
     
     }
     
       /* Don't forget to clear the flag. */
      f_wdt = 0;
     
      /* Re-enter sleep mode. */
      enterSleep();
     
 
     
    }
    else
    {
     
      /* Do nothing. */
    }
  }
 
 
  void downloadData(void)
  {while (dummyVar > 0){
                                  myFile = SD.open("Sensor4.txt", FILE_WRITE);   
                                   
                                    Serial.begin(57600);           
                                    delay(1000);                   
                                   
                                    Serial.print('k');             
                                   
                                    tempTimeStart = millis();     
                                    while(!Serial.available()){     
                                      tempTimeEnd = millis();       
                                     
                                      if ((tempTimeEnd - tempTimeStart) > 5000){  //5 seconds of no serial contact has elapsed, re-start while loop by setting dummyVar to 0.
                                           
                                            dummyVar = 0;                    Serial.readBytes times out
                                      }   
                                    };   
                                 
                                   
                                    while(Serial.available() > 0){ 
                                         Serial.readBytes(a,8);     
                                         delay(1);                 
                                         
                                         myFile.print(a);           
                                    }
                                 
                                 
                                   Serial.print('A') ;             
                                   tempTimeStart = millis();       
                                      while(!Serial.available()){
                                      tempTimeEnd = millis();       
                                     
                                      if ((tempTimeEnd - tempTimeStart) > 1000){ 
                                       
                                            dummyVar = 0;                   
                                      }   
                                   }
                                   
                                   
                                   
                                  tempTimeStart = millis();     //record temporary time
                                   while (placeHolder > 0){          //Keep looping until Serial.readBytes doesn't see any more data in buffer
                                       byteNumber = Serial.readBytes(a,8);        //read 8 bytes at a time
                                       tempTimeEnd = millis();       //record temporary time
                                     
                                      if ((tempTimeEnd - tempTimeStart) > 10000){  //once it takes Serial.readBytes longer than XX seconds to get more data, exit while loop
                                            placeHolder = 0;                     //causes while loop to end when Serial.readBytes times out
                                      }
                                         
                                     myFile.print(a);                 //Send data to SD card
                                   }
                                   
                                   
                                   
                                   myFile.print("Bytes available on buffer right NOW: ");
                                   myFile.println(Serial.available());   //Make sure no data remains in the buffer
                                                                   
                                 
                                  Serial.print('X');                   //delete data
                                  Serial.print('Y');                   //confirm delition
                                  Serial.print('E');                   //exit from logging mode
                                 
                                   myFile.close();                     // Close file (otherwise it doesn't save properly)
                               
                                  Serial.end();      //Close serial connection
                                  placeHolder = 1;   //reset placeholder to 1
                                 
                                                                 
                                break;  //end the downloadData function once data has been collected
                                }
                               
                             
                                myFile.close();                     // Close file (otherwise it doesn't save properly)
                                Serial.end();  //Close serial connection
                                dummyVar = 1;   //reset dummyVar to 1 to enter while loop again, this way Arduino gets another shot at establishing serial connection
                               
                               
   
  }

pert

Please always do a Tools > Auto Format on your code before posting it. This will make it easier for you to spot bugs and make it easier for us to read. If you're using the Arduino Web Editor you will not have access to this useful tool but it's still unacceptable to post poorly formatted code. I recommend you to use the standard IDE instead.

Please remove unnecessary blank lines from your code before posting to the forum. One or two to separate code into logical sections is fine but large spaces for no reason or random blank lines just make for more scrolling when we're trying to read your code.


Have you successfully used the example sketches under File > Examples > SD?

bors

I used AutoFormat now, hope the script is easier to read now.
The example sketches are running without problem.

Code: [Select]


#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>
#include <SD.h>
#define LED_PIN (13)

volatile int f_wdt=1;
int counter = 1;    //initialize to 1
int X = 1;       //# of watchdog interrupt cycles between data downloading sequence.  Each cycle is ~8 seconds, so 2700 cycles = 6 hours

File myFile;         
int byteNumber = 1;   
char a[9];           
int placeHolder = 1;
int dummyVar = 1;     
int tempTimeStart;   
int tempTimeEnd;     
int variable = 3;

void enterSleep(void)
{
  set_sleep_mode(SLEEP_MODE_PWR_SAVE);   /* EDIT: could also use SLEEP_MODE_PWR_DOWN for lowest power consumption. */
  sleep_enable();

  /* Now enter sleep mode. */
  sleep_mode();

  /* The program will continue from here after the WDT timeout*/
  sleep_disable(); /* First thing to do is disable sleep. */

  /* Re-enable the peripherals. */
  power_all_enable();
}

void setup()
{

  pinMode(13, OUTPUT);

  /*** Setup the WDT ***/

  /* Clear the reset flag. */
  MCUSR &= ~(1<<WDRF);

  /* In order to change WDE or the prescaler, we need to
   * set WDCE (This will allow updates for 4 clock cycles).
   */
  WDTCSR |= (1<<WDCE) | (1<<WDE);

  /* set new watchdog timeout prescaler value */
  WDTCSR = 1<<WDP0 | 1<<WDP3; /* 8.0 seconds */

  /* Enable the WD interrupt (note no reset). */
  WDTCSR |= _BV(WDIE);


  pinMode(10, OUTPUT);             
  a[8] = 0;                       
  Serial.setTimeout(5000);         

  delay(7000);                    //delay 7 seconds every time battery is restarted so the bottom arduino has time to initialize.  It can't be more than 8 seconds or the watchdog timer runs over.
  SD.begin();                   
}


void loop()
{
  if(f_wdt == 1)    //Every 8 seconds the Arduino will wake.  Every X wakeups it will toggle the LED
  {


    if(counter == X){  //If the Arduino has woken up X number of times, run through data-gathering sequence

      downloadData();
      counter = 1;      //reset the counter variable to 1 for sleep cycle code   

    }

    else{
      counter = counter + 1;   //update counter variable

    }

    /* Don't forget to clear the flag. */
    f_wdt = 0;

    /* Re-enter sleep mode. */
    enterSleep();

  }
  else
  {

    /* Do nothing. */
  }
}
void downloadData(void)
{
  while (dummyVar > 0){
    myFile = SD.open("Sensor4.txt", FILE_WRITE);   

    Serial.begin(57600);           
    delay(1000);                   

    Serial.print('k');             

    tempTimeStart = millis();     
    while(!Serial.available()){     
      tempTimeEnd = millis();       

      if ((tempTimeEnd - tempTimeStart) > 5000){  //5 seconds of no serial contact has elapsed, re-start while loop by setting dummyVar to 0.

        dummyVar = 0;                   
        Serial.readBytes times out
      }   
    };   


    while(Serial.available() > 0){
      Serial.readBytes(a,8);     
      delay(1);                 

      myFile.print(a);           
    }


    Serial.print('A') ;             
    tempTimeStart = millis();       
    while(!Serial.available()){
      tempTimeEnd = millis();       

      if ((tempTimeEnd - tempTimeStart) > 1000){

        dummyVar = 0;                   
      }   
    }

    tempTimeStart = millis();     //record temporary time
    while (placeHolder > 0){          //Keep looping until Serial.readBytes doesn't see any more data in buffer
      byteNumber = Serial.readBytes(a,8);        //read 8 bytes at a time
      tempTimeEnd = millis();       //record temporary time

      if ((tempTimeEnd - tempTimeStart) > 10000){  //once it takes Serial.readBytes longer than XX seconds to get more data, exit while loop
        placeHolder = 0;                     //causes while loop to end when Serial.readBytes times out
      }

      myFile.print(a);                 //Send data to SD card
    }

    myFile.print("Bytes available on buffer right NOW: ");
    myFile.println(Serial.available());   //Make sure no data remains in the buffer
    Serial.print('X');                   //delete data
    Serial.print('Y');                   //confirm delition
    Serial.print('E');                   //exit from logging mode

    myFile.close();                     // Close file (otherwise it doesn't save properly)

    Serial.end();      //Close serial connection
    placeHolder = 1;   //reset placeholder to 1


      break;  //end the downloadData function once data has been collected
  }


  myFile.close();                     // Close file (otherwise it doesn't save properly)
  Serial.end();  //Close serial connection
  dummyVar = 1;   //reset dummyVar to 1 to enter while loop again, this way Arduino gets another shot at establishing serial connection

}

Lucario448

Why SD.begin() doesn't even have specified the CS pin? In this case, I think it defaults to pin 10.

It's also a bad idea to assume that the card will be always initialized and the file opened, because... what if not?

bors

The CS pin on my SD-Shield is pin 10, so I did not see the need to put it in. I tried to specifie it (and also tried other Pin-numbers) but with no success.

Is the following not for initialising the card and open a file? What do you suggest?
 
Code: [Select]
myFile = SD.open("Sensor4.txt", FILE_WRITE);   

    Serial.begin(57600);           
    delay(1000);         

Lucario448

Is the following not for initialising the card and open a file? What do you suggest?
If the SD card fails to initialize, no file can be opened. If it does but still no file can be even created, that's weird; it only should happen due to defective hardware or the card being completely full.

cattledog

Quote
Unfortunately, the code will not even create a file on my SD-Card.
If the file is already created on the card, will it open and write to it?

How are you powering the SD shield, and what state is it in during sleep? If the sd card is being powered down and back up, there are issues with how to make multiple calls to SD.begin().

You also have considerable logic and conditionals in downloadData(), and I recommend that you sort out the issues of sleep/wake from the rest of your code.

If instead of going to sleep, you manage an 8 second millis() timer, does the sd file writing function correctly? If you sleep 8 seconds and wake, an you confirm that all is correct with either Serial output or an led on/off instead of an sd write?

bors

It works now. I checked everything again, tried the timer and rewrote my script and now it works.

Thanks a lot everyone :)

cattledog

Quote
It works now. I checked everything again, tried the timer and rewrote my script and now it works.
Please share your solution with the forum.

The use of an SD shield or module with a sleeping Arduino and the software and power management of the SD device has multiple complications. Your solution will be of interest to others.

bors

The solution was a bit embarassing, just reinstall the software with all the libraries, change the script completely, than change it back to how it was befor, and now it works. I have no clue, what I really did.

Go Up