SD-Logger mit Arduino Mega2560

Hallo!

Ich habe Probleme mit meinem Logg-Shield, das ich bereits erfolgreich mit einem UNO betrieben habe. Leider ist das Programm so groß, dass es instabil wird, weshalb ich mir einen Mega angeschafft habe. Leider gibt es jetzt Probleme mit dem Shield, die SD-Karte wird nicht erkannt.
Ich habe schon recherchiert und festgestellt, dass es da wohl schon länger diverse Probleme gibt, obwohl die ganzen ähnlichen Shields als kompatibel mit dem Mega angegeben werden. Ich habe einige der Lösungsvorschläge versucht, aber leider ohne Erfolg oder vielleicht auch nicht korrekt durchgeführt. IDE 1.0 habe ich noch nicht probiert, das wäre noch eine Möglichkeit.

Gibt es inzwischen eine saubere Lösung für die Verwendung der SD.h mit dem Mega und der aktuellen IDE? Am besten ohne Löten...
Das Schild ist dieses hier: Data Logging Shield for Arduino - RobotShop

Hallo,

die Hinweise in der Beschreibung zum ATmega2560 hast Du beachtet?

Wobei:
while (!card.init(SPI_HALF_SPEED,1,11,12,13))
müßte meiner Meinung nach 10,11,12,13 heißen, scheint ein Tippfehler zu sein...

Gruß aus Berlin
Michael

amithlon:
Hallo,

die Hinweise in der Beschreibung zum ATmega2560 hast Du beachtet?

Wobei:
while (!card.init(SPI_HALF_SPEED,1,11,12,13))
müßte meiner Meinung nach 10,11,12,13 heißen, scheint ein Tippfehler zu sein...

Gruß aus Berlin
Michael

Hi!

Ja, das war einer der Lösungsversuche, die ich hinter mir habe. Ich habe die .zip mit den beiden angepassten libraries (SD und RTC) von der Produktseite geladen, und mit ersteren die ursprüngliche ersetzt.
In CardInfo finde ich entgegen der Beschreibung kein

while (!card.init(SPI_HALF_SPEED, chipSelect)) {

sondern nur ein entsprechendes if ..., aber auch wenn ich dort das chipSelect ersetze bekomme ich den Fehler

"no matching function for call to 'Sd2Card::init(const uint8_t&, int, int, int, int, int)'"

Ich habe schon die Karte auf fat16 formatiert, eine weitere library (adafruit) versucht, außerdem die SDFat.h die hier beschrieben wird... Ich kann aber nicht ausschließen, dass ich in den workarounds irgendwo Fehler gemacht habe, mein Englisch ist nicht das beste. Eine deutschsprachige Lösung von A-Z wäre schön, aber leider habe ich bisher keine entdeckt.

Dank der "absurden" Konstruktion des Shields wird Soft SPI genutzt werden müssen.

no matching function for call to 'Sd2Card::init(const uint8_t&, int, int, int, int, int)'

Die Lib, welche du versuchst, kann das offensichtlich nicht.
Zumindest nicht so, wie du es versuchst.

Das Datenblatt sagt dazu:

Also, an updated SD library is needed in order to avoid error messages. How to replace the SD library:

Tue das , was da gesagt wird, und deine Chancen stehen besser.

Entschuldigung, ich muss noch ein Mal nachfragen;

Ich habe von der Seite eine .zip mit zwei library-master und einer .ino heruntergeladen. Eine library ist für die RTC. Den Inhalt der zweiten habe ich manuell in den alten sd.h-Ordner geschoben, nachdem ich ihn geleert habe. dann habe ich IDE gestartet.

Wenn ich in CardInfo wie angegeben das ChipSelect ersetze, bekomme ich wie gesagt die erwähnte Fehlermeldung. Mit dem mitgelieferten example passiert gar nichts.

Hier ist das Beispiel:

#include <OneWire.h>
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include "RTClib.h"
const int chipSelect = 10; //cs or the save select pin from the sd shield is connected to 10.
RTC_DS1307 RTC;
float celsius, fahrenheit;

OneWire  ds(8);  // temperature senor on pin 8 (a 4.7K resistor is necessary) //

File dataFile;
DateTime now;

void setup(void) {
  Serial.begin(9600);
  //setup clock
  Wire.begin();
  RTC.begin();
//check or the Real Time Clock is on
  if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    // uncomment it & upload to set the time, date and start run the RTC!
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }
//setup SD card
   Serial.print("Initializing SD card...");

  // see if the SD 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.");

  //write down the date (year / month / day         prints only the start, so if the logger runs for sevenal days you only findt the start back at the begin.
    now = RTC.now();
    dataFile = SD.open("datalog.txt", FILE_WRITE);
    dataFile.print("Start logging on: ");
    dataFile.print(now.year(),DEC);
    dataFile.print('/');
    dataFile.print(now.month(),DEC);
    dataFile.print('/');
    dataFile.print(now.day(),DEC);
    dataFile.println(" ");
    dataFile.println("Celsius              Time");
    dataFile.close();
}

void loop(void) {
  
// read temperature
pickUpTemperature();
//read the time
  now = RTC.now();
  
  //open file to log data in.
   dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  // log the temperature and time.
  if (dataFile) {
    dataFile.print(celsius);
    dataFile.print("                 ");
    
    dataFile.print(now.hour(),DEC);
    dataFile.print(":");
    dataFile.print(now.minute(),DEC);
    dataFile.print(":");
    dataFile.println(now.second(),DEC);
   
    dataFile.close();
    // print to the serial port too:
    Serial.println("data stored");
    Serial.print(celsius);
    Serial.print(" C                ");
    
    Serial.print(now.hour(),DEC);
    Serial.print(":");
    Serial.print(now.minute(),DEC);
    Serial.print(":");
    Serial.println(now.second(),DEC);
   
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  }
  //delay(60000); // this will log the temperature every minute.
  delay(3000);
}


