Problems with writing on the sd card

Hello guys, I am new here !!!

Im trying to build me a DIY Powermeter, with the INA219, a 9.96" Oled display and a SD card reader (8gb Fat32 micro SD-card). I use the Arduino NANO.

I have the problem, that I can not write the informations (Time, current and voltage) on the sd card. sometimes it works but mostly it doesn´t. extra information: on the SD card should be 3 txt files (TIME.txt, VOLT.txt, CUR.txt), in every file should be written the appropriate value.

I dont know why, i know that there are allready a few of this projects on google but i can´t fix my problem till now.
I have also already checked if my SD-card-reader is working and my is SD-card is compatible, it seems like it is working fine. I checkt it with the Arduino examplecode "Cardinfo".

I hope some of you can help me.

Im sorry if something like this was already postet here but im new on reddit and can´t find something.

Thank you guys

//Powermeter by keppioo5
//===================================Libaries====================================
#include <Wire.h>
#include <Adafruit_INA219.h>
#include <Adafruit_SSD1306.h>
#include <SPI.h>
#include "SdFat.h"
#define OLED_RESET 4

//===========================Deklaration & Initialisation========================
Adafruit_SSD1306 display(OLED_RESET);
Adafruit_INA219 ina219;
SdFat SD;
unsigned long previousMillis = 0;
unsigned long interval = 100;
const int chipSelect = 10;
float current_mA = 0;
float voltage = 0;
float energy = 0;
File TimeFile;
File VoltFile;
File CurFile;

//==============================================================================
void setup() {
  SD.begin(chipSelect); //SD begin
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //Display begin
  ina219.begin(); // Current-sensor "INA219" begin
}
//==============================================================================
void loop() {
  unsigned long currentMillis = millis(); //ms counter
  if (currentMillis - previousMillis >= interval) 
  /*waits 100ms, that means that every 100ms the values will be refreshed on the 
  display and the "new" values of time, current and voltage will be written on the sd card.*/
  
  {
    previousMillis = currentMillis;
    ina219values(); //get Values

    TimeFile = SD.open("TIME.txt", FILE_WRITE); //open SD file: TIME.txt
    if (TimeFile) {
      TimeFile.println(currentMillis); //writes the time in ms into the file
      TimeFile.close(); // close file
    }

    VoltFile = SD.open("VOLT.txt", FILE_WRITE); //open SD file: VOLT.txt
    if (VoltFile) {
      VoltFile.println(voltage); //writes the voltage value into the file
      VoltFile.close(); //close file
    }

    CurFile = SD.open("CUR.txt", FILE_WRITE); //open SD file: CUR.txt
    if (CurFile) {
      CurFile.println(current_mA); //writes the current value into the file
      CurFile.close(); //close file
    }
    displaydata(); // opens the desplaydata methode
  }
}
//==============================================================================
void displaydata() {
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(1);
  display.setCursor(0, 0);
  display.println(voltage);
  display.setCursor(35, 0);
  display.println("V");
  display.setCursor(50, 0);
  display.println(current_mA);
  display.setCursor(95, 0);
  display.println("mA");
  display.setCursor(0, 10);
  display.println(voltage * current_mA);
  display.setCursor(65, 10);
  display.println("mW");
  display.setCursor(0, 20);
  display.println(energy);
  display.setCursor(65, 20);
  display.println("mWh");
  display.display();
}
//===============================================================================
void ina219values() { // Current-sensor methode
  current_mA = ina219.getCurrent_mA(); //Current measurement
  voltage = (current_mA/1000)* 6.1; // calculate the voltage with current * //resistor, here the total resistance is 6.1ohm             
  energy = energy + (voltage)* current_mA /3600; // calculating the energy
  }



Well, when it doesn't work, what happens, exactly?

Why are you logging related information to three separate files? Why not just the usual, all on each line?

It is a very bad idea to open a file, write one line of data, and close the file again. Doing so vastly increases the SD card error rate and failure rate, the current consumption, and is very, very slow. Especially when you are trying to use several different files.

