Помогите с чтение с SD карт в двумерный массив

Jacks_d
Offline
Зарегистрирован: 31.12.2011

Сейчас работает так: отправляю в км порт последовательность, в которой есть команда соответствиющая установке будильника, время включения будильника и на какой день недели он устанавливается. После изменения данных в массиве записываю  этот массив на карту памяти. Ниобходимо читать из карты настройки и записывать в массив при старте ардуины

В общем это настройки будильника: 

byte alarm[7][8] = {{23, 28, 1, 2, 23, 29, 3, 4},
                    {0, 29, 12, 13, 14, 15, 16, 17},
                    {20, 21, 22, 23, 24, 25, 26, 27},
                    {30, 31, 32, 33, 34, 35, 36, 37},
                    {15, 33, 42, 41, 15, 34, 46, 47},
                    {50, 51, 52, 53, 54, 55, 56, 57},
                    {60, 61, 62, 63, 64, 65, 66, 67}};

Вот так пишу на SD карточку, покрайней мере для первой строки, т.е. понедельника:

     SD.remove("Setup/alarm.txt");
     myFile = SD.open("Setup/alarm.txt", FILE_WRITE);
     if (myFile) 
         {
          myFile.print(alarm[0][0]); myFile.print(";");
          myFile.print(alarm[0][1]); myFile.print(";");
          myFile.print(alarm[0][2]); myFile.print(";");
          myFile.print(alarm[0][3]); myFile.print(";");
          myFile.print(alarm[0][4]); myFile.print(";");
          myFile.print(alarm[0][5]); myFile.print(";");
          myFile.print(alarm[0][6]); myFile.print(";");
          myFile.println(alarm[0][7]);
          myFile.close();
          
          Serial.println("done.");
         }

В файле получаю вот такую строку: 

23;22;1;2;23;29;3;4

Вот так читаю его в ком порт:

 myFile = SD.open("Setup/alarm.txt");
     if (myFile) 
        {
         Serial.println("alarm.txt:");
         myFile.close();
         }

