Sample program to read and write data using the builtin sd card reader of Teensy 4.1

Yes, there are 6 example programs for SD card access. In Arduino, click File > Examples > SD.

You will need to edit the chip select pin to BUILTIN_SDCARD, which is a special constant that tells the SD library to access the SD socket using fast SDIO protocol rather than a SD card connected to the SPI pins. Look for the comments in those examples which explain this.
 
Code:
#ifndef LOGGING_H
#define LOGGING_H

/*
Esta classe vai ter uma ou mais funções que se vão responsabilizar em
escrever os dados num ficheiro pedidos por VD (Lemos):
  BMS:
  int soc -> state of charge;
  int current -> current;
  int packVoltage -> pack voltage;
  
  BAMOCAR:
  int Nact -> Actual speed value filtered;
  int Vout -> Output-voltage usage;
  int Iq_cmd -> command current;
  int Iq_actual -> Q-current actual;
  int Mout -> Digital Torque Intern;
  int I_lim_inuse -> actual current limit;
  int I_actual_filtered -> Filtered actual current;
  int Tpeak -> Timing for peak current;
  int Imax_peak -> Limit for peak current;
  int I_con_eff -> Limit for continius current;
  int motorTemp -> motor temperature;
  int powerStageTemp -> power stage temperature;
  int ACCurrent -> current actual value;


Tenho de perguntar ao Lemos se é a corrente do BAMO ou a do BMS que eles querem
*/

#include <SdFat.h>
#include <FlexCAN_T4.h>
#include <CSVFile.h>

#define PIN_SPI_CLK 45
#define PIN_SPI_MOSI 43
#define PIN_SPI_MISO 42
#define PIN_SD_CS 44
// If you have connected other SPI device then
// put here number of pin for disable its.
// Provide -1 if you don't have other devices.
#define PIN_OTHER_DEVICE_CS -1
// Change this value if you have problems with SD card
// Available values: SPI_QUARTER_SPEED //SPI_HALF_SPEED
// It is enum from SdFat
#define SD_CARD_SPEED SPI_FULL_SPEED

#define REGID_MOUT 0xA0
#define REGID_IGBT 0x4A
#define REGID_NACT 0xA8
#define REGID_VOUT 0x8A
#define REGID_T_PEAK 0xF0
#define REGID_CMD_IQ 0x26
#define REGID_I_CON_EFF 0xC5
#define REGID_ACTUAL_IQ 0x27
#define REGID_I_MAX_PEAK 0xC4
#define REGID_AC_CURRENT 0x20
#define REGID_MOTOR_TEMP 0x49
#define REGID_I_LIM_INUSE 0x48
#define REGID_ACTUAL_SPEED 0x30
#define REGID_I_ACT_FILTERED 0x5F

#define BAMO_RESPONSE_ID 0x181
#define BMS_ID 0x675
#define BAMO_COMMAND_ID 0x201

class Logging {

 public:
  
  void set_CAN_messages(); //sets all the messages in the private field
  void write_to_file();
  void setup_log();

  CAN_message_t get_Nact_filtered();
  CAN_message_t get_Vout_msg();
  CAN_message_t get_Iq_cmd_msg();
  CAN_message_t get_Iq_actual_msg();
  CAN_message_t get_Mout_msg();
  CAN_message_t get_I_lim_inuse_msg();
  CAN_message_t get_I_actual_filtered_msg();
  CAN_message_t get_Tpeak_msg();
  CAN_message_t get_Imax_peak_msg();
  CAN_message_t get_I_con_eff_msg();
  CAN_message_t get_powerStageTempRequest();
  CAN_message_t get_motorTempRequest();

  int get_soc();
  int get_current();
  int get_packVoltage();
  int get_Nact();
  int get_Vout();
  int get_Iq_cmd();
  int get_Iq_actual();
  int get_Mout();
  int get_I_lim_inuse();
  int get_I_actual_filtered();
  int get_Tpeak();
  int get_Imax_peak();
  int get_I_con_eff();
  int get_motorTemp();
  int get_powerStageTemp();
  int get_ACCurrent();