Open one file in setup(), write all of the data, then close it when you are done collecting data.

For long term data collection, it is a good idea to issue SD .flush() commands, every hour or so, to prevent data loss on power outage.

Are you certain this completed successfully?

At first, thanks for your comment.

I have now changed it to one File.

 Power = SD.open("Power.txt", FILE_WRITE); //open SD file: TIME.txt
    if (Power) {
      Power.print(currentMillis);//writes the time in ms into the file
      Power.print(" :");
      Power.print(voltage);
      Power.print(" :");
      Power.println(current_mA);
      Power.close(); // close file
    }

Now, only the first line is written into the file

I found a other, working way which makes use of a buffer. this works really good, but here is the problem, that my oled display will not work


#include <Wire.h>
#include <Adafruit_INA219.h>
#include <Adafruit_SSD1306.h>
#include <SPI.h>
#define OLED_RESET 4
#include <SD.h>

Adafruit_SSD1306 display(OLED_RESET);
Adafruit_INA219 ina219;


const int chipSelect = 10;
float current_mA = 0;
float voltage = 0;
float energy = 0;
File TimeFile;
File VoltFile;
File CurFile;

// string to buffer output
String buffer, buffer1,buffer2;



unsigned long lastMillis = 0;

void setup() {
  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //Display begin
  ina219.begin(); // Current-sensor "INA219" begin
  while (!Serial);

  // reserve 1kB for String used as a buffer
  buffer.reserve(1024);

  // set LED pin to output, used to blink when writing
  pinMode(LED_BUILTIN, OUTPUT);

  // init the SD card
  if (!SD.begin()) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1);
  }

  // If you want to start from an empty file,
  // uncomment the next line:
   SD.remove("VOLT.txt");
   SD.remove("TIME.txt");
   SD.remove("CUR.txt");

  // try to open the file for writing
  VoltFile = SD.open("VOLT.txt", FILE_WRITE);
  if (!VoltFile) {
    Serial.print("error opening ");
    Serial.println("VOLT.txt");
    while (1);
    
     // try to open the file for writing
  TimeFile = SD.open("TIME.txt", FILE_WRITE);
  if (!TimeFile) {
    Serial.print("error opening ");
    Serial.println("TIME.txt");
    while (1);
    
     // try to open the file for writing
  CurFile = SD.open("CUR.txt", FILE_WRITE);
  if (!CurFile) {
    Serial.print("error opening ");
    Serial.println("CUR.txt");
    while (1);
  }

  
  }}}

void loop() {
  // check if it's been over 10 ms since the last line added
  unsigned long now = millis();
  if ((now - lastMillis) >= 100) {
     ina219values(); //get Values

    TimeFile = SD.open("TIME.txt", FILE_WRITE); //open SD file: TIME.txt
    if (TimeFile) {
      TimeFile.println(now); //writes the time in ms into the file
      TimeFile.close(); // close file
    }

    VoltFile = SD.open("VOLT.txt", FILE_WRITE); //open SD file: VOLT.txt
    if (VoltFile) {
      VoltFile.println(voltage); //writes the voltage value into the file
      VoltFile.close(); //close file
    }

    CurFile = SD.open("CUR.txt", FILE_WRITE); //open SD file: CUR.txt
    if (CurFile) {
      CurFile.println(current_mA); //writes the current value into the file
      CurFile.close(); //close file
    }
   
    buffer += voltage;
    buffer1 += now;
    buffer2 += current_mA;

    lastMillis = now;
  }

  // check if the SD card is available to write data without blocking
  // and if the buffered data is enough for the full chunk size
  unsigned int chunkSize = VoltFile.availableForWrite();
  if (chunkSize && buffer.length() >= chunkSize) {
    // write to file and blink LED
    digitalWrite(LED_BUILTIN, HIGH);
    VoltFile.write(buffer.c_str(), chunkSize);
    digitalWrite(LED_BUILTIN, LOW);

    // remove written data from buffer
    buffer.remove(0, chunkSize);}

     // check if the SD card is available to write data without blocking
  // and if the buffered data is enough for the full chunk size
  unsigned int chunkSize1 = TimeFile.availableForWrite();
  if (chunkSize1 && buffer1.length() >= chunkSize1) {
    // write to file and blink LED
    digitalWrite(LED_BUILTIN, HIGH);
    TimeFile.write(buffer1.c_str(), chunkSize1);
    digitalWrite(LED_BUILTIN, LOW);

    // remove written data from buffer
    buffer1.remove(0, chunkSize1);}

     // check if the SD card is available to write data without blocking
  // and if the buffered data is enough for the full chunk size
  unsigned int chunkSize2 = CurFile.availableForWrite();
  if (chunkSize2 && buffer2.length() >= chunkSize2) {
    // write to file and blink LED
    digitalWrite(LED_BUILTIN, HIGH);
    CurFile.write(buffer2.c_str(), chunkSize2);
    digitalWrite(LED_BUILTIN, LOW);

    // remove written data from buffer
    buffer2.remove(0, chunkSize);}

    
}