Умнейшие, помогите пожалуйста! Как стоит записывать в файл и как читать? была здесь подобная тема, с чтением в массив, но сейчас не смог найти( 

Как разделять часы и минуты разницы нет, главное чтоб работало. Думал, сделать как вариант дописывания нуля перед теми значениями которые меньще 10, но получится сильно грамоздко, записывать за 7*8 тактов, как то не то, учитывая что это будит далеко не единственный массив. или просто подскажите как сделать расделение прочитанового из файла чтобы можно было записать в массив.

 

 

leshak
Offline
Зарегистрирован: 29.09.2011
Ну, во первых не линиво же было вам набирать все эти принты... IMHO писать лучше так (хотя ваш вариант тоже полностью рабочий)
 
for(int j=0;j<8;i++){
  myfile.prtin(alarm[0][j]); myFile.print(";");
}
или, что-бы уже два раза не вставать, и выводить все строчки в файл, а не только первую
 
 
for(int i=0;i<7;i++){ // бежим по строкам
   for(int j=0;j<8;j++) { // бежим по  элементам строки
       myfile.print(alarm[i][j]); myFile.print(";");
   }
   myfile.println(); // перевод строки
}
 

 Ну, а дальше (читать) уж очень сильно зависит от того что в каком виде нужно отправить это в serial. Кто там читать будет прога или человек? Если прога, то возможно и сохранять нужно чуть-чуть по другому (что-бы не танцевать с конвертациями int<->string), если нужно "отправить копию файла в serial" - чуть-чуть по другому. Просто вычитывам по байту с помощью http://arduino.cc/en/Reference/FileRead и отправляем в serial

Jacks_d
Offline
Зарегистрирован: 31.12.2011

 leshak, я вас понял, но мне нужно впихнуть чтение в void setup(), чтобы читалось только при запуске, а писалось только при изменении, насколько я понял for  будит писать по одной ячейке за один проход цикла, а для void setup() это не подходит, может и ошибаюсь, просто вообще програмирую только с начала этого января.

Сейчас меня больше итерисует как писать в двумерный массив alarm[][] получая инфу с SD карты, точнее как ее делить по ячейкам. Можно дописывать ноль перед теми значениями которые меньше 10 при записи на SD карту, и там по накатанному. А каким способом писать на карточку как то всеравно.

В общем подскажите как оптимальнее вписать за один такт в массив с SD карты!

leshak
Offline
Зарегистрирован: 29.09.2011
for(int i=0;i<7;i++) // бежим по строкам
   for(int j=0;j<8;j++)  // бежим по элементам строки
      myfile.write(alarm[i][j]); 
   

 >leshak, я вас понял, но мне нужно впихнуть чтение в void setup()

Значит не поняли. Мой первый пример - практически полный аналог ваших строчек с 5 по 12-тую включительно. Разница только в том, что у вас в итоге после последнего элемента в строке не будет точки с запятой, а у меня будет.

Если же перед  myFile.print(";"); написать if(j!=7) то получится полный аналог.

И без раницы где этот код использовать. В loop или setup. Между ними разница только в том, что setup вызывается один раз при старте контроллера, а loop - бесконечно. Поэтому то что вам нужно "выполнить" один раз - помещаете в setup, а что "много раз" - в loop. Но "что именно выполнить" - ограниченно только вашей фантазией.

Если задача "прочитать в массив", то я бы пожертвовал "читаемостью файла для человека" (если его открыть в Блокноте там будут кракозяблы), но зато упростился-бы код. Нужно, всего-лишь, писать в файл не с помощью  print, а с помощью write и выкинуть все точки с запятой и переводы строк - они нужны для человека.

Итак пишем массив:

for(int i=0;i<7;i++) // бежим по строкам
   for(int j=0;j<8;j++)  // бежим по элементам строки
      myfile.write(alarm[i][j]); 

Читаем массив

for(int i=0;i<7;i++) // бежим по строкам
   for(int j=0;j<8;j++)  // бежим по элементам строки
      alarm[i][j]=myfile.read(); 

>записывать за 7*8 тактов

Если вы хотите оперировать "тактами", то вам нужна не ардуина а голый камень и ассемблер. И то 7*8 тактов у вас не получится. Далеко не каждая команда выполняется за один такт. Только самые базовые. Причем под "командой" подразумевается машинная команда, а не "строка кода на C++". А уж работа с SD картой это вообще тысячи тактов. Не говоря про то что сама операция записи, по меркам контроллера это жутко медленно ее ждать ее завершения это почти века. Когда вы пишете file.Open - поверьте это далеко не один такт :)

Вернемся к нашим баранам.  Данные примеры примеры предполагают, что читается и пишется массив одинаковой длины. То есть если записали 7x8, то и читать нужно 7x8, а не 8x7 или 9x8.

В данных примерах и записывается и читается "по одному байту". Запись можно немного "ускорить", если вы посмотрите на http://arduino.cc/en/Reference/FileWrite то у нее есть вариант вызова, когда передается не "один байт", а буффер (массив) и его длина. А вот вычитывать, все равно прийдется "под одному".

Jacks_d
Offline
Зарегистрирован: 31.12.2011

 Ну про for, я таки понял сразу, сам использую такой метод для сравнения тоже двумерных масивов и выводил двумерный массив в serial.ptint, когда искал ошибки в коде.

С myfile.write буду сейчас пробовать. К тому же, вы скорее правы, ведь все же использую библиотеки... просто мой выбор скорее с практичной стороны уменьшения вычеслений и просто тыкать в нужное положение данных, а не вычислять их положения, чем со стороны объема кода, пока мой код занимает 24 Кб  из 256 у меги. Мне так казалось правильным с точки зрения скорости, покрайней мере с этим я столкнулся при случае когда изменяется яркость 12 светодиодов и в промежутке извенения поступает другая команда, на выполнение других действий, например снятие температуры с DS18B20. К тому же, каждый раз будит открываться запись на SD карту и закрываться, пока не пройдет обв for. В моем случае, вроди как за один заход открытия/закрытия. В общем пока добьюсь нормальной работы, а потом буду думать над упрощением жизни, если это будит необходимо.

