Teensy 4.0: SD card problems/errors

Status
Not open for further replies.

3Domse3

Member
I want to hook up my Micro-SD Card with my Teensy 4.0. I want to use the SPI-Pins of my Teensy rather than the pads on the back (I connected it correct but for CS i used Pin 10 instead of 4 and changed chipSelect to 10). Is this possible? And how do I get the SD library to work with my board? I'm only getting errors :(

I already talked with someone on Reddit (maybe the chat will help): https://www.reddit.com/r/arduino/comments/enm4a5/question_i_want_to_hook_up_my_microsd_card_with/

I hope nothing is mission or it is too messy. It's my first post on aa forum like this...

Error message: no matching function for call to 'SDClass::eek:pen(String&, int)'

Code:
#include <SPI.h>
#include <SD.h>
#include <math.h>

#define LED_PIN 2

const int chipSelect = 10;

long randNumber;
String filename = "";
String dataString = "";

unsigned long i = 3;
unsigned long nr = 2;
unsigned long old_t = 0;
unsigned long delta_t = 0;

/*
unsigned long long i = 3;
unsigned long long nr = 2;
unsigned long long old_t = 0;
unsigned long long delta_t = 0;
*/

void setup() {
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);
  
  Serial.begin(115200);
  
  Serial.print("Initializing SD card... ");
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present!");
    digitalWrite(LED_PIN, HIGH);
    while (1);
  }
  
  Serial.println("Card initialized.");

  randomSeed(analogRead(0));
  randNumber = random(10000000, 100000000);
  filename += String(randNumber);
  filename += String(".txt");

  [B]File dataFile = SD.open(filename, FILE_WRITE);     // Line of Error[/B]

  if (dataFile) {
    dataFile.println("Nr;Prime;Calc_Time(us);Runtime(us)");
    
    dataString = "";
  
    dataString += String("1;2;0;");
    dataString += String(micros());

    dataFile.println(dataString);

    dataFile.close();
  }

  else {
    Serial.print("Error opening ");
    Serial.print(filename);
    Serial.println(".");
    digitalWrite(LED_PIN, HIGH);
    while (1);
  }

  Serial.println();

}

void loop() {
  old_t = 0;
 
  old_t = micros();
  long prime = is_prime(i);
  delta_t = micros() - old_t;
 
  if (prime == 1) {
    Serial.println(nr);

    dataString = "";
  
    dataString += String(nr);
    dataString += String(";");
    dataString += String(i);
    dataString += String(";");
    dataString += String(delta_t);
    dataString += String(";");
    dataString += String(micros());

    File dataFile = SD.open(filename, FILE_WRITE);

    if (dataFile) {
      dataFile.println(dataString);
      dataFile.close();
    }

    else {
      Serial.print("Error opening ");
      Serial.print(filename);
      Serial.println(".");
      digitalWrite(LED_PIN, HIGH);
      while (1);
    }
       
    nr++;
  }

  i = i + 2;
}


bool is_prime(uint32_t n){
  if(n<=1) return false;
  else if (n<=3) return true;
  else if(n%2==0 or n%3==0) return false;
  uint32_t i= 5;
    while (i * i <=n)
    {
      if(n%i== 0 or n%(i + 2) == 0) return false;
       i+=6;
    }
  return true;
  nr++;
}
 
Your issue is the SD library does not accept the String library. Generally, due to the limited memory on microprocessors, it isn't a good idea to use the String class (granted the 4.0 has more memory, but still it can be a problem).

Instead you should use the C string functions (strcpy, strcat, memcpy) and/or sprintf to build up the filename.

Code:
#define MAX_NAME_LEN 32
#define MAX_DATA_LEN 32
char filename[MAX_NAME_LEN];
char dataString[MAX_DATA_LEN];

// ...

  randomSeed(analogRead(0));
  randNumber = random(10000000, 100000000);
  sprintf (filename, "%ld.txt", randNumber);
 
Thx. That worked. But now I got a new problem...

It says: incompatible types in assignment of 'const char [1]' to 'char [32]'

Could it be that I have to change all my dataString += ... commands and my write command? If so, how do I do that? I'm a C++ beginner, only used to easy "Arduino-C" ;)

And does #define MAX_DATA_LEN 32 mean I have to split my write command if I want to write more than 32 characters? Because my output lenght rises very fast thanks to the 600MHz chip :)


Code:
  if (dataFile) {
    dataFile.println("Nr;Prime;Calc_Time(us);Runtime(us)");
    
    dataString = "";       [B]//Line of Error[/B]
  
    dataString += String("1;2;0;");
    dataString += String(micros());

    dataFile.println(dataString);

    dataFile.close();
  }
 
You could also use the c_str() StringObject Function.
Code:
File dataFile = SD.open(filename.c_str(), FILE_WRITE);
 
Thx. That worked. But now I got a new problem...