  void set_soc(int a);
  void set_current(int a);
  void set_packVoltage(int a);
  void set_Nact(int a);
  void set_Vout(int a);
  void set_Iq_cmd(int a);
  void set_Iq_actual(int a);
  void set_Mout(int a);
  void set_I_lim_inuse(int a);
  void set_I_actual_filtered(int a);
  void set_Tpeak(int a);
  void set_Imax_peak(int a);
  void set_I_con_eff(int a);
  void set_motorTemp(int a);
  void set_powerStageTemp(int a);
  void set_ACCurrent(int a);

  void increment_t();
 
 private:
  
  CAN_message_t Nact_filtered;
  CAN_message_t Vout_msg;
  CAN_message_t Iq_cmd_msg;
  CAN_message_t Iq_actual_msg;
  CAN_message_t Mout_msg;
  CAN_message_t I_lim_inuse_msg;
  CAN_message_t I_actual_filtered_msg;
  CAN_message_t Tpeak_msg;
  CAN_message_t Imax_peak_msg;
  CAN_message_t I_con_eff_msg;
  CAN_message_t powerStageTempRequest;
  CAN_message_t motorTempRequest;


  int soc;
  int current;
  int packVoltage;
  int Nact;
  int Vout;
  int Iq_cmd;
  int Iq_actual;
  int Mout;
  int I_lim_inuse;
  int I_actual_filtered;
  int Tpeak;
  int Imax_peak;
  int I_con_eff;
  int motorTemp;
  int powerStageTemp;
  int ACCurrent;
  
  SdFat sd;
  elapsedMillis writeTIMER;


  int t = 0;
};

#endif

Code:
#include "logging.h"

extern FlexCAN_T4<CAN2, RX_SIZE_256, TX_SIZE_16> can2;
CSVFile csv;

CAN_message_t Logging::get_Nact_filtered(){
    return Nact_filtered;
}
CAN_message_t Logging::get_Vout_msg(){
    return Vout_msg;
}
CAN_message_t Logging::get_Iq_cmd_msg(){
    return Iq_cmd_msg;
}
CAN_message_t Logging::get_Iq_actual_msg(){
    return Iq_actual_msg;
}
CAN_message_t Logging::get_Mout_msg(){
    return Mout_msg;
}
CAN_message_t Logging::get_I_lim_inuse_msg(){
    return I_lim_inuse_msg;
}
CAN_message_t Logging::get_I_actual_filtered_msg(){
    return I_actual_filtered_msg;
}
CAN_message_t Logging::get_Tpeak_msg(){
    return Tpeak_msg;
}
CAN_message_t Logging::get_Imax_peak_msg(){
    return Imax_peak_msg;
}
CAN_message_t Logging::get_I_con_eff_msg(){
    return I_con_eff_msg;
}
CAN_message_t Logging::get_powerStageTempRequest(){
    return powerStageTempRequest;
}
CAN_message_t Logging::get_motorTempRequest(){
    return motorTempRequest;
}

int Logging::get_soc(){
    return soc;
}
int Logging::get_current(){
    return current;
}
int Logging::get_packVoltage(){
    return packVoltage;
}
int Logging::get_Nact(){
    return Nact;
}
int Logging::get_Vout(){
    return Vout;
}
int Logging::get_Iq_cmd(){
    return Iq_cmd;
}
int Logging::get_Iq_actual(){
    return Iq_actual;
}
int Logging::get_Mout(){
    return Mout;
}
int Logging::get_I_lim_inuse(){
    return I_lim_inuse;
}
int Logging::get_I_actual_filtered(){
    return I_actual_filtered;
}
int Logging::get_Tpeak(){
    return Tpeak;
}
int Logging::get_Imax_peak(){
    return Imax_peak;
}
int Logging::get_I_con_eff(){
    return I_con_eff;
}
int Logging::get_motorTemp(){
    return motorTemp;
}
int Logging::get_powerStageTemp(){
    return powerStageTemp;
}
int Logging::get_ACCurrent(){
    return ACCurrent;
}