Кстати, я так понял с SD картами вы работали, тут ситуация такая, на FAT32 скорось записи и чтения гораздо медленее чем на FAT16. Столкнулся с этим когда запустил цикл на постоянную запись и чтение, и в serial monitor-е скорость таки кординально отличима на глаз!

Есть еще вопрос. Как правильно будит выйти из цыула for, примерно так:

for(int i=0;i<7;i++) // бежим по строкам
   for(int j=0;j<8;j++)  // бежим по элементам строки
      myfile.write(alarm[i][j]);

if(j==7)
  {
   break;
   }

Просто если не выйти из цикло то у меня все уйдет в бесконечный цикл, а поменять условие входа в цикл я не могу, т.к. слишком много переделывать, и это будут скорее костыли..

 

leshak
Offline
Зарегистрирован: 29.09.2011

 >В моем случае, вроди как за один заход открытия/закрытия.

Так и в моем же случае тоже самое. Перез циклом открыли, после - закрыли. Еще раз, это же аналог вашего кода. Просто написанный без использования copy-paste.

>Кстати, я так понял с SD картами вы работали

Неа. Просто почитал документацию. На этом форуме 80% ответов можно дать просто "заглянув в доки", еще 10% нужно погуглить, 5% подумать и только осташиеся пять "нужно копаться или знать ответ заранее".

Ну то есть с файлами-то я работал, только на большом компе. Но ведь "алгоритмы"/логика не отличаются. Те же объекты, те же методы. Открыть/закрыть. Записать. Просто смотришь в доку и подбираешь какие функции лучше сделаю что-ты хочешь. Из тех что доступны. В данном случае, по крайней мере пока, я не вижу ничего "ардуино" или SD-картно специфического. Работа с массивами и потоками.

> В общем пока добьюсь нормальной работы, а потом буду думать над упрощением жизни, если это будит необходимо.

А вот это очень здраво. "Преждевременная оптимизация" это один из грехов :) Правда нужно старатся код писать так, что-бы потом его было не трудно менять, в том числе и оптимизировать. И вот в этом случае "копипас-ты" ни к чему хорошему не приводят. Вот в моем примере, нужно было поменять print на write - сменил в одном месте. А у вам пришлось-бы в 8 ми местах менять. А если бы вы так сохранили полностью массив, то в 56-ти. Я конечно понимаю что есть "глобальная замена", но если поменять нужно что-то сложней чем "слово" на "слово" - она не поможет.

По хорошему, вообщем эти записи/чтения нужно вынести в отдельные функции типа saveArray(fileName) и loadArray(fileName). Тогда вы сможете менять их логику, оптимизировать, подкручивать форматы записи не затрагивая остальной скетч.

>Есть еще вопрос. Как правильно будит выйти из цыула for

http://arduino.ru/Reference/Break  и arduino.ru/Reference/Continue в зависимости от того что вам нужно.

 

ну и посмотрите еще http://arduino.ru/Reference/While и arduino.ru/Reference/DoWhile . Возможно они больше подойдут в вашей ситуации чем for. Раз возник такой вопрос.

>примерно так:

да примерно так. Ну разве что break, так как он один оператор который нужно выполнить при j==7 можно было не оборачивать в {} (но это не ошибка).

А вот myfile.write и if(j==7) уже нужно было "совместно обернуть". Это уже ошибка. Я не "оборачивал" write потому что он единственным оператором в теле цикла. Раз вы захотели туда еще что-то добавить, то нужно "обернуть". А то у вас получилось. Отдельно цикл, отдельно if(j==7)break;  То есть вы попытались выйти из цикла не находясь в нем. В этом случае break; скоре всего будет интерпретирован как "выйти из текущей функции", а не цикла.   Правда и до такой катастрофы-бы дело не дошло. Так как j локальная переменная внутри цикла, а if(j==7) у вас получился "вне цикла", то компилятор вам бы сразу сказал "а не знаю я такой переменной j" на строчке if(j==7)

