External power vs. USB power and SD card initialization problems, Arduino Micro

Hi All,

I am writing this post based on a problem and solution I discovered when using the Arduino Micro (ATmega32u4) and using the SD Library to initialize a Adafruit Micro SD Card Break-out board.

In short the problem began when using not USB power from the computer to supply power to the Arduino while it ran its initialization. I was using a combination of libraries taken from Sparkfun for my SD card functions.

To replicate the problem try using the code below to drive the breakout board with the MOSI, RX_LED/SS, SCK, and MISO pin connections on the Micro, as specified by datasheet on the arduino website.

  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(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");

In my case I noticed that for the variable chipSelect, it did not matter what value I passed; the code would compile and run when connected to the USB power. If I powered the board via the VIN, +5V or USB via a wall adapter the code would fail to initialize. It seems that there is some "magical" (read variable declaration mismatch within the pin mapping support files) connection by using the computer for the initialization.

The solution to my problem was the change the variable chipSelect to instead be SS (See Below), I assumed that this was a hardcoded pin name for the Micro (matching pin names and numbers for the micro is a nightmare) and presto chango the code works with any type of power supply.

I also commented out the serial communication lines for my debugging and haven't gone back to replace the function to see if this breaks the code again.

  // see if the card is present and can be initialized:
  if (!SD.begin(SS)) {
//    Serial.println("Card failed, or not present");
      digitalWrite(GREENLED, HIGH); //Indicates that SD Card is being written to
  
    // don't do anything more:
//    return;
  }
//  Serial.println("card initialized.");

I hope this helps someone else out there, I know there was a lot of discussion around setting Pin Modes to Outputs and writing them HIGH before initializing and those tips could help as well.

Thanks, SE

As follow up here is my code, before and after when I was debugging it.

Before (with Power Problems):

//Time stamped datalogger onto SD Card 


// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
const int chipSelect = 4; 
const int REDLED = 7;
const int GREENLED = 6;

//The RTC Library needs Wire
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 rtc;


//The SDlibrary needs SPI
#include <SPI.h>
#include "SD.h"

//Include the Accelerometer Libraries

#include <SFE_MMA8452Q.h> // Includes the SFE_MMA8452Q library

//Some SD Card code borrowed from Adafruit library examples
// set up variables using the SD utility library functions:

File dataFile;
#define LOGFILE "datalog.txt"

//Array Declarations

int ArrayAvg[3];


void setup() {

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


//RTC Setup + Some Initialization for First Time Upload  
//  Serial.println("Starting Real Time Clock");
  #ifdef AVR
    Wire.begin();
  #else
    Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due
  #endif

  rtc.begin();
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));  //uncomment this once and upload. Then comment it out and upload again
  //This will set the time the first time you upload it and if you don't upload again with it commented out it will 
  //reset the clock to the time the code was compliled each time.
  
  if (! rtc.isrunning()) {  //code borrowed from adafruit example rtc code
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }

// LED Setup

  pinMode(REDLED, OUTPUT);
  pinMode(GREENLED, OUTPUT);
  

}
void loop(){

  digitalWrite(REDLED, HIGH); // Power to the Main Code
  
  DateTime now = rtc.now();
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(' ');
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.println(now.second(), DEC);

  

  int sensorValue = analogRead(A0);  // read the input on analog pin 0:
  double Sum = 0;
  
    for (int i =0; i <3; i++)
    {
      ArrayAvg[i] = sensorValue;
      Sum = ArrayAvg[i] + Sum;
    }
    // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
    float voltage = (Sum/3) * (5.0 / 1023.0);
  // print out the value you read:
  
//  Serial.println(voltage);
 
  int buttonState = digitalRead(12);
 // Serial.println(buttonState); //Used for Troubleshooting Button State
  if (buttonState == HIGH){
   
    // open the file. note that only one file can be open at a time,
    // so you have to close this one before opening another.
    // NOTE: You cannot manipulate the data on the SD Card on the computer
    File dataFile = SD.open("datalog.txt", FILE_WRITE);
    digitalWrite(GREENLED, HIGH); //Indicates that SD Card is being written to
  
    // if the file is available, write to it:
    if (dataFile) {
    
      //Time Stamping
        dataFile.print(now.year(), DEC);
        dataFile.print('/');
        dataFile.print(now.month(), DEC);
        dataFile.print('/');
        dataFile.print(now.day(), DEC);
        dataFile.print(' ');
        dataFile.print(now.hour(), DEC);
        dataFile.print(':');
        dataFile.print(now.minute(), DEC);
        dataFile.print(':');
        dataFile.print(now.second(), DEC);   
        dataFile.print(' ');
      
      dataFile.println(voltage);
      dataFile.close();
      // print to the serial port too:
      Serial.println(voltage);
    }  
    // if the file isn't open, pop up an error:
    else {
      Serial.println("error opening datalog.txt");
    } 
  }
  else
  {
   digitalWrite(GREENLED, LOW); // Turn off LED when not in use
  }
  
  delay(100); //Slow Code Down
}

