Всем привет, сегодня разберем что такое SPIFFS и как с ним работать, создадим веб-сервер и научимся выводить показания с датчика bme280.
Что такое SPIFFS?
SPIFFS – (Serial Peripheral Interface Flash File System) файловая система флеш-памяти, подключаемой по последовательному периферийному интерфейсу. У микроконтроллеров Esp есть встроенная перезаписываемая энергонезависимая NOR-память, в которой хранятся: настройки (Preferences), загрузчик (Bootloader), микропрограмма (скомпилированный скетч) и файловая система (SPIFFS). На картинке ниже видна структура микроконтроллера:
NOR-память – это вид энергонезависимой перезаписываемой памяти, который имеет высокую скорость считывания, но низкую скорость записи и стирания.
Объем памяти достаточно большой, но зависит от микроконтроллера, для ESP32 стандарт 4 мегабайта.
SPIFFS имеет некоторые недостатки например:
Но они не критичны по сравнению с теми плюсами которые предоставляет нам SPIFFS. Мы можем использовать SPIFFS для:
Для начала работы с SPIFFS надо настроить Arduino IDE:
Версия IDE 2.0, к сожалению, пока не поддерживается.
Скачайте архив с инструментом для ESP32 тут. Или же для ESP8266 тут.
Распакуйте архив и перенесете папку arduino ide по адресу:
C:\Users\имя\Documents\Arduino\tools\ESP32FS(ESP8266FS)\tool\esp32fs(esp8266fs).jar
После перемещения откройте ardino ide и проверьте, во вкладке инструменты должен появиться доп вариант:
Если появился, значит все успешно, если нет, попробуйте еще раз.
Создайте новый скетч и поместите в него содержимое:
#include "SPIFFS.h" //Подключаем библиотеку String data; void setup() { Serial.begin(115200); if(!SPIFFS.begin(true)){ //Инициализируем SPIFFS Serial.println("An Error has occurred while mounting SPIFFS"); return; } File file = SPIFFS.open("/test.txt"); //Открываем файл if(!file){ //Проверка наличия Serial.println("Failed to open file for reading"); return; } data = file.readString(); //Конвертируем данные в нормальное представление uint8_t data1[data.length()]; data.getBytes(data1, data.length()); //168 file.close(); //Завершаем работу с файлом Serial.println(data); //Выводим информацию в монитор порта } void loop() {}
Далее, во вкладке Скетч выберите вариант показать папку скетча (или воспользуйтесь сочетанием клавиш CTRL+K). В открывшейся папке создайте новую папку с именем data и поместите в неё файл test.txt. В файл запишите любое текстовое послание.
После во вкладке инструменты выберите ESP32/8266 Sketch Data Upload. Должен начаться процесс загрузки данных из папки data в память esp (на некоторых платах надо зажать кнопку boot). Разберем возможные ошибки:
Traceback (most recent call last): File "site-packages\serial\serialwin32.py", line 62, in open serial.serialutil.SerialException: could not open port 'COM3': WindowsError(5, '\xce\xf2\xea\xe0\xe7\xe0\xed\xee \xe2 \xe4\xee\xf1\xf2\xf3\xef\xe5.') Failed to execute script esptool SPIFFS Upload failed!
Если вы видите что-то похожее на это, необходимо проверить есть ли еще открытые экземпляры arduino ide или монитор порта. Оставьте одно окно и попробуйте еще раз. Эта ошибка возникает если порт занят другой программой (многие сталкивались с ней когда в фоне была запущена программа Cura).
Также если вы неправильно назвали папку или она отсутствует, среда предложит вам её создать, отвечайте Yes.
Если вы добавите в папку дата слишком большой файл (больше памяти esp) вам выдаст ошибку:
SPIFFS_write error(-10001): File system is full. error adding file! SPIFFS Create Failed!
При записи новых данных, все старые файлы в SPIFFS будут уничтожены!
Если все прошло успешно, вы увидите вывод:
Uploading stub... Running stub... Configuring flash size... Auto-detected Flash size: 4MB Compressed 1507328 bytes to 2933... Writing at 0x00290000... (100 %) Wrote 1507328 bytes (2933 compressed) at 0x00290000 in 0.0 seconds Hash of data verified.
Теперь загрузите скетч и откройте монитор порта:
Вы должны увидеть содержимое файла test.txt
Попробуем придать этому немного смысла, создадим веб-страничку на которую esp будет выводить данные датчика bme280.
Для начала подключим датчик по стандартной схеме:
Далее нам нужна сама веб страница и стили для неё чтобы в последствии загрузить их в SPIFFS. В качестве стилей я возьму готовую библиотеку bootstrap.
Создайте файл index.html со следующим содержимым:
<!DOCTYPE html> <html lang="ru"> <head> <title>BME280 TEST</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="bootstrap.min.css"> </head> <body class="bg-dark text-light"> <div class="position-absolute top-50 start-50 translate-middle"> <div class="container-fluid text-dark"> <center><h1 class="text-white">ESP32-BME280 Meteostation</h1><br></center> <div class="row row-cols-2 row-cols-md-2 g-2"> <div class="col"> <div class="card text-dark bg-danger mb-3"> <div class="card-body"> <h5 class="card-title">Температура</h5> <p class="card-text"><h3>%TEMP%</h3></p> </div> </div> </div> <div class="col"> <div class="card text-dark bg-info mb-3"> <div class="card-body"> <h5 class="card-title">Влажность</h5> <p class="card-text"><h3>%HUMID%</h3></p> </div> </div> </div> <div class="col"> <div class="card text-dark bg-success mb-3"> <div class="card-body"> <h5 class="card-title">Давление</h5> <p class="card-text"><h3>%PRESS%</h3></p> </div> </div> </div> <div class="col"> <div class="card text-dark bg-warning mb-3"> <div class="card-body"> <h5 class="card-title">Высота над уровнем моря</h5> <p class="card-text"><h3>%ALT%</h3></p> </div> </div> </div> </div> </div> </div> </body> <script> setInterval(function ( ) { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { document.getElementById("TEMP").innerHTML = this.responseText; } }; xhttp.open("GET", "/temp", true); xhttp.send(); }, 10000 ) ; setInterval(function ( ) { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { document.getElementById("HUMID").innerHTML = this.responseText; } }; xhttp.open("GET", "/humid", true); xhttp.send(); }, 10000 ) ; setInterval(function ( ) { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { document.getElementById("PRESS").innerHTML = this.responseText; } }; xhttp.open("GET", "/press", true); xhttp.send(); }, 10000 ) ; setInterval(function ( ) { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { document.getElementById("ALT").innerHTML = this.responseText; } }; xhttp.open("GET", "/alt", true); xhttp.send(); }, 10000 ) ; </script> </html>
В этом файле два раздела, первый это обычный html, а второй, это javascript который запрашивает переменные у esp.
Библиотеку bootstrap можно скачать тут.
Поместите два файла (index.html и bootstrap.min.css) в папку data и загрузите в SPIFFS.
Напишем скетч для обработки данных:
#include "SPIFFS.h" //Подключаем библиотеку #include <Wire.h> #include <Adafruit_Sensor.h> #include <Adafruit_BME280.h> //Библиотека датчика #include <ESPAsyncWebServer.h> //Библиотека сервера #include <WiFi.h> //wifi const char* ssid = "12"; //Имя wifi сети const char* password = "12345678"; //пароль wifi сети #define SEALEVELPRESSURE_HPA (1013.25) AsyncWebServer server(80); Adafruit_BME280 bme; // I2C String data; void setup() { Serial.begin(115200); WiFi.begin(ssid, password); //Подключаемся к wifi if (WiFi.waitForConnectResult() != WL_CONNECTED) { return; } if(!SPIFFS.begin(true)){ //Инициализируем SPIFFS Serial.println("An Error has occurred while mounting SPIFFS"); return; } bool status; status = bme.begin(0x76); //Инициализируем BME280 if (!status) { Serial.println("Could not find a valid BME280 sensor, check wiring!"); while (1); } server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ //Достаем index.html и отправляем на сервер request->send(SPIFFS, "/index.html", String(), false, processor); }); server.on("/bootstrap.min.css", HTTP_GET, [](AsyncWebServerRequest *request){ //Подключаем стили request->send(SPIFFS, "/bootstrap.min.css", "text/css"); }); server.begin(); //сервер запускаем } void loop() { if (WiFi.status() == WL_CONNECTED) { delay(1000); } } String processor(const String& var){ //Функция которая передает переменные на сервер if (var == "TEMP"){ return String(bme.readTemperature()); } if (var == "HUMID"){ return String(bme.readHumidity()); } if (var == "PRESS"){ return String(bme.readPressure() / 100.0F); } if (var == "ALT"){ return String(bme.readAltitude(SEALEVELPRESSURE_HPA)); } return String(); }
Загружаем, далее ip сканером либо в настройках роутера находим ip адрес и заходим по нему в браузер.
Демонстрация на видео:
Чтобы сделать авто обновление данных, добавите строчку в index.html в <head>
<meta http-equiv="Refresh" content="1" />
На этом у меня все, Спасибо за внимание, удачи в ваших проектах!
Данная статья является собственностью Amperkot.ru. При перепечатке данного материала активная ссылка на первоисточник, не закрытая для индексации поисковыми системами, обязательна.
Комментарии