Problems with SD-Card on Teensy 4.1 / Teensy gets slow

Mike0675

Member
Hi :)

Im try to LOG serveral Informations on SD-Card. This LOGs are in memory in an Array of Strings . When i got an new line the old File gets deleted and an new one is written.
Im also got a Funktion whitch reads the SD-Card completly and put it in an HTML-String passing this to the webserver.

Heres the first Problem : If this is done Teensy gets slow and I2C won´t work any more. Webserver is working but nothing else.

On the other Side sometimes i´m got read/write errors in the File.

My Programm now gets very big so im show here only the SD-Card related .cpp.

Im Work with Sloeber/Eclipse on WIN10. Teensy got 8MB of PSRAM.

Code:
/*
 * my_LOGtoSD.cpp
 *
 *  Created on: 24.12.2021
 *      Author: Mike
 */

#include <Arduino.h>
#include <SD.h>
#include <FS.h>

#include "my_ethernet.h"
#include "my_LOGtoSD.h"
#include "main.h"

EXTMEM myLOG LOG;

void write_File(const char *path, const char *message) {

	//debug("Einstieg in SUB write_File()");

	SD.begin(BUILTIN_SDCARD);

	if (SD.exists(path)) {
		SD.remove(path);
	}

	File file = SD.open(path, FILE_WRITE);
	file.println(message);
	file.close();
}

void write_File(const char *path, double message) {

	SD.begin(BUILTIN_SDCARD);
	if (SD.exists(path)) {
		SD.remove(path);
	}

	File file = SD.open(path, FILE_WRITE);
	file.println(message);
	file.close();
}

void write_File(const char *path, int message) {

	SD.begin(BUILTIN_SDCARD);

	if (SD.exists(path)) {
		SD.remove(path);
	}

	File file = SD.open(path, FILE_WRITE);
	file.println(message, DEC);
	file.close();
}

//--------------------------------------------------------------------------------

String read_File(const char *path) {

	SD.begin(BUILTIN_SDCARD);

	String message;
	File file = SD.open(path);
	if (!file) {
		debug("Failed to open file for reading");
		file.close();
		return String("Failed to open file for reading");
	}
	while (file.available()) {
		message += char(file.read());
	}
	file.close();
	debug(message);
	return message;
}

//--------------------------------------------------------------------------------

void LOGtoSD_begin() {

	//zum Anfang die LOG-Array mit Daten füllen:
	for (byte j = 0; j <= 3; j++) {
		for (byte i = 0; i <= 49; i++) {

			LOG.LOG_STRING[j][i] = TimeStamp_Formated() + " --------------------";
			LOG.LOG_STRING_COLOR[j][i] = 1;

		}
	}

	/*
	 LOGwrite(0, 1, "");
	 LOGwrite(1, 1, "");
	 LOGwrite(2, 1, "");
	 LOGwrite(3, 1, "");
	 */
	debug("LOG-Dateien von SD lesen.");
	LOGread();  // LOG-Dateien von SD-Karte lesen

}

void write_WindowContact_WatchdogState(byte Number, const double Timestamp, const int BatteryCharge) {

	char NumberAsChar[2];
	NumberAsChar[0] = Number + '0';
	NumberAsChar[1] = '\0';

	if (SD.begin(BUILTIN_SDCARD)) {
		char Path[40] = "/WindowContact_Last_Report_";

		strcat(Path, NumberAsChar);
		strcat(Path, ".txt");

		write_File(Path, Timestamp);

		strcpy(Path, "/WindowContact_BatteryCharge_");
		strcat(Path, NumberAsChar);
		strcat(Path, ".txt");

		write_File(Path, BatteryCharge);

	}

}

//--------------------------------------------------------------------------------

void write_STATE_WINDOWCONTACT(byte Number, byte State) {

	debug("Einstieg in SUB write_STATE_WINDOWCONTACT()");

	char NumberAsChar[1];
	NumberAsChar[0] = Number + '0';

	char StatusAsChar[2];
	StatusAsChar[0] = State + '0';
	StatusAsChar[1] = '\0';

	char Path[30] = "/STATE_WINDOWCONTACT_";
	strcat(Path, NumberAsChar);
	strcat(Path, ".txt");

	write_File(Path, StatusAsChar);

}

//--------------------------------------------------------------------------------

double read_WindowContact_Last_Report(byte Number) {

	char NumberAsChar[2];
	NumberAsChar[0] = Number + '0';
	NumberAsChar[1] = '\0';

	double TimeStamp;

	char Path[40] = "/WindowContact_Last_Report_";
	strcat(Path, NumberAsChar);
	strcat(Path, ".txt");

	String tmp;
	tmp = read_File(Path);

	TimeStamp = atof(tmp.c_str());

	return TimeStamp;

}