void Logging::set_soc(int a){
    soc = a;
}
void Logging::set_current(int a){
    current = a;
}
void Logging::set_packVoltage(int a){
    packVoltage = a;
}
void Logging::set_Nact(int a){
    Nact = a;
}
void Logging::set_Vout(int a){
    Vout = a;
}
void Logging::set_Iq_cmd(int a){
    Iq_cmd = a;
}
void Logging::set_Iq_actual(int a){
    Iq_actual = a;
}
void Logging::set_Mout(int a){
    Mout = a;
}
void Logging::set_I_lim_inuse(int a){
    I_lim_inuse = a;
}
void Logging::set_I_actual_filtered(int a){
    I_actual_filtered = a;
}
void Logging::set_Tpeak(int a){
    Tpeak = a;
}
void Logging::set_Imax_peak(int a){
    Imax_peak = a;
}
void Logging::set_I_con_eff(int a){
    I_con_eff = a;
}
void Logging::set_motorTemp(int a){
    motorTemp = a;
}
void Logging::set_powerStageTemp(int a){
    powerStageTemp = a;
}
void Logging::set_ACCurrent(int a){
    ACCurrent = a;
}

void Logging::increment_t() {
    t++;
}


void Logging::setup_log() {
    // Setup pinout
    pinMode(PIN_SPI_MOSI, OUTPUT);
    pinMode(PIN_SPI_MISO, INPUT);
    pinMode(PIN_SPI_SCK, OUTPUT);
    // Disable SPI devices
    pinMode(PIN_SD_CS, OUTPUT);
    digitalWrite(PIN_SD_CS, HIGH);


    // Setup serial
    Serial.begin(9600);

    // Setup SD card
    if (!sd.begin(PIN_SD_CS, SD_CARD_SPEED)) {
        Serial.println("SD card begin error");
        return;
    }


    /*
    set_CAN_messages();

    can2.write(get_Nact_filtered()); 
    can2.write(get_Vout_msg());
    can2.write(get_Iq_cmd_msg());
    can2.write(get_Iq_actual_msg());
    can2.write(get_Mout_msg());
    can2.write(get_I_lim_inuse_msg());
    can2.write(get_I_actual_filtered_msg());
    can2.write(get_Tpeak_msg());
    can2.write(get_Imax_peak_msg());
    can2.write(get_I_con_eff_msg());
    can2.write(get_motorTempRequest());
    can2.write(get_powerStageTempRequest());
    */
}