After (with significant portions of functions removed for testing);

const int REDLED = 7;
const int GREENLED = 6;

#include <Wire.h>
#include "RTClib.h"

RTC_DS1307 rtc;

#include <SPI.h>
#include "SD.h"

File dataFile;
#define LOGFILE "datalog.txt"

//Array Declarations

int ArrayAvg[3];


void setup() {

//  Serial.begin(9600);
  
//  Serial.print("Initializing SD card...");
//  // make sure that the default chip select pin is set to
//  // output, even if you don't use it:
  pinMode(10, OUTPUT);
  
  delay(100);
  
 
  // see if the card is present and can be initialized:
  if (!SD.begin(SS)) {
//    Serial.println("Card failed, or not present");
      digitalWrite(GREENLED, HIGH); //Indicates that SD Card is being written to
  
    // don't do anything more:
//    return;
  }
//  Serial.println("card initialized.");


//RTC Setup + Some Initialization for First Time Upload  
//  Serial.println("Starting Real Time Clock");
  #ifdef AVR
    Wire.begin();
  #else
    Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due
  #endif

  rtc.begin();
//  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));  //uncomment this once and upload. Then comment it out and upload again
  //This will set the time the first time you upload it and if you don't upload again with it commented out it will 
  //reset the clock to the time the code was compliled each time.
  
  if (! rtc.isrunning()) {  //code borrowed from adafruit example rtc code
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }

// LED Setup

  pinMode(REDLED, OUTPUT);
  pinMode(GREENLED, OUTPUT);
  

}                                                                                                                                                                                                                                                                                  
void loop(){

  digitalWrite(REDLED, HIGH); // Power to the Main Code
  
//  DateTime now = rtc.now();

//    Serial.print(now.year(), DEC);
//    Serial.print('/');
//    Serial.print(now.month(), DEC);
//    Serial.print('/');
//    Serial.print(now.day(), DEC);
//    Serial.print(' ');
//    Serial.print(now.hour(), DEC);
//    Serial.print(':');
//    Serial.print(now.minute(), DEC);
//    Serial.print(':');
//    Serial.println(now.second(), DEC);

  

  int sensorValue = analogRead(A0);  // read the input on analog pin 0:
  double Sum = 0;
  
    for (int i =0; i <3; i++)
    {
      ArrayAvg[i] = sensorValue;
      Sum = ArrayAvg[i] + Sum;
    }
    // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
    float voltage = (Sum/3) * (5.0 / 1023.0);
  // print out the value you read:
  
//  Serial.println(voltage);
 
  int buttonState = digitalRead(12);
 // Serial.println(buttonState); //Used for Troubleshooting Button State
  if (buttonState == HIGH){
   
    // open the file. note that only one file can be open at a time,
    // so you have to close this one before opening another.
    // NOTE: You cannot manipulate the data on the SD Card on the computer
    File dataFile = SD.open("datalog.txt", FILE_WRITE);
    
    // if the file is available, write to it:
    if (dataFile) {
    
      //Time Stamping
//        dataFile.print(now.year(), DEC);
//        dataFile.print('/');
//        dataFile.print(now.month(), DEC);
//        dataFile.print('/');
//        dataFile.print(now.day(), DEC);
//        dataFile.print(' ');
//        dataFile.print(now.hour(), DEC);
//        dataFile.print(':');
//        dataFile.print(now.minute(), DEC);
//        dataFile.print(':');
//        dataFile.print(now.second(), DEC);   
//        dataFile.print(' ');
      
      dataFile.println(voltage);
      dataFile.close();
      // print to the serial port too:
//      Serial.println(voltage);
    }  
    // if the file isn't open, pop up an error:
    else {
//      Serial.println("error opening datalog.txt");
    } 
  }
  else
  {
//   digitalWrite(GREENLED, LOW); // Turn off LED when not in use
  }
  
  delay(100); //Slow Code Down
}