int read_WindowContact_BatteryCharge(byte Number) {

	char NumberAsChar[2];
	NumberAsChar[0] = Number + '0';
	NumberAsChar[1] = '\0';

	int BatteryCharge = 0;

	char Path[40] = "/WindowContact_BatteryCharge_";

	strcat(Path, NumberAsChar);
	strcat(Path, ".txt");

	String tmp;
	tmp = read_File(Path);
	BatteryCharge = tmp.toInt();

	//telnet.println("------------------------");

	return BatteryCharge;

}

//--------------------------------------------------------------------------------

int read_STATE_WINDOWCONTACT(byte Number) {

	char NumberAsChar[2];
	NumberAsChar[0] = Number + '0';
	NumberAsChar[1] = '\0';

	int MK_State = 0;

	char Path[30] = "/STATE_WINDOWCONTACT_";
	String tmp;
	strcat(Path, NumberAsChar);
	strcat(Path, ".txt");
	//telnet.println(Path);

	tmp = read_File(Path);
	//telnet.println(tmp);

	//telnet.println("------------------------");
	MK_State = tmp.toInt();

	return MK_State;

}

//--------------------------------------------------------------------------------

void write_System_RestartReason(const char *message) {

	write_File("/System_RestartReason.txt", message);

}

//--------------------------------------------------------------------------------

String read_System_RestartReason() {

	String message = read_File("/System_RestartReason.txt");

	return message;
}

//--------------------------------------------------------------------------------

void LOGread() {

	debug("LOG-Dateien einlesen:");

	for (byte i = 0; i <= 3; i++) {  // Alle 4 LOGs auslesen

		char LOGtypeAsChar[2];
		LOGtypeAsChar[0] = i + '0';
		LOGtypeAsChar[1] = '\0';

		char Path[30] = "/LOG_";
		strcat(Path, LOGtypeAsChar);
		strcat(Path, ".txt");

		SD.begin(BUILTIN_SDCARD);
		File file = SD.open(Path);

		String buffer;

		// Erste Zeile > Aktuelle Zeile auslesen
		buffer = file.readStringUntil('\n', 150);
		LOG.LOG_CurrentLine[i] = buffer.substring(1, 3).toInt() - 10;

		// Die Meldungen auslesen:

		int x = 0;

		for (byte j = 0; j <= LOG.LOG_MaxLines; j++) {
			buffer = file.readStringUntil('\n', 150);

			debug(buffer);

			x = buffer.substring(0, 2).toInt() - 10;

			LOG.LOG_STRING[i][j] = buffer.substring(6);
			LOG.LOG_STRING_COLOR[i][j] = buffer.substring(3, 4).toInt();
			debug(String(j));
			debug(LOG.LOG_STRING[i][j]);
		}

		file.close();

	}

}

//--------------------------------------------------------------------------------

// LOGtype: 0 = LOG, 1 = Technisches LOG, 2 = Meldekontakte LOG, 3 = 12h Meldungen Meldekontakte
// Color  : 1 = Weiss, 2 = Gelb, 3 = Grün, 4 = Rot
void LOGwrite(int LOGtype, int Color, String message) {

	// Zeile in ARRAY einfügen:
	LOG.LOG_STRING[LOGtype][LOG.LOG_CurrentLine[LOGtype]] = TimeStamp_Formated() + " " + message;
	LOG.LOG_STRING_COLOR[LOGtype][LOG.LOG_CurrentLine[LOGtype]] = Color;

	// LOG auf SD-Karte schreiben:

	SD.begin(BUILTIN_SDCARD);

	char LOGtypeAsChar[2];
	LOGtypeAsChar[0] = LOGtype + '0';
	LOGtypeAsChar[1] = '\0';

	char Path[30] = "/LOG_";
	strcat(Path, LOGtypeAsChar);
	strcat(Path, ".txt");

	if (SD.exists(Path)) {
		SD.remove(Path);
	}

	File file = SD.open(Path, FILE_WRITE);

	//Serial.print("open File: ");
	//Serial.println(Path);

	file.println(">" + String(LOG.LOG_CurrentLine[LOGtype] + 11) + "< // Zuerst die aktuelle Zeile +10, danach folgen die einzelnen Einträge:");

	for (byte i = 0; i <= LOG.LOG_MaxLines; i++) {

		file.println(String(i + 10) + "_" + String(LOG.LOG_STRING_COLOR[LOGtype][i]) + "_" + LOG.LOG_STRING[LOGtype][i]);

	}

	file.close();

	// Aktuelle Zeile hochzählen:
	LOG.LOG_CurrentLine[LOGtype] = LOG.LOG_CurrentLine[LOGtype] + 1;
	// Wenn die maximale Anzahl der Zeilen erreicht ist wieder auf 0:
	if (LOG.LOG_CurrentLine[LOGtype] == LOG.LOG_MaxLines + 1) {
		LOG.LOG_CurrentLine[LOGtype] = 0;
	}

}

