Построчное чтение данных с SD карты

Mizar
Offline
Зарегистрирован: 23.12.2018

Добрый день!

Рисую один проект, где на карте есть файл, в файле построчно данные.

Желаю в общем цикле считывать строчки по мере необходимости.

Между чтением разумеется выполняется остальной код, где строчки будут разбираться и обрабатываться.

Но вот незадача,

Если файл открыть, сразу прочитать весь и закрыть, то при следующем вызове файл снова можно открыть и прочитать, но естественно не работает основной цикл.

Но вот если файл открыть, прочитать часть, выйти из функции, то при следующем вызове функции данные для чтения не доступны.

Не могу понять как работает этот механизм.

Подготовил пробник для проверки: 

//-------НАСТРОЙКИ---------
const int PIN_CHIP_S_SD = 7;
//-------НАСТРОЙКИ---------
String fString, fStringFileName, rwBuff;
//-------БИБЛИОТЕКИ---------
String buffer;//тут хранится прочитанный из карты текст
boolean FileOpen, FileClose, FileReady;
#include <SPI.h>
#include <SD.h>
//File dataFile;
//-------БИБЛИОТЕКИ---------
void FileRead() {
  File dataFile;
  if (FileOpen != 1) {
    Serial.print("Initializing SD card...");
    // see if the card is present and can be initialized:
    if (!SD.begin(PIN_CHIP_S_SD)) {
      Serial.println("Card failed, or not present");
      // don't do anything more:
      while (1);
    }
    Serial.println("card initialized.");
    FileOpen = 1;
    // open the file. note that only one file can be open at a time,
    // so you have to close this one before opening another.
    dataFile = SD.open("test.txt");
    Serial.println("File Open");
    if (dataFile) {
      FileReady = 1;
    } //if (dataFile)
    // if the file isn't open, pop up an error:
    else {
      Serial.println("error opening");
    }
  }
  // if the file is available, write to it:
// это работает, только  первую строку, при повторном чтении данных нет
  if (dataFile.available() > 0) {
         buffer = dataFile.readStringUntil('\n');//Считываем с карты одну строку.
        Serial.println(buffer); // для отладки отправляем по UART все что прочитали с карты.
    //      Serial.write(dataFile.read());
         delay(500);
  }
  else FileClose = 1;
  /*
    // это работает, только  весь файл за один раз
      while (dataFile.available()) {
        buffer = dataFile.readStringUntil('\n');//Считываем с карты одну строку.
        Serial.println(buffer); // для отладки отправляем по UART все что прочитали с карты.
        //     //      Serial.write(dataFile.read());
        delay(500);
      } // while
      FileClose = 1;
  */
  if (FileClose == 1) {
    dataFile.close();
    FileClose = 0;
    FileOpen = 0;
    Serial.println("File Close");
  }
}
void setup() {
  Serial.begin(115200);                   // открыть порт для связи с ПК для отладки
}

void loop() {
  FileRead();
  for (int i = 0; i < 5; i++) {
    Serial.print(i);
    delay(1000);
  }
  Serial.println("");
}

Что посоветуете для решения?

Что я делаю не так?

b707
Онлайн
Зарегистрирован: 26.05.2017

Mizar пишет:

если файл открыть, прочитать часть, выйти из функции, то при следующем вызове функции данные для чтения не доступны.

Что я делаю не так?

и что вас удивляет? в строке 13 у вас переменная-файл - локальная для функции. если вы из функции выходите, то при следующем входе, конечно же, этой переменной уже нет.

Сделайте перемнную глобальной

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Или статической

rkit
Онлайн
Зарегистрирован: 23.11.2016

или аргументом по ссылке

b707
Онлайн
Зарегистрирован: 26.05.2017

еще можно (нужно!) закрывать файл при каждом выходе из функции, а заходя снова - открывать опять. тогда будет работать и с локальной переменной, но каждый раз файл нужно будет читать сначала

Mizar
Offline
Зарегистрирован: 23.12.2018

тут с вами согласен.

Обратите внимание, что эта переменная глобально тоже объявлялась, но сейчас закомментирована, с глобальной компилятор ругается.

