Как записать и прочитать из файла SPIFFS как данные объекта на ESP8266
Я пытаюсь записать четырехзначное число в файл SPIFFS, прочитать эту четырехзначную цифру из файла SPIFFS и отобразить ее на семисегментном дисплее.
Код, который я пишу, как показано ниже, я получил "0" на каждом сегменте, но если вручную сделать число = 4567; то семь сегментов показывают правильное число на каждом сегменте.
Пожалуйста, помогите мне узнать больше о том, как читать и записывать и преобразовывать объектные данные.
Вот мой код;
#include <FS.h>
const char* filename = "/InputInt.txt";
int digit_1 = 0;
int digit_2 = 0;
int digit_3 = 0;
int digit_4 = 0;
int Anode_1 = 16;
int Anode_2 = 14;
int Anode_3 = 5;
int Anode_4 = 4;
int count = 0;
int digits[4] ;
int AnodePins[4] = {4, 5, 14, 16};
int clockPin = 12;
int latchPin = 13;
int dataPin = 15;
int number = 0;
byte numbers[10] {B00000011, B10011111, B00100101, B00001101, B10011001, B01001001, B01000001, B00011111, B00000001, B00001001};
void setup() {
Serial.begin(115200);
Serial.println();
bool success = SPIFFS.begin();
if (!success) {
Serial.println("Error mounting the file system");
return;
}
SPIFFS.format();
File fw = SPIFFS.open(filename, "w");
if (!fw) {
Serial.println("Error opening file for writing");
return;
}
char Written = fw.print("1234");
if (Written == 0) {
Serial.println("File write failed");
return;
}
fw.close();
pinMode(Anode_1, OUTPUT);
pinMode(Anode_2, OUTPUT);
pinMode(Anode_3, OUTPUT);
pinMode(Anode_4, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(latchPin, OUTPUT);
pinMode(dataPin, OUTPUT);
} //End of setup
void loop() {
int i;
File fr = SPIFFS.open(filename, "r");
if (!fr) {
Serial.println("Failed to open file for reading");
return;
}
for (i = 0; i < 4; i++) {
byte number = (Serial.write(fr.read()));
}
fr.close();
break_number(number);
display_number();
delay(3000);
} // End of loop
// seperate the input number into 4 single digits
void break_number(int num) {
Serial.println("");
digit_1 = num / 1000;
digits[0] = digit_1;
Serial.print(" Digit_1: ");
Serial.println(digit_1);
int dig_1_remove = num - (digit_1 * 1000);
digit_2 = dig_1_remove / 100;
digits[1] = digit_2;
Serial.print(" Digit_2: ");
Serial.println(digit_2);
int dig_2_remove = dig_1_remove - (digit_2 * 100);
digit_3 = dig_2_remove / 10;
digits[2] = digit_3;
Serial.print(" Digit_3: ");
Serial.println(digit_3);
digit_4 = dig_2_remove - (digit_3 * 10);
digits[3] = digit_4;
Serial.print(" Digit_4: ");
Serial.println(digit_4);
}
void display_number() { //сканирование
digitalWrite(AnodePins[count], HIGH); //включить соответствующие цифры
digitalWrite(latchPin, LOW); //поставить сдвиговый регистр чтения
shiftOut(dataPin, clockPin, LSBFIRST, numbers[digits[count]]); //отправить данные
digitalWrite(latchPin, HIGH); //поставить сдвиговый регистр, в режим записи
delay(0);
digitalWrite(AnodePins[count], LOW); //включить соответствующий счетчик цифр
count++; //подсчитать цифру
if (count == 4) { //держать счет между 0-3
count = 0;
}
}
Вот результат;
1234
Digit_1: 0
Digit_2: 0
Digit_3: 0
Digit_4: 0
1234
Digit_1: 0
Digit_2: 0
Digit_3: 0
Digit_4: 0
1234
Digit_1: 0
Digit_2: 0
Digit_3: 0
Digit_4: 0
Спасибо,
@Ali Morawej, 👍1
1 ответ
Лучший ответ:
Я прямо вижу 3 проблемы с вашим кодом:
Функция Serial.write()возвращает не записанные данные, а количество отправленных байтов. Это означает, что в цикле for вы присваиваете переменной только записанное количество байтов, а не данные. Но я предполагаю, что вы хотите отобразить фактические данные, которые были прочитаны из файла. Вы должны присвоить возвращаемое значениеfr.read()переменной. Затем вы можете отправить его черезSerial.write()и все еще использовать эту переменную для других вещей позже (например, для отображения).Вам нужно заглянуть в область переменных. У вас есть
номер глобальной переменной. Но в цикле for вы определяете локальную переменную с тем же именем черезbyte number = ...Эта переменная действительна только в той конкретной итерации цикла for. Когда итерация заканчивается, переменная выбрасывается и повторно объявляется на следующей итерации. Его больше не будет, когда вы покинете цикл for. Таким образом, в настоящее время вы сохраняете свои данные в переменной, локальной для цикла for. Он не касается глобальной переменной. Таким образом, другие функции видят только нулевое значение, которым
была инициализирована глобальная переменная number. Вы можете удалитьбайт типаперед переменной в цикле for. Это превращает его в задание, а не в определение. Таким образом, вы действительно записываете данные в глобальную переменную.Кодировка данных: Очевидно, что ваш номер находится в файле в виде текста в кодировке ASCII. Но вы, похоже, обращаетесь с ними как с двоичными данными. Это не может сработать. Например: Когда вы читаете первый символ
1234(который записан в файле), то получаете" 1 "(символ, а не число). Если посмотреть на таблицу ASCII, то можно увидеть, что этот символ соответствует десятичному числу 49 (или0x31в шестнадцатеричном формате). Вы можете преобразовать цифру в кодировке ASCII в действительное число, вычитая значение символа"0":int number = fr.read() - '0';или
int number = fr.read() - 48;(оба эквивалентны).
Кроме того, в настоящее время вы просто сохраняете считанный символ в одну переменную. Это означает, что после цикла for остается только последний символ. Поскольку это составное число, вы должны что-то сделать, чтобы составить его. Вот так:
number = 0; int factor = 1000; for(int i = 0; i<4; i++){ number += (fr.read() - '0') * factor; factor /= 10; }Примечание: Это непроверенный способ, он не самый лучший, но самый простой на данный момент, и он работает только для чисел от 1000 до 9999 (4-значные числа). Вы можете реализовать это более универсально.
Сначала мы сбрасываем переменную
number, чтобы старые значения не мешали нам. Мы используем переменную, удерживающую текущий коэффициент (начиная с 1000, так как это цифра, в которой лежит первая цифра). Затем мы проходим через 4 символа, читая их. Мы вычитаем символ" 0 "(как описано выше), а затем умножим на коэффициент. Это результирующее число добавляется к переменномучислу. Затем делим коэффициент на 10 (получаем от 1000 до 100, затем на 10 и, наконец, на 1). В конце мы можем использоватьчислокак любую другую целочисленную переменную.
Альтернативная реализация чтения числа, которая подходит для разного количества цифр:
number = 0;
// Подготовить символьный буфер для чтения числа
char buffer[10] = ""; // пробел максимум для 9 цифр
int pos = 0; // переменная позиции в буфере
while(fr.available() && pos < 9){ // loop while there is data left to read in the file or we have no pace left in buffer (leaving one character for the terminating null character
char c = fr.read(); // read character into variable
if(isDigit(c)){
buffer[pos] = c; // сохранить цифру в буфере
pos++; // increment position for the next character
} else {
break; //выйти из цикла, если прочитанный символ не является цифрой (мы не хотим читать дальше, когда появляется нецифровый символ)
}
}
buffer[pos] = 0; // завершить буфер нулевым символьным
number = atoi(buffer); // использовать стандартную функцию для преобразования в целое число
Примечание:
- Этот код не тестируется, хотя компилируется без ошибок
- Вы видите, что он не меньше, чем другой, но может обрабатывать разное количество цифр.
- Вы все еще можете использовать первую версию с меньшими числами, если вы всегда дополняете их нулями. Поэтому вместо
991вы бы написали0991в файл. Это заставит работать первую версию.
- Драйверы для чипа последовательного порта CH9102X
- Преобразование строки в IP-адрес
- ESP32: отключить детектор отключения питания
- Какую плату выбрать в PlatformIO для ESP Wroom 32?
- esp32 Stack canary watchpoint срабатывает
- ESP32S v1.1 NodeMCU vs ESP32 DevKitV1
- Постоянная частота дискретизации АЦП на ESP8266 или ESP32
- esp32-cam публикует изображение в mqtt
Спасибо Крисл, я отредактировал то, что вы упомянули, теперь все работает хорошо, вы абсолютно правы., @Ali Morawej
Пожалуйста, дайте мне знать, как сохранить число в виде четырехзначного числа (ОКТ), число равно 1000, а минута 4 должна отображать 0996, но отображать 9911., @Ali Morawej
Извините, я не совсем понимаю. Пожалуйста объясните яснее, @chrisl
Хорошо, запишите номер 1008 в файл, затем прочитайте его правильно на дисплее, я добавляю какой-то код в цикл окончательного
number = number -4;и снова отобразите номер, начните правильно со 1008, 1004, 1000 и перейдите к 9911 вместо 0996., @Ali MorawejВы почти наверняка не заполняете число нулями до 4 цифр, когда записываете его в файл. Как я уже писал, это сломает фрагмент кода. Я добавил еще один способ чтения числа, который также поддерживает другие цифровые числа., @chrisl