//==============================================================================================
void ina219values() { // Current-sensor methode
  current_mA = ina219.getCurrent_mA(); //Current measurement
  voltage = (current_mA/1000)* 6.1; // calculate the voltage with current * resistor, here the total resistance is 6.1ohm
  energy = energy + (voltage)* current_mA /3600; // calculating the energy
  }

I have to put the two following parts which are needed because of the display into the code, but it don´t works

//This part into the void loop()
displaydata(); // opens the desplaydata methode
//and this part below the void loop() as methode
void displaydata() {
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(1);
  display.setCursor(0, 0);
  display.println(voltage);
  display.setCursor(35, 0);
  display.println("V");
  display.setCursor(50, 0);
  display.println(current_mA);
  display.setCursor(95, 0);
  display.println("mA");
  display.setCursor(0, 10);
  display.println(voltage * current_mA);
  display.setCursor(65, 10);
  display.println("mW");
  display.setCursor(0, 20);
  display.println(energy);
  display.setCursor(65, 20);
  display.println("mWh");
  display.display();
}

Thanks for helping me

Are you sure there are no pin conflicts between the SD and the display? Can we please see a schematic?

I´m new on this platform, i can not upload any files
INA219:
VCC >5V
GND
SCL > A5
SDA >A4
Vin-
Vin+

OLED:
GND
VCC >5V
SCL > A5
SDA > A4

SD card Reader:
GND
VCC > +5V
Miso >12
Mosi > 11
SCK > 13
CS > 10

Might be the I2C bus between INA219 and Oled

Run the I2C scan sketch and post the output.

Is your OLED really 5V powered? Most are 3.3V devices.

And what about this?

#define OLED_RESET 4

Have you connected pin 4 to the OLED?

yes this oled is 5V powered

I2C Scanner
Scanning...
I2C device found at address 0x3C  !
I2C device found at address 0x40  !
done

No, my oled has 4 Connections
GND
VCC >5V
SCL > A5
SDA > A4

What about the I/O pins? Are they also 5V logic level? I'm skeptical, because I have personally been burned on that.

i have this oled display already often used befor, i know that it works, or what do you mean exactly

The damage that can be caused by overvoltage is not always catastrophic. Often the device keeps working, but not 100% reliably, or fails mysteriously at a later date.

Understand that you need an electron microscope to see the damage...

What I mean exactly, is that you can't be 100% sure without having reliable documentation on the part. Having used it for some time, means almost nothing except for a fun, non-critical hobby project that can fail.

What OLED do you have?

Do you think its damaged? the datasheet says 5V

Post it. Also, have you reverted to OLED library examples for testing?

I can not post files because i am a new user, i can only say that i have the 0.96" oled display

You mean the Fleabay and Alley Express ones? Looking forward to seeing that data sheet...

yeah like that
If i seach for them in the internet, it says 5V

I think the issue is in the software