Как записать и прочитать из файла 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
- ESP32: отключить детектор отключения питания
- Преобразование строки в IP-адрес
- Какую плату выбрать в PlatformIO для ESP Wroom 32?
- esp32 Stack canary watchpoint срабатывает
- Постоянная частота дискретизации АЦП на ESP8266 или ESP32
- ESP32S v1.1 NodeMCU vs ESP32 DevKitV1
- 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