Вообщем читайте arduino.ru/Reference/Braces

Ну и смысл делать break; когда после него ничего нет, да и условие break совпадает с условием выхода из цикла - от меня ускользает. Разве что из подхода "кашу маслом не испортишь".

>Просто если не выйти из цикло то у меня все уйдет в бесконечный цикл

Это я тоже не понимаю. Но, видимо, вы говорите про какой-то другой свой код.

Кстати break; это "синтаксически сахар" (просто что-бы компкатней писать), вполне можно обходится и без него. Только if-ми или химича с переменными входящими в условие for-a (но эту "химию" стоит делать только в образователь целях, что-бы лучше понять for , в реальном коде за такое руки отбивают, так как поведение кода становится "очень не очевидно").

А вообще я бы советовал отложить, пока, реальную задачу и поигратся разобратся с управляющими операторами, синтаксисом, типами. Писать поэму не ознакомившись с буквами - немного странно. Хотя-бы прочитайте бегло "что имеется в наличии". А потом уже, когда оно потребуется вспомните что "где-то было такое" и "где нужно почитать/углубится".

Почитайте книжечки по C++, JAVA, C# на большом компе. Почитайте книжки типа "Идеальный код", Рефакторинг и т.п. Задачей выработки "правильного стиля" лучше начать заниматся как можно раньше ( эх.... а ведь мне тоже говорили :), не слушал, потом намного тяжелей).

А то получите такой код, который от которого самого будет тошнить. И "поменять не могу, бо слишком долго переделывать" - первые звоночки этого. Того что вы уже "не можете нормально управлять кодом". Причем кода у вас сейчас - максимум несколько сотен строк.

У меня например, в текущем домашем хобби-проекте-выходного-дня (на компе, не ардуино) 5476 строк кода. И я спокойно могу поменять любую часть и любую логику. Без страха что "все остальное навернется". И это вообщем-то "очень маленький проект", который только начался. (вообщем "сам себя не похвалишь - сидишь как оплеванный" ;)  . Потому что старатся писать код который "легко поддерживать", в реальной жизни намного важней чем "пытаться выжать лишний такт на каждой операции". В микроконтроллерах это правило конечно немного "отступает", но все равно старатся нужно.

 

Jacks_d
Offline
Зарегистрирован: 31.12.2011

 Написал вот так:

SD.remove("Setup/alarm.txt");
     myFile = SD.open("Setup/alarm.txt", FILE_WRITE);
     if (myFile) 
         {
          for(int i=0;i<7;i++) // бежим по строкам
             for(int j=0;j<8;j++)  // бежим по элементам строки
                {
                 if(alarm[i][j] < 10) // если часы или минуты меньше 10, то пишем перед значением 0
                    {
                     myFile.print(0);
                      }
                  myFile.print(alarm[i][j]);
                 }
           myFile.close();
         }

Все получается нормально, вроди относительно быстро. Дописывание нуля неред цифрами меньше 10, необходимы чтобы потом проще было писать в массив, и не смешать данные. 

leshak
Offline
Зарегистрирован: 29.09.2011

 Ну если цель сделать, все-таки "человекочитаемый" .txt файл, то да все выглядит здорово. И решение с "пишем 0 что-бы потом было легче читать" - тоже здравое. Действительно логику чтения это существенно упростит. 

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

Ну и, чисто для красоты, строчки 08-11 написал-бы "в одну строчку" и убрал-бы как необязательные фигурные скобки (строки 09 и 11).

Правда не забудте, при чтении. Что раз вы писали в файл print-том, то в файле у вас будет не значение записанного байта, а код его символа. И read прочитает этот код.

То есть если вы сделаете, например, myFile.print(3), а потом прочитаете его byte bt=myFile.read(); , то в bt будет не 3, как возможно вы ожидаете, а 51 