// fuction with check the temperature sensor and update the tempeature. 
void pickUpTemperature(){
    byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
 
  
  if ( !ds.search(addr)) {
    //Serial.println("No more addresses.");
   //Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }
  
  //Serial.print("ROM =");
  for( i = 0; i < 8; i++) {
   // Serial.write(' ');
   // Serial.print(addr[i], HEX);
  }

  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
      return;
  }
  Serial.println();
 
  // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
     // Serial.println("  Chip = DS18S20");  // or old DS1820
      type_s = 1;
      break;
    case 0x28:
    //  Serial.println("  Chip = DS18B20");
      type_s = 0;
      break;
    case 0x22:
    //  Serial.println("  Chip = DS1822");
      type_s = 0;
      break;
    default:
   //   Serial.println("Device is not a DS18x20 family device.");
      return;
  } 

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end
  
  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
  
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad

  //Serial.print("  Data = ");
  //Serial.print(present, HEX);
  //Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
   // Serial.print(data[i], HEX);
   // Serial.print(" ");
  }
 // Serial.print(" CRC=");
 // Serial.print(OneWire::crc8(data, 8), HEX);
 // Serial.println();

  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0;
  Serial.print("  Temperature = ");
  Serial.print(celsius);
  Serial.print(" Celsius, ");
  Serial.print(fahrenheit);
  Serial.println(" Fahrenheit");
  
}

...und hier die library:

/*

 SD - a slightly more friendly wrapper for sdfatlib

 This library aims to expose a subset of SD card functionality
 in the form of a higher level "wrapper" object.

 License: GNU General Public License V3
          (Because sdfatlib is licensed with this.)

 (C) Copyright 2010 SparkFun Electronics

 */

#ifndef __SD_H__
#define __SD_H__

#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

#include <SPI.h>
#include <utility/SdFat.h>
#include <utility/SdFatUtil.h>

#define FILE_READ O_READ
#define FILE_WRITE (O_READ | O_WRITE | O_CREAT)

class File : public Stream {
 private:
  char _name[13]; // our name
  SdFile *_file;  // underlying file pointer

public:
  File(SdFile f, const char *name);     // wraps an underlying SdFile
  File(void);      // 'empty' constructor
  ~File(void);     // destructor
#if ARDUINO >= 100
  virtual size_t write(uint8_t);
  virtual size_t write(const uint8_t *buf, size_t size);
#else
  virtual void write(uint8_t);
  virtual void write(const uint8_t *buf, size_t size);
#endif
  virtual int read();
  virtual int peek();
  virtual int available();
  virtual void flush();
  int read(void *buf, uint16_t nbyte);
  boolean seek(uint32_t pos);
  uint32_t position();
  uint32_t size();
  void close();
  operator bool();
  char * name();

  boolean isDirectory(void);
  File openNextFile(uint8_t mode = O_RDONLY);
  void rewindDirectory(void);
  
  using Print::write;
};

class SDClass {

private:
  // These are required for initialisation and use of sdfatlib
  Sd2Card card;
  SdVolume volume;
  SdFile root;
  
  // my quick&dirty iterator, should be replaced
  SdFile getParentDir(const char *filepath, int *indx);
public:
  // This needs to be called to set up the connection to the SD card
  // before other methods are used.
  boolean begin(uint8_t csPin = SD_CHIP_SELECT_PIN, int8_t mosi = -1, int8_t miso = -1, int8_t sck = -1);
  
  //call this when a card is removed. It will allow you to inster and initialise a new card.
  void end(); 
  
  // Open the specified file/directory with the supplied mode (e.g. read or
  // write, etc). Returns a File object for interacting with the file.
  // Note that currently only one file can be open at a time.
  File open(const char *filename, uint8_t mode = FILE_READ);

  // Methods to determine if the requested file path exists.
  boolean exists(char *filepath);

  // Create the requested directory heirarchy--if intermediate directories
  // do not exist they will be created.
  boolean mkdir(char *filepath);
  
  // Delete the file.
  boolean remove(char *filepath);
  
  boolean rmdir(char *filepath);
  
  void enableCRC(boolean mode);

private:

  // This is used to determine the mode used to open a file
  // it's here because it's the easiest place to pass the 
  // information through the directory walking function. But
  // it's probably not the best place for it.
  // It shouldn't be set directly--it is set via the parameters to `open`.
  int fileOpenMode;
  
  friend class File;
  friend boolean callback_openPath(SdFile&, char *, boolean, void *); 
};

extern SDClass SD;

#endif

Kann ich irgendwie kontrollieren, ob beim kompillieren die richtige (neue) library eingebunden wird?

Ist das der erwähnte Software-SPI?

Hallo,

die Lib scheint die richtige zu sein. Ich hatte doch oben schon auf die Doku hingewiesen.
Ich sehe nicht, daß Du SD.begin(chipSelect) entsprechend angepasst hast.
Du mußt alle Pinnummern für SPI richtig im Aufrauf mitgeben weil das Shield auf einem Mega2560 nur SoftSPI nutzen kann.

SD.begin(10,11,12,13) könnte also passen...

Gruß aus Berlin
Michael