It says: incompatible types in assignment of 'const char [1]' to 'char [32]'

Could it be that I have to change all my dataString += ... commands and my write command? If so, how do I do that? I'm a C++ beginner, only used to easy "Arduino-C" ;)

And does #define MAX_DATA_LEN 32 mean I have to split my write command if I want to write more than 32 characters? Because my output lenght rises very fast thanks to the 600MHz chip :)

No, just bump up MAX_DATA_LEN to whatever size that is the maximum for your output + 1 for the trailing null byte.
 
But what is this error: incompatible types in assignment of 'const char [1]' to 'char [32]'

Can't figure it out :(
 
But what is this error: incompatible types in assignment of 'const char [1]' to 'char [32]'

Can't figure it out :(

you cant treat a c character array like a c++ String object.

Code:
#define MAX_NAME_LEN 32
#define MAX_DATA_LEN 32
char filename[MAX_NAME_LEN];
char dataString[MAX_DATA_LEN];


Code:
    dataString = "";       //Line of Error
  
    dataString += String("1;2;0;");
    dataString += String(micros());


its probably best if you go back to using the String object like you did before and then calling dataString.c_str() when you want to convert it into a c character array for the library.

this is a bit ugly but otherwise you will have to learn how to use all the c character array functions like sprintf and so forth.
 
What do you mean with
its probably best if you go back to using the String object like you did before and then calling dataString.c_str() when you want to convert it into a c character array for the library.
 
What do you mean with

Use your original code, and use the c_str() method where it complains to change String into normal C-style char arrays.

Code:
#include <SPI.h>
#include <SD.h>
#include <math.h>

#define LED_PIN 2

const int chipSelect = 10;

long randNumber;
String filename = "";
String dataString = "";

unsigned long i = 3;
unsigned long nr = 2;
unsigned long old_t = 0;
unsigned long delta_t = 0;

/*
unsigned long long i = 3;
unsigned long long nr = 2;
unsigned long long old_t = 0;
unsigned long long delta_t = 0;
*/

void setup() {
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);
  
  Serial.begin(115200);
  
  Serial.print("Initializing SD card... ");
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present!");
    digitalWrite(LED_PIN, HIGH);
    while (1);
  }
  
  Serial.println("Card initialized.");

  randomSeed(analogRead(0));
  randNumber = random(10000000, 100000000);
  filename += String(randNumber);
  filename += String(".txt");

  File dataFile = SD.open(filename[COLOR="#000080"].c_str()[/COLOR], FILE_WRITE);     // Line of Error

  if (dataFile) {
    dataFile.println("Nr;Prime;Calc_Time(us);Runtime(us)");
    
    dataString = "";
  
    dataString += String("1;2;0;");
    dataString += String(micros());

    dataFile.println(dataString);

    dataFile.close();
  }

  else {
    Serial.print("Error opening ");
    Serial.print(filename);
    Serial.println(".");
    digitalWrite(LED_PIN, HIGH);
    while (1);
  }

  Serial.println();

}

void loop() {
  old_t = 0;
 
  old_t = micros();
  long prime = is_prime(i);
  delta_t = micros() - old_t;
 
  if (prime == 1) {
    Serial.println(nr);

    dataString = "";
  
    dataString += String(nr);
    dataString += String(";");
    dataString += String(i);
    dataString += String(";");
    dataString += String(delta_t);
    dataString += String(";");
    dataString += String(micros());

    File dataFile = SD.open(filename[COLOR="#000080"].c_str()[/COLOR], FILE_WRITE);

    if (dataFile) {
      dataFile.println(dataString);
      dataFile.close();
    }

    else {
      Serial.print("Error opening ");
      Serial.print(filename);
      Serial.println(".");
      digitalWrite(LED_PIN, HIGH);
      while (1);
    }
       
    nr++;
  }

  i = i + 2;
}


bool is_prime(uint32_t n){
  if(n<=1) return false;
  else if (n<=3) return true;
  else if(n%2==0 or n%3==0) return false;
  uint32_t i= 5;
    while (i * i <=n)
    {
      if(n%i== 0 or n%(i + 2) == 0) return false;
       i+=6;
    }
  return true;
  nr++;
}

Note, I do not use the String library, but others have said that is the syntax to convert between String and char[].
 
Thank you very much. It compiles now without any Errors. As soon as I'm at home I'll try uploading it and will post an update.

Already a big thanks to everyone who answered and tried to help me :D

You are awesome :)
 
New problem... :rolleyes:

I'm using the code from MichaelMeissner and it compiles and uploads without any errors. But my SD card isn't getting recognised.

My connections:
Code:
Module:  T4:
GND   - GND
VCC   - 3V
MISO  - 12
MOSI  - 11
SCK   - 13
CS    - 10