:)  что-бы в нем было "то шо нужно", нужно вычитывать так byte bt=myFile.read()-'0';

Jacks_d
Offline
Зарегистрирован: 31.12.2011

>А вот это очень здраво. "Преждевременная оптимизация" это один из грехов :) Правда нужно старатся код писать так, что-бы потом его было не трудно менять, в том числе и оптимизировать. И вот в этом случае "копипас-ты" ни к чему хорошему не приводят. Вот в моем примере, нужно было поменять print на write - сменил в одном месте. А у вам пришлось-бы в 8 ми местах менять. А если бы вы так сохранили полностью массив, то в 56-ти. Я конечно понимаю что есть "глобальная замена", но если поменять нужно что-то сложней чем "слово" на "слово" - она не поможет.

Когда начал учился, и не использовал еще массивы, то мне помогало копирование участка кода в блокнот, и замена в этом куске)

>Это я тоже не понимаю. Но, видимо, вы говорите про какой-то другой свой код.

Таки свой, правильно, вот:

 if ((inserial[3]*10 + inserial[4]) > 1 && (inserial[3]*10 + inserial[4]) < 6 )// устанавливаем будильники
    { 
     alarmX = inserial[3]*10 + inserial[4]; //номер будильника
     alarmHX = ( alarmX - 2 ) * 2; // место установки часа будильника в матрице
     alarmMX = ( alarmX - 2 ) * 2 + 1; // место установки минут будильника в матрице
     alarmY = inserial[9] - 1; // днень недели будильника 
     alarm[alarmY][alarmHX] = inserial[5] * 10 + inserial[6]; // устанавливаем в матрицу час будильника
     alarm[alarmY][alarmMX] = inserial[7] * 10 + inserial[8]; // устанавливаем в матрицу минуты будильника
     
     SD.remove("Setup/alarm.txt");
     myFile = SD.open("Setup/alarm.txt", FILE_WRITE);
     if (myFile) 
         {
          for(int i=0;i<7;i++) // бежим по строкам
             for(int j=0;j<8;j++)  // бежим по элементам строки
                {
                 if(alarm[i][j] < 10) // если часы или минуты меньше 10, то пишем перед значением 0
                    {
                     myFile.print(0);
                      }
                  myFile.print(alarm[i][j]);
                 }
          myFile.close();
         Serial.println("done.");
         }
     }

Что читать нужно, я согласен и читаю, вообще изначально думал, что меня ткнут в подобную задачу, 2 месяца назад ее сдесь видел, но сейчас найти не смог(

Почитав книжки, и ничего не поняв, да и на некоторых своих примерах понял что мыслю я совсем не как програмист и мне необходимо наглядное проявление кода, иногда почти каждую строчку принтил, да и програмированием до этого вообще не занимался, для себя решил делать так:

1. Учусь на примерах из книжки, кстати очень помогли видео уроки джереми блума с переводом.

2.  Дальшес играюсь с примерами в доль и поперек.

3. А вот сейчас собираю потихоньку в кучу, допиливая то что не мог сделать по отдельности

leshak
Offline
Зарегистрирован: 29.09.2011

 Да и еще, в байт-то помещаются значения от нуля до 255. Поэтому если нет 100% уверенности что в массиве никогда не будет лежать ничего >99, то при <10 нужно дописывать  00, а при if(arg[i][j]<100 && arg[i][j]>9) один ноль.

Jacks_d
Offline
Зарегистрирован: 31.12.2011

 Если использовать:

Итак пишем массив:

1
for(int i=0;i<7;i++) // бежим по строкам
2
   for(int j=0;j<8;j++)  // бежим по элементам строки
3
      myfile.write(alarm[i][j]);

то ничего не выходит, с вот такой ошидкой:

sketch_feb26b.cpp: In function 'void loop()':
sketch_feb26b:276: error: 'myfile' was not declared in this scope
а с print все без запинок

leshak
Offline
Зарегистрирован: 29.09.2011

 >Когда начал учился, и не использовал еще массивы, то мне помогало копирование участка кода в блокнот,

Программист должен быть ленив. Если какая-то работа "рутинна", то нужно найти способ возложить ее на компьютер :)