Закрывать файл после чтения строки не вариант, так как в файле Gcode его нужно читать построчно по мере готовности станка принять новую посылку. Пока станок трудится, программа должна работать в общем цикле. 

Пока вы отвечали, выкинул часть кода в отдельные функции, и почему-то заработало.

//-------НАСТРОЙКИ---------

const int PIN_CHIP_S_SD = 7;
//-------НАСТРОЙКИ---------

String fString, fStringFileName, rwBuff;
char logfile[] = {"testLase.nc"};


//-------БИБЛИОТЕКИ---------
String buffer;//тут хранится прочитанный из карты текст
boolean FileOpen, FileClose, FileReady;

#include <SPI.h>
#include <SD.h>
File file;

//File dataFile;
//-------БИБЛИОТЕКИ---------

void initializeSD() {
  Serial.println("Initializing SD card...");
  pinMode(PIN_CHIP_S_SD, OUTPUT);
  if (SD.begin()) {
    Serial.println("SD card is ready to use.");
  } else {
    Serial.println("SD card initialization failed");
    return;
  }
}

void closeFile() {
  if (file) {
    file.close();
    Serial.println("File closed");
  }
}

int openFile(char filename[]) {
  file = SD.open(filename);
  if (file) {
    Serial.println("File opened with success!");
    return 1;
  } else {
    Serial.println("Error opening file...");
    return 0;
  }
}
String readLine() {
  String received = "";
  char ch;
  while (file.available()) {
    ch = file.read();
    if (ch == '\n') {
      return String(received);
    } else {
      received += ch;
    }
  }
  return "";
}

void FileRead() {
  if (FileOpen != 1) {
    initializeSD();
    openFile(logfile);
    FileOpen = 1;
  }
  if (file.available() > 0) {
    Serial.println(readLine());
  }
  else FileClose = 1;

  if (FileClose == 1) {
    closeFile();
    FileClose = 0;
    FileOpen = 0;
    //    Serial.println("File Close");
  }
}
void setup() {
  Serial.begin(115200);                   // открыть порт для связи с ПК для отладки
}


void loop() {
  FileRead();
  for (int i = 0; i < 6; i++) {
    Serial.print(i);
    delay(200);
  }
  Serial.println("");
}

Думаю еще String readLine() упростить до чтения всей строки целиком.

И еще попутный вопрос, можно с карты читать имена файлов форматом больше 8.3 ????

b707
Онлайн
Зарегистрирован: 26.05.2017

Mizar пишет:

Пока вы отвечали, выкинул часть кода в отдельные функции, и почему-то заработало.

почему-то? :)

потому и заработало. что переменная теперь глобальная (строка 14)

Учитесь программировать. а то на каждом шагу будете спотыкаться

Mizar
Offline
Зарегистрирован: 23.12.2018

так постоянно чему-то и приходится учится. Два дня мучаю этот контроллер, уже в тупик зашел, наверно замкнутость мысли. 

Что на счет длинны имени файла? 

Создавать файлы с учетом длинны имени уже давно люди не заморачиваются.

На 3д принтере читается любая длинна, а в этой библиотеке файл более 8 добивается ~ и крякозяблами.

Возможно ли чтение списка и работа с файлами больше 8 ??? в рамках этой библиотеки?

Mizar
Offline
Зарегистрирован: 23.12.2018