My module: https://www.ebay.de/itm/2Stks-Micro-SD-Storage-Board-SD-TF-Card-Memory-Shield-Module-6P-SPI-For-Arduino/272493058912?ssPageName=STRK%3AMEBIDX%3AIT&_trksid=p2057872.m2749.l2649

SD-Card: 4GB Micro SD, FAT32-System

Does someone have an idea what's wrong? (Module works with Arduino Nano)
 
New problem... :rolleyes:

Does someone have an idea what's wrong? (Module works with Arduino Nano)

Looking at the ebay page, the documentation says you need to feed it 4.5v or higher for VCC. So, you need to use VIN and not 3.3v to power the SD card reader. VIN is 5v if you use USB to power your Teensy. Presumably you would not be able to use a lithium-ion battery to power it, since they only produce 3.7-4.2v.

Note, many of the Nanos run at 5v, while the Teensy LC/3.x/4.0 all run at 3.3v, which is presumably why it runs for the Nano. You can damage some Teensys (LC, 3.6, 4.0) if they get 5v on a data input line. So you need to be careful about mixing voltage. But the google translated document claimed that it was safe to use (whether it actually is, I don't know).
 
I tested it with the VCC pin connected to VIN after measuring all voltages and making (as good as possible) sure nothing will explode;)
Everything works fine and the SD card gets written.

Only promblem I have now is the slow write-speed. Without an SD I'm getting about 75,000 primes/s, now only 50 primes/s: /
I don't think I can do much about it because my SD card or maybe the SPI communication is limiting me. If someone has an idea for improvements I'd appreciate it if you posted your ideas.

My fixed and working code:

Code:
#include <SPI.h>
#include <SD.h>
#include <math.h>

#define CONTR_LED 2

const int chipSelect = 10;

long randNumber;
String filename = "";
String dataString = "";

unsigned long i = 3;
unsigned long nr = 2;

unsigned long old_t = 0;
unsigned long delta_t = 0;
unsigned int oflw1 = 0;
unsigned int oflw2 = 0;


void setup() {
  pinMode(CONTR_LED, OUTPUT);
  digitalWrite(CONTR_LED, LOW);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
  
  Serial.begin(115200);
  
  Serial.print("Initializing SD card... ");
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present!");
    digitalWrite(CONTR_LED, HIGH);
    while(1);
  }
  
  Serial.println("Card initialized.");

  randomSeed(analogRead(0));
  randNumber = random(10000000, 100000000);
  filename += String(randNumber);
  filename += String(".txt");

  File dataFile = SD.open(filename.c_str(), FILE_WRITE);

  if (dataFile) {
    dataFile.println("Nr;Prime;Overflows;Calc_Time(us);Runtime(us);Overflows");
    
    dataString = "";
  
    dataString += String("1;2;0;0;");
    dataString += String(micros());
    dataString += String(";0");

    dataFile.println(dataString);

    dataFile.close();
  }

  else {
    Serial.print("Error opening ");
    Serial.print(filename);
    Serial.println(".");
    digitalWrite(CONTR_LED, HIGH);
    while(1);
  }

  Serial.println();
}


void loop() {
  digitalWrite(LED_BUILTIN, LOW);
  
  old_t = micros();
  long prime = is_prime(i);
  delta_t = micros() - old_t;
 
  if (prime == 1) {
    digitalWrite(LED_BUILTIN, HIGH);
    
    Serial.println(nr);

    if(i > 4200000000){
    oflw1++;
    }
  
  if(micros() > 4200000000){
    oflw2++;
    }

    dataString = "";
  
    dataString += String(nr);
    dataString += String(";");
    dataString += String(i);
    dataString += String(";");
    dataString += String(oflw1);
    dataString += String(";");
    dataString += String(delta_t);
    dataString += String(";");
    dataString += String(micros());
    dataString += String(";");
    dataString += String(oflw2);

    File dataFile = SD.open(filename.c_str(), FILE_WRITE);

    if (dataFile) {
      dataFile.println(dataString);
      dataFile.close();
    }

    else {
      Serial.print("Error opening ");
      Serial.print(filename);
      Serial.println(".");
      digitalWrite(CONTR_LED, HIGH);
      while(1);
    }
       
    nr++;
  }

  i = i + 2;
}


bool is_prime(uint32_t n){
  if(n<=1){
    return false;
  }
  
  else if(n<=3){
    return true;
  }
  
  else if(n%2==0 or n%3==0){
    return false;
  }
  
  uint32_t i= 5;
    while (i * i <=n){
      if(n%i== 0 or n%(i + 2) == 0) return false;
      i+=6;
    }
    
  return true;
  nr++;
}

Again, thanks to everyone who helped me fixing my problems and explained my mistakes :)
 
Attachment:

I know that stuff like turning LEDs on and off and serial output will slow it down but I suspect the main bottleneck at transferring data to the SD card.
 
Status
Not open for further replies.
Back
Top