>Таки свой, правильно, вот:

Ну тут потребности в break; - я не вижу. И шансов "войти в бесконечный цикл" - тоже. Разве что вы где-то внутри цикла начнете менять i,j но это как раз и будет "за что нужно бить по рукам".

>мыслю я совсем не как програмист

Наоборот. В точности. "Познание через примеры" и "пощупать" это, IMHO вообще единственный способ научится программить. Лекции и "только чтение" точно ничего не дадут.  Просто по вашим вопросам возникло впечатление что вы чтением "вообще пренебрегаете", но видимо это ошибочное впечатление.

А финт с "дописыванием нуля" это вообще типично программерский ход мышления. Может вам он и кажется "очевидным", но поверте, для среднего человека это "мозговой выкрутас" который в голову не пришел бы.

> для себя решил делать так

Ни по одному пункту нельзя возразить. Все-бы так подходили к обучению программинга :)

leshak
Offline
Зарегистрирован: 29.09.2011

 >то ничего не выходит, с вот такой ошидкой:

Ну само-собой. Я же дал "кусочек кода", а не скетч целиком. Файл-то открыть надо и закрыть тоже нужно. Это кусок записи должен был заменить строки 05-12 из вашего первого сообщения, во  втором кусоке кода. А все что "вне их" и так "подразумевалось". Я же упоминал что это "аналог ваших строк с myFile.print", а  не "аналог всего вашего примера". Я только запись и показал. Открытие/закрытие файла вы же, вроде уже сами сделали. 

Да и тут, раз компилятор сказал что 'myfile' was not declared (переменная myfile не определена), то логично предположить что ее нужно объявить где-то раньше (ну и потом закрыть).

Да и в #8 вы показали вполне-себе рабочий пример. Так что я удивлен вашим вопросом. Возможно уже таки "пора спать".  Обоим ;)

Кстати вы же, когда давали пример в #8 тоже "где-то за кадром" оставили объявление массива inserial, да и сами setup(), loop() не видны :)

Jacks_d
Offline
Зарегистрирован: 31.12.2011

 Кстати вспомнил почему хотел сделать запись в файл за один цикл прохода всего кода.

if ((inserial[3]*10 + inserial[4]) > 1 && (inserial[3]*10 + inserial[4]) < 6 )// устанавливаем будильники
    { 
     alarmX = inserial[3]*10 + inserial[4]; //номер будильника
     alarmHX = ( alarmX - 2 ) * 2; // место установки часа будильника в матрице
     alarmMX = ( alarmX - 2 ) * 2 + 1; // место установки минут будильника в матрице
     alarmY = inserial[9] - 1; // днень недели будильника 
     alarm[alarmY][alarmHX] = inserial[5] * 10 + inserial[6]; // устанавливаем в матрицу час будильника
     alarm[alarmY][alarmMX] = inserial[7] * 10 + inserial[8]; // устанавливаем в матрицу минуты будильника
     
     SD.remove("Setup/alarm.txt");
     myFile = SD.open("Setup/alarm.txt", FILE_WRITE);
     if (myFile) 
         {
          for(int i=0;i<7;i++) // бежим по строкам
             for(int j=0;j<8;j++)  // бежим по элементам строки
                {
                /* if(alarm[i][j] < 10) // если часы или минуты меньше 10, то пишем перед значением 0
                    {
              //       myfile.write(0);
                      }*/
                  myfile.write(alarm[i][j]);
                 }
          myFile.close();
         
          Serial.println("done.");
         }

 

После прихода команды на изменение настройки будильника запустит if в сторке 01, и сразу же прийдет другая команда которая не входит в условие if в строке 01, то на карточку у меня не допишется весь массив!

Jacks_d
Offline
Зарегистрирован: 31.12.2011

>Ну само-собой. Я же дал "кусочек кода", а не скетч целиком. Файл-то открыть надо и закрыть тоже нужно. Это кусок записи должен был заменить строки 05-12 из вашего первого сообщения, во  втором кусоке кода. А все что "вне их" и так "подразумевалось". Я же упоминал что это "аналог ваших строк с myFile.print", а  не "аналог всего вашего примера". Я только запись и показал. Открытие/закрытие файла вы же, вроде уже сами сделали. 

само сабой так и сделал, просто заменил ptint на write, и другие комбинации пробывал, нихочет и все, может библиотека такая, просто я уже боюсь их менять, т.к. несколько дней убил на поиски совместимых в одной куче для ds1307, 1-wire, SD, Wire(I2C) под Arduino IDE 1.0 и еще нужно прикрутить Ethernet

>Да и тут, раз компилятор сказал что 'myfile' was not declared (переменная myfile не определена), то логично предположить что ее нужно объявить где-то раньше (ну и потом закрыть).

таки объявлена как глобальная, почему и не понял что происходит, просто забил

Да и в #8 вы показали вполне-себе рабочий пример. Так что я удивлен вашим вопросом. Возможно уже таки "пора спать".  Обоим ;)

Кстати вы же, когда давали пример в #8 тоже "где-то за кадром" оставили объявление массива inserial, да и сами setup(), loop() не видны :)

За кадром только для глобальных переменных уже получилось 125 строк), полностью уже перевалило за 500, и по задумке это еще очень далеко до конца)