void Logging::set_CAN_messages() {
    Nact_filtered.id = BAMO_COMMAND_ID;
    Nact_filtered.len = 3;
    Nact_filtered.buf[0] = 0x3D;
    Nact_filtered.buf[1] = 0xA8;
    Nact_filtered.buf[2] = 0x64;

    Vout_msg.id = BAMO_COMMAND_ID;
    Vout_msg.len = 3;
    Vout_msg.buf[0] = 0x3D;
    Vout_msg.buf[1] = 0x8A;
    Vout_msg.buf[2] = 0x64;

    Iq_cmd_msg.id = BAMO_COMMAND_ID;
    Iq_cmd_msg.len = 3;
    Iq_cmd_msg.buf[0] = 0x3D;
    Iq_cmd_msg.buf[1] = 0x26;
    Iq_cmd_msg.buf[2] = 0x64;

    Iq_actual_msg.id = BAMO_COMMAND_ID;
    Iq_actual_msg.len = 3;
    Iq_actual_msg.buf[0] = 0x3D;
    Iq_actual_msg.buf[1] = 0x27;
    Iq_actual_msg.buf[2] = 0x64;

    Mout_msg.id = BAMO_COMMAND_ID;
    Mout_msg.len = 3;
    Mout_msg.buf[0] = 0x3D;
    Mout_msg.buf[1] = 0xA0;
    Mout_msg.buf[2] = 0x64;

    I_lim_inuse_msg.id = BAMO_COMMAND_ID;
    I_lim_inuse_msg.len = 3;
    I_lim_inuse_msg.buf[0] = 0x3D;
    I_lim_inuse_msg.buf[1] = 0x48;
    I_lim_inuse_msg.buf[2] = 0x64;

    I_actual_filtered_msg.id = BAMO_COMMAND_ID;
    I_actual_filtered_msg.len = 3;
    I_actual_filtered_msg.buf[0] = 0x3D;
    I_actual_filtered_msg.buf[1] = 0x5F;
    I_actual_filtered_msg.buf[2] = 0x64;

    Tpeak_msg.id = BAMO_COMMAND_ID;
    Tpeak_msg.len = 3;
    Tpeak_msg.buf[0] = 0x3D;
    Tpeak_msg.buf[1] = 0xF0;
    Tpeak_msg.buf[2] = 0x64;

    Imax_peak_msg.id = BAMO_COMMAND_ID;
    Imax_peak_msg.len = 3;
    Imax_peak_msg.buf[0] = 0x3D;
    Imax_peak_msg.buf[1] = 0xC4;
    Imax_peak_msg.buf[2] = 0x64;

    I_con_eff_msg.id = BAMO_COMMAND_ID;
    I_con_eff_msg.len = 3;
    I_con_eff_msg.buf[0] = 0x3D;
    I_con_eff_msg.buf[1] = 0xC5;
    I_con_eff_msg.buf[2] = 0x64;

    powerStageTempRequest.id = BAMO_COMMAND_ID;
    powerStageTempRequest.len = 3;
    powerStageTempRequest.buf[0] = 0x3D;
    powerStageTempRequest.buf[1] = 0x4A;
    powerStageTempRequest.buf[0] = 0x64;
    
    motorTempRequest.id = BAMO_COMMAND_ID;
    motorTempRequest.len = 3;
    motorTempRequest.buf[0] = 0x3D;
    motorTempRequest.buf[1] = 0x49;
    motorTempRequest.buf[2] = 0x64;
}

void Logging::write_to_file() {
    
    if(writeTIMER > 100){

        if (!csv.open("data.csv", O_RDWR | O_CREAT)) {
            Serial.println("Failed open file");
        }

        Serial.print("File opened");

        csv.write("Hellow World!");

        Serial.print("Printed into the sd hello world");
        
        csv.close();

        /*
        // N act (filt) - 0xA8
        csv.addField(Nact);
        Serial.printf("N act filtered - %d \n",Nact);

        // Vout - 0x8A
        csv.addField(Vout);
        Serial.printf("Vout - %d \n",Vout);

        // Iq cmd - 0x26
        csv.addField(Iq_cmd);
        Serial.printf("Iq command - %d \n",Iq_cmd);

        // Iq actual - 0x27
        csv.addField(Iq_actual);
        Serial.printf("Iq actual - %d \n",Iq_actual);

        // M out - 0xA0
        csv.addField(Mout);
        Serial.printf("M out - %d \n",Mout);

        // I lim inuse - 0x48
        csv.addField(I_lim_inuse);
        Serial.printf("I lim inuse - %d \n",I_lim_inuse);

        // I act (filt) - 0x5F
        csv.addField(I_actual_filtered);
        Serial.printf("I actual filtered - %d \n",I_actual_filtered);

        // T-peak - 0xF0
        csv.addField(Tpeak);
        Serial.printf("T-peak - %d \n",Tpeak);

        // Imax pk - 0xC4
        csv.addField(Imax_peak);
        Serial.printf("I max peak - %d \n",Imax_peak);

        // I con eff - 0xC5
        csv.addField(I_con_eff);
        Serial.printf("I con eff - %d \n",I_con_eff);

        // T-motor - 0x49
        csv.addField(motorTemp);
        Serial.printf("T-motor - %d \n",motorTemp);

        // T-igbt - 0x4A
        csv.addField(powerStageTemp);
        Serial.printf("T-igbt - %d \n",powerStageTemp);

        // SoC
        csv.addField(soc);
        Serial.printf("SoC - %d \n",soc);

        // V bat
        csv.addField(packVoltage);
        Serial.printf("V bat - %d \n",packVoltage);

        // I bat
        csv.addField(current);
        Serial.printf("I bat - %d \n",current);

        csv.addLine();

        // We don't add empty line at the end of file.
        // CSV file shouldn't end by '\n' char.
        increment_t();
        // Don't forget close the file.
        */
       writeTIMER = 0;
    }
}

