Считывание данных с SD карты и сохранение их в виде переменных
- Войдите на сайт для отправки комментариев
Вс, 03/02/2013 - 19:28
Здравствуйте.
Есть задача, на Sd карте записан текстовый файл в котором записаны параметры которые используются в программе. Примерной вид текстового файла 10,0,20,20,1.
Код который разбивает эти данные по переменным и сохраняет их:
byte h=0; // считываем массив входящего конфигурвционного файла
byte array[]={}; // массив выходящих значений конфигурационного файла
configFile = SD.open("config.txt");
if (configFile) {
Serial.println("configFile.txt open OK");
while (configFile.available()) {
// считываем байт входящего файла
symbol = configFile.read();
array[h]=symbol;
h=h++;
}
configFile.close();
byte outputArray [] [5] ={ /// массив с выходящими значениями в который записываются побайтово цифры из конфигурвционного файла
{},
{},
{}};
byte t=0; // переменная которая в массиве outputArray [t] [] переключает строки
byte z=0; // переменная которая содержит значение i, используется для возвращения намера столца outputArray[t][i-z] в нулевое положение
byte x=0; // определяет количество параметров которое мы задаем с SD карты.
byte u=0; // количество символов считываемого значения
for(int i = 0; i<=h; i++){
symbol = array[i];
if ( symbol == 44 && x == 0 ){ /// Начинаем обрабатывать первое значение из входящего массива данных
// Часть кода которая отвечает за сохранение параметров которые мы считываем с SD карты
u = i;
// если у нас параметр состоит из двух числе
if (u == 2){
SolenoidTime = outputArray[0][i-z-1]+ outputArray[0][i-z-2]*10;
}
// если у нас параметр состоит из трёх чисел
else if (u == 3){
SolenoidTime = outputArray[0][i-z-1]+ outputArray[0][i-z-2]*10+outputArray[0][i-z-3]*100;
}
// если первый пареметр состоит из четырёх символов
else if (u == 4){
SolenoidTime = outputArray[0][i-z-1]+ outputArray[0][i-z-2]*10+outputArray[0][i-z-3]*100+outputArray[0][i-z-4]*1000;
}
t = t + 1;
x = 1;
z = i + 1; // пееменная z сдвигает номер столбца выходного массива в ноль
}
else if ( symbol == 44 && x == 1){ /// Начинаем обрабатывать второе значение из входящего массива данных
u = i-z;
// если у нас параметр состоит из двух числе
if (u == 2){
DelayTime = outputArray[1][i-z-1]+ outputArray[1][i-z-2]*10;
}
// если у нас параметр состоит из трёх чисел
else if (u == 3){
DelayTime = outputArray[1][i-z-1]+ outputArray[1][i-z-2]*10+outputArray[1][i-z-3]*100;
}
// если первый пареметр состоит из четырёх символов
else if (u == 4){
DelayTime = outputArray[1][i-z-1]+ outputArray[1][i-z-2]*10+outputArray[1][i-z-3]*100+outputArray[1][i-z-4]*1000;
}
t = t + 1;
z = i + 1;
x = 2;
}
else if ( symbol == 44 && x == 2){ /// Начинаем обрабатывать третье значение из входящего массива данных
u = i-z;
// если у нас параметр состоит из двух числе
if (u == 2){
KerningTime = outputArray[2][i-z-1] + outputArray[2][i-z-2]*10;
}
// если у нас параметр состоит из трёх чисел
else if (u == 3){
KerningTime = outputArray[2][i-z-1] + (outputArray[2][i-z-2]*10) + (outputArray[2][i-z-3]*100);
}
// если первый пареметр состоит из четырёх символов
else if (u == 4){
KerningTime = outputArray[2][i-z-1] + (outputArray[2][i-z-2]*10) + (outputArray[2][i-z-3]*100) + (outputArray[2][i-z-4]*1000);
}
t=t+1; z=i+1;x=3;
}
else if ( symbol == 44 && x == 3){ /// Начинаем обрабатывать четвёртое значение из входящего массива данных
u = i-z;
// если у нас параметр состоит из двух числе
if (u == 1){
loopcycle = outputArray[3][i-z-1];
}
t=t+1; z=i+1;x=4;
}
else if ( symbol == 44 && x == 4){ /// Начинаем обрабатывать третье значение из входящего массива данных
u = i-z;
// если у нас параметр состоит из двух числе
if (u == 2){
looptime = outputArray[4][i-z-1] + outputArray[4][i-z-2]*10;
}
// если у нас параметр состоит из трёх чисел
else if (u == 3){
looptime = outputArray[4][i-z-1] + (outputArray[4][i-z-2]*10) + (outputArray[4][i-z-3]*100);
}
// если первый пареметр состоит из четырёх символов
else if (u == 4){
looptime = outputArray[4][i-z-1] + (outputArray[4][i-z-2]*10) + (outputArray[4][i-z-3]*100) + (outputArray[4][i-z-4]*1000);
}
t=t+1; z=i+1;x=5;
}
else if ( symbol == 46 && x == 5){ /// Начинаем обрабатывать четвёртое значение из входящего массива данных
u = i-z;
// если у нас параметр состоит из двух числе
if (u == 1){
system = outputArray[5][i-z-1];
Serial.print("sys");Serial.print(system);
}
t=t+1; z=i+1;x=6;
}
else if ( symbol == 48){ outputArray[t][i-z] = 0; } // 0
else if ( symbol == 49){ outputArray[t][i-z] = 1; } // 1
else if ( symbol == 50){ outputArray[t][i-z] = 2; } // 2
else if ( symbol == 51){ outputArray[t][i-z] = 3; } // 3
else if ( symbol == 52){ outputArray[t][i-z] = 4; } // 4
else if ( symbol == 53){ outputArray[t][i-z] = 5; } // 5
else if ( symbol == 54){ outputArray[t][i-z] = 6; } // 6
else if ( symbol == 55){ outputArray[t][i-z] = 7; } // 7
else if ( symbol == 56){ outputArray[t][i-z] = 8; } // 8
else if ( symbol == 57){ outputArray[t][i-z] = 9; } // 9
else {} // Если вводиться что-то не преднамеренное
}
}
else {
// Если файл не открылся соощаем об ошибке:
Serial.println("error configFile.txt");
}
Serial.print("Solenoid ");Serial.println(SolenoidTime);
Serial.print("Delay "); Serial.println(DelayTime);
Serial.print("Kerning "); Serial.println(KerningTime);
Serial.print("Loop"); Serial.println(loopcycle);
Serial.print("Loop"); Serial.println(looptime);
Serial.print("font");
if (system == 0){
Serial.println("ENG");
}
else if (system == 1){
Serial.println("RUS");
}
else {}
Как вы видите моя программа обрабатывает побайтово входящий массив значений, определяет что за цифра скрывается за ASCII кодом, и знаки препинания разделяющие сами параметры, являются флагами и сообщают о том что один параметр закончился и начался новый.
Вопрос, как можно сделать это ещё лучше?
Возможно я не знаю, чего-то.
Как можно сократить объем используемой памяти?
так понял из кода и ваших пояснений к нему,что у вас львиная доля кода уходит на то что бы расшифровать какое значение вы считали из файла ?
советую почитать про функции strtok(); и atoi();
то есть я предлагаю вместо того что бы определять из скольких цифр состоит число и т.д. и т.п. ...считывать число из файла как массив символов,а затем сразу же переводить его в тип int и сохранять в нужный вам массив
int h=0; // считываем массив входящего конфигурвционного файла char buffer[5]; //так как в кажде данное не больше 4 цифр int num,i=0; configFile = SD.open("config.txt"); if (configFile) { Serial.println("configFile.txt open OK"); char array[ConfigFile.size()]; // массив выходящих значений конфигурационного файла while (configFile.available()) { // считываем байт входящего файла symbol = configFile.read(); array[h]=symbol; h++; } array[h]='\0'; configFile.close(); do { buffer=strtok(array,","); num =atoi(buffer); outputArray[i]=num; //тут особо не обращайте внимание,остюда уже идут операции размещения считанных данных куда вам надо по массивам i++; } while(buffer!=NULL);как то примерно так,просто с SD карточками особо не заморачивался
mixail844, спасибо Вам большое за помощь. буду разбираться
Переделал код, он сйечас выглядит так:
int h=0; // считываем массив входящего конфигурвционного файла int num,i=0; char array[]={}; char *outArray[]={}; char *buffer; //char conf; configFile = SD.open("config.txt"); if (configFile) { Serial.println("configFile.txt open OK"); while (configFile.available()) { // считываем байт входящего файла symbol = configFile.read(); array[h] = symbol; //Serial.println(array[h]); h++; delay(1); } //array[h]='\0'; configFile.close(); //Serial.println("configFile.txt END"); } else {//Serial.println("configFile.txt open ERROR"); } char *p; byte t = 0; for( buffer = strtok_r(array, ",.", &p); buffer; buffer = strtok_r(NULL, ",.", &p) ) { Serial.print(t);Serial.print(" = ");Serial.println(buffer); delay(1); outArray[t]=buffer; t++; } Serial.print("Solenoid ");Serial.println(SolenoidTime); Serial.print("Delay "); Serial.println(DelayTime); Serial.print("Kerning "); Serial.println(KerningTime); Serial.print("Loop"); Serial.println(loopcycle); Serial.print("Loop time "); Serial.println(looptime);При выполнении кода получаем:
configFile = SD.open("config.txt");//считывание и присваивание адресса файлу if (configFile) Serial.println("configFile.txt open OK"); else Serial.println("configFile.txt open ERROR"); char buffer[5];//малый буффер для strtok(); char symbol; char array[configFile.size()+1]; //создание "большого" буффера для данных,насчет этой строчки не уверен так как примеров как работает команда file.size(); невидел,в принципе,по идее можно заменить на char array[configFile.avialable()+1]; char OutArray[configFile.size()/2+1][4];//двумерный массив данных.для принемаемых значений,по желанию можно изменить его в массив типа int для мат пераций над данными.и естественно пользоваться функцией atoi int h=0,i=0;//вспомогательные переменные while (configFile.available()) { // считываем байт входящего файла symbol = configFile.read();//присваивание символа символу array[h] = symbol; //присваивание символа символу //Serial.println(array[h]); h++; delay(1); } array[h]= '\0'; //добавления символа окончания строки для функции strtok() поэтому и "+1" при обьявлении array configFile.close(); buffer=strtok(array,",");//если нужно что бы разделение было и по признаку "." тогда перепишите strtok(array,",."); h=0; while(buffer!=NULL){ //для этого и добавлялся '\0'в конце array { Serial.println(buffer); strcpy(OutArray[h][0],buffer)//компирование "строчки в строчку",простым "=" тут не обойтись,надеюсь с "0" я не перемудрил h++; } for(i=0;i<h;i++) Serial.println(OutArray[i][0]);извините,но мне ваш код, слегка выносил мозг.переписал ,как мне кажеться, более читабельно.
функция strtok() сама в себе использует фунцию strcpy(),и сама же продвивает указатель по "большому" массиву символов
Михаил, спасибо Вам большое за помощь. Разобрался.
мой финальный код, выглядит так:
int h = 0; // считываем массив входящего конфигурвционного файла int num,i=0; char array[]={}; char *buffer; char symbol2 = 0; configFile = SD.open("config.txt"); if (configFile) { //Serial.println("configFile.txt open OK"); while (configFile.available()) { // считываем байт входящего файла symbol2 = configFile.read(); array[h] = symbol2; h++; delay(1); } array[h]='\0'; configFile.close(); } char *p; byte t = 0; for( buffer = strtok_r(array, ",.", &p); buffer; buffer = strtok_r(NULL, ",.", &p) ) { Serial.print(t);Serial.print(" = ");Serial.println(atoi(buffer)); delay(1); outArray[t]=atoi(buffer); t++; } }Благодара Вам, код сократился в 5 раз!! Ура!
Здравствуйте.
Подскажите, а если задача похожа (есть текстовый файл, но в нем несколько строк - например 48), как считать данные из последней строки -48й, 47й, 46й итд.. или из любой строки и занести эти данные в массив? 48строк - это максимальное количество строк в файле, добавляются по мере поступления данных от датчиков. На самом деле может быть и 10 строк и 1 строка...
Данные будут записываться в массив int p_g[48];
Например: из 48 строки последняя цифра -749 p_g[0]=749;
из 47 строки последняя цифра - 748 p_g[1]=748;
из 46 p_g[2]=748;
из 45 p_g[3]=747;
файл имеет структуру:
............................
0,0,26,35,745
0,30,26,35,745
1,0,26,35,745
1,30,26,35,745
10,0,23,33,747
10,30,24,33,747
11,0,24,32,748 -46 строка
11,30,25,31,748 -47 строка
12,0,25,31,749 -48 строка
есть текстовый файл, но в нем несколько строк - например 48), как считать данные из последней строки -48й, 47й, 46й итд..
Если речь идет о файле и файловой системе - то почти всегда он читается целиком от начала, просто часть данных пропускается по определенному сценарию. Тут надо знать: каким символом заканчивается строка и по нему отсчитывать нужное количество строк, достигнув которое начинаем помещать строчки в массив переменных.
ок, идею я понял, спасибо.
Попробовал ваш код применительно своей задачи. У меня несколько строк, я подумал, что с помощью вашего кода смогу сделать массив всех своих данных, так как считываются все строчки по байтам, однако почему-то максимум что удается занести в массив outarray[t] - 40 значений. Подскажите, как исправить, чтобы заносились все данные из всех строк?
0,0,26,27,756. ----заносятся
7,0,23,30,757. ----заносятся
8,0,14,34,755. ----заносятся
8,30,20,33,755. ----заносятся
9,0,22,29,755. ----заносятся
9,30,22,30,755. ----заносятся
10,0,22,30,755. ----заносятся
10,30,23,30,755. ----заносятся
11,0,23,30,755. ---------уже не заносятся
11,30,23,30,755. ---------уже не заносятся
12,0,23,29,755. ---------уже не заносятся
Попробовал ваш код применительно своей задачи.
То, что в массив попадает всего ВОСЕМЬ строк - ни на какие мысли не наталкивает? "Переменная типа char занимает 1 байт памяти". Скорее всего отсюда и ногти растут... Объявите длину массива с запасом - и посмотрите что получится.
Здравствуйте, подскажите пожалуйста, как реализовать данный алгоритм:
Есть файл на SD-карте следующего вида:
1234567
9999999
3231321
1234123
И так далее. Т.е. набор чисел в столбик. С RFID ридера приходят данные, типа "0000000" необходимо сравнить входящее число со всеми числами из файла на флешке. Если есть совпадение, то сделать определенные действия, если нет - то другие действия.
Вся сложность сводится к тому, что не удается реализовать считывание с карты каждой строки в массив.
С уважением, Евгений. Знающих людей прошу помощи.
написал когд парсинга данных из файла на флешке
void SD_recepies() { if (!SD.begin(chipSelect)) { myGLCD.setFont(SmallFont); myGLCD.print("Card failed, or not present", CENTER, 50); } int h = 0; int q=0; char array[10][100]; char *buffer; char symbol2 = 0; File configFile = SD.open("config.txt"); if (configFile) { //Serial.println("configFile.txt open OK"); while (configFile.available()) { // считываем байт входящего файла symbol2 = configFile.read(); if (symbol2==';') {array[q][h]='\0'; q++; h=0; kol_receptov++;} else {array[q][h] = symbol2; h++;} delay(1); } configFile.close(); } char *p; byte t; for (int j=0; j <kol_receptov ; j++) { t = 0; for( buffer = strtok_r(array[j], ",", &p); buffer; buffer = strtok_r(NULL, ",", &p) ){ recepies[j][t]=buffer; t++;} } }Храню данные в следующем формате
Всем привет) Четвертый день мучаюсь с кодом... Подскажите в чем ошибка.
Задача проекта: есть файл ardu.txt на флешке. В нем записи типа:
10;h
20;l
30;h
E
Числа - время в секундах включений/выключений (в данном случае светодиода на ардуино), "h" и "l" - команды (HIGH, LOW), E - символ конца файла.
Нужно включать, или выключать светодиод по времени, прописанному в файле (потом, по аналогии, добавлю еще светодиоды... пока так)
#include <SPI.h> #include <SD.h> File myFile;//инициализируем myFile char PinCommand;//переменной задается команда на ВКЛ/ВЫКЛ на пине 13 long ActionTime;//переменной задается время ВКЛ/ВЫКЛ на пине 13 int i = 0;//переменной задается объем буфера чтения char End = 'E';//пееменной задается символ конца файла char buffer []{};//инициализируется буфер void setup() { pinMode(13, OUTPUT);//задается канал на светодиод Serial.begin(9600);//задается Serial-соединение unsigned long CurrentTime = millis()/1000;//переменной CurrentTime задается текущее время в секундах myFile = SD.open ("ardu.txt", FILE_READ);//задаем значение myFile //пока не будет доступно Serial-соединение ничего не произойдет... while (Serial.available()) { //если myFile открыт, то... if (myFile) { //если myFile доступен, то... while (myFile.available()) { //если при чтении myFile текущий символ не равен End ("E"), то while (myFile.read() != End) { //если при чтении myFile текущий символ это не символ конца строки, то... if (myFile.read() != '\0') { buffer [i++] = myFile.read();//заносим в буфер читаемый символ } else { sscanf (buffer, "%[^';'],%s", &ActionTime, &PinCommand);//иначе разбираем буфер на ActionTime и PinCommand } //если текущее время = времени в текущей строке в файле, то if (CurrentTime == ActionTime) { switch (PinCommand) { case 'h': digitalWrite(13, HIGH);//если PinCommand = h, то включаем светодиод break; case 'l': digitalWrite(13, LOW);//если PinCommand = l, то выключаем светодиод break; } } } } } } }не могли бы вы помочь с моим кодом нужно считать значение из файла( последнее) ли бо же просто всегда после считования стирать, потом добавить к етому значению другое записать, и так повторять.
#include <SD.h>02#include <SimpleTimer.h>03File myFile;04inttimewalkcurrent=0;05longintglobalruntime;06SimpleTimer timer2;07voidsetup(){08timer2.setInterval(1000, timerrunglobal );0910{11Serial.begin(9600);12Serial.println(SD_CHIP_SELECT_PIN);//5313Serial.println(SPI_MOSI_PIN);//5114Serial.println(SPI_MISO_PIN);//5015Serial.println(SPI_SCK_PIN);//5216while(!Serial) {17;18}1920voidtimerrunglobal(){21timerrunglobal++;22}23voidrefreshsd(){2425pinMode(53, OUTPUT);26myFile = SD.open("time.txt");27if(myFile) {28while(myFile.available()) {29globalruntime=myFile.read();30}31myFile.close();32}33longintprof=globalruntime;34globalruntime=prof+timerrunglobal;35timerrunglobal==zero;36SD.remove("time.txt");37pinMode(53, OUTPUT);38myFile = SD.open("time.txt", FILE_WRITE);39if(myFile) {4041myFile.write(globalruntime);42myFile.close();4344}}45voidloop(void)46{4748unsignedlongcurrentMillis = millis();49if(currentMillis - previousMillis >= interval) {50previousMillis = currentMillis;51refreshsd();52}535455constlonginterval = 0; }5657Serial.println("");58Serial.println(globalruntime);59Serial.println("");60}доброго времени суток...
у мения тоже самое интересуеть... помогите пожалуйста...
в тхт фаиле в ручную записанны строки пример 0123456789... нужно найдти определную строку и делат какието деиствия пример нужно искать 0123456789 и при совпадении выдат сообшения например "Ok".
для тестирования Arduino подключен теминалу и спомошю терминала ввожу 10 цифр и при совпадении выдает сообшение "Ok" при отсувствии "Error"
hard виглидить так SD Card+Arduino+Uart
я мало знаю програмировании а то не беспокоил
заранее благодаоень...