Официальный сайт компании Arduino по адресу arduino.cc
Не корректно работает SD карта
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Пнд, 17/09/2018 - 20:26
Здравствуйте. У меня ардуино mega 2560 с SD шилдом. Подключен он по стандартной SPI шине. Проблема в том что данные на карту пишутся только один раз за время работы контроллера. В первый раз запись проходит хорошо, а в последующие контроллер не видит карту. Стоит только перезагрузить контроллер все начинается по кругу. В чем может быть причина такого поведения?
void LogingWorkOnSD(String text){ // Ф-ция записи логов на карту byte LOGING_TO_SERIAL = EEPROM_int_read(E_LOGING_TO_SERIAL); digitalWrite(SD_VCC_RUN, HIGH); digitalWrite(SD_CARD_CS, HIGH); _delay_ms(50); if (SD.begin(SD_CARD_CS)) { // Если карта доступна if (SD.exists("logs.txt")) { // Если файл существует ErrorSDcard = 0; // Сбрасываем ошибку и пишем данные SDcard = SD.open("logs.txt", FILE_WRITE); // Открываем файл if(SDcard){ if(LOGING_TO_SERIAL == 1 || LOGING_TO_SERIAL == 3){ Serial.print(F("log file open...")); } SDcard.print(time.gettime("d-m-Y, H:i:s")); SDcard.print(F(" ")); SDcard.println(text); if(LOGING_TO_SERIAL == 1 || LOGING_TO_SERIAL == 3){ Serial.print(F("written done...")); } SDcard.close(); // закрываем файл if(LOGING_TO_SERIAL == 1 || LOGING_TO_SERIAL == 3){ Serial.println(F("file is closed")); } _delay_ms(200); } else{ if(LOGING_TO_SERIAL == 1 || LOGING_TO_SERIAL == 3){ Serial.println(F("log file not open")); } StatusLED(11); // Световая индикация ошибки } } else { // Создаем файл if(LOGING_TO_SERIAL == 1 || LOGING_TO_SERIAL == 3){ Serial.print(F("creating LogFile.csv...")); } SDcard = SD.open("logs.txt", FILE_WRITE); // Пишем начальные данные (заголовки столбцов) } } else { // Если карта не доступна if(LOGING_TO_SERIAL == 1 || LOGING_TO_SERIAL == 3){ Serial.println(F("SD-card not found")); } ErrorSDcard = true; // Ошибка карты памяти StatusLED(11); // Световая индикация ошибки } SPI.end(); pinMode(51, OUTPUT); digitalWrite(51, LOW); digitalWrite(SD_CARD_CS, LOW); digitalWrite(SD_VCC_RUN, LOW); }
Очень, нет, ОЧЕНЬ сомнительное решение - каждый раз в начале функции инициализировать SD, а в конце - прибивать SPI. Такое себе, вот он и источник проблем, собственно.
Немного не понял где в начале инициализируется SD. У меня SD_VCC_RUN включает питание на SD карте, а втора поднимает SS пин на высокий уровень.
digitalWrite(SD_CARD_CS, HIGH);
digitalWrite(SD_VCC_RUN, HIGH);
еще и каждом проходе лупа выдавать на карту питание и снимать его. Странное решение, как минимум. Кстати, правильнее уж тогда было бы сначала поднять CS у карты, а потом выдавать питание. Ну уж потом ставить задержку.
Немного не понял где в начале инициализируется SD.
SD.begin
Эта ф-ция не в loop висит. Она вызывается только при записи данных на карту.
В чем особенность сначала поднятия CS а потом подачи питания? Попробовал так сделать, ничего не изменилось в поведении ф-ции.
Так SD.begin же вроде проверка на доступность карты. По крайней мере я ее так использую. Можно как нибудь по другому проверять на доступность карты?
Вопрос: зачем такие заморочки, объясните, плз? Вы рассыпали граблей, и теперь героически пытаетесь их обойти, имхо. Если поясните, к чему все эти танцы - будет понятнее, что делать дальше.
Мне кажется что перед тем как работать с картой нужно знать а она вообще в наличии то есть. Если есть, то уже проверяем есть ли файл и дальше либо пишем в него, либо создаем и пишем.
Я не про то: зачем вам управление питанием модуля SD, и прибивание SPI.end каждый раз при записи на карту?
Ну управление питанием чтобы экономить батарею. А SPI.end для теста воткнул, думал поможет решить проблему, не помогло.
Управление питанием там простое, просто поднимается нога EN на DC-DC. Саму карту эта процедура не трогает.
Что вы собрались экономить по питанию на SD-карте, собственно? Вот правда - что? Может, я чего упустил?
ну 2-3 ma экономлю. SD же не одна на плате. Есть еще экран, шаговые моторы, ESP8266. Вся переферия отключается по питания во время простоя и контроллер уходит в сон, а будится либо по прерываниям либо по таймеру.
Строка 37 внушает подозрения: файл открывается, но - не закрывается нигде ниже. Нашёл также вот такую тему про энергосбережение и SD: https://forum.arduino.cc/index.php?topic=149504.0
Да, пропустил закрытия файла.
Добавил. Еще убрал из кода выключение питания SD, теперь она всегда включена. Но это не помогло. Мне кажется что какой то косяк в шине SPI, ведь один раз карточка срабатывает и записывает файл, а дальше не может. Может шина остается всегда занятой?
Да, пропустил закрытия файла.
Добавил. Еще убрал из кода выключение питания SD, теперь она всегда включена. Но это не помогло. Мне кажется что какой то косяк в шине SPI, ведь один раз карточка срабатывает и записывает файл, а дальше не может. Может шина остается всегда занятой?
Управление питанием там простое, просто поднимается нога EN на DC-DC.
Да там одна микруха копеечная стоит, MIC5219-3.3 :) Проблема точно не в питании. Контроллер не отрабаотывает SD.begin(SD_CARD_CS) или как то не правильно отрабатывает. Вот что он Serial пишет при выполнении "SD-card not found", хотя карта вставлена, питание на ней есть.
попробуйте вывести в монитор состояние контрольного и статусного регистра SPI при обращении в функцию. А то Вы с такой легкостью использовали SPI.end();, что остается вопросом не задезейблили ли Вы шину еще где-то.
И это, Вы вроде изменения сделали, а что изменилось в поведении - не раскрыли.
У меня работает логгер, и так же проц засыпает и просыпается. Но у меня SD.begin вынесено в setup. его не надо дрыгать каждый раз.
Да там одна микруха копеечная стоит, MIC5219-3.3 :)
микруха + минимум входная и выходная емкость, дроссель, диод (хотя он может быть и интегрирован), емкость на BOOТ, резистор подтяжки на EN, vs 1 транзистор. :)
У меня работает логгер, и так же проц засыпает и просыпается. Но у меня SD.begin вынесено в setup. его не надо дрыгать каждый раз, так как Вы получается по новой создаете объект класса SD, на сколько я понимаю.
Мне вот тоже кажется, что с этим проблема. Скорее всего работоспособность более одного объекта в принципе не предусмотрена (Автор, можете просто в сетапе попробовать два раза подряд инициализировать карту, скорее всего второй раз будет неудачным). А тем более, если их (объекты) ещё и в цикле плодить.
Мне вот тоже кажется, что с этим проблема. Скорее всего работоспособность более одного объекта в принципе не предусмотрена
насколько я помню, там создается буфер в 512 или 1024 байт...
Я прям по даташиту сделал, керамика на входе и выходе.
Вот что выдает в сериал:
01:01:01, 01.01.2001, Sun Loging data to file...Start function SD
SPCR: 10000 SPSR: 0 SPDR: 10010100
Pin SS_PIN: 1 Pin MOSI_PIN: 0 Pin MISO_PIN: 1 Pin SCK_PIN: 0
Run SD.begin(SD_CARD_CS))
SD-card not found
SPCR: 1010000 SPSR: 10000000 SPDR: 10010100
Pin SS_PIN: 1 Pin MOSI_PIN: 1 Pin MISO_PIN: 1 Pin SCK_PIN: 0
Exit func SD card
SPCR: 10000 SPSR: 0 SPDR: 10010100
Pin SS_PIN: 0 Pin MOSI_PIN: 0 Pin MISO_PIN: 1 Pin SCK_PIN: 0
Код вот такой:
Меня очень смущает что после команд digitalWrite(MISO_PIN, LOW); и SPI.end(); на линии MISO всегда высокий уровень.
ну как я и думал: у вас шина SPI при передаче управления в функцию не активна. Код работает в точности как он написан.
Хинт: Вам уже в этой ветке все расписали, попробуйте ее прочесть. Или возьмите рабочий пример логгера из библиотеки SD, и допиливайте его под свои нужды.
Меня очень смущает что после команд digitalWrite(MISO_PIN, LOW); и SPI.end(); на линии MISO всегда высокий уровень.
Вот немного причесал код, убрал лишнее. Инициализацию делаю в ф-ции, но один раз. Питание карты не снимаю. Поведение абсолютно такое же - не пишет:)
а в монитор чего пишет?
В монитор вот это пишет:
Start function SD
SPCR: 1010011 SPSR: 0 SPDR: 11111111
Pin SS_PIN: 1 Pin MOSI_PIN: 1 Pin MISO_PIN: 1 Pin SCK_PIN: 0
Run SD.begin(SD_CARD_CS))
SD card is run
log file not open
Exit func SD card
SPCR: 1010011 SPSR: 0 SPDR: 11111111
Pin SS_PIN: 1 Pin MOSI_PIN: 1 Pin MISO_PIN: 1 Pin SCK_PIN: 0
Получается что не выполняется SDcard = SD.open("logs.txt", FILE_WRITE); потому как файл на карте не создается. Пробовал форматировать карту в FAT, FAT32, NTFS, везде одинаковое поведение. Пробовал выносить инициализацию в Setup, ничего не меняется.
Добавил в инициализацию
if(!InitSD){ // Инициируем карту
SD.begin(SD_CARD_CS);
InitSD = true; // Поднимаем флаг чтобы не было повторной инициализации
if (!SD.begin(SD_CARD_CS)) {
Serial.println("Card failed, or not present");
}
else{
Serial.println("card initialized.");
}
}
В сериал контроллер пишет "Card failed, or not present". Он вообще не обращается к карте.
Слушай, мы так и будем в грабельки играть? Что мешает открыть код из примеров, где идёт работа с SD - и запустить его? А уже потом - понять, что грабельки надо рассыпать аккуратно, а не абы как.
Что мешает запустить код из примеров? Религия?
В общем разобрался.
Вот абсолютно рабочий код:
Проблема была в том, что Arduino IDE очень фривольно относится в коду и так же его компилирует.
Эту конструкцию она успешно переваривает.
Я же пишу в AVR Studio и она уже такого не прощает.
Проблема была в том, что Arduino IDE очень фривольно относится в коду и так же его компилирует.
Эту конструкцию она успешно переваривает.
Я же пишу в AVR Studio и она уже такого не прощает.
Ошибаетесь, это не Ардуино ИДЕ "фривольно относится к коду", а вы лично. Вы принципиально не читаете документацию? Нафига SD.begin() два раза вызывать?
Да и последний. "абсолютно рабочй код", над которым вы корпели три месяца - прям глаза режет своей корявостью. К чему, например, вызывать pinMode при каждой записи файла? Вы язык программирования совсем не знаете?
Вместо того, чтоб фигню вымучивать - почитали бы примеры к библиотеке, как Вам Дийман еще в сентябре советовал.