Simple SD datalogging on Arduino MEGA ADK

Dear community,

I am trying to do a very simple data logging test. Basically I measure the voltage between two points, print it on an LCD screen and am now also trying to write it in an SD card. The voltmeter works fine, the LCD screen also gives me what I want. However I can’t overcome the SD initialization process. I have been looking on internet and have read some solutions which seem very personalized and which I did not understand due to my lack of experience and knowledge. For instance, I found this in a post in this forum:

“The SD card uses the SPI bus - so it needs addressing.
The Deek robot seems to use as follows:
D10 - Chip Select
D11 - SPI MOSI
D12 - SPI MISO
D13 - SPI SCK”

Information which I do not know how to use, especially because it seems that there are differences for UNO or MEGA arduinos. What I thought I understood is that I had to put const int chipSelect = 10; in my code. However, I get the message “Card failed, or not present” due to the following code line:

 if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");

Is there any extra information I should add? Thank you so much!

Here is my code:

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

LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

float input_voltage = 0.0;
float temp = 0.0;
const int chipSelect = 10;


void setup()
{
  Serial.begin(9600);     //  opens serial port, sets data rate to 9600 bps
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  lcd.begin(16, 2);       //// set up the LCD's number of columns and rows:
  lcd.print("DIGITAL VOLTMETER");
  // pinMode(10, OUTPUT);
  //digitalWrite(10, HIGH);


  Serial.print("Initializing SD card...");
  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.");
}

void loop()
{

  //Conversion formula for voltage

  int analog_value = analogRead(A0);
  input_voltage = (analog_value * 5.0) / 1024.0;


  if (input_voltage < 0.1)
  {
    input_voltage = 0.0;
  }

  lcd.setCursor(0, 1);
  lcd.print("Voltage= ");
  lcd.print(input_voltage);

  // make a string for assembling the data to log:
  String dataString = "";
  dataString += "Voltage=";
  dataString += String(input_voltage);

  // 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(dataString);
    dataFile.close();
    // print to the serial port too:
    Serial.println(dataString);
  }

  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  }

  delay(1000);

}

The Mega uses different SPI pins. You need to determine the relationship between pins 10, 11, 12, and 13 on the Uno and pins 50, 51, 52, and 53 on the Mega (the products page has both sets of pins with functions).

Instead of making pin 10 an output, you need to make the corresponding Mega pin an output.

Instead of connecting to pins 11, 12, and 13, you need to connect to the corresponding pins on the Mega.

If your device plugs onto the Mega, add some wires on the bottom of the Mega from pins 50-51-52-53 to 10-11-12-13. Compare the Uno schematic to the Mega schematic to make sure you get the pins correct.
Then don't use 10-11-12-13 in your coding. SPI.h library in Mega will use 50 (MISO), 51 (MOSI), 52 (SCK), 53 (SS).
53 has to be an output for the Mega to be SPI master. You may use another pin for SS if you want.

Thank you PaulS and CrossRoads.

I connected the pins 10 to 53, 11 to 51, 12 to 50 and 13 to 52, and changed 10 to 53 in the code. It works! thank you. Now I'm wondering: is this something everyone does? Isn't there a cleaner way to make this work without needing to connect pins between the shield and the arduino board? Anyways, this works so I'm relieved, I have spent quite some time on troubleshooting this, thanks a lot!

Nongsai:
<…>Now I’m wondering: is this something everyone does? Isn’t there a cleaner way to make this work without needing to connect pins between the shield and the arduino board? <…>

In Arduino land, there is the concept of stacked-modules/boards also known as shields. One can purchase shields that already have the SD card on the correct pinouts: Mega SD shield.

I also offer a '1284P board with SD card, RS232 interface as an option for Serial1, and battery-backed DS1307 RTC chip. 1284P is nice with its 16K of SRAM when more is needed than the 8K of the 2560. Some prototype area for addng an RF card or a chip and some parts, and Power/Gnd/Signal are available at each header location as well.
http://www.crossroadsfencing.com/BobuinoRev17/


Screw terminals and USB onboard or offboard are options

Don't use delay otherwise your code will stop for 1 second every loop.
I cannot compile your code I get and error saying "stray\302 in program"
try it this way, add this to your code, But you need to alter the pins for the mega as mentioned in the other post

int refresh_rate = 1000;// 1 second delay
unsigned long lastUpdate = 0; // Keep track of last update time

Then in your loop

if (millis() > (lastUpdate + refresh_rate))
  {
// make a string for assembling the data to log:
  String dataString = "";
  dataString += "Voltage=";
  dataString += String(input_voltage);

  // 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(dataString);
    dataFile.close();
    // print to the serial port too:
    Serial.println(dataString);
  }

  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  }

   lastUpdate = millis();

    }

This way it will only write to the SD every one second without delaying everything else