Что то снова не выходит :(

Конфликт двух

File file;
File root;

Сначала получаю список файлов

        initializeSD();
        root = SD.open("/");
        printDirectory(root, 0);
        root.close();

где из примера

void printDirectory(File dir, int numTabs) {
  index_myFileDir = 0;
  TotalFile = 0;
  while (true) { // копаемся в дерриктории
    File entry =  dir.openNextFile();
    if (! entry) {
      // no more files если нет больше файлов
      break;
    }
    //    Serial.println("AddList: ");
    if (entry.isDirectory()) {} // если это папка
    else {// если это НЕ папка
      fString = String(entry.name()); // считываем имя файла
      AddListDir(fString, index_myFileDir); // добавляем в массив свписок файлов обрезаем до 8 символов точка и расширение 3
      //   Serial.println(entry.name());
      index_myFileDir++;
    }
    entry.close();
  }

только пишем список в массив функцией AddListDir(fString, index_myFileDir);

Далее в меню устройства открываем список, выбираем нужный файл, сохраняем его имя, и можно переходить к открытию этого файла для чтения.

Примером выше у меня получилось построчно выводить файл, тут все хорошо.

Но когда компилируются обе переменных file и root, даже без исполнения кода с переменной file,  root почему то не работает.

printDirectory не работает.

Если операции с переменной file выполнять в основном цикле, то компилятор на нее ругался, поэтому и вынес ее в локальную, так хоть что то работало.

А теперь все операции с file  выполняются в теле функций, и с успехом компилируются вне основного цикла, но вся конструкция не работает.

Весь код, если интересно:

/*
  Card Info – это извлечение информации, хранящейся в SD карте. С ее помощью можно узнать, в какую файловую систему отформатирована карта, наличие свободного места, какие данные записаны.
  Yun Datalogger – позволяет записывать лог-данные с трех сенсоров на карту.
  Datalogger – регистрирует и созраняет данные, полученные с датчика на карту.
  Dump File – считывание данные с карты, передает их в серийный порт.
  Files – создает и удаляет данные. Существует функция file.write(), которая помещает записанные данные в буфер. Перемещение информации на карту происходит при вызове функций flush() или close(), поэтому важно закрывать его после каждого открытия файла, иначе данные будут потеряны.
  Read Write – записывает и считывает файлы с карты.

  Функции библиотеки SD
  begin() – функция инициализирует библиотеку, присваивает контакт для сигнала.
  exists() – призвана проверить, имеется ли на карте необходимая информация.
  mkdir() – позволяет создать нужную папку на карте памяти.
  rmdir() – с помощью этой функции можно удалить папку. Важно, чтобы удаляемая папка была пустой.
  open() – позволяет открыть файл, который нужен для записи или чтения. Если нужный файл отсутствует на карте, то он будет создан.
  remove() – удаляет любой файл.
  Схема подключения:
   Аналоговые сенсоры подключаются к аналоговым пинам
   Модуль SD карты подключен в SPI по стандартной схеме:
 ** MOSI - пин 11
 ** MISO - пин12
 ** CLK - пин 13
 ** CS - pin 7
*/
// correct voltage to the module.
//      SCK  - Pin 8
//      MOSI - Pin 9
//      DC   - Pin 10
//      RST  - Pin 6 // 11
//      CS   - Pin 5 // 12


//-------НАСТРОЙКИ---------
const int PIN_CHIP_S_SD = 7;
const int PIN_CHIP_S_LCD = 12;
//-------НАСТРОЙКИ---------

char mode, fmode; // страницы экранов
char SD_status, fileStat; // статус наличия карточки
float moveX, moveY, moveZ;
float moveXAbsolut, moveYAbsolut, moveZAbsolut;
#define Xlimit  240
#define Ylimit  470
#define Zlimit  54
int Speed;
float fmoveX, fmoveY, fmoveZ;
//float Step;

float ValStep[] = {0.01, 0.1, 1, 5, 10, 100, 200};
byte num_Step = sizeof(ValStep) / 4;       // получить количество
byte nStep;
int temp;
String fString, fStringFileName, rwBuff;
char buff[15];
//char *myFileDir[] = {"File1", "File2", "File3"} ; // 16 файлов в списке
char myFileDir[16][13]; // 16 файлов в списке длина8 + 1 + 3 =12 '\0'
char index_myFileDir;
char IndexSelect; // выбор файла на экране
int TotalFile; // количество файлов на карточке
int StringIndex, findex, Pindex; // позиция выбора строки, курсор
int s1, s2, s3, s4, s5; // номера строк
boolean dataRW; // rwBuff
int incomingByte = 0;   // переменная для хранения полученного байта
char ErrCode, AlrCode;
boolean ErrCodeReset, AlrCodeReset;
boolean SendFile; // можно передавать файл
boolean fileEnd, fileOpen, SendString;
boolean FileOpen, FileClose, FileReady;
char inByteFile;
signed long fTimer;
//-------БИБЛИОТЕКИ---------

#include <LCD5110_Basic.h>
LCD5110 myGLCD(8, 9, 10, 6, 5);
extern uint8_t SmallFont[];
extern uint8_t MediumNumbers[];
extern uint8_t BigNumbers[];

#include <SPI.h>
#include <SD.h>
File file;
File root;


//-------БИБЛИОТЕКИ---------

#include <Keypad.h> // подключаем библиотеку для управление клавиатурой
//-------КНОПКИ---------
const byte ROWS = 3; //число строк у нашей клавиатуры
const byte COLS = 4; //число столбцов у нашей клавиатуры
char hexaKeys[ROWS][COLS] = {// здесь мы располагаем названия наших клавиш, как на клавиатуре,для удобства пользования
  {'M', 'Y', 'Z', 'H'}, // меню   У+
  {'x', 'E', 'X', 'V'},
  {'S', 'y', 'z', 'K'}
};
byte rowPins[ROWS] = {2, 3, 4}; //к каким выводам подключаем управление строками
byte colPins[COLS] = {A0, A1, A2, A3}; //к каким выводам подключаем управление столбцами
//передаем все эти данные библиотеке:
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

//-------КНОПКИ---------

void initializeSD() {
  Serial.println("Initializing SD card...");
  pinMode(PIN_CHIP_S_SD, OUTPUT);
  if (SD.begin()) {
    SD_status = 1;
    Serial.println("SD card is ready to use.");
  } else {
    Serial.println("SD card initialization failed");
    SD_status = 0;
    return;
  }
}

void closeFile() {
  if (file) {
     file.close();
     Serial.println("File closed");
   }
}
int openFile() {
  file = SD.open(fStringFileName);
  if (file) {
    Serial.println("File opened with success!");
    return 1;
  } else {
    Serial.println("Error opening file...");
    return 0;
  }
}


String readLine() {
  String received = "";
  char ch;
  while (file.available()) {
    ch = file.read();
    if (ch == '\n') {
      return String(received);
    } else {
      received += ch;
    }
  }
  return "";
}


void SD_FileRead() {
  Serial.println("readLine");
  if (FileOpen != 1) {
    if (SD_status != 1) initializeSD(); // если карта не найдена, ищем карту
    openFile();
    FileOpen = 1;
  }
  if (file.available() > 0) {
    Serial.println(readLine());
  }
  else FileClose = 1;

  if (FileClose == 1) {
    closeFile();
    FileClose = 0;
    FileOpen = 0;
  }
}


// =========================================================

void LCD_PrintHome() { // вывод массива на дисплей
  fString = "";
  if (findex != StringIndex) {
    if (StringIndex > findex) { // увеличиваем счетчик индекса
      if (Pindex < 4) Pindex++;
      else {
        s1++;
        s2++;
        s3++;
        s4++;
        s5++;
      }
    }
    if (StringIndex < findex) { // уменьшаем  счетчик индекса
      if (Pindex > 0) Pindex--;
      else {
        s1--;
        s2--;
        s3--;
        s4--;
        s5--;
      }
    }
    findex = StringIndex;
  }
  // вывод списка на экран и прокрутка его
  if (Pindex == 0) ListDir(s1, 1);
  else ListDir(s1, 0);
  myGLCD.print(fString, LEFT, 8);
  if (Pindex == 1) ListDir(s2, 1);
  else ListDir(s2, 0);
  myGLCD.print(fString, LEFT, 16);
  if (Pindex == 2) ListDir(s3, 1);
  else ListDir(s3, 0);
  myGLCD.print(fString, LEFT, 24);
  if (Pindex == 3) ListDir(s4, 1);
  else ListDir(s4, 0);
  myGLCD.print(fString, LEFT, 32);
  if (Pindex == 4) ListDir(s5, 1);
  else ListDir(s5, 0);
  myGLCD.print(fString, LEFT, 40);
}

void LCD_index_clear() { // очистка индексов перед выводом списка
  StringIndex = 0;
  Pindex = 0;
  findex = 0;
  s1 = 0; s2 = 1; s3 = 2; s4 = 3; s5 = 4;
}

void ListDir(int stIndex, int cur) { // выбираем имя файла из массива, обрезка до 8 символов + точка + расширение и прибавляем в начало пробел или курсор
  int Lhg;
  if (cur != 3) {
    if (cur == 1) fString = ">";
    else fString = " ";
  }
  else fString = "";
  for (byte ii = 0; ii < 13; ii++) {
    if (myFileDir[stIndex][ii] == '\0') return;
    fString += myFileDir[stIndex][ii];
  }
}


void AddListDir(String text, int ListIndex) { //  добавляем в массив имя файла, но обрезаем строку для экрана
  int icut;
  int Lhg;
  if (ListIndex > 15) return; // ограничение массива до 16 файлов в списке
  TotalFile++; // счетчик найденных файлов
  Lhg = text.length();
  fString = "";
  if (Lhg > 12) Lhg = 12;
  for (icut = 0; icut < Lhg; icut++) {
    myFileDir[ListIndex][icut] = text[icut];
  }
  icut++;
  myFileDir[ListIndex][icut] = '\0';
}

void printDirectory(File dir, int numTabs) {
  index_myFileDir = 0;
  TotalFile = 0;
  while (true) { // копаемся в дерриктории
    File entry =  dir.openNextFile();
    if (! entry) {
      // no more files если нет больше файлов
      break;
    }
    //    Serial.println("AddList: ");
    if (entry.isDirectory()) {} // если это папка
    else {// если это НЕ папка
      fString = String(entry.name()); // считываем имя файла
      AddListDir(fString, index_myFileDir); // добавляем в массив свписок файлов обрезаем до 8 символов точка и расширение 3
      //   Serial.println(entry.name());
      index_myFileDir++;
    }
    entry.close();
  }

}
// =====================================
void serialEvent() {
  int dlstr;
  char incomingByte;
  char ind1, ind2;
  // проверка буфера приемника последовательного порта, формирование приемного пакета
  if (Serial.available() > 0) {  //если есть доступные данные
    dataRW = 1; //  выставляем флаг, что мы полчили эти данные
    //   myGLCD.clrScr();
    rwBuff = "";
    fString = "";
    while (Serial.available() > 0) {
      incomingByte = Serial.read();
      if ((incomingByte != '\n') && (incomingByte != '\r')) {
        rwBuff += incomingByte;
      }
      else rwBuff += " ";
    }
    dlstr = rwBuff.length();
    for (int n = 0; n < 13 - dlstr; n++) { // добиваем строку пробелами, что бы не очищать экран
      rwBuff += " ";
    }
    //   fString =  Serial.readString();  // принимаем всю строку
    // ищем ответ
    if (rwBuff.startsWith("error")) {
      ind1 = rwBuff.indexOf(":", 0);
      ind2 = rwBuff.indexOf(" ", ind1);
      ErrCode = rwBuff.substring (ind1 + 1, ind2).toInt();
      //      Serial.println(ErrCode,DEC);
    }

    if (rwBuff.startsWith("ALARM")) {
      ind1 = rwBuff.indexOf(":", 0);
      ind2 = rwBuff.indexOf(" ", ind1);
      AlrCode = rwBuff.substring (ind1 + 1, ind2).toInt();
      //      Serial.println(ErrCode,DEC);
    }

    if (rwBuff.startsWith("[MSG")) {
      ind1 = rwBuff.indexOf(":", 0);
      ind2 = rwBuff.indexOf(" ", ind1);
      rwBuff = rwBuff.substring (ind1 + 1, dlstr - 1);
    }
    if (rwBuff.startsWith("ok")) {
      //  Serial.println("OK!");
      if (ErrCodeReset == 1) {
        ErrCodeReset = 0;
        ErrCode = 0;
      }
      if (AlrCodeReset == 1) {
        AlrCodeReset = 0;
        AlrCode = 0;
      }
    }
  }
}
// ==============================
void setup() {
  Serial.begin(115200);                   // открыть порт для связи с ПК для отладки
  // Serial.println("Start");
  //  Serial.println(num_Step);
  // инициализация дисплея
  myGLCD.InitLCD();
  myGLCD.setFont(SmallFont);
  myGLCD.clrScr();
  myGLCD.print("Start", CENTER, 1);
  //  delay(1000);
  pinMode(10, OUTPUT);
  // Пытаемся проинициализировать модуль
  myGLCD.clrScr();
  //  initSDcard(); //ищем карточку
  LCD_index_clear();
  nStep = 4;// начальный шаг 10
  Speed = 100; // начальная скорость 100%
  rwBuff = "           "; // начальный текст в строке отправки\приема данных
}

void loop() {
  if (SD_status != 1) initializeSD(); // если карта не найдена, ищем карту


  char customKey = customKeypad.getKey();//записывем нажатый символ
  if (customKey) { //если что-то нажато
    //     Serial.println(customKey);//выводим нажатый символ в монитор порта
    myGLCD.clrScr();
    if (mode == 0) { // начальная страница, кнопками меняем координаты
      if (customKey == 'S') { // изменение шага, перебираем массив с передопределенными шагами
        nStep++;
        if (nStep > num_Step - 1) nStep = 0; //  начинаем сначала
        //     Serial.println(nStep);
      }

      if (customKey == 'H') { // кнопка домой
        rwBuff = F("$H"); //  выставляем сообщение в буфер
        dataRW = 0; //  выставляем флаг, что мы отправили эти данные
        Serial.println(rwBuff);
        ErrCodeReset = 1; // разрешение сбросить флаг, если поступит ОК
        AlrCodeReset = 1;
        moveX = 0;
        moveY = 0;
        moveZ = 0;
        fmoveX = 0;
        fmoveY = 0;
        fmoveZ = 0;
        moveXAbsolut = 0;

      }
      // обрабатываем кнопки координат
      if (customKey == 'X') { // Х++
        if (moveXAbsolut + ValStep[nStep] <=  Xlimit) { // не выходим на лимиты машины
          moveXAbsolut += ValStep[nStep]; // сохраняем абсолютные значения
          moveX += ValStep[nStep]; // сохраняем экранные значения
        }
        else rwBuff = String(F("Xlimit>")) + Xlimit;
      }
      if (customKey == 'x') { // Х++
        if (moveXAbsolut - ValStep[nStep] >= 0) { // не выходим на лимиты машины
          moveXAbsolut -= ValStep[nStep];
          moveX -= ValStep[nStep];
        }
        else rwBuff = String(F("Xlimit<0"));
      }
      if (customKey == 'Y') { // Х++
        if (moveYAbsolut + ValStep[nStep] <=  Ylimit) { // не выходим на лимиты машины
          moveYAbsolut += ValStep[nStep]; // сохраняем абсолютные значения
          moveY += ValStep[nStep]; // сохраняем экранные значения
        }
        else rwBuff = String(F("Ylimit>")) + Ylimit;
      }
      if (customKey == 'y') { // Х++
        if (moveYAbsolut - ValStep[nStep] >= 0) { // не выходим на лимиты машины
          moveYAbsolut -= ValStep[nStep];
          moveY -= ValStep[nStep];
        }
        else rwBuff = String(F("Ylimit<0"));
      }
      if (customKey == 'Z') { // Х++
        if (moveZAbsolut + ValStep[nStep] <=  Zlimit) { // не выходим на лимиты машины
          moveZAbsolut += ValStep[nStep]; // сохраняем абсолютные значения
          moveZ += ValStep[nStep]; // сохраняем экранные значения
        }
        else rwBuff = String(F("Zlimit>")) + Zlimit;
      }
      if (customKey == 'z') { // Х++
        if (moveZAbsolut - ValStep[nStep] >= 0) { // не выходим на лимиты машины
          moveZAbsolut -= ValStep[nStep];
          moveZ -= ValStep[nStep];
        }
        else rwBuff = String(F("Zlimit<0"));
      }

      if (customKey == 'K') { // снятие блокировки
        //       moveX = 0;
        //       moveY = 0;
        //       moveZ = 0;
        //     Serial.println(F("G10 P0 X0 Y0 Z0"));
        rwBuff = F("$X");
        dataRW = 0; //  выставляем флаг, что мы отправили эти данные
        Serial.println(rwBuff);
        //      Serial.println(F("G92 X0 Y0 Z0"));
      }
      if (customKey == 'V') { //комвнда щупа
        rwBuff = F("Probe Begin"); dataRW = 0; //  выставляем флаг, что мы отправили эти данные
        Serial.println(F("G91G21"));
        Serial.println(F("G0 X0 Y45 F800"));
        Serial.println(F("G38.2Z-50F200"));
        Serial.println(F("G0Z1"));
        Serial.println(F("G38.2Z-1F10"));
        Serial.println(F("G0Z4"));
        Serial.println(F("G0 X0 Y-45 F800"));
        Serial.println(F("G92 X0 Y0 Z0"));
      }

      // проверим если изменились координаты, то отправляем разницу между тем, что было на экране и новый с учетом шага
      if (fmoveX != moveX) { // изменилась система координат //$J=G21G91X10F1000
        rwBuff = String(F("$J=G21G91X")) + (moveX - fmoveX) + F("F800");// отправляем разницу
        fmoveX = moveX; // запоминаем послденее положение
        dataRW = 0; //  выставляем флаг, что мы отправили эти данные
        ErrCodeReset = 1; // разрешение сбросить флаг, если поступит ОК
        Serial.println(rwBuff);
      }

      if (fmoveY != moveY) { // изменилась система координат //$J=G21G91X10F1000
        rwBuff = String(F("$J=G21G91Y")) + (moveY - fmoveY) + F("F800");// отправляем разницу
        fmoveY = moveY; // запоминаем послденее положение
        dataRW = 0; //  выставляем флаг, что мы отправили эти данные
        ErrCodeReset = 1; // разрешение сбросить флаг, если поступит ОК
        Serial.println(rwBuff);
      }
      if (fmoveZ != moveZ) { // изменилась система координат //$J=G21G91X10F1000
        rwBuff = String(F("$J=G21G91Z")) + (moveZ - fmoveZ) + F("F800");// отправляем разницу
        fmoveZ = moveZ; // запоминаем послденее положение
        dataRW = 0; //  выставляем флаг, что мы отправили эти данные
        ErrCodeReset = 1; // разрешение сбросить флаг, если поступит ОК
        Serial.println(rwBuff);
      }

      if (customKey == 'E') { // // запуск выбор файла
        if (fileStat == 2) { // если выбран файл открываем и запускаем чтение
          //   SendFile = SendFile ^ 1;
          SendFile =  1;
          rwBuff = "";
        }
        else { //, если мы на основном экране и файл не выбран, то просто обнуляем свои и станка координаты
          moveX = 0;
          moveY = 0;
          moveZ = 0;
          fmoveX = 0;
          fmoveY = 0;
          fmoveZ = 0;
          rwBuff = String(F("G92X0Y0Z0"));
          dataRW = 0; //  выставляем флаг, что мы отправили эти данные
          Serial.println(rwBuff);
        }
      }
    }
    //=================================================
    if (mode == 1) { // выбор файлов, кнопками навигация между файлами
      if (customKey == 'y') { // двигаемся в конец списка. исходя из общего колва файлов пока макс 16
        StringIndex++;
        if (StringIndex > TotalFile - 1)  StringIndex = TotalFile - 1;
      }
      if (customKey == 'Y') { //
        if (StringIndex >= 1) StringIndex--;
      }
      if (customKey == 'E') { // // выбор файла
        ListDir(StringIndex, 3); // обрабатываем имя файла, не больше 8 символов + расширение, без курсора
        fStringFileName = "";
        fStringFileName = fString; // сохраняем имя выбранного файла
        fileStat = 2; // выбрали файл
        mode = 0;// вернемся в главный экран
      }

    }

    if (customKey == 'M') { // пока входим в файловый менеджер и выходим
      switch (mode) {
        case  0: mode = 1; fileStat = 0; break; // входим в карточку
        case  1: mode = 0; rwBuff = ""; break;
      }
    }
  }

  //  if (mode != fmode) myGLCD.clrScr(); // если изменилась страница экраа, послностью его очистим
  // обработка режимов экрана
  if (mode == 0) { // начальный экран
    // первая строка
    fString = String("X:") + String(moveX); // координаты оси, собираем строку перед выводом на экран
    myGLCD.print(fString, LEFT, 0);
    fString = String("F") + Speed + "%"; // скорость, собираем и добавляем на туже строку но справа
    myGLCD.print(fString, RIGHT, 0);
    // вторая строка
    fString = String("Y:") + String(moveY);
    myGLCD.print(fString, LEFT, 8);
    if (ErrCode == 0) {
      fString = String("Err") + "--";
    }
    else  fString = String("Err") + String(ErrCode, DEC);
    myGLCD.print(fString, RIGHT, 8);
    // 3 строка
    fString = String("Z:") + String(moveZ);
    myGLCD.print(fString, LEFT, 16);
    if (AlrCode == 0) {
      fString = String("Alr") + "--";
    }
    else
      fString = String("Alr") + String(AlrCode, DEC);
    myGLCD.print(fString, RIGHT, 16);
    // 4 строка
    fString = String("Step:") + String(ValStep[nStep]);
    myGLCD.print(fString, LEFT, 24);
    // 5 строка данных, отправка и получение
    //dataRW; // rwBuff
    if (dataRW == 0) { //был режим передачи данных
      fString = String(">") + rwBuff;
      myGLCD.print(fString, LEFT, 32);
    }
    else {
      fString = String("<") + rwBuff;
      myGLCD.print(fString, LEFT, 32);
    }

    // 6 строка
    if (SD_status != 1) { // карточки нет
      myGLCD.print(F("NO SD Card....."), LEFT, 40);
    }
    else if (fileStat != 2) { //
      myGLCD.print(F("SD Insert"), LEFT, 40);
    }
    else { // выбран файл
      myGLCD.print(fStringFileName, LEFT, 40);
    }
  }
  if (mode == 1) { // экран выбора файла
    if (SD_status != 1) { // карточки нет
      //   initializeSD();
      myGLCD.print(F("NO SD Card....."), LEFT, 0);
    }
    else { //карта вставлена
      fString = String("OpenFile (") + TotalFile + ")";
      myGLCD.print(fString, LEFT, 0);
      if (fileStat == 0) { // поулчаем списко файлов
        initializeSD();
        root = SD.open("/");
        //  TotalFile = 0;
        printDirectory(root, 0);
        root.close();
        fileStat = 1;

      }
      if (fileStat == 1) { //
        // fileStat = 1;
        LCD_PrintHome(); //обновляем экран со списком файлов
      }
    }
  }

  if (SendFile == 1) {
    SendFile = 0;
    SD_FileRead();
  }
}// главный цикл

Если включить при компиляции строки 116 и 122, то код не работает. Хотя условий для запуска 589 строки нет.

Если отключить 589 строку, список файлов формируется. 

 
Komandir
Offline
Зарегистрирован: 18.08.2018

А ОЗУ то хватает на все эти хотелки ?

Mizar
Offline
Зарегистрирован: 23.12.2018

пока да. там еще есть лишние вещи, позже оптимизирую. (сейчас 80%). Сейчас много диагностических сообщений и временных переменных. Какие то можно из int  в char  перевести, константы в ПЗУ переместить.

По сути осталось парсить строчки и по готовности станка отправлять их. Ну и на ходу подменять пакетах скорость перемещения.

Нашел глюк. мешали тестовые Serial.print. Убрал, заработало, видимо ели ресурсы. Сейчас все работает.

Делаю OffLine контроллер для GRBL.

m.yakovenko
Offline
Зарегистрирован: 02.08.2020

Подскажите пожалуйста, правильно ли я понял - вы реализовали чтение и отправку G-code с SD карты непосредственно на ЧПУ? Если да - напишите пожалуйста на maxgoldmark@gmai.com - интересуют некоторые наработки. Платно конечно же.

Mizar
Offline
Зарегистрирован: 23.12.2018

Да, это off-line контроллер управления трех координатным ЧПУ станком, лазерным и\или фрезерным.

svm
Offline
Зарегистрирован: 06.11.2016

Я немного занимался с подобным, в принципе работает, но кое-что надо доработать. Сейчас отложил, нужно по быстрому автономный ЧПУ плазморез до ума довести.  Исходники есть https://www.cnc-club.ru/forum/viewtopic.php?p=551630#p551630 может что пригодится.