These are my logging.h and .cpp files, my goal is to test and try to write "hello wolrd" continuously in the sd card, just to make sure that everything is okay. The data.csv file is already created and the sd card is this one: https://mauser.pt/catalog/product_i...t1Qg_Odqknhj6PurHuFJi0YagI4ihB4xoCv0kQAvD_BwE

The only thing I am getting in the serial moniter is this: "SD card begin error". What am I doing wrong?? Besides that, the code to write in the file is correct?

There are a lot of things that are commented because the objective is to write specific data, but for now i am just trying to write "hello world"
 
...

These are my logging.h and .cpp files, my goal is to test and try to write "hello wolrd" continuously in the sd card, just to make sure that everything is okay. The data.csv file is already created and the sd card is this one: https://mauser.pt/catalog/product_i...t1Qg_Odqknhj6PurHuFJi0YagI4ihB4xoCv0kQAvD_BwE

The only thing I am getting in the serial moniter is this: "SD card begin error". What am I doing wrong?? Besides that, the code to write in the file is correct?

There are a lot of things that are commented because the objective is to write specific data, but for now i am just trying to write "hello world"

See post #2 above and see how those examples work with BUILTIN_SDCARD

The code in p#4 is trying to use the BUILTIN_SDCARD wired to SDIO as a normal SPI device using the pin numbers and that cannot work - and would be slower if it did work.
Code:
#define PIN_SPI_CLK 45
#define PIN_SPI_MOSI 43
#define PIN_SPI_MISO 42
#define PIN_SD_CS 44
 
See post #2 above and see how those examples work with BUILTIN_SDCARD

The code in p#4 is trying to use the BUILTIN_SDCARD wired to SDIO as a normal SPI device using the pin numbers and that cannot work - and would be slower if it did work.
Code:
#define PIN_SPI_CLK 45
#define PIN_SPI_MOSI 43
#define PIN_SPI_MISO 42
#define PIN_SD_CS 44