leshak
Offline
Зарегистрирован: 29.09.2011

 Ну, во первых, написание логики в наждне на то "одна команда УСПЕЕТ выполнится раньше чем прийдет следующая" - вкорне неверна.

Какую бы быструю реализацию вы не написали, всегда есть шанс что следующая прийдет еще быстрее. Поэтому нужно организовывать отдельную "очередь команд" и одна логика "ложит команды в эту очередь", а другая их "по одной выполняет". Тогда последовательный порядок их выполнение будет гарантирован. 

Во вторых: откуда у вас, в микроконтроллере появится вторая команда? Это же не PC, тут многопоточности нет. Весь код выполняется последовательно. Пока вы не отработаете этот if о существовании "новой команды" вы просто не узнаете.

Псевдо-многопоточность, может появится только при использовании прерываний. Но, если вы собираетесь в функцию обработки прерывания всадить всю эту логику "записи", то "ох-хо-хо". У вас скетч будут работать "от левой пятки и фазы луны". Стабильности вы не сможете добится. Но работа с прерываниями - это, уж извините, не сегодня.

Общий подход, вратце, таков: в функции обработчике - минимальное количество кода. только регистрация самого факта "прерывание прозошло". Взведение какого-нибудь "флага-переменной", фиксация времени этого события - и все. Нужно выйти из обработчика "как можно скорее". У уж в loop() мы спокойно и не спеша, крутясь посматриваем на эти "флаги" и если кто-то из них оказался "взведенным" мы выполняем "длинную операцию" (сохранение, отсылка в serial и т.п.)

leshak
Offline
Зарегистрирован: 29.09.2011

 >может библиотека такая

это вряд ли. Если бы "библиотека не такая", то оно бы без этих циклов не компилировалось.

>просто я уже боюсь их менять

Для этого существуют системы "контроля версий". типа git, svn, mercurial . Помогают следить за "изменениями в исходниках", дают возможность "откатится на любой предыдущие состояние кода (можно менять что угодно безбоязненно) и т.п. И еще много чего помогающего в "управлении исходниками".

Но это на будущие. Сейчас, боюсь, разбирательство с ними вообще "взорвет мозг".

>таки объявлена как глобальная, почему и не понял что происходит

спать :) чудес не бывает. либо объявлена "не глобально", либо где-то скобку потеряли, либо еще что-то.

Но вообще, использование глобальных переменных - не самый лучший стиль программирования. Хотя, в ардуино, довольно распространненый. Просто потому что скетчи, как правило, очень небольшие и негатив от подобного "стиля" не успевает проявить себя в полную силу.