/*
 * my_LOGtoSD.h
 *
 *  Created on: 24.12.2021
 *      Author: Mike
 */

#ifndef MY_LOGTOSD_H_
#define MY_LOGTOSD_H_

void write_File(const char *path, const char *message);
void write_File(const char *path, double message);
void write_File(const char *path, int message);

void LOGtoSD_begin();
String read_File(const char *path);

// WiFi-Meldekontakte:
void write_WindowContact_WatchdogState(byte Number, const double Timestamp, const int Battery);
void write_STATE_WINDOWCONTACT(byte Number, byte Status);

int read_STATE_WINDOWCONTACT(byte Number);
double read_WindowContact_Last_Report(byte Number);
int read_WindowContact_BatteryCharge(byte Number);

// Warum wurde neu gestartet?
void write_System_RestartReason(const char *message);
String read_System_RestartReason();

void LOGwrite(int LOGtype, int Color, String message);
void LOGread();

struct myLOG {
	String LOG_STRING[4][50];
	int LOG_STRING_COLOR[4][50];
	int LOG_MaxLines = 49;
	int LOG_CurrentLine[4];
};

#endif /* MY_LOGTOSD_H_ */


Here the Function to get all Data from SD-Card to the webserver:

Code:
void build_SD_HTML() {

	debug("Einstieg in SUB build_SD_HTML()");
	debug(" ");

	SD.begin(BUILTIN_SDCARD);

	String buffer;

	HTML_BUFFER_SD = "<!DOCTYPE html><html>"
			"<head><meta http-equiv='content-type' content='text/html;charset=utf-8'/>"
			"<title>Alarmanlage	SD-Karte</title>"
			"</head>"
			"<body>"
			"<h1>SD-Karte:</h1>"
			"<p> </p>";

	/*
	 HTML_BUFFER[LOGtype] += "Card type: ";
	 switch (card.type()) {
	 case SD_CARD_TYPE_SD1:
	 HTML_BUFFER[LOGtype] += "SD1";
	 break;
	 case SD_CARD_TYPE_SD2:
	 HTML_BUFFER[LOGtype] += "SD2";
	 break;
	 case SD_CARD_TYPE_SDHC:
	 HTML_BUFFER[LOGtype] += "SDHC";
	 break;
	 default:
	 HTML_BUFFER[LOGtype] += "Unknown";
	 }

	 HTML_BUFFER[LOGtype] += "<br />";

	 uint32_t volumesize;
	 HTML_BUFFER[LOGtype] += "Volume type is FAT";
	 HTML_BUFFER[LOGtype] += String(volume.fatType());

	 volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
	 volumesize *= volume.clusterCount();       // we'll have a lot of clusters
	 if (volumesize < 8388608ul) {
	 HTML_BUFFER[LOGtype] += String("<br />Volume size (bytes): ");
	 HTML_BUFFER[LOGtype] += String(volumesize * 512);        // SD card blocks are always 512 bytes
	 }
	 HTML_BUFFER[LOGtype] += "<br />Volume size (Kbytes): ";
	 volumesize /= 2;
	 HTML_BUFFER[LOGtype] += String(volumesize);
	 HTML_BUFFER[LOGtype] += "<br />Volume size (Mbytes): ";
	 volumesize /= 1024;
	 HTML_BUFFER[LOGtype] += String(volumesize);

	 HTML_BUFFER[LOGtype] += "<p> </p>";
	 */

	HTML_BUFFER_SD += "Listing directory: /";

	File root = SD.open("/");
	if (!root) {
		HTML_BUFFER_SD += "Failed to open directory";
		return;
	}
	if (!root.isDirectory()) {
		HTML_BUFFER_SD += "Not a directory";
		return;
	}

	HTML_BUFFER_SD += "<p> </p>";

	File file = root.openNextFile();
	while (file) {
		if (file.isDirectory()) {
			HTML_BUFFER_SD += "  DIR : ";
			HTML_BUFFER_SD += String(file.name());
			HTML_BUFFER_SD += "<br />";
		} else {
			HTML_BUFFER_SD += "  FILE: ";
			HTML_BUFFER_SD += String(file.name());
			HTML_BUFFER_SD += "<br />";
			HTML_BUFFER_SD += "<BLOCKQUOTE>";

			while (file.available()) {
				yield();
				buffer = file.readStringUntil('\n', 200);

				debug(buffer.length());
				debug(buffer);
				HTML_BUFFER_SD += "<br />";
				HTML_BUFFER_SD += buffer;
			}

			HTML_BUFFER_SD += "</BLOCKQUOTE>";
			HTML_BUFFER_SD += "<p> </p>";
		}
		file.close();
		file = root.openNextFile();
	}

//letzte Zeile HTML
	HTML_BUFFER_SD += "</body></html>";


	root.close();


}
 
Back
Top