Code:
void Logging::write_to_file() {
    
    if(writeTIMER > 100){

        myFile = SD.open("example.txt", FILE_WRITE);

        myFile.println("Hello World!");
    
        myFile.close();
        
        /*
        if (!csv.open("data.csv", O_RDWR | O_CREAT)) {
            Serial.println("Failed open file");
        }

        Serial.print("File opened");

        csv.write("Hellow World!");

        Serial.print("Printed into the sd hello world");
        
        csv.close();
        */

        /*
        // N act (filt) - 0xA8
        csv.addField(Nact);
        Serial.printf("N act filtered - %d \n",Nact);

        // Vout - 0x8A
        csv.addField(Vout);
        Serial.printf("Vout - %d \n",Vout);

        // Iq cmd - 0x26
        csv.addField(Iq_cmd);
        Serial.printf("Iq command - %d \n",Iq_cmd);

        // Iq actual - 0x27
        csv.addField(Iq_actual);
        Serial.printf("Iq actual - %d \n",Iq_actual);

        // M out - 0xA0
        csv.addField(Mout);
        Serial.printf("M out - %d \n",Mout);

        // I lim inuse - 0x48
        csv.addField(I_lim_inuse);
        Serial.printf("I lim inuse - %d \n",I_lim_inuse);

        // I act (filt) - 0x5F
        csv.addField(I_actual_filtered);
        Serial.printf("I actual filtered - %d \n",I_actual_filtered);

        // T-peak - 0xF0
        csv.addField(Tpeak);
        Serial.printf("T-peak - %d \n",Tpeak);

        // Imax pk - 0xC4
        csv.addField(Imax_peak);
        Serial.printf("I max peak - %d \n",Imax_peak);

        // I con eff - 0xC5
        csv.addField(I_con_eff);
        Serial.printf("I con eff - %d \n",I_con_eff);

        // T-motor - 0x49
        csv.addField(motorTemp);
        Serial.printf("T-motor - %d \n",motorTemp);

        // T-igbt - 0x4A
        csv.addField(powerStageTemp);
        Serial.printf("T-igbt - %d \n",powerStageTemp);

        // SoC
        csv.addField(soc);
        Serial.printf("SoC - %d \n",soc);

        // V bat
        csv.addField(packVoltage);
        Serial.printf("V bat - %d \n",packVoltage);

        // I bat
        csv.addField(current);
        Serial.printf("I bat - %d \n",current);

        csv.addLine();

        // We don't add empty line at the end of file.
        // CSV file shouldn't end by '\n' char.
        increment_t();
        // Don't forget close the file.
        */
       writeTIMER = 0;
    }
}

void Logging::setup_log() {
    // Setup pinout
    pinMode(PIN_SPI_MOSI, OUTPUT);
    pinMode(PIN_SPI_MISO, INPUT);
    pinMode(PIN_SPI_SCK, OUTPUT);
    // Disable SPI devices
    pinMode(PIN_SD_CS, OUTPUT);
    digitalWrite(PIN_SD_CS, HIGH);


    // Setup serial
    Serial.begin(9600);

    // Setup SD card
    if (!SD.begin(PIN_SD_CS)) {
        Serial.println("initialization failed!");
        return;
    }

    /*
    set_CAN_messages();

    can2.write(get_Nact_filtered()); 
    can2.write(get_Vout_msg());
    can2.write(get_Iq_cmd_msg());
    can2.write(get_Iq_actual_msg());
    can2.write(get_Mout_msg());
    can2.write(get_I_lim_inuse_msg());
    can2.write(get_I_actual_filtered_msg());
    can2.write(get_Tpeak_msg());
    can2.write(get_Imax_peak_msg());
    can2.write(get_I_con_eff_msg());
    can2.write(get_motorTempRequest());
    can2.write(get_powerStageTempRequest());
    */
}

I changed these functions to this but still the initialization keeps failing...
 
Change your SD.begin to use BUILTIN_SDCARD as per Paul's post at #2
Code:
    // Setup SD card
[COLOR="#FF0000"]    if (!SD.begin(BUILTIN_SDCARD)) {[/COLOR]
        Serial.println("initialization failed!");
        return;
    }
 
All of this is wrong for a T_4.1 with SDIO based SD socket - see examples noted in p#2
Code:
void Logging::setup_log() {
    // Setup pinout
[B]    pinMode(PIN_SPI_MOSI, OUTPUT);
    pinMode(PIN_SPI_MISO, INPUT);
    pinMode(PIN_SPI_SCK, OUTPUT);
    // Disable SPI devices
    pinMode(PIN_SD_CS, OUTPUT);
    digitalWrite(PIN_SD_CS, HIGH);
[/B]

    // Setup serial
    Serial.begin(9600);

    // Setup SD card
    if (!SD.begin(PIN_SD_CS)) {
        Serial.println("initialization failed!");
        return;
    }

This is okay as long as if (!SD.begin(PIN_SD_CS)) {

has: #define PIN_SD_CS BUILTIN_SDCARD

As noted in p#7 and prior
 
Back
Top