I started an Arduino project that could execute instructions from an SD card file on the screen. I managed to do it, but another problem appeared: I can't print all the files from the SD card to the serial port to show it on the pc. I think it happened because of the lack of memory. Since I'm using an Arduino Nano, my sketch takes up 90% of the memory and 71% of the dynamic memory. I assumed so because the function works perfectly if I shorten the code I would like to hear suggestions on how to optimize my code to make it work again or hear what the problem is if I'm wrong.
Here is my code:
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>
#include <SD.h>
//SD:
//GND = GND
//VCC = 5v
//MISO = 12
//MOSI = 11
//SCK = 13
//CS = 10
//ST7735:
//GND = GND
//VCC = 5v
//DC = 7
//RES = 5
//CS = 6
//SDA = 11
//SCL = 13
//BLK #
Sd2Card card;
SdVolume volume;
SdFile root;
const int chipSelect = 10;
String mode;
int len;
#define TFT_CS 6
#define TFT_RST 5
#define TFT_DC 7
int x = 0;
int y = 0;
int color;
String codeStr = "Screen.SetObjectColor('0')\nScreen.SetCursor('120,32')\nScreen.SetTextSize('3')\nScreen.Print('SF')"; //code to execute
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
String split(String text, String separator, int index){
//splits string by separator and returns string by the index
for(int i = 0; i < index; i++){
text = text.substring(text.indexOf(separator)+1,text.length());
}
return(text.substring(0,text.indexOf(separator)));
}
void compile(String code) {
//executes command
if (code.indexOf("Screen.Print(") != -1) {
tft.setCursor(x, y);
tft.print(code.substring(14, code.length()-2));
} else if (code.indexOf("Screen.SetCursor(") != -1) {
x = code.substring(18, code.indexOf(",")).toInt();
y = code.substring(code.indexOf(",")+1, code.length()-2).toInt();
tft.setCursor(x,y);
} else if (code.indexOf("Screen.SetObjectColor(") != -1) {
tft.setTextColor(code.substring(23, code.length()-2).toInt());
color = code.substring(23, code.length()-2).toInt();
} else if (code.indexOf("Screen.Fill(") != -1) {
tft.fillScreen(code.substring(13, code.length()-2).toInt());
} else if (code.indexOf("Screen.SetTextSize(") != -1) {
tft.setTextSize(code.substring(20, code.length()-2).toInt());
} else if (code.indexOf("Screen.DrawLine(") != -1) {
tft.drawLine(x, y, code.substring(17, code.indexOf(",")).toInt(), code.substring(code.indexOf(",")+1, code.length()-2).toInt(), color);
}
}
void showFiles(File dir, int numTabs) {
//i got this form SD example and it dose not work here but if i delete some code to clear memory it will
while (true) {
File entry = dir.openNextFile();
if (!entry) {
dir.rewindDirectory();
break;
}
for (uint8_t i = 0; i < numTabs; i++) {
Serial.print('\t');
}
Serial.print(entry.name());
if (entry.isDirectory()) {
Serial.println("/");
showFiles(entry, numTabs + 1);
} else {
Serial.print("\t\t");
Serial.println(entry.size(), DEC);
}
entry.close();
}
}
//functions that triggers from the serial port in void loop()
void state(){
if (card.init(SPI_HALF_SPEED, chipSelect)) {
Serial.print("Wiring is correct and a card is present.");
}
}
void createFile(String text, String dir){
File newFile = SD.open(dir, FILE_WRITE);
newFile.print(text);
newFile.close();
}
void readFile(String dir){
File readingFile = SD.open(dir, FILE_READ);
if (readingFile) {
while (readingFile.available()) {
Serial.write(readingFile.read());
}
readingFile.close();
}
}
int countLines(String file){
int del = -1;
int count = 0;
String string = SD.open(file, FILE_READ).readString();
while(true){
if(string.indexOf("\n", (del + 1)) == -1){
return(count);
break;
}
else{
del = string.indexOf("\n", (del + 1));
count++;
}
}
}
void setup() {
Serial.begin(9600);
tft.initR(INITR_MINI160x80);
tft.setRotation(3);
tft.fillScreen(ST7735_WHITE);
}
void loop() {
if (!SD.begin(chipSelect)) {
Serial.println("SD card mount failed!");
while (true);
}
while (!Serial) {;}
//gets input from the serial port
String input = Serial.readString();
if (input == "showfiles" or input == "sf") {
//prints directory(don`t work)
showFiles(SD.open("/"), 0);
} else if (input == "state" or input == "s") {
state();
} else if (input == "clearinput" or input == "ci") {
SD.remove("file.txt");
} else if (input == "delete" or input == "d" or mode == "d") {
mode = "d";
delay(100);
if (input!="d" and input!="delete"){
SD.remove(input);
}
} else if (input == "deletefolder" or input == "df" or mode == "df") {
mode = "df";
delay(100);
if (input!="df" or input!="deletefolder"){
SD.rmdir(input);
}
} else if (input == "rename" or input == "rn" or mode=="rn") {
mode = "rn";
delay(1000);
if (input!="rn" and input!="rename"){
File renameFile = SD.open("file.txt");
String text = "";
while (renameFile.available()){
text += (char)renameFile.read();
}
renameFile.close();
createFile(text.substring(text.length()-len ,text.length()), input);
}
} else if (input == "create" or input == "c" or mode == "c") {
mode = "c";
delay(100);
if (input!="c" and input!="create" and input.length()!=0){
len = input.length();
createFile(input, "file.txt");
}
} else if (input == "createfolder" or input == "cf" or mode == "cf") {
mode = "cf";
delay(100);
if (input!="cf" and input!="createfolder"){
SD.mkdir(input);
}
} else if (input == "read" or input == "r" or mode == "r") {
mode = "r";
delay(100);
readFile(input);
} else if (input == "cl" or mode == "cl") {
mode = "cl";
delay(100);
if (input!="cl"){
Serial.print(countLines(input));
}
}
for(int i = 0; i < 4; i++){
//compiles every line in text(i'll make it so that the file executes here)
compile(split(codeStr, "\n", i));
}
}