Прочитать один байт из файла и преобразовать в десятичное число.

Хорошо, я новичок в Arduino и пытаюсь прочитать байты из файла на SD-карте и преобразовать их в целочисленные значения (0–255).

У меня есть файл размером 1 байт (значение 128 int, созданное в Python, при необходимости можно предоставить код) и шестнадцатеричный дамп (двоичный режим):

xxd -b single_byte.dat
00000000: 10000000

Пока все хорошо, верно? Поэтому я ожидал прочитать этот байт из файла (SD-карты), а затем преобразовать его обратно в значение 128. Это мой код Arduino:

#include <SPI.h>
#include <SD.h>

// устанавливаем переменные с помощью функций библиотеки утилит SD:
Sd2Card card;
SdVolume volume;
SdFile root;
const int chipSelect = 4;

void setup() {
  // Открытие последовательной связи и ожидание открытия порта:
  Serial.begin(9600);
  while (!Serial) {
    ;
  }

  delay(100);
  Serial.print("\nInitializing SD card...");

  if (!card.init(SPI_HALF_SPEED, chipSelect)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("* is a card inserted?");
    Serial.println("* is your wiring correct?");
    Serial.println("* did you change the chipSelect pin to match your shield or module?");
    while (1);
  } else {
    Serial.println("Wiring is correct and a card is present.");
  }

  // печатаем тип карты
  Serial.println();
  Serial.print("Card type:         ");
  switch (card.type()) {
    case SD_CARD_TYPE_SD1:
      Serial.println("SD1");
      break;
    case SD_CARD_TYPE_SD2:
      Serial.println("SD2");
      break;
    case SD_CARD_TYPE_SDHC:
      Serial.println("SDHC");
      break;
    default:
      Serial.println("Unknown");
  }

  // Теперь попробуем открыть "том"/"раздел" - это должна быть FAT16 или FAT32
  if (!volume.init(card)) {
    while (1);
  }

  File file;
  byte one_byte;
  int dec_value;

  file = SD.open("single_byte.dat", FILE_READ);
  one_byte = file.read();
  file.close();
  
  dec_value = int(one_byte);

  Serial.println(dec_value, DEC);
  
}

void loop(void) {
}

Я ожидал, что результат будет 128.

Однако я получаю:

Фактический результат

Что мне не хватает? (да, я пытался создать файл .dat с кодировкой с обратным порядком байтов, результат тот же)

, 👍2

Обсуждение

Какую версию Python вы используете? «Примечание. Начиная с Python 3.6, все файлы читаются и записываются Python с использованием utf-8 по умолчанию, даже в Windows». Возможно, вы пишете UTF16 и не осознаете этого. Что произойдет, если вы попытаетесь прочитать следующий байт и следующий?, @st2000

Я использую Python 3.9 (в Debian 11)... Я не пробовал читать больше байтов, но шестнадцатеричный дамп отображает один байт в файле, так что, я думаю, с файлом все в порядке?, @melev

О, кажется, я понимаю, что ты сделал. Попробуйте добавить SD.begin., @st2000

Я только что попробовал добавить код SD.begin(4), но безуспешно, результат тот же, что и раньше: отображается сообщение «инициализация выполнена», но вывод моей переменной тот же. Что еще я могу попробовать? Может быть, int(one_byte) — не тот вариант, и нужно сделать что-то еще (манипулирование битами?)?, @melev

@melev Можете ли вы обновить свой код, чтобы показать, где вы добавили SD.begin(4)?, @Fahad

... @melev, я вижу, где вы берете большую часть своего кода из [второго примера на странице arduino.cc, на которую я ссылаюсь в ответе ниже](https://docs.arduino.cc/learn/programming/sd -гид). Предполагая, что все примеры на этой странице работают, рассмотрите возможность использования только первого примера на той же странице. Правда, он не дает вам столько диагностических подробностей, но, возможно, с него лучше начать, учитывая наше предположение, что пример может успешно открыть и прочитать файл на SDCard., @st2000

@st2000 st2000 У меня все заработало, оказывается, я идиот, лол. ваш комментарий «учитывая наше предположение, что пример может открыть файл» заставил меня задуматься, поэтому я добавил if(file) и угадайте, что... это не так!!! так что я просто читал фигню, я думаю. Я публикую полное объяснение в качестве ответа, БОЛЬШОЕ спасибо за ваше время., @melev

@Фахад, у меня все заработало, проблема была в чертовом имени файла, проверь мой ответ. Спасибо!, @melev

Кстати, xxd ясно показывает, что файл не содержит ни одного байта, а содержит 4 байта. Вероятно, это uint32le. Но преимущество прямого порядка байтов в том, что если вы прочитаете его как один байт, вы в любом случае получите правильный ответ, если значение <256., @hobbs


2 ответа


Лучший ответ:

5

Хорошо, теперь все заработало, вот что произошло:

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

root.openRoot(volume);
// перечисляем все файлы на карте с датой и размером
root.ls(LS_R | LS_DATE | LS_SIZE)

И, конечно же, мой файл не был обнаружен как single_byte.dat, но это было что-то вроде: single_~.dat, поэтому я переименовал файл в test. да и тада! код теперь работает как часы.

Думаю, я упустил из виду это ограничение в документации, поэтому имейте это в виду при использовании SD-карты.

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

Просто убедитесь, что у вас есть:

file = SD.open(filename, FILE_READ);
if(file){
    // Делайте что-нибудь здесь.
}
else{
    Serial.println("You're out of luck: Can't open file");
}

Хорошо, вот и подошло мое воскресенье. Спасибо всем за прочтение!!!

,

Корнем этого ограничения является частично Microsoft, частично библиотека. С одной стороны, Microsoft вставила длинные имена файлов в свои старые файловые системы FAT, пытаясь обеспечить обратную совместимость. Каждый файл имеет короткое имя 8+3 и длинное имя, следующее за некоторыми записями каталога. С другой стороны, библиотека, видимо, сэкономила на размере и исключила код для работы с длинными именами. -- Однако главный урок, который вы усвоили: всегда проверяйте возвращаемые значения!, @the busybee

Ах, хороший улов! Итак, вы спросили: «Почему? Кажется, есть ограничение на длину имени файла, я заметил это после добавления строк:» «Почему» связано с тем, что формат файловой системы FAT появился еще с тех пор, как Билл Гейтс взял с какого-то компьютера что-то под названием DOS. клуб. Это исправило все имена файлов до версии 8.3 или трехсимвольного формата с восемью десятичными запятыми. Это все еще существует. Чтобы скрыть это, используются некоторые хитрые обходные пути. Но оно все еще существует. Таким образом, фактическое имя файла «искажается», когда вы пытаетесь выйти за рамки формата 8.3. Я думаю, что хитрость в том, что все они «искажаются» однозначно., @st2000


1

Рассмотрите возможность добавления вызова SD.begin(), как это сделано в примере, найденном на сайте arduino.cc. страница.

Вот раздел примера кода, где используется SD.begin():

  Serial.print("Initializing SD card...");

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    